Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file qle.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230(* This file is free software, part of Zipperposition. See file "license" for more details. *)(** {1 Quasipure Literal Elimination} *)openLogtkopenLibzipperpositionletk_enabled=Flex_state.create_key()letk_inprocessing=Flex_state.create_key()letk_check_at=Flex_state.create_key()letk_pure_only=Flex_state.create_key()letsection=Util.Section.make~parent:Const.section"qle"moduleA=Libzipperposition_avatarmoduletypeS=sigmoduleEnv:Env.Svalsetup:unit->unitendmoduleMake(E:Env.S):SwithmoduleEnv=E=structmoduleEnv=EmoduleC=Env.CmoduleCS=C.ClauseSetmoduleL=LiteralmoduleT=TermmoduleSAT=Sat_solver.Make()letremove_from_proof_statec=Util.debugf~section1"removing @[%a@]"(funk->kC.ppc);C.mark_redundantc;Env.remove_active(Iter.singletonc);Env.remove_passive(Iter.singletonc);Env.remove_simpl(Iter.singletonc)letdo_qlepure_onlyc_iter=Util.debugf~section2"init: @[%a@]@."(funk->k(Iter.pp_seqC.pp)c_iter);letadd_SAT_clausec=SAT.add_clause~proof:Proof.Step.trivialcinletpred_of_litlit=matchlitwith|L.Equation(lhs,_,_)whenL.is_predicate_litlit->if(T.is_const(T.head_termlhs))thenletsym=T.as_const_exn(T.head_termlhs)inSome(L.is_positivoidlit,sym)elseNone|_->Noneinletall_syms=ID.Tbl.create128inSAT.clear();(* For each clause l1 \/ ... \/ lN (ignoring equality literals), if
pure_only is false, generate N SAT clauses
v1 \/ ... \/ vI-1 \/ ~wI \/ vI+1 \/ ... \/ vN,
where vJ is the variable associated with lJ (sign and predicate symbol)
and wJ is the variable associated with its negation.
If pure_only is true, generate N SAT clauses ~wI. *)Iter.iter(func->letpred_subcl=CCArray.filter_mappred_of_lit(C.litsc)inletmk_pure_clauses(pol,pred)=let(pos_var,neg_var)=ID.Tbl.findall_symspredin[SAT.Lit.neg(ifnotpolthenpos_varelseneg_var)]|>add_SAT_clauseinletmk_quasipure_clausesspecial=Array.map(fun((pol,pred)aslit)->let(make_lit_pos,use_pos_var)=iflit=specialthen(false,notpol)else(true,pol)inlet(pos_var,neg_var)=ID.Tbl.findall_symspredin(ifuse_pos_varthenpos_varelseneg_var)|>(ifmake_lit_posthen(funlit->lit)elseSAT.Lit.neg))pred_subcl|>Array.to_list|>add_SAT_clausein(* Create p+, p- variables for each predicate symbol p. *)Array.iter(fun(_,pred)->ifnot(ID.Tbl.memall_symspred)thenID.Tbl.replaceall_symspred(BBox.make_fresh(),BBox.make_fresh()))pred_subcl;(* Create a number of SAT clauses for each clause. *)Array.iter(ifpure_onlythenmk_pure_clauseselsemk_quasipure_clauses)pred_subcl)c_iter;(* Detect problematic higher-order features and forget about some predicate
symbols if necessary. *)Iter.iter(func->letforget_syms=Iter.iter(funbad->ID.Tbl.updateall_syms~f:(fun__->None)~k:bad)inArray.iter(funlit->matchlitwith|L.Equation(lhs,_,_)whenL.is_predicate_litlit->if(T.is_const(T.head_termlhs))thenletbad_syms=Iter.flat_mapT.Seq.symbols(Iter.of_list(T.argslhs))inforget_symsbad_symselseforget_syms(T.Seq.symbolslhs)|L.Equation(lhs,rhs,_)->forget_syms(T.Seq.symbolslhs);forget_syms(T.Seq.symbolsrhs)|_->())(C.litsc))c_iter;(* For each predicate p, generate a SAT clause ~p+ \/ ~p-. *)Iter.iter(fun(pos_var,neg_var)->add_SAT_clause[SAT.Lit.negpos_var;SAT.Lit.negneg_var])(ID.Tbl.valuesall_syms);letunknown_syms=ID.Tbl.copyall_symsinletquasipure_syms=ID.Tbl.create32in(* Generate a SAT clause p1+ \/ p1- \/ ... \/ pN+ \/ pN-, where the pIs are
the predicate symbols of unknown purity status (initially all). *)letgenerate_nontrivial_solution_SAT_clause()=add_SAT_clause(CCList.flat_map(fun(pos_var,neg_var)->[pos_var;neg_var])(CCList.of_iter(ID.Tbl.valuesunknown_syms)))inletrecmaximize_valuation()=Iter.iter(fun(pred,(pos_var,neg_var))->ifSAT.valuationpos_varthen(add_SAT_clause[pos_var];ID.Tbl.replacequasipure_symspredpos_var;ID.Tbl.removeunknown_symspred);ifSAT.valuationneg_varthen(add_SAT_clause[neg_var];ID.Tbl.replacequasipure_symspredneg_var;ID.Tbl.removeunknown_symspred))(ID.Tbl.to_iterunknown_syms);generate_nontrivial_solution_SAT_clause();(matchSAT.check~full:true()with|Sat_solver.Sat->maximize_valuation()|_->())inletfilter_clauses()=letis_quasipure_litlit=matchlitwith|L.Equation(lhs,rhs,true)->if(T.is_const(T.head_termlhs))thenletsym=T.as_const_exn(T.head_termlhs)inID.Tbl.memquasipure_symssymelsefalse|_->falseinletcontains_quasipure_symc=CCArray.existsis_quasipure_lit(C.litsc)inUtil.debugf~section1"quasipure syms: @[%a@]"(funk->k(CCList.ppID.pp)(ID.Tbl.keys_listquasipure_syms));Iter.iter(func->ifcontains_quasipure_symcthenremove_from_proof_statec)c_iterinUtil.debugf~section1"In do_qle()@."CCFun.id;generate_nontrivial_solution_SAT_clause();(matchSAT.check~full:true()with|Sat_solver.Sat->Util.debugf~section1"Maximizing()@."CCFun.id;maximize_valuation();filter_clauses()|_->Util.debugf~section1"Unsat()@."CCFun.id;());SAT.clear()letget_clauses()=Iter.append(Env.get_passive())(Env.get_active())letsteps=ref0letinprocessing()=if!steps=0then(Util.debugf~section1"doing inprocessing@."CCFun.id;do_qle(E.flex_getk_pure_only)(get_clauses()));steps:=(!steps+1)modEnv.flex_getk_check_atletsetup()=ifE.flex_getk_enabledthenifnot(Env.flex_getA.k_avatar_enabled)thenifE.flex_getk_inprocessingthenE.add_clause_elimination_rule~priority:4"qle"inprocessingelseSignal.onceEnv.on_start(fun()->do_qle(E.flex_getk_pure_only)(get_clauses()))elseCCFormat.printf"AVATAR is not yet compatible with QLE@."endlet_enabled=reffalselet_inprocessing=reffalselet_check_at=ref100let_pure_only=reffalseletextension=letactionenv=letmoduleE=(valenv:Env.S)inletmoduleQLE=Make(E)inE.flex_addk_enabled!_enabled;E.flex_addk_inprocessing!_inprocessing;E.flex_addk_check_at!_check_at;E.flex_addk_pure_only!_pure_only;QLE.setup()in{Extensions.defaultwithExtensions.name="qle";prio=40;env_actions=[action]}let()=Options.add_opts["--qle",Arg.Bool((:=)_enabled)," enable QLE";"--qle-inprocessing",Arg.Bool((:=)_inprocessing)," enable QLE as inprocessing rule";"--qle-check-at",Arg.Int((:=)_check_at)," QLE inprocessing periodicity";"--qle-pure-only",Arg.Bool((:=)_pure_only)," enable PLE";]