123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599(* This file is free software, part of Zipperposition. See file "license" for more details. *)(** {1 Clauses} *)openLogtkmoduleBV=CCBVmoduleT=TermmoduleS=SubstmoduleLit=LiteralmoduleLits=LiteralsmoduleStmt=Statementletstat_clause_create=Util.mk_stat"clause.create"moduletypeS=Clause_intf.Stypeproof_step=Proof.Step.t(** Bundle of clause sets *)type'csets={c_set:'cCCVector.ro_vector;(** main set of clauses *)c_sos:'cCCVector.ro_vector;(** set of support *)}(** {2 Type def} *)moduleMake(Ctx:Ctx.S):SwithmoduleCtx=Ctx=structmoduleCtx=Ctxtypeflag=SClause.flag(* re-export type, to access fields *)typesclause=SClause.t=private{id:int;lits:Literals.t;trail:Trail.t;mutableflags:flag;}typet={sclause:sclause;mutablepenalty:int;(** heuristic penalty *)selected:BV.tLazy.t;(** bitvector for selected lits*)bool_selected:(Term.t*Position.t)listLazy.t;max_lits:intlistLazy.t;(** bitvector for maximal lits *)mutableproof:proof_step;(** Proof of the clause *)mutableeligible_res:BV.toption;(* eligible for resolution? *)mutableeligible_bool:SClause.TPSet.toption;}typeclause=t(** {2 boolean flags} *)letget_flagflagc=SClause.get_flagflagc.sclauseletset_flagflagcb=SClause.set_flagflagc.sclausebletmark_redundantc=set_flagSClause.flag_redundantctrueletis_redundantc=get_flagSClause.flag_redundantcletmark_backward_simplifiedc=set_flagSClause.flag_backward_simplifiedctrueletis_backward_simplifiedc=get_flagSClause.flag_backward_simplifiedc(** {2 Hashcons} *)letequalc1c2=SClause.equalc1.sclausec2.sclauseletcomparec1c2=SClause.comparec1.sclausec2.sclauselethashc=SClause.hashc.sclauseletidc=SClause.idc.sclauseletis_groundc=Literals.is_groundc.sclause.litsletweightc=Lits.weightc.sclause.litsletho_weightc=Lits.Seq.termsc.sclause.lits|>Iter.fold(funacct->T.ho_weightt+acc)0lettrailc=c.sclause.traillethas_trailc=not(Trail.is_emptyc.sclause.trail)lettrail_subsumesc1c2=Trail.subsumesc1.sclause.trailc2.sclause.trailletis_activec~v=Trail.is_activec.sclause.trail~vletpenaltyc=c.penaltyletinc_penaltycinc=c.penalty<-c.penalty+inclettrail_l=function|[]->Trail.empty|[c]->c.sclause.trail|[c1;c2]->Trail.mergec1.sclause.trailc2.sclause.trail|l->Trail.merge_l(List.maptraill)letlitsc=c.sclause.litsmoduleTbl=CCHashtbl.Make(structtypet=clauselethash=hashletequal=equalend)(** {2 Utils} *)letis_goalc=Proof.Step.is_goalc.proofletdistance_to_goalc=Proof.Step.distance_to_goalc.proofletcomes_from_goalc=CCOpt.is_some@@distance_to_goalc(* private function for building clauses *)letcreate_inner~penalty~selected~bool_selectedsclauseproof=(* create the structure *)letord=Ctx.ord()inletmax_lits=lazy(BV.to_list@@Lits.maxlitssclause.lits~ord)inletrecc={sclause;penalty;selected;bool_selected;proof;max_lits;eligible_res=None;eligible_bool=None;}in(* return clause *)Util.incr_statstat_clause_create;cletof_sclause?(penalty=1)cproof=letselected=lazy(Ctx.selectc.lits)inletbool_selected=lazy(Ctx.bool_selectc.lits)increate_inner~penalty~selected~bool_selectedcproofletlit_is_false_=function|Literal.False->true|_->falseletcreate_a~penalty~traillitsproof=(* remove spurious "false" literals automatically *)letlits=ifCCArray.existslit_is_false_litsthenCCArray.filter(funlit->not(lit_is_false_lit))litselselitsinletselected=lazy(Ctx.selectlits)inletbool_selected=lazy(Ctx.bool_selectlits)increate_inner~penalty~selected~bool_selected(SClause.make~traillits)proofletcreate~penalty~traillitsproof=(* let lits = List.fast_sort (fun l1 l2 -> -CCInt.compare (Lit.hash l1) (Lit.hash l2)) lits in *)create_a~penalty~trail(Array.of_listlits)proofletof_forms?(penalty=1)~trailformsproof=letlits=List.mapCtx.Lit.of_formforms|>Array.of_listincreate_a~penalty~traillitsproofletof_forms_axiom?(penalty=1)~file~nameforms=letlits=List.mapCtx.Lit.of_formformsinletproof=Proof.Step.assert'~file~name()increate~penalty~trail:Trail.emptylitsproofletof_statement?(convert_defs=false)st=letof_litslits=(* convert literals *)letlits=List.mapCtx.Lit.of_formlitsinletproof=Stmt.proof_stepstinletc=create~trail:Trail.empty~penalty:1litsproofincinmatchStmt.viewstwith|Stmt.Data_|Stmt.TyDecl_->[]|Stmt.Def_|Stmt.Rewrite_->ifnotconvert_defsthen[](*dealt with by rewriting *)(* dealt with *)elseList.mapof_lits(Stmt.get_formulas_from_defsst)|Stmt.Assertlits->[of_litslits]|Stmt.Goallits->[of_litslits]|Stmt.Lemmal|Stmt.NegatedGoal(_,l)->List.mapof_litslletupdate_trailfc=letsclause=SClause.update_trailfc.sclauseincreate_innersclausec.proof~selected:c.selected~bool_selected:c.bool_selected~penalty:c.penaltyletproof_stepc=c.proofletproofc=Proof.S.mkc.proof(SClause.mk_proof_resc.sclause)letproof_parentc=Proof.Parent.from(proofc)letproof_parent_substrenaming(c,sc)subst=Proof.Parent.from_substrenaming(proofc,sc)substletupdate_proofcf=letnew_proof=fc.proofincreate_a~trail:c.sclause.trail~penalty:c.penaltyc.sclause.litsnew_proofletis_emptyc=Lits.is_absurdc.sclause.lits&&Trail.is_emptyc.sclause.trailletlengthc=SClause.lengthc.sclauselet_apply_subst_no_simplsubst(lits,sc)=ifSubst.is_emptysubstthenlits(* id *)elseletrenaming=S.Renaming.create()inArray.map(funl->Lit.apply_subst_no_simprenamingsubst(l,sc))lits(** Bitvector that indicates which of the literals of [subst(clause)]
are maximal under [ord] *)letmaxlits(c,sc)subst=letord=Ctx.ord()inifnot@@Subst.is_emptysubstthen(letlits'=_apply_subst_no_simplsubst(litsc,sc)inLits.maxlits~ordlits')elseBV.of_list@@Lazy.forcec.max_lits(** Check whether the literal is maximal *)letis_maxlit(c,sc)subst~idx=ifnot@@Subst.is_emptysubstthen(letord=Ctx.ord()inletlits'=_apply_subst_no_simplsubst(litsc,sc)inLits.is_max~ordlits'idx)else(BV.get(BV.of_list@@Lazy.forcec.max_lits)idx)(** Bitvector that indicates which of the literals of [subst(clause)]
are eligible for resolution. *)leteligible_res(c,sc)subst=letord=Ctx.ord()inletselected=Lazy.forcec.selectedinletbool_selected=Lazy.forcec.bool_selectedinifBV.is_emptyselected&&CCList.is_emptybool_selectedthen((* maximal literals *)ifnot@@Subst.is_emptysubstthen(letlits'=_apply_subst_no_simplsubst(litsc,sc)inLits.maxlits~ordlits')else(BV.of_list@@Lazy.forcec.max_lits))else(letlits'=_apply_subst_no_simplsubst(litsc,sc)inletbv=BV.copyselectedinletn=Array.lengthlits'in(* Only keep literals that are maximal among selected literals of the
same sign. *)fori=0ton-1do(* i-th lit is already known not to be max? *)ifnot(BV.getbvi)then()elseletlit=lits'.(i)inforj=i+1ton-1doletlit'=lits'.(j)in(* check if both lits are still potentially eligible, and have the same
sign if [check_sign] is true. *)ifLit.is_positivoidlit=Lit.is_positivoidlit'&&BV.getbvjthenmatchLit.Comp.compare~ordlitlit'with|Comparison.Incomparable|Comparison.Eq->()(* no further information about i-th and j-th *)|Comparison.Gt->BV.resetbvj(* j-th cannot be max *)|Comparison.Lt->BV.resetbvi(* i-th cannot be max *)done;done;bv)leteligible_res_no_substc=beginmatchc.eligible_reswith|Somer->r|None->letbv=eligible_res(c,0)Subst.emptyinc.eligible_res<-Somebv;bvendleteligible_subterms_of_bool_c=letmodulePB=Position.Buildinletstarting_positions=Lazy.forcec.bool_selected|>List.map(fun(_,pos)->Position.Build.of_pospos)inletres=(* directly at position of selected booleans *)Lazy.forcec.bool_selected@(* below selected selected booleans *)CCList.flat_map(funpb->letpos=Position.Build.to_pospbinlett=Literals.Pos.at(litsc)posin(* selects --subterms-- of given t that are eligible *)Iter.to_list(Bool_selection.all_eligible_subterms~ord:(Ctx.ord())~pos_builder:pbt))(starting_positions)inletres=List.filter(fun(_,p)->letmoduleP=Positioninmatchpwith|P.Arg(idx,P.LeftP.Stop)|P.Arg(idx,P.RightP.Stop)->(match(litsc).(idx)with|Lit.Equation(_,_,false)->true|_->false)|_->true)resinifCCList.is_emptyresthen(Util.debugf1"nothing selected for @[%a@]@."(funk->kLits.pp(litsc));)else(Util.debugf1"For @[%a@]@."(funk->kLits.pp(litsc));CCList.iter(fun(t,p)->Util.debugf1" |@[%a@] -> @[%a@]@."(funk->kPosition.pppT.ppt);)res;);resleteligible_subterms_of_boolc=matchc.eligible_boolwith|None->letres=SClause.TPSet.of_list(eligible_subterms_of_bool_c)inc.eligible_bool<-Someres;res|Somecache->cacheleteta_reducec=letlit_arr=litscinletchanged=reffalseinletnew_lits=Literals.map(funt->letreduced=Lambda.eta_reduce(Lambda.snft)inifnot(Term.equaltreduced)thenchanged:=true;reduced)lit_arrinif!changedthen(letpenalty=penaltycandtrail=trailcandproof=proof_stepcinSome(create~penalty~trail(CCArray.to_listnew_lits)proof))elseNone(** Bitvector that indicates which of the literals of [subst(clause)]
are eligible for paramodulation. *)leteligible_param(c,sc)subst=letord=Ctx.ord()inifBV.is_empty(Lazy.forcec.selected)&&CCList.is_empty(Lazy.forcec.bool_selected)then(letbv,lits'=ifnot@@Subst.is_emptysubstthen(letlits'=_apply_subst_no_simplsubst(litsc,sc)in(* maximal ones *)Lits.maxlits~ordlits',lits')else(BV.of_list@@Lazy.forcec.max_lits,litsc)in(* only keep literals that are positive equations *)BV.filterbv(funi->Lit.eqn_signlits'.(i)(* == true*));bv)elseBV.empty()(* no eligible literal when some are selected *)letis_eligible_param(c,sc)subst~idx=Lit.eqn_signc.sclause.lits.(idx)&&BV.is_empty(Lazy.forcec.selected)&&CCList.is_empty(Lazy.forcec.bool_selected)&&is_maxlit(c,sc)subst~idx(** are there selected literals in the clause? *)lethas_selected_litsc=not(BV.is_empty(Lazy.forcec.selected))(** Check whether the literal is selected *)letis_selectedci=BV.get(Lazy.forcec.selected)i(** Indexed list of selected literals *)letselected_litsc=BV.selecti(Lazy.forcec.selected)c.sclause.litsletselected_lits_bvc=Lazy.forcec.selectedletbool_selectedc=Lazy.forcec.bool_selected(** is the clause a unit clause? *)letis_unit_clausec=matchc.sclause.litswith|[|_|]->true|_->falseletis_oriented_rulec=letord=Ctx.ord()inmatchc.sclause.litswith|[|Lit.Equation(l,r,true)|]->(* counting predicate literals of the form p = FALSE as rewrite rules *)beginmatchOrdering.compareordlrwith|Comparison.Gt|Comparison.Lt->true|Comparison.Eq|Comparison.Incomparable->falseend|_->falseletsymbols?(init=ID.Set.empty)?(include_types=false)seq=Iter.fold(funsetc->Lits.symbols~include_types~init:setc.sclause.lits)initseqletto_formsc=Lits.Conv.to_formsc.sclause.litsletto_sclausec=c.sclauseletto_s_formc=SClause.to_s_formc.sclauseletis_inj_axiomc=ifCCArray.length(litsc)=2then(letinj_defs=CCArray.filter_mapLit.as_inj_def(litsc)inif(CCArray.lengthinj_defs)!=1thenNoneelse(letsym,var_pairs=CCArray.getinj_defs0inletl=CCArray.filter_mapLit.as_pos_pure_var(litsc)|>CCArray.to_listinifList.lengthl!=1thenNoneelse(let(x,y)=List.hdlinletv_eq=HVar.equalType.equalinletrecargs_samen=function|[]->None|(x',y')::xs->if(v_eqxx'&&v_eqyy')||(v_eqxy'&&v_eqyx')thenSome(sym,n)elseargs_same(n+1)xsinargs_same0var_pairs)))elseNoneletproof_depthc=Proof.Step.inferences_performed(proof_stepc)moduleSeq=structletlitsc=Iter.of_arrayc.sclause.litslettermsc=litsc|>Iter.flat_mapLit.Seq.termsletvarsc=termsc|>Iter.flat_mapT.Seq.varsendletapply_subst?(renaming)?(proof=None)?(penalty_inc=None)(c,sc)subst=letlits=litscinletrenaming=CCOpt.get_or~default:(S.Renaming.create())renaminginletnew_lits=Literals.apply_substrenamingsubst(lits,sc)inletproof_step=CCOpt.get_or~default:(proof_stepc)proofin(* increase can be negative if we perform a simplification *)letpenalty=max((CCOpt.get_or~default:0penalty_inc)+(penaltyc))1increate~trail:(trailc)~penalty(CCArray.to_listnew_lits)proof_stepletground_clausec=letnew_lits=CCArray.to_list@@Lits.ground_lits(litsc)inletproof_step=proof_stepcincreate~trail:(trailc)~penalty:(penaltyc)new_litsproof_stepletis_orphanedc=letauxproof=letp_res,step=Proof.S.resultproof,Proof.S.stepproofin(* we reached the root *)ifProof.Result.is_stmtp_resthenfalseelse(Proof.Step.is_inferencestep&¬(List.memProof.Tag.T_cannot_orphan(Proof.Step.tagsstep))&&List.exists(funpr->Proof.Result.is_dead_cl(Proof.S.resultpr)())(List.mapProof.Parent.proof(Proof.Step.parentsstep)))innot(is_emptyc)&&aux(proofc)(** {2 Filter literals} *)moduleEligible=structtypet=int->Lit.t->boolletresc=letbv=eligible_res(Scoped.makec0)S.emptyinfuni_lit->BV.getbviletparamc=letbv=eligible_param(Scoped.makec0)S.emptyinfuni_lit->BV.getbvileteq_lit=matchlitwith|Lit.Equation(_,_,true)->true|_->falseletfilterf_lit=flitletmaxc=funi_->BV.get(BV.of_list@@Lazy.forcec.max_lits)iletpos_lit=Lit.is_positivoidlitletpos_eq_lit=matchlitwith|Lit.Equation(l,r,s)->s|_->falseletneg_lit=Lit.is_negativoidlitletalways__=trueletcombinel=matchlwith|[]->(fun__->true)|[x]->x|[x;y]->(funilit->xilit&&yilit)|[x;y;z]->(funilit->xilit&&yilit&&zilit)|_->(funilit->List.for_all(funeligible->eligibleilit)l)let(**)f1f2ilit=f1ilit&&f2ilitlet(++)f1f2ilit=f1ilit||f2ilitlet(~~)filit=not(filit)end(** {2 Set of clauses} *)(** Simple set *)moduleClauseSet=CCSet.Make(structtypet=clauseletcomparec1c2=SClause.comparec1.sclausec2.sclauseend)(** {2 Positions in clauses} *)modulePos=structletatcpos=Lits.Pos.atc.sclause.litsposendmoduleWithPos=structtypet={clause:clause;pos:Position.t;term:T.t;}letcomparet1t2=letc=SClause.comparet1.clause.sclauset2.clause.sclauseinifc<>0thencelseletc=T.comparet1.termt2.terminifc<>0thencelsePosition.comparet1.post2.posletppoutt=Format.fprintfout"@[clause @[%a@]@ at pos @[%a@]@]"Lits.ppt.clause.sclause.litsPosition.ppt.posend(** {2 IO} *)letpp_trail=SClause.pp_trailletppoutc=letpp_selectedselectedouti=ifBV.getselectedithenFormat.fprintfout"+"andpp_maxlitmaxlitsouti=ifBV.getmaxlitsithenFormat.fprintfout"*"in(* print literals with a '*' for maximal, and '+' for selected *)letselected=Lazy.forcec.selectedinletmax=maxlits(Scoped.makec0)S.emptyinletpp_litsoutlits=ifArray.lengthlits=0thenCCFormat.stringout"⊥"else(letpp_litout(i,lit)=Format.fprintfout"@[%a%a%a@]"Lit.pplit(pp_selectedselected)i(pp_maxlitmax)iinFormat.fprintfout"[@[%a@]]"(Util.pp_iter~sep:" ∨ "pp_lit)(Iter.of_array_ilits))inFormat.fprintfout"@[%a@[<2>%a%a@]@]/id:%d/depth:%d/penalty:%d/red:%b"SClause.pp_varsc.sclausepp_litsc.sclause.litsSClause.pp_trailc.sclause.trailc.sclause.id(proof_depthc)(penaltyc)(is_redundantc);()letpp_tstpoutc=SClause.pp_tstpoutc.sclauseletpp_tstp_fulloutc=SClause.pp_tstp_fulloutc.sclauseletto_string=CCFormat.to_stringppletto_string_tstp=CCFormat.to_stringpp_tstpletpp_setoutset=Format.fprintfout"{@[<hv>%a@]}"(Util.pp_iter~sep:","pp)(ClauseSet.to_iterset)letpp_set_tstpoutset=Format.fprintfout"@[<v>%a@]"(Util.pp_iter~sep:","pp_tstp)(ClauseSet.to_iterset)letcheck_typesc=Util.debugf5"(@[check_types@ %a@])"(funk->kppc);litsc|>Literals.Seq.terms|>Iter.iter(funt->ignore(Term.rebuild_rect))end