Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file saturate.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309(* This file is free software, part of Zipperposition. See file "license" for more details. *)(** {1 Main saturation algorithm.}
It uses inference rules and simplification rules from Superposition. *)openLogtkmoduleC=ClausemoduleO=OrderingmodulePS=ProofStatemoduleSel=SelectionmoduleEIntf=Eprover_interfaceletstat_redundant_given=Util.mk_stat"saturate.redundant given clauses"letstat_processed_given=Util.mk_stat"saturate.processed given clauses"letstat_steps=Util.mk_stat"saturate.steps"letsection=Util.Section.make~parent:Const.section"saturate"letk_abort_after_fragment_check=Flex_state.create_key()letcheck_timeout=function|None->false|Sometimeout->Util.total_time_s()>timeoutlete_path=ref(None:stringoption)lettried_e=reffalselete_call_point=ref0.2letshould_try_e=function|SometimeoutwhenCCOpt.is_some!e_path->letpassed=Util.total_time_s()inifnot!tried_e&&passed>!e_call_point*.timeoutthen(tried_e:=true;true)elsefalse|_->falselet_progress=reffalse(* progress bar? *)let_check_types=reffalse(* print progress (i out of steps) *)letprint_progressi~steps=letprefix=Printf.sprintf"\r\027[K[%.2fs] "(Util.total_time_s())inmatchstepswith|Somej->letn=i*40/jinletbar=CCString.init40(funi->ifi<=nthen'#'else' ')inPrintf.printf"%s [%s] %d/%d%!"prefixbarij;|None->Printf.printf"%s %d steps%!"prefixi;(** The SZS status of a state *)typeszs_status=|UnsatofProof.S.t|Sat|Unknown|Errorofstring|TimeoutmoduletypeS=sigmoduleEnv:Env.Svalgiven_clause_step:?generating:bool->int->szs_status(** Perform one step of the given clause algorithm.
It performs generating inferences only if [generating] is true (default);
other parameters are the iteration number and the environment *)valgiven_clause:?generating:bool->?steps:int->?timeout:float->unit->szs_status*int(** run the given clause until a timeout occurs or a result
is found. It returns a tuple (new state, result, number of steps done).
It performs generating inferences only if [generating] is true (default) *)valpresaturate:unit->szs_status*int(** Interreduction of the given state, without generating inferences. Returns
the number of steps done for presaturation, with status of the set. *)endmoduleMake(E:Env.S)=structmoduleEnv=EmoduleEInterface=EIntf.Make(E)let[@inline]check_clause_c=if!_check_typesthenEnv.C.check_typesc;assert(Env.C.Seq.termsc|>Iter.for_allTerm.DB.is_closed);ifnot(Env.C.litsc|>Literals.vars_distinct)then(CCFormat.printf"Vars not distinct: @[%a@].@."Env.C.pp_tstpc;CCFormat.printf"proof:@[%a@].@."Proof.S.pp_normal(Env.C.proofc);assertfalse;);ifEnv.flex_getCombinators.k_enable_combinators&¬(Env.C.Seq.termsc|>Iter.flat_map(funt->Term.Seq.subterms~include_builtin:true~ignore_head:falset)|>Iter.for_all(funt->not@@Term.is_funt))then(CCFormat.printf"ENCODED WRONGLY: %a:%d.\n"Env.C.pp_tstpc(Env.C.proof_depthc);CCFormat.printf"proof : %a.\n"Proof.S.pp_normal(Env.C.proofc);assert(false));CCArray.iter(funt->assert(Literal.no_prop_invariantt))(Env.C.litsc)let[@inline]check_clauses_seq=Iter.itercheck_clause_seq(** One iteration of the main loop ("given clause loop") *)letgiven_clause_step?(generating=true)num=E.step_init();(* select next given clause *)matchEnv.next_passive()with|None->(* final check: might generate other clauses *)letclauses=Env.do_generate~full:true()inifIter.is_emptyclausesthen(Util.debugf~section1"final clauses: @[%a@]"(funk->k(Iter.pp_seqEnv.C.pp)(Env.get_active()));Sat)else(letclauses=clauses|>Iter.filter_map(func->check_clause_c;letc,_=Env.unary_simplifycinifEnv.is_trivialc||Env.is_activec||Env.is_passivecthenNoneelseSomec)|>Iter.to_listinUtil.debugf3~section"@[<2>inferred @{<green>new clauses@}@ @[<v>%a@]@]"(funk->k(CCFormat.listEnv.C.pp)clauses);Env.add_passive(Iter.of_listclauses);Unknown)|Somec->letpicked_clause=cinUtil.debugf~section2"@[<2>@{<green>given@} (before simplification):@ `@[%a@]`@]"(funk->kEnv.C.ppc);Util.debugf~section10"@[proof:@[%a@]@]"(funk->kProof.S.pp_tstp(Env.C.proofc));check_clause_c;Util.incr_statstat_steps;beginmatchEnv.all_simplifycwith|[],_->Util.incr_statstat_redundant_given;Util.debugf~section1"@[@{<Yellow>### step %5d ###@}@]"(funk->knum);Util.debugf~section1"@[<2>given clause dropped@ @[%a@]@]"(funk->kEnv.C.ppc);Util.debugf~section10"@[proof:@[%a@]@]"(funk->kProof.S.pp_zf(Env.C.proofc));Signal.sendEnv.on_forward_simplified(c,None);Unknown|l,_whenList.existsEnv.C.is_emptyl->(* empty clause found *)letproof=Env.C.proof(List.findEnv.C.is_emptyl)in(* not sending any signal, because WE HAVE WON!!! *)Unsatproof|c::l',state->(* put clauses of [l'] back in passive set *)Util.debugf~section2"@[ remaining after simplification:@.@[%a@]@. @]"(funk->k(CCList.ppEnv.C.pp)l');Env.add_passive(Iter.of_listl');Signal.sendEnv.on_forward_simplified(picked_clause,Somec);Env.do_clause_eliminate();(* assert(not (Env.C.is_redundant c)); *)(* clause might have been removed *)ifEnv.C.is_redundantcthenUnknownelse((* process the clause [c] *)letnew_clauses=CCVector.create()in(* very expensive assert *)(* assert (not (Env.is_redundant c)); *)(* process the given clause! *)Util.incr_statstat_processed_given;Util.debugf~section1"@[@{<Yellow>### step %5d ###@}@]"(funk->knum);Util.debugf~section1"@[<2>@{<green>given@} (%d steps, penalty %d):@ `@[%a@]`@]"(funk->knum(Env.C.penaltyc)Env.C.ppc);Util.debugf~section3"@[proof:@[%a@]@]"(funk->kProof.S.pp_tstp(Env.C.proofc));(* find clauses that are subsumed by given in active_set *)letsubsumed_active=Env.C.ClauseSet.to_iter(Env.subsumed_byc)inEnv.remove_activesubsumed_active;Env.remove_simplsubsumed_active;(* add given clause to simpl_set *)Env.add_simpl(Iter.singletonc);(* simplify active set using c *)letsimplified_actives,newly_simplified=Env.backward_simplifycinletsimplified_actives=Env.C.ClauseSet.to_itersimplified_activesin(* the simplified active clauses are removed from active set and
added to the set of new clauses. Their descendants are also removed
from passive set *)check_clauses_simplified_actives;check_clauses_newly_simplified;Env.remove_activesimplified_actives;Env.remove_simplsimplified_actives;CCVector.append_iternew_clausesnewly_simplified;ifnot(Iter.is_emptysimplified_actives)thenUtil.debugf~section1"simplified_actives:@ @[%a@]@."(funk->k(Iter.pp_seqEnv.C.pp)simplified_actives);Util.debugf~section5"newly_simplified:@ @[%a@]@."(funk->k(Iter.pp_seqEnv.C.pp)newly_simplified);(* add given clause to active set *)Env.add_active(Iter.singletonc);(* do inferences between c and the active set (including c),
if [generate] is set to true *)letinferred_clauses=ifgeneratingthenEnv.generatecelseIter.emptyin(* simplification of inferred clauses w.r.t active set; only the non-trivial ones
are kept (by list-simplify) *)letinferred_clauses=Iter.filter_map(func->Util.debugf~section4"inferred: `@[%a@]`"(funk->kEnv.C.ppc);letc,_=Env.forward_simplifycincheck_clause_c;(* keep clauses that are not redundant *)ifEnv.is_trivialc||Env.is_activec||Env.is_passivecthen(Util.debugf~section4"clause `@[%a@]` is trivial, dump"(funk->kEnv.C.ppc);Util.debugf~section10"@[proof:@[%a@]@]"(funk->kProof.S.pp_tstp(Env.C.proofc));None)elseSomec)inferred_clausesinletinferred_clauses=Env.immediate_simplifycinferred_clausesinletinferred_clauses=(* After forward simplification, do cheap multi simplification like AVATAR *)Iter.flat_map_l(func->CCOpt.get_or~default:[c](Env.cheap_multi_simplifyc))inferred_clausesinCCVector.append_iternew_clausesinferred_clauses;Util.debugf~section1"@[<2>inferred @{<green>new clauses@}:@ [@[<v>%a@]]@]"(funk->k(Util.pp_iterEnv.C.pp)(CCVector.to_iternew_clauses));(* add new clauses (including simplified active clauses)
to passive set and simpl_set *)Env.add_passive(CCVector.to_iternew_clauses);(* test whether the empty clause has been found *)matchEnv.get_some_empty_clause()with|None->Unknown|Somec->Unsat(Env.C.proofc))endletgiven_clause?(generating=true)?steps?timeout()=ifCCOpt.is_some!e_paththen(EInterface.set_e_bin(CCOpt.get_exn!e_path));Util.debugf~section1"init@.active:@[%a@]@.passive:@[%a@]"(funk->k(Iter.pp_seqEnv.C.pp_tstp_full)(Env.get_active())(Iter.pp_seqEnv.C.pp_tstp_full)(Env.get_passive()));(* num: number of steps done so far *)letrecdo_stepnum=ifcheck_timeouttimeoutthenTimeout,numelsematchstepswith|Someiwhennum>=i->Unknown,num|_->(* do one step *)if!_progressthenprint_progressnum~steps;ifshould_try_etimeoutthen(letres=EInterface.try_e(Env.get_active())(Env.get_passive())inmatchreswith|Somec->Env.add_passive(Iter.singletonc);|_->());letstatus=given_clause_step~generatingnuminmatchstatuswith|Sat|Unsat_|Error_->status,num(* finished *)|Timeout->assertfalse|Unknown->do_step(num+1)indo_step0letpresaturate()=given_clause?steps:None?timeout:None~generating:false()letcheck_fragment()=ifnot(Env.get_passive()|>Iter.for_allEnv.check_fragment)theninvalid_arg"Problem out of fragment"elseif(try(Env.flex_getk_abort_after_fragment_check)withNot_found->false)then(print_endline"Problem in fragment";exit0)letregister_conjectures()=Env.get_passive()|>Iter.iterEnv.ProofState.CQueue.register_conjecture_clauselet()=Signal.on_everyEnv.on_startcheck_fragment;Signal.on_everyEnv.on_startregister_conjectures;endlet()=Params.add_opts["--progress",Arg.Set_progress," progress bar";"-p",Arg.Set_progress," alias for --progress";"--check-types",Arg.Set_check_types," check types in new clauses";"--try-e",Arg.String(funpath->e_path:=Somepath)," try the given eprover binary on the problem";"--e-call-point",Arg.Float(funv->ifv>1.0||v<0.0theninvalid_arg"0 <= e-call-point <= 1.0"elsee_call_point:=v)," point in the runtime when E is called in range 0.0 to 1.0 ";]