123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670openLogtkopenLibzipperpositionmoduleL=LiteralmoduleLs=LiteralsmoduleT=Termletenabled=reffalseletk_lazy_cnf_kind=Flex_state.create_key()letk_renaming_threshold=Flex_state.create_key()letk_rename_eq=Flex_state.create_key()letk_scoping=Flex_state.create_key()letk_solve_formulas=Flex_state.create_key()letk_skolem_mode=Flex_state.create_key()letsection=Util.Section.make~parent:Const.section"lazy_cnf"moduletypeS=sigmoduleEnv:Env.SmoduleC:moduletypeofEnv.Cwithtypet=Env.C.t(** {5 Registration} *)valsetup:unit->unit(** Register rules in the environment *)valupdate_form_counter:action:[<`Decrease|`Increase]->C.t->unitvalsolve_bool_formulas:C.t->C.tCCList.toptionendmoduleMake(E:Env.S):SwithmoduleEnv=E=structmoduleEnv=EmoduleC=Env.CmoduleCombs=Combinators.Make(Env)let_form_counter=Term.Tbl.create256moduleIdx=Fingerprint.Make(structtypet=T.t*((C.t*bool)listref)letcompare(a1,_)(a2,_)=(T.comparea1a2)end)letsign_presentsign=function|[(c,sign1)]->sign1=sign|[(c1,sign1);(c2,sign2)]->ifsign1=sign2theninvalid_arg"signs must be different!";true|_->invalid_arg"only one or two element lists"let_skolem_idx=ref@@Idx.empty()let_renaming_idx=ref@@Idx.empty()let_renamer_symbols=ref@@ID.Set.emptyletsolve_bool_formulasc=letmodulePUnif=PUnif.Make(structletst=Env.flex_state()|>Flex_state.addPragUnifParams.k_fixpoint_decidertrue|>Flex_state.addPragUnifParams.k_pattern_decidertrue|>Flex_state.addPragUnifParams.k_solid_decidertrue|>Flex_state.addPragUnifParams.k_max_inferences1|>Flex_state.addPragUnifParams.k_max_depth4|>Flex_state.addPragUnifParams.k_max_app_projections2|>Flex_state.addPragUnifParams.k_max_rigid_imitations2|>Flex_state.addPragUnifParams.k_max_elims0|>Flex_state.addPragUnifParams.k_max_identifications0end)inletnormalize_nott=letrecauxt=matchT.viewtwith|T.AppBuiltin(Not,[f])->beginmatchT.viewfwith|T.AppBuiltin(Not,[g])->auxg|T.AppBuiltin(((Eq|Equiv)asb),l)->letflipped=ifb=Builtin.EqthenBuiltin.NeqelseBuiltin.XorinT.app_builtinflippedl~ty:(T.tyf)|T.AppBuiltin(((Neq|Xor)asb),l)->letflipped=ifb=Builtin.NeqthenBuiltin.EqelseBuiltin.EquivinT.app_builtinflippedl~ty:(T.tyf)|_->tend|_->tinauxtinletfind_resolvable_formlit=letis_var_headedt=T.is_var(T.head_termt)in(* Rewrite positive equations of the form F s = t, where t is not
var-headed into F s != (not t). *)letfind_pos_var_headed_eqlr=ifis_var_headedl&¬(is_var_headedr)then(Some(l,T.Form.not_r))elseifis_var_headedr&¬(is_var_headedl)then(Some(r,T.Form.not_l))elseNoneinmatch(Literal.View.as_eqnlit)with|Some(l,r,sign)->ifnot(T.is_true_or_falser)&&Type.is_prop(T.tyl)then(ifnotsignthenSome(l,r)elsefind_pos_var_headed_eqlr)elseifT.is_true_or_falserthen(letneg=ifsignthenCCFun.idelseT.Form.not_inmatchT.view(normalize_not(negl))with|T.AppBuiltin((Neq|Xor),([f;g]|[_;f;g]))whenType.is_prop(T.tyf)->assert(Type.equal(T.tyf)(T.tyg));Some(f,g)|T.AppBuiltin((Eq|Equiv),([f;g]|[_;f;g]))whenType.is_prop(T.tyf)->assert(Type.equal(T.tyf)(T.tyg));find_pos_var_headed_eqfg|_->None)elseNone|None->Noneinletunif_alglr=ifnot(Env.flex_getCombinators.k_enable_combinators)then(PUnif.unify_scoped(l,0)(r,0)|>OSeq.filter_mapCCFun.id|>OSeq.nth0)elseUnif_subst.of_subst@@Unif.FO.unify_syn(l,0)(r,0)inUtil.debugf~section2"bool solving @[%a@]@."(funk->kC.ppc);C.litsc|>CCArray.mapi(funilit->matchfind_resolvable_formlitwith|None->None|Some(l,r)->letmoduleUS=Unif_substintryUtil.debugf~section2"trying lit @[%d:%a@]@."(funk->kiLiteral.pplit);Util.debugf~section2"unif problem: @[%a=?=%a@]@."(funk->kT.pplT.ppr);letsubst=unif_alglrinassert(not@@Unif_subst.has_constrsubst);letrenaming=Subst.Renaming.create()inletnew_lits=CCArray.except_idx(C.litsc)i|>CCArray.of_list|>(funl->Literals.apply_substrenaming(US.substsubst)(l,0))|>CCArray.to_listinletproof=Proof.Step.simp~tags:[Proof.Tag.T_ho]~rule:(Proof.Rule.mk"solve_formulas")[C.proof_parent_substrenaming(c,0)(US.substsubst)]inletres=C.create~penalty:(C.penaltyc)~trail:(C.trailc)new_litsproofinUtil.debugf~section2"solved by @[%a@]@."(funk->kC.ppres);Somereswith_->Util.debugf~section2"failed @."(funk->k);None)|>CCArray.filter_mapCCFun.id|>CCArray.to_list|>(funl->ifCCList.is_emptylthenNoneelseSomel)(* Two-literal clause of which one is a renaming literal
and the other one is a formula *)letis_renaming_clausec=letis_renaming_lit=function|L.Equation(lhs,rhs,_)whenT.equalT.true_rhs->lethd=T.head_termlhsinbeginmatchT.headhdwith|Someid->ID.Set.memid!_renamer_symbols|None->falseend|_->falseinletis_formula_lit=function|L.Equation(lhs,rhs,_)->ifT.equalT.true_rhsthenT.is_appbuiltinlhselseType.is_prop(T.tylhs)&¬(T.equalT.true_rhs)|_->falseinmatchC.litscwith|[|a;b|]->CCArray.length(CCArray.filteris_renaming_lit(C.litsc))=1&&CCArray.length(CCArray.filteris_formula_lit(C.litsc))=1|_->falseletupdate_form_counter~actionc=ifnot(is_renaming_clausec)then(Ls.fold_eqn~both:false~ord:(E.Ctx.ord())~eligible:(C.Eligible.always)(C.litsc)|>Iter.iter(fun(lhs,rhs,_,_)->letterms=ifT.equalT.true_rhs&&T.is_appbuiltinlhsthen[lhs]elseifType.is_prop(T.tylhs)&¬(T.equalT.true_rhs)&&(Term.is_appbuiltinlhs||T.is_appbuiltinrhs)then[T.Form.equivlhsrhs]else[]inList.iter(funt->matchactionwith|`Increase->Term.Tbl.incr_form_countert|`Decrease->Term.Tbl.decr_form_countert)terms))letfold_litsc=Ls.fold_eqn_simple(C.litsc)letproof~constructor~name~parentsc=constructor~rule:(Proof.Rule.mkname)(List.mapC.proof_parentparents)letmk_renaming_clauseparent~renamer~formsign=letproof=Proof.Step.define_internal(T.head_exnrenamer)[C.proof_parentparent]inletres=ifsignthen(C.create~penalty:1~trail:Trail.empty[L.mk_falserenamer;L.mk_trueform]proof)else(C.create~penalty:1~trail:Trail.empty[L.mk_truerenamer;L.mk_falseform]proof)inresletrename~cformsign=assert(Type.is_prop(T.tyform));ifis_renaming_clausec||not(T.is_appbuiltinform)||T.is_true_or_falseformthenNoneelse(letgen=Iter.head@@Idx.retrieve_generalizations(!_renaming_idx,0)(form,1)inmatchgenwith|Some(orig,(renamer,defined_as),subst)->letrenamer_sub=Subst.FO.applySubst.Renaming.nonesubst(renamer,0)inletrenamer_sub,new_defs,parents=ifsign_presentsign!defined_asthen((renamer_sub,[],!defined_as))else(letdef=mk_renaming_clausec~renamer~form:origsignindefined_as:=(def,sign)::!defined_as;(renamer_sub,[def],!defined_as))inSome(renamer_sub,new_defs,CCList.filter_map(fun(c,sign')->ifsign!=sign'thenNoneelseSomec)parents)|None->(* maybe we need to define it if it appears too many times *)letnum_occurrences=Term.Tbl.get_or_form_counterform~default:0inifnum_occurrences>=Env.flex_getk_renaming_threshold(*&&
CCArray.length (C.lits c) > 1*)then(Term.Tbl.remove_form_counterform;letfree_vars=T.varsform|>T.VarSet.to_listinlet(id,ty),renamer=T.mk_fresh_skolem~prefix:"form"free_varsType.propinE.Ctx.declareidty;letdef=mk_renaming_clausec~renamer~formsignin_renaming_idx:=Idx.add!_renaming_idxform(renamer,ref[(def,sign)]);_renamer_symbols:=ID.Set.addid!_renamer_symbols;Some(renamer,[def],[def]))elseNone)letrename_eq~clhsrhssign=assert(Type.equal(T.tylhs)(T.tyrhs));assert(Type.is_prop(T.tylhs));ifEnv.flex_getk_rename_eqthenrename~c(T.Form.equivlhsrhs)signelseNoneletmk_and~proof_cons~rule_nameand_argsc?(parents=[c])lit_idx=letlits=CCArray.except_idx(C.litsc)lit_idxinletproof=proof~constructor:proof_cons~parents~name:rule_namecinList.map(funt->C.create~penalty:(C.penaltyc)~trail:(C.trailc)(L.mk_truet::lits)proof)and_argsletmk_or~proof_cons~rule_nameor_argsc?(parents=[c])lit_idx=letlits=(List.mapL.mk_trueor_args)@(CCArray.except_idx(C.litsc)lit_idx)inletproof=proof~constructor:proof_cons~parents~name:rule_namecin[C.create~penalty:(C.penaltyc)~trail:(C.trailc)litsproof]letcnf_scope_formform=letkind=Env.flex_getk_scopinginletopenCCOptinletrecmaxiscoping_eligiblel=letget_quantt=lett=Combs.expandtinmatchT.viewtwith|T.AppBuiltin((ForallConst|ExistsConst)asb,[x])->letty,body=T.open_funxinassert(List.lengthty=1);Some(b,List.hdty,[body])|_->Noneinmatchlwith|[]->assertfalse;|[x]->get_quantx|x::xs->get_quantx>>=(fun(b,ty,body)->maxiscoping_eligiblexs>>=(fun(b',ty',bodies)->ifBuiltin.equalbb'&&Type.equaltyty'then(Some(b,ty,(List.hdbody)::bodies))elseNone))inletminiscopehdf=letdistribute_quanthdtybodies=letquant_hd=ifBuiltin.equalhdOrthenT.Form.existselseT.Form.forallinletouter_hd=ifBuiltin.equalhdOrthenT.Form.or_lelseT.Form.and_linouter_hd(List.map(funt->quant_hd(T.fun_tyt))bodies)inletf=Combs.expandfinifT.is_funfthen(letty,body=T.open_funfinassert(List.lengthty=1);matchT.viewbodywith|T.AppBuiltin(Or,l)whenBuiltin.equalhdExistsConst->Some(distribute_quantOr(List.hdty)l)|T.AppBuiltin(And,l)whenBuiltin.equalhdForallConst->Some(distribute_quantAnd(List.hdty)l)|_->None)elseNoneinmatchT.viewformwith|T.AppBuiltin(And,((_::_)asl))whenkind=`Maxi->beginmatchmaxiscoping_eligiblelwith|Some(ForallConst,ty,bodies)->Some(T.Form.forall(T.fun_ty(T.Form.and_lbodies)))|_->Noneend|T.AppBuiltin(Or,((_::_)asl))whenkind=`Maxi->beginmatchmaxiscoping_eligiblelwith|Some(ExistsConst,ty,bodies)->Some(T.Form.exists(T.fun_ty(T.Form.or_lbodies)))|_->Noneend|T.AppBuiltin(((ExistsConst|ForallConst)asb),[f])whenkind=`Mini->miniscopebf|_->Noneletchoice_tbl=Type.Tbl.create32letlazy_clausify_driver?(ignore_eq=false)~proof_consc=letreturnl=Iter.of_listl,`Stopinletcontinue=Iter.empty,`Continueinleteligible_for_ignore_eq~ignore_eqlhsrhs=ignore_eq&¬(T.is_true_or_falselhs)&¬(T.is_true_or_falserhs)inletget_skolem~free_vars~ret_ty~modef=matchmodewith|`Skolem->letgen=Iter.head@@Idx.retrieve_generalizations(!_skolem_idx,0)(f,1)inbeginmatchgenwith|Some(orig,(skolem,_),subst)->Subst.FO.applySubst.Renaming.nonesubst(skolem,0)|None->letfree_vars_l=T.VarSet.to_list(T.VarSet.of_iterfree_vars)inlet(id,ty),t=T.mk_fresh_skolem~prefix:"sk"free_vars_lret_tyinE.Ctx.declareidty;Signal.sendEnv.on_pred_skolem_introduction(c,t);_skolem_idx:=Idx.add!_skolem_idxf(t,ref[]);tend|`Choice->lethd=Type.Tbl.get_or_addchoice_tbl~f:(funty->letarg_tys,ret_ty_form=Type.open_funtyinassert(List.lengtharg_tys==1);assert(Type.is_propret_ty_form);assert(Type.equal(List.hdarg_tys)ret_ty);let(hd_id,hd_ty),res=Term.mk_fresh_skolem~prefix:"$_choose"[](Type.arrow[ty](List.hdarg_tys))inE.Ctx.declarehd_idhd_ty;res)~k:(T.tyf)inT.apphd[f]inUtil.debugf~section2"lazy_cnf(@[%a@])@."(funk->kC.ppc);letinit=ifEnv.flex_getk_solve_formulasthenIter.of_list(CCOpt.get_or~default:[](solve_bool_formulasc))elseIter.emptyinfold_litsc|>Iter.fold_while(fun_(lhs,rhs,sign,pos)->leti,_=Ls.Pos.cutposinifT.equalrhsT.true_then(Util.debugf~section2" subformula:%d:@[%a@]"(funk->kiL.pp(C.litsc).(i));beginmatchT.viewlhswith|T.AppBuiltin(And,l)whenList.lengthl>=2->letrule_name="lazy_cnf_and"inifsignthenreturn@@mk_and~proof_conslci~rule_nameelsereturn@@mk_or~proof_cons(List.mapT.Form.not_l)ci~rule_name|T.AppBuiltin(Or,l)whenList.lengthl>=2->letrule_name="lazy_cnf_or"inifsignthenreturn@@mk_or~proof_conslci~rule_nameelsereturn@@mk_and~proof_cons(List.mapT.Form.not_l)ci~rule_name|T.AppBuiltin(Imply,[a;b])->letrule_name="lazy_cnf_imply"inifsignthenreturn@@mk_or~proof_cons[T.Form.not_a;b]ci~rule_nameelsereturn@@mk_and~proof_cons[a;T.Form.not_b]ci~rule_name|T.AppBuiltin((Equiv|Xor)ashd,[a;b])->lethd=ifsignthenhdelse(ifhd=EquivthenXorelseEquiv)inifeligible_for_ignore_eq~ignore_eqabthencontinueelse(letrule_name=CCFormat.sprintf"lazy_cnf_%s"(ifhd=Equivthen"equiv"else"xor")inifhd=Equivthen(return@@(mk_or~proof_cons~rule_name[T.Form.not_a;b]ci@mk_or~proof_cons~rule_name[a;T.Form.not_b]ci))else(return@@(mk_or~proof_cons~rule_name[T.Form.not_a;T.Form.not_b]ci@mk_or~proof_cons~rule_name[a;b]ci)))|T.AppBuiltin((ForallConst|ExistsConst)ashd,[f])->letfree_vars=T.Seq.varsfinletvar_id=T.Seq.max_var(C.Seq.varsc)+1inletf=Combs.expandfinletvar_tys,body=T.open_funfinassert(List.lengthvar_tys=1);letvar_ty=List.hdvar_tysinlethd,f=ifsignthenhd,felse((ifhd=ForallConstthenExistsConstelseForallConst),T.fun_var_ty(T.Form.not_body))inletrule_name=CCFormat.sprintf"lazy_cnf_%s"(ifhd=ForallConstthen"forall"else"exists")inletsubst_term=ifhd=ForallConstthen(T.var@@HVar.make~ty:var_tyvar_id)else(get_skolem~free_vars~ret_ty:var_ty~mode:(Env.flex_getk_skolem_mode)f)inletres=Lambda.eta_reduce@@Lambda.snf@@T.appf[subst_term]inassert(Type.is_prop(T.tyres));letres_cl=mk_or~proof_cons~rule_name[res]ciinifType.returns_propvar_ty&&hd==ForallConstthen(assert(List.lengthres_cl==1);assert(T.is_varsubst_term);Signal.sendEnv.on_pred_var_elimination(List.hdres_cl,subst_term));returnres_cl|T.AppBuiltin(Not,_)->assertfalse|_->continueend)elseifType.is_prop(T.tylhs)&¬(T.equalT.true_rhs)then(letrule_name=CCFormat.sprintf"lazy_cnf_%s"(ifsignthen"equiv"else"xor")inUtil.debugf~section2" subeq:%d:@[%a %s= %a@]"(funk->kiT.pplhs(ifsignthen""else"~")T.pprhs);ifeligible_for_ignore_eq~ignore_eqlhsrhsthencontinueelseifsignthen(return@@(mk_or~proof_cons~rule_name[T.Form.not_lhs;rhs]ci@mk_or~proof_cons~rule_name[lhs;T.Form.not_rhs]ci))else(return@@(mk_or~proof_cons~rule_name[T.Form.not_lhs;T.Form.not_rhs]ci@mk_or~proof_cons~rule_name[lhs;rhs]ci)))elsecontinue)(init)letrename_subformulasc=Util.debugf~section2"lazy-cnf-rename(@[%a@])@."(funk->kC.ppc);fold_litsc|>Iter.fold_while(fun_(lhs,rhs,sign,pos)->leti,_=Ls.Pos.cutposinletproof_cons=Proof.Step.simp~infos:[]~tags:[Proof.Tag.T_live_cnf;Proof.Tag.T_dont_increase_depth]inifT.equalrhsT.true_&&T.is_appbuiltinlhsthen(matchrename~clhssignwith|Some(renamer,new_defs,parents)->letrule_name="renaming"inletrenamer=(ifsignthenCCFun.idelseT.Form.not_)renamerinletrenamed=mk_or~proof_cons~rule_name[renamer]c~parents:(c::parents)iinletres=renamed@new_defsinUtil.debugf~section2" @[renamed subformula %d:(@[%a@])=@. @[%a@]@]@."(funk->kiC.ppc(CCList.ppC.pp)renamed);Util.debugf~section2" new defs:@[%a@]@."(funk->k(CCList.ppC.pp)new_defs);Someres,`Stop|None->None,`Continue)elseifType.is_prop(T.tylhs)&¬(T.equalrhsT.true_)&&(T.is_appbuiltinlhs||T.is_appbuiltinrhs)then(matchrename_eq~clhsrhssignwith|Some(renamer,new_defs,parents)->letrule_name="renaming"inletrenamer=(ifsignthenCCFun.idelseT.Form.not_)renamerinletrenamed=mk_or~proof_cons~rule_name[renamer]c~parents:(c::parents)iinletres=renamed@new_defsinUtil.debugf~section2" @[renamed eq %d(@[%a@]) into @[%a@]@]@."(funk->kiL.pp(C.litsc).(i)(CCList.ppC.pp)renamed);Util.debugf~section2" new defs:@[%a@]@."(funk->k(CCList.ppC.pp)new_defs);Someres,`Stop|None->None,`Continue)elseNone,`Continue)Noneletclausify_eqc=letrule_name="eq_elim"infold_litsc|>Iter.fold(funacc(lhs,rhs,sign,pos)->leti,_=Ls.Pos.cutposinletproof_cons=Proof.Step.inference~infos:[]~tags:[Proof.Tag.T_live_cnf;Proof.Tag.T_dont_increase_depth]inifnot(T.is_true_or_falserhs)&&Type.is_prop(T.tylhs)then(letnew_cls=ifsignthen(mk_or~proof_cons~rule_name[T.Form.not_lhs;rhs]ci@mk_or~proof_cons~rule_name[lhs;T.Form.not_rhs]ci)else((mk_or~proof_cons~rule_name[T.Form.not_lhs;T.Form.not_rhs]ci)@(mk_or~proof_cons~rule_name[lhs;rhs]ci))inletpen_inc=if(T.is_groundlhs&&T.is_groundrhs)then0else(ifT.is_app_varlhs||T.is_app_varrhsthen3else1)inList.iter(func->C.inc_penaltycpen_inc)new_cls;new_cls@acc)elseacc)[]letcnf_scopec=fold_litsc|>Iter.fold_while(fun_(lhs,rhs,sign,pos)->leti,_=Ls.Pos.cutposinletproof_cons=Proof.Step.simp~infos:[]~tags:[Proof.Tag.T_live_cnf;Proof.Tag.T_dont_increase_depth]inifT.equalrhsT.true_&&T.is_appbuiltinlhsthen(matchcnf_scope_formlhswith|Somef->letrule_name=CCFormat.sprintf"lazy_cnf_%sscoping"(ifEnv.flex_getk_scoping==`Maxithen"maxi"else"mini")inletapp_sign=ifsignthenCCFun.idelseT.Form.not_inSome(mk_or~proof_cons[app_signf]ci~rule_name),`Stop|None->None,`Continue)elseNone,`Continue)Noneletlazy_clausify_simplc=update_form_counter~action:`Increasec;letproof_cons=Proof.Step.simp~infos:[]~tags:[Proof.Tag.T_live_cnf;Proof.Tag.T_dont_increase_depth]inletres=Iter.to_list@@lazy_clausify_driver~ignore_eq:true~proof_conscinifnot@@CCList.is_emptyresthen(Util.debugf~section2"lazy_cnf_simp(@[%a@])="(funk->kC.ppc);Util.debugf~section2"@[%a@]@."(funk->k(CCList.ppC.pp)res);update_form_counter~action:`Decreasec;CCList.iter(update_form_counter~action:`Increase)res;)elseUtil.debugf~section3"lazy_cnf_simp(@[%a@])=Ø"(funk->kC.ppc);ifCCList.is_emptyresthenNoneelse(Someres)letlazy_clausify_infc=letproof_cons=Proof.Step.inference~infos:[]~tags:[Proof.Tag.T_live_cnf;Proof.Tag.T_dont_increase_depth]inletres=Iter.to_list(lazy_clausify_driver~ignore_eq:false~proof_consc)inifnot@@CCList.is_emptyresthen(Util.debugf~section2"lazy_cnf_inf(@[%a@])="(funk->kC.ppc);Util.debugf~section2"@[%a@]@."(funk->k(CCList.ppC.pp)res);)elseUtil.debugf~section3"lazy_cnf_simp(@[%a@])=Ø"(funk->kC.ppc);resletsetup()=if!enabledthen((* orders are still not really fixed for completeness *)Env.Ctx.lost_completeness();beginmatchEnv.flex_getk_lazy_cnf_kindwith|`Inf->Env.add_unary_inf"lazy_cnf"lazy_clausify_inf|`Simp->Env.add_unary_inf"elim eq"clausify_eq;Env.add_multi_simpl_rule~priority:5lazy_clausify_simplend;(* ** IMPORTANT **
RENAMING MUST BE ADDED AFTER CLAUSIFICATION RULES (so that
it runs ***before*** lazy_clausify_simpl) *)ifEnv.flex_getk_renaming_threshold>0then(Env.add_multi_simpl_rule~priority:5rename_subformulas);ifEnv.flex_getk_scoping!=`Offthen(Env.add_multi_simpl_rule~priority:5cnf_scope;))endlet_lazy_cnf_kind=ref`Simplet_renaming_threshold=ref8let_rename_eq=reftruelet_scoping=ref`Offlet_solve_formulas=reffalselet_skolem_mode=ref`Skolemletextension=letregisterenv=letmoduleE=(valenv:Env.S)inletmoduleET=Make(E)inE.flex_addk_lazy_cnf_kind!_lazy_cnf_kind;E.flex_addk_renaming_threshold!_renaming_threshold;E.flex_addk_rename_eq!_rename_eq;E.flex_addk_scoping!_scoping;E.flex_addk_solve_formulas!_solve_formulas;E.flex_addk_skolem_mode!_skolem_mode;lethandlerfc=fc;Signal.ContinueListeninginifE.flex_getk_lazy_cnf_kind==`Infthen(Signal.onE.ProofState.PassiveSet.on_add_clause(handler(ET.update_form_counter~action:`Increase));Signal.onE.ProofState.ActiveSet.on_add_clause(handler(ET.update_form_counter~action:`Increase));Signal.onE.ProofState.PassiveSet.on_remove_clause(handler(ET.update_form_counter~action:`Decrease));Signal.onE.ProofState.ActiveSet.on_remove_clause(handler(ET.update_form_counter~action:`Decrease)));ET.setup()in{Extensions.defaultwithExtensions.name="lazy_cnf";env_actions=[register];}let()=Options.add_opts["--lazy-cnf",Arg.Bool((:=)enabled)," turn on lazy clausification";"--lazy-cnf-scoping",Arg.Symbol(["off";"mini";"maxi"],(funstr->matchstrwith|"mini"->_scoping:=`Mini|"maxi"->_scoping:=`Maxi|"off"->_scoping:=`Off|_->assertfalse))," use mini/maxi scoping rules for lazy cnf";"--lazy-cnf-renaming-threshold",Arg.Int((:=)_renaming_threshold)," set the subformula renaming threshold -- negative value turns renaming off";"--solve-formulas",Arg.Bool(funv->_solve_formulas:=v)," solve phi != psi eagerly using unification, where phi and psi are formulas";"--lazy-cnf-skolem-mode",Arg.Symbol(["skolem";"choice"],(funstr->matchstrwith|"skolem"->_skolem_mode:=`Skolem|"choice"->_skolem_mode:=`Choice|_->assertfalse))," use lazy cnf as either simplification or inference";"--lazy-cnf-kind",Arg.Symbol(["inf";"simp"],(funstr->matchstrwith|"inf"->_lazy_cnf_kind:=`Inf|"simp"->_lazy_cnf_kind:=`Simp|_->assertfalse))," use lazy cnf as either simplification or inference";"--lazy-cnf-rename-eq",Arg.Bool((:=)_rename_eq)," turn on/of renaming of boolean equalities"];Params.add_to_modes["ho-complete-basic";"ho-pragmatic";"lambda-free-intensional";"lambda-free-purify-intensional";"lambda-free-extensional";"ho-comb-complete";"lambda-free-purify-extensional";"fo-complete-basic"](fun()->enabled:=false;);Extensions.registerextension