123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812openLogtkopenLibzipperpositionmoduleT=TermmoduleTy=TypemoduleLits=LiteralsmoduleLit=LiteralmoduleA=Libzipperposition_avatarletsection=Util.Section.make~parent:Const.section"hlt-elim"letk_enabled=Flex_state.create_key()letk_max_depth=Flex_state.create_key()letk_simpl_new=Flex_state.create_key()letk_clauses_to_track=Flex_state.create_key()letk_max_self_impls=Flex_state.create_key()letk_unit_propagated_hle=Flex_state.create_key()letk_unit_htr=Flex_state.create_key()letk_hte=Flex_state.create_key()letk_hle=Flex_state.create_key()letk_max_tracked_clauses=Flex_state.create_key()letk_track_eq=Flex_state.create_key()letk_insert_only_ordered=Flex_state.create_key()moduletypeS=sigmoduleEnv:Env.SmoduleC:moduletypeofEnv.C(** {5 Registration} *)valsetup:unit->unitendmoduleMake(E:Env.S):SwithmoduleEnv=E=structmoduleEnv=EmoduleC=Env.CmoduleCS=C.ClauseSetmoduleL=Literal(* index from literals to the map implied literal
-> clauses necessary for the proof
with an additional field storing whether there are literals
l, \neg l in the set of implied literals*)modulePremiseIdx=NPDtree.MakeTerm(structtypet=(CS.tT.Tbl.t)*(CS.toption)(* as we will maintain the invariant that each term is mapped to a single
table, comparing the lengths suffices *)letcompare(a1,_)(a2,_)=compare(T.Tbl.lengtha1)(T.Tbl.lengtha2)end)(* index from literals that appear as conclusions to all the premises
in which they appear *)moduleConclusionIdx=NPDtree.MakeTerm(structtypet=T.tletcompare=Term.compareend)moduleUnitIdx=NPDtree.MakeTerm(structtypet=C.tletcompare=C.compareend)letprems_=ref(PremiseIdx.empty())letconcls_=ref(ConclusionIdx.empty())letunits_=ref(UnitIdx.empty())(* occurrences of the clause in the premise_idx *)letcl_occs=refUtil.Int_map.empty(* clauses tracked so far *)lettracked_cls=ref0let[@inline]tracking_eq()=Env.flex_getk_track_eq(* constants denoting the scope of index and the query, respectively *)letidx_sc,q_sc=0,1letretrieve_idx~getter(premise,q_sc)=matchT.viewpremisewith|T.AppBuiltin(Builtin.Eq,([_;a;b]|[a;b]))whentracking_eq()->Iter.append(getter(premise,q_sc))(getter((T.Form.eqba),q_sc))|T.AppBuiltin(Builtin.Neq,([_;a;b]|[a;b]))whentracking_eq()->Iter.append(getter(premise,q_sc))(getter((T.Form.neqba),q_sc))|_->getter(premise,q_sc)letretrieve_gen_prem_idx()=retrieve_idx~getter:(PremiseIdx.retrieve_generalizations(!prems_,idx_sc))letretrieve_spec_prem_idx()=retrieve_idx~getter:(PremiseIdx.retrieve_specializations(!prems_,idx_sc))letretrieve_gen_concl_idx()=retrieve_idx~getter:(ConclusionIdx.retrieve_generalizations(!concls_,idx_sc))letretrieve_spec_concl_idx()=retrieve_idx~getter:(ConclusionIdx.retrieve_specializations(!concls_,idx_sc))letretrieve_gen_unit_idxunit_sc=retrieve_idx~getter:(UnitIdx.retrieve_generalizations(!units_,unit_sc))let[@inline]get_predicatelit=matchlitwith|L.Equation(lhs,_,_)whenL.is_predicate_litlit->Some(lhs,Lit.is_poslit)|L.Equation(lhs,rhs,sign)whentracking_eq()->Some(T.Form.eqlhsrhs,sign)|_->Nonelet[@inline]matching_eq~subst~pattern(t,sc)=tryUnif.FO.matching~subst~pattern(t,sc)withUnif.Fail->matchT.viewtwith|T.AppBuiltin(Builtin.Eq,([_;a;b]|[a;b]))whentracking_eq()->Unif.FO.matching~subst~pattern(T.Form.eqba,sc)|T.AppBuiltin(Builtin.Neq,([_;a;b]|[a;b]))whentracking_eq()->Unif.FO.matching~subst~pattern(T.Form.neqba,sc)|_->raiseUnif.Faillet[@inline]flip_eqt=matchT.viewtwith|T.AppBuiltin(Builtin.Eq,([a;b]|[_;a;b]))whentracking_eq()->T.Form.eqba|T.AppBuiltin(Builtin.Neq,([a;b]|[_;a;b]))whentracking_eq()->T.Form.neqba|_->tlet[@inline]cl_is_ht_trackablecl=Trail.is_empty(C.trailcl)&&(matchC.litsclwith|[|l1;l2|]->CCOpt.is_some(get_predicatel1)&&CCOpt.is_some(get_predicatel2)|_->false)let[@inline]recnormalize_negationslhs=matchT.viewlhswith|T.AppBuiltin(Builtin.Not,[t])->(matchT.viewtwith|T.AppBuiltin(Builtin.Not,[s])->normalize_negationss|T.AppBuiltin(Builtin.Eq,([_;a;b]|[a;b]))->T.Form.neqab|T.AppBuiltin(Builtin.Neq,([_;a;b]|[a;b]))->T.Form.eqab|_->lhs)|_->lhslet[@inline]lit_to_term?(negate=false)a_lhssign=letsign=ifnegatethennotsignelsesigninnormalize_negations(ifsignthena_lhselseT.Form.not_a_lhs)letregister_cl_termclpremise=letpremise_set=Term.Set.addpremise(Util.Int_map.get_or~default:Term.Set.empty(C.idcl)!cl_occs)incl_occs:=Util.Int_map.add(C.idcl)premise_set!cl_occsletgeneralization_presentpremiseconcl=retrieve_gen_prem_idx()(premise,q_sc)|>Iter.exists(fun(_,(tbl,_),subst)->T.Tbl.keystbl|>Iter.exists(funt->tryignore(matching_eq~subst~pattern:(t,idx_sc)(concl,q_sc));truewithUnif.Fail->false))letremove_instancespremiseconcl=retrieve_spec_prem_idx()(premise,q_sc)|>(funi->Iter.fold(funtasks(t,(tbl,_),subst)->letsets_to_remove=Iter.fold(funacc(s,cls)->tryletsubst=matching_eq~subst~pattern:(concl,q_sc)(s,idx_sc)inifSubst.is_renamingsubstthenaccelsecls::accwithUnif.Fail->acc)[](T.Tbl.to_itertbl)in(t,sets_to_remove)::tasks)[]i)|>CCList.iter(fun(t,sets)->prems_:=PremiseIdx.update_leaf!prems_t(fun(tbl,_)->T.Tbl.filter_map_inplace(funconclproofset->concls_:=ConclusionIdx.remove!concls_conclt;ifList.exists(funset->CS.subsetsetproofset)setsthenNoneelseSomeproofset)tbl;T.Tbl.lengthtbl==0);)letcompute_is_unittblconclcl=ifEnv.flex_getk_unit_htrthen(letneg_concl=normalize_negations(T.Form.not_concl)inletneg_concl_flip=normalize_negations(T.Form.not_(flip_eqconcl))inT.Tbl.find_opttblneg_concl|>CCOpt.(<+>)(T.Tbl.find_opttblneg_concl_flip)|>CCOpt.(<$>)(CS.addcl))elseNoneletadd_transitive_conclusionspremiseconclcl=Util.debugf~section3"transitive conclusion: @[%a@] --> @[%a@]"(funk->kT.pppremiseT.ppconcl);retrieve_spec_concl_idx()(premise,q_sc)|>Iter.iter(fun(concl',premise',subst)->(* add implication premise' -> subst (concl) *)Util.debugf~section3"found: @[%a@] --> @[%a@]"(funk->kT.pppremise'T.ppconcl');letbecame_unit=refNoneinprems_:=PremiseIdx.update_leaf!prems_premise'(fun(tbl,is_unit)->(matchT.Tbl.gettblconcl'with|Someold_proofset->ifCS.cardinalold_proofset<Env.flex_getk_max_depththen(letproofset=CS.addclold_proofsetinregister_cl_termclpremise';letconcl=(Subst.FO.applySubst.Renaming.nonesubst(concl,q_sc))inconcls_:=ConclusionIdx.add!concls_conclpremise';(* ConclusionIdx.pp_keys !concls_; *)T.Tbl.addtblconclproofset;ifCCOpt.is_noneis_unitthen(matchcompute_is_unittblconclclwith|Someproofset->became_unit:=Some(proofset,tbl)|None->()))|None->assertfalse;);(* if by adding concl something became unit we remove
the leaf as the new one with updated unit status will be added *)CCOpt.is_none!became_unit);(match!became_unitwith|Some(ps,tbl)->ignore(PremiseIdx.update_leaf!prems_premise'(fun(tbl,is_unit)->assertfalse));prems_:=PremiseIdx.add!prems_premise'(tbl,Someps)|_->());)lettriggered_conclusionstblpremise'conclcl=letauxconcl=T.Tbl.addtblconcl(CS.singletoncl);concls_:=ConclusionIdx.add!concls_conclpremise';register_cl_termclpremise';letmax_proof_size=Env.flex_getk_max_depthinretrieve_gen_prem_idx()(concl,q_sc)|>Iter.iter(fun(_,(tbl',_),subst)->T.Tbl.to_itertbl'|>Iter.iter(fun(t,proof_set)->ifC.ClauseSet.cardinalproof_set<max_proof_sizethen(letnew_cls=CS.addclproof_setinCS.iter(funcl->register_cl_termclpremise')new_cls;letconcl=(Subst.FO.applySubst.Renaming.nonesubst(t,idx_sc))inconcls_:=ConclusionIdx.add!concls_conclpremise';(* ConclusionIdx.pp_keys !concls_; *)T.Tbl.addtblconcl(new_cls))))intryletsubst=Unif.FO.matching~pattern:(premise',0)(concl,1)inleti=ref0inletconcl'=Subst.FO.applySubst.Renaming.nonesubst(concl,0)in(* if the terms are the same -- variable does not get bound to a term containing
that variable we cannot pump the term -- give up *)ifT.equalconclconcl'thenraiseUnif.Fail;letconcl=refconclinwhile!i<=Env.flex_getk_max_self_implsdoaux!concl;(* PUTTING concl IN THE SCOPE OF premise' -- intentional!!! *)concl:=Subst.FO.applySubst.Renaming.nonesubst(!concl,0);ifT.depth!concl>3then((* breaking out of the loop for the very deep terms *)i:=Env.flex_getk_max_self_impls+1);i:=!i+1;done;withUnif.Fail->auxconclletget_unit_predicatecl=ifTrail.is_empty(C.trailcl)then(matchC.litsclwith|[|(L.Equation(lhs,_,_)asl)|]whenL.is_predicate_litl->Some(lit_to_termlhs(L.is_posl))|[|L.Equation(lhs,rhs,sign)|]whentracking_eq()->Some(lit_to_term(T.Form.eqlhsrhs)(sign))|_->None)elseNoneletadd_new_premisepremiseconclcl=letalpha_renaming=retrieve_spec_prem_idx()(premise,q_sc)|>Iter.find(fun(premise',tbl,subst)->ifSubst.is_renamingsubstthenSome(premise',subst)elseNone)inmatchalpha_renamingwith|Some(premise',subst)->letconcl=Subst.FO.applySubst.Renaming.nonesubst(concl,q_sc)inlettbl_=ref(T.Tbl.create0)inletbecame_unit=refNoneinprems_:=PremiseIdx.update_leaf!prems_premise'(fun(tbl,is_unit)->ifnot(T.Tbl.memtblconcl)&¬(T.Tbl.memtbl(flip_eqconcl))then(triggered_conclusionstblpremise'conclcl;ifCCOpt.is_noneis_unitthen((matchcompute_is_unit!tbl_conclclwith|Someps->became_unit:=Some(ps,tbl)|None->());));(* if by adding concl something became unit we remove
the leaf as the new one with updated unit status will be added *)CCOpt.is_none!became_unit);(match!became_unitwith|Some(ps,tbl)->ignore(PremiseIdx.update_leaf!prems_premise'(fun(tbl,is_unit)->assertfalse));prems_:=PremiseIdx.add!prems_premise(tbl,Someps)|None->())|_->lettbl=T.Tbl.create64intriggered_conclusionstblpremiseconclcl;prems_:=PremiseIdx.add!prems_premise(tbl,compute_is_unittblconclcl)letinsert_implicationpremiseconclcl=ifnot(generalization_presentpremiseconcl)&¬(T.equalpremiseconcl)&¬(T.equalpremise(flip_eqconcl))then(remove_instancespremiseconcl;add_transitive_conclusionspremiseconclcl;add_new_premisepremiseconclcl;)letinsert_into_indicescl=matchCCArray.mapget_predicate(C.litscl)with|[|Some(a_lhs,a_sign);Some(b_lhs,b_sign)|]->letelig=ifEnv.flex_getk_insert_only_orderedthenC.eligible_param(cl,0)Subst.emptyelseCCBV.create~size:2trueinif(CCBV.getelig0)then(insert_implication(lit_to_term~negate:truea_lhsa_sign)(lit_to_termb_lhsb_sign)cl);if(CCBV.getelig1)then(insert_implication(lit_to_term~negate:trueb_lhsb_sign)(lit_to_terma_lhsa_sign)cl)|_->()letlimit_not_reached()=lettracked=!tracked_clsinlettracked_max=Env.flex_getk_max_tracked_clausesintracked_max==-1||tracked<=tracked_maxlettrack_clausecl=ifcl_is_ht_trackablecl&&limit_not_reached()then(Util.debugf~section3"tracking @[%a@]"(funk->kC.ppcl);insert_into_indicescl;incrtracked_cls;Util.debugf~section2"idx_size: @[%d@]"(funk->k(PremiseIdx.size!prems_));Util.debugf~section3"premises:"CCFun.id;PremiseIdx.iter!prems_(funt(tbl,_)->Util.debugf~section3"@[%a@] --> @[%a@]"(funk->kT.ppt(Iter.pp_seqT.pp)(T.Tbl.keystbl)));)elseifEnv.flex_getk_unit_propagated_hlethen(matchget_unit_predicateclwith|Someunit->units_:=UnitIdx.add!units_unitcl|None->())letfind_implicationclpremiseconcl=retrieve_gen_prem_idx()(premise,q_sc)|>Iter.find(fun(premise',(tbl,_),subst)->T.Tbl.to_itertbl|>Iter.find(fun(concl',proofset)->tryifCS.memclproofsetthenNoneelse((* TODO: fix *)letsubst=matching_eq~subst~pattern:(concl',idx_sc)(concl,q_sc)inSome(premise',concl',proofset,subst))withUnif.Fail->None))letdo_propagated_simplcl=letbv=CCBV.create~size:(C.lengthcl)trueinletproofset=ref(CS.empty)inletexceptionPropagatedHTEofT.t*CS.tinletis_unit=C.lengthcl==1intryCCArray.iteri(funilit->matchget_predicatelitwith|Some(lhs,sign)->letlhs_neg=lit_to_term~negate:truelhssigninletlhs=lit_to_termlhssigninletunit_sc=(maxidx_scq_sc)+1inlet(<+>)=CCOpt.(<+>)in(* checking if we can replace the clause with the literal i *)ifis_unitthen()else(CCOpt.get_or~default:()((* for the literal l we are looking for implications p -> c such that
c\sigma = l. Then we see if there is an unit clause p' such that
p\sigma = p'\rho *)retrieve_gen_concl_idx()(lhs,q_sc)|>Iter.find_map(fun(concl,premise,subst)->letorig_premise=premiseinletpremise=Subst.FO.applySubst.Renaming.nonesubst(premise,idx_sc)inretrieve_gen_unit_idxunit_sc(premise,idx_sc)|>Iter.head|>CCOpt.map(fun(_,unit_cl,_)->prems_:=PremiseIdx.update_leaf!prems_orig_premise(fun(tbl,_)->letproofset'=CS.addunit_cl(T.Tbl.findtblconcl)inifnot(CS.memclproofset')then(raise(PropagatedHTE(lhs,proofset')););true);))<+>((* for the literal l we are looking for implications p -> c such that
p\sigma = ~l. Then we see if there is an unit clause p' such that
~c\sigma = p'\rho *)retrieve_gen_prem_idx()(lhs_neg,q_sc)|>Iter.find_map(fun(premise,(tbl,_),subst)->T.Tbl.to_itertbl|>Iter.find_map(fun(concl,ps)->letconcl=Subst.FO.applySubst.Renaming.nonesubst(concl,idx_sc)inletneg_concl=normalize_negations(T.Form.not_concl)inletunit_sc=(maxidx_scq_sc)+1inretrieve_gen_unit_idxunit_sc(neg_concl,idx_sc)|>Iter.head|>CCOpt.map(fun(_,unit_cl,_)->letproofset'=CS.addunit_clpsinifnot(CS.memclproofset')then(raise(PropagatedHTE(lhs,proofset'));)))))));(* checking if we can kill the literal i *)CCOpt.get_or~default:()((* for the literal l we are looking for implications p -> c such that
c\sigma = ~l. Then we see if there is an unit clause p' such that
p\sigma = p'\rho *)retrieve_gen_concl_idx()(lhs_neg,q_sc)|>Iter.find_map(fun(concl,premise,subst)->letorig_premise=premiseinletpremise=Subst.FO.applySubst.Renaming.nonesubst(premise,idx_sc)inretrieve_gen_unit_idxunit_sc(premise,idx_sc)|>Iter.head|>CCOpt.map(fun(_,unit_cl,_)->prems_:=PremiseIdx.update_leaf!prems_orig_premise(fun(tbl,_)->letproofset'=T.Tbl.findtblconclinifnot(CS.memclproofset')then(proofset:=CS.union(CS.addunit_cl(proofset'))!proofset;CCBV.resetbvi);true);))<+>((* for the literal l we are looking for implications p -> c such that
p\sigma = l. Then we see if there is an unit clause p' such that
~c\sigma = p'\rho *)retrieve_gen_prem_idx()(lhs,q_sc)|>Iter.find_map(fun(_,(tbl,_),subst)->T.Tbl.to_itertbl|>Iter.find_map(fun(concl,ps)->letconcl=Subst.FO.applySubst.Renaming.nonesubst(concl,idx_sc)inletneg_concl=normalize_negations(T.Form.not_concl)inletunit_sc=(maxidx_scq_sc)+1inretrieve_gen_unit_idxunit_sc(neg_concl,idx_sc)|>Iter.head|>CCOpt.map(fun(_,unit_cl,_)->letproofset'=CS.addunit_clpsinifnot(CS.memclproofset')then(proofset:=CS.unionproofset'!proofset;CCBV.resetbvi))))))|None->())(C.litscl);ifCCBV.is_empty(CCBV.negatebv)thenNoneelse(letlit_l=List.rev(CCBV.selectbv(C.litscl))inletproof=Proof.Step.simp~rule:(Proof.Rule.mk"propagated_hle")(List.mapC.proof_parent(cl::CS.to_list!proofset))inSome(C.create~penalty:(C.penaltycl)~trail:(C.trailcl)lit_lproof))withPropagatedHTE(lit_t,proofset)->letlit_l=[L.mk_proplit_ttrue]inletproof=Proof.Step.simp~rule:(Proof.Rule.mk"propagated_htr")(List.mapC.proof_parent(cl::CS.to_listproofset))inletrepl=C.create~penalty:(C.penaltycl)~trail:(C.trailcl)lit_lproofinlettauto=C.create~penalty:(C.penaltycl)~trail:(C.trailcl)[L.mk_tauto]proofinUtil.debugf~section1"simplified[unit_htr(%a)]: @[@[%a@] --> @[%a@]@]@. using @[%a@]"(funk->kT.pplit_tC.ppclC.pprepl(CS.ppC.pp)proofset);E.add_passive(Iter.singletonrepl);Some(tauto)letunit_simplifycl=letexceptionUnitHTRofT.t*CS.tinletn=C.lengthclinletbv=CCBV.create~size:ntrueinletproofset=refCS.emptyintryCCArray.iteri(funii_lit->matchget_predicatei_litwith|Some(i_lhs,i_sign)->leti_t=lit_to_term(i_lhs)(i_sign)inleti_neg_t=lit_to_term~negate:true(i_lhs)(i_sign)inletunit_htr()=retrieve_gen_prem_idx()(i_neg_t,q_sc)|>Iter.find_map(fun(_,(_,is_unit),subst)->ifSubst.is_renamingsubstthenNoneelseis_unit)inletunit_hle()=retrieve_gen_prem_idx()(i_t,q_sc)|>Iter.find_map(fun(_,(_,is_unit),_)->is_unit)in(matchunit_htr()with|Somecs->raise(UnitHTR(i_t,cs))|None->(matchunit_hle()with|Somecs->CCBV.resetbvi;proofset:=CS.unioncs!proofset|None->()))|None->())(C.litscl);ifCCBV.is_empty(CCBV.negatebv)thenNoneelse(letlit_l=List.rev@@CCBV.selectbv(C.litscl)inletproof=Proof.Step.simp~rule:(Proof.Rule.mk"unit_hle")(List.mapC.proof_parent(cl::CS.to_list!proofset))inletres=C.create~penalty:(C.penaltycl)~trail:(C.trailcl)lit_lproofinUtil.debugf~section1"simplified[hle]: @[%a@] --> @[%a@]"(funk->kC.ppclC.ppres);Util.debugf~section1"used: @[%a@]"(funk->k(CS.ppC.pp)!proofset);Some(res))withUnitHTR(lit_t,proofset)->letlit_l=[L.mk_proplit_ttrue]inletproof=Proof.Step.simp~rule:(Proof.Rule.mk"unit_htr")(List.mapC.proof_parent(cl::CS.to_listproofset))inletrepl=C.create~penalty:(C.penaltycl)~trail:(C.trailcl)lit_lproofinlettauto=C.create~penalty:(C.penaltycl)~trail:(C.trailcl)[L.mk_tauto]proofinUtil.debugf~section1"simplified[unit_htr(%a)]: @[@[%a@] --> @[%a@]@]"(funk->kT.pplit_tC.ppclC.pprepl);E.add_passive(Iter.singletonrepl);Some(tauto)letdo_hte_hlecl=letexceptionHiddenTautoofT.t*T.t*CS.tinletn=C.lengthclinifn>=2then(tryletbv=CCBV.create~size:ntrueinletproofset=refCS.emptyinCCArray.iteri(funii_lit->matchget_predicatei_litwith|Some(i_lhs,i_sign)whenCCBV.getbvi->leti_t=lit_to_term(i_lhs)(i_sign)inleti_neg_t=lit_to_term~negate:true(i_lhs)(i_sign)inCCArray.iteri(funjj_lit->beginmatchget_predicatej_litwith|Some(j_lhs,j_sign)whenCCBV.getbvj&&i!=j->letj_t=lit_to_term(j_lhs)(j_sign)inletj_neg_t=lit_to_term~negate:true(j_lhs)(j_sign)inifEnv.flex_getk_htethen((matchfind_implicationcli_neg_tj_twith|Some(lit_a,lit_b,proofset,subst)when(C.lengthcl!=2||not(Subst.is_renamingsubst))->(* stopping further search *)raise(HiddenTauto(lit_a,lit_b,proofset))|_->()));ifEnv.flex_getk_hlethen(let(<+>)=CCOpt.(<+>)in(matchfind_implicationcli_neg_tj_neg_t<+>find_implicationclj_ti_twith|Some(_,_,proofset',subst)->CCBV.resetbvj;Util.debugf~section3"@[%a@] --> @[%a@]"(funk->kT.ppi_neg_tT.ppj_neg_t);Util.debugf~section3"used(%d): @[%a@]"(funk->kj(CS.ppC.pp)proofset');proofset:=CS.unionproofset'!proofset|_->()))|_->()end)(C.litscl)|_->())(C.litscl);ifCCBV.is_empty(CCBV.negatebv)thenNoneelse((* assert (validate_proofset_ !proofset); *)letlit_l=List.rev@@CCBV.selectbv(C.litscl)inletproof=Proof.Step.simp~rule:(Proof.Rule.mk"hidden_literal_elimination")(List.mapC.proof_parent(cl::CS.to_list!proofset))inletres=C.create~penalty:(C.penaltycl)~trail:(C.trailcl)lit_lproofinUtil.debugf~section1"simplified[hle]: @[%a@] --> @[%a@]"(funk->kC.ppclC.ppres);Util.debugf~section1"used: @[%a@]"(funk->k(CS.ppC.pp)!proofset);Some(res))withHiddenTauto(lit_a,lit_b,proofset)->(* assert (validate_proofset_ proofset); *)letlit_l=[L.mk_proplit_afalse;L.mk_proplit_btrue]inletproof=Proof.Step.simp~rule:(Proof.Rule.mk"hidden_tautology_elimination")(List.mapC.proof_parent(cl::CS.to_listproofset))inlettauto=C.create~penalty:(C.penaltycl)~trail:(C.trailcl)[L.mk_tauto]proofinletrepl=C.create~penalty:(C.penaltycl+(ifCS.cardinalproofset!=1then0else1))~trail:(C.trailcl)lit_lproofinE.add_passive(Iter.singletonrepl);Util.debugf~section1"simplified[hte]: @[@[%a@] --> @[%a@]@]"(funk->kC.ppclC.pprepl);Util.debugf~section1"used @[%a@] --> @[%a@] @[(%a)@]"(funk->kT.pplit_aT.pplit_b(CS.ppC.pp)proofset);(* else the clause is subsumed *)Some(tauto))elseNoneletsimplify_opt~fcl=matchfclwith|Somecl'->SimplM.return_newcl'|None->SimplM.return_sameclletsimplify_cl=simplify_opt~f:do_hte_hleletpropagated_hle_hte=simplify_opt~f:do_propagated_simplletunit_htr=simplify_opt~f:unit_simplifyletuntrack_clausecl=(matchUtil.Int_map.get(C.idcl)!cl_occswith|Somepremises->Term.Set.iter(funpremise->prems_:=PremiseIdx.update_leaf!prems_premise(fun(tbl,_)->T.Tbl.filter_map_inplace(funconclproofset->ifCS.memclproofsetthen(concls_:=ConclusionIdx.remove!concls_conclpremise;None)elseSomeproofset)tbl;T.Tbl.lengthtbl!=0))premises;|_->());ifUtil.Int_map.mem(C.idcl)!cl_occsthen(Util.debugf~section3"removed: @[%a@]."(funk->kC.ppcl);decrtracked_cls;);cl_occs:=Util.Int_map.remove(C.idcl)!cl_occs;matchget_unit_predicateclwith|Someunit->units_:=UnitIdx.remove!units_unitcl|None->()letinitialize()=lettrack_active()=Signal.on_everyEnv.ProofState.ActiveSet.on_add_clausetrack_clause;Signal.on_everyEnv.ProofState.ActiveSet.on_remove_clauseuntrack_clauseinlettrack_passive()=Signal.on_everyEnv.ProofState.PassiveSet.on_add_clausetrack_clause;Signal.on_everyEnv.ProofState.PassiveSet.on_remove_clauseuntrack_clauseinlettrack_all()=Signal.on_everyEnv.ProofState.PassiveSet.on_add_clausetrack_clause;Signal.on_everyEnv.ProofState.ActiveSet.on_remove_clauseuntrack_clause;Signal.on_everyEnv.on_forward_simplified(fun(c,new_state)->matchnew_statewith|Somec'->ifnot(C.equalcc')then((* untrack_clause c; *)track_clausec')|_->untrack_clausec(* c is redundant *))inletinitialize_with_passive()=assert(Iter.is_empty@@E.get_active());Iter.itertrack_clause(E.get_passive());Util.debugf~section3"discovered implications:"CCFun.id;PremiseIdx.iter!prems_(funpremise(tbl,_)->Util.debugf~section3"@[%a@] --> @[%a@]"(funk->kT.pppremise(Iter.pp_seqT.pp)(T.Tbl.keystbl)))inbeginmatchEnv.flex_getk_clauses_to_trackwith|`Passive->initialize_with_passive();track_passive()|`Active->track_active()|`All->initialize_with_passive();track_all()end;Signal.StopListeningletsetup()=ifE.flex_getk_enabledthen(Signal.onEnv.on_startinitialize;letadd_simpl=ifEnv.flex_getk_simpl_newthenEnv.add_basic_simplifyelseEnv.add_active_simplifyinadd_simplsimplify_cl;ifEnv.flex_getk_unit_propagated_hlethen(add_simplpropagated_hle_hte);ifEnv.flex_getk_unit_htrthen(add_simplunit_htr))endletmax_depth_=ref3letenabled_=reffalseletsimpl_new_=reffalseletclauses_to_track_=ref`Activeletmax_self_impls_=ref1letmax_tracked_clauses=ref(-1)letpropagated_hle=reftrueletunit_htr_=reftruelethte_=reftruelethle_=reftruelettrack_eq_=reffalseletinsert_ordered_=reffalseletextension=letregisterenv=letmoduleE=(valenv:Env.S)inletmoduleHLT=Make(E)inE.flex_addk_enabled!enabled_;E.flex_addk_max_depth!max_depth_;E.flex_addk_simpl_new!simpl_new_;E.flex_addk_clauses_to_track!clauses_to_track_;E.flex_addk_max_self_impls!max_self_impls_;E.flex_addk_unit_propagated_hle!propagated_hle;E.flex_addk_unit_htr!unit_htr_;E.flex_addk_max_tracked_clauses!max_tracked_clauses;E.flex_addk_track_eq!track_eq_;E.flex_addk_hle!hle_;E.flex_addk_hte!hte_;E.flex_addk_insert_only_ordered!insert_ordered_;HLT.setup()in{Extensions.defaultwithExtensions.name="hidden literal elimination";prio=100;env_actions=[register]}let()=Options.add_opts["--hidden-lt-elim",Arg.Bool((:=)enabled_)," enable/disable hidden literal and tautology elimination";"--hidden-lt-elim-max-tracked",Arg.Int((:=)max_tracked_clauses)," negative value for disabling the limit";"--hidden-lt-elim-hle",Arg.Bool((:=)hle_)," enable/disable hidden literal elimination (hidden-lt-elim must be on)";"--hidden-lt-elim-hte",Arg.Bool((:=)hte_)," enable/disable hidden literal tautology elimination (hidden-lt-elim must be on)";"--hidden-lt-max-depth",Arg.Set_intmax_depth_," max depth of binary implication graph precomputation";"--hidden-lt-simplify-new",Arg.Bool((:=)simpl_new_)," apply HLTe also when moving a clause from fresh to passive";"--hidden-lt-track-eq",Arg.Bool((:=)track_eq_)," enable/disable tracking and simplifying equality literals";"--hidden-lt-clauses-to-track",Arg.Symbol(["all";"passive";"active"],(function|"all"->clauses_to_track_:=`All;|"passive"->clauses_to_track_:=`Passive;|"active"->clauses_to_track_:=`Active;|_->()))," what clauses to use for simplification";"--hidden-lt-max-self-implications",Arg.Int((:=)max_self_impls_)," how many times do we loop implications of the kind p(X) -> p(f(X)) ";"--hidden-lt-propagated-hle",Arg.Bool((:=)propagated_hle)," do unit-triggered removal of literals ";"--hidden-lt-unit-htr",Arg.Bool((:=)unit_htr_)," do unit hidden tautology removal ";"--hidden-lt-insert-ordered",Arg.Bool((:=)insert_ordered_)," for clauses of the form l|r where l > r then insert only ~l -> r ";];Extensions.registerextension