123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849openLogtkopenLibzipperpositionmoduleL=LiteralmoduleLs=LiteralsmoduleT=Termletenabled=reffalselet_eager_lcnf=reffalseletk_lazy_cnf_kind=Flex_state.create_key()letk_lazy_cnf_eager=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_skolem_mode=Flex_state.create_key()letk_enum_bool_funs=Flex_state.create_key()letk_replace_bool_fun_quants=Flex_state.create_key()letk_pa_renaming=Flex_state.create_key()letk_only_eligible=Flex_state.create_key()letk_penalize_eq_cnf=Flex_state.create_key()letk_clausify_eq_max_nonint=Flex_state.create_key()letk_clausify_implications=Flex_state.create_key()letk_simp_limit=Flex_state.create_key()letk_simplify_quant=Flex_state.create_key()letk_inf_quant=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->unitendmoduleMake(E:Env.S):SwithmoduleEnv=E=structmoduleEnv=EmoduleC=Env.CmoduleCombs=Combinators.Make(Env)moduleFR=Env.FormRenamelet_form_counter=Term.Tbl.create256let_counted_clauses=refUtil.Int_set.emptyletupdate_form_counter~actionc=letshould_updatec=not(FR.is_renaming_clausec)&&(* we make sure than we do not add or remove the clause twice *)(matchactionwith|`Increase->ifUtil.Int_set.mem(C.idc)!_counted_clausesthenfalseelse(_counted_clauses:=Util.Int_set.add(C.idc)!_counted_clauses;true)|`Decrease->ifnot(Util.Int_set.mem(C.idc)!_counted_clauses)thenfalseelse(_counted_clauses:=Util.Int_set.remove(C.idc)!_counted_clauses;true;))inifshould_updatecthen(Ls.fold_eqn~both:false~ord:(E.Ctx.ord())~eligible:(C.Eligible.always)(C.litsc)|>Iter.iter(fun(lhs,rhs,_,pos)->leti,_=Ls.Pos.cutposinletlit=(C.litsc).(i)inletterms=ifL.is_predicate_litlit&&T.is_appbuiltinlhsthen[lhs]elseifType.is_prop(T.tylhs)&¬(L.is_predicate_litlit)&&(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))else((* CCFormat.printf "not updating @[%a@]@." C.pp c; *))letfold_litsc=letlits=Ls.fold_eqn_simple(C.litsc)inifEnv.flex_getk_only_eligiblethen(leteligible=C.eligible_res_no_substcinIter.filter(fun(_,_,_,p)->CCBV.geteligible(Ls.Pos.idxp))lits)elselits(* if k_clausify_eq_max_nonint is disabled, then we will not clausify
if the max side is non-interpreted *)letcheck_eq_cnf_ordering_conditionslhsrhs=letis_noninterpetedt=CCOpt.is_some(Term.headt)inletord=E.Ctx.ord()in(E.flex_getk_clausify_eq_max_nonint)||(matchOrdering.compareordlhsrhswith|Comparison.Lt->is_noninterpetedrhs|Comparison.Gt->is_noninterpetedlhs|_->is_noninterpetedlhs||is_noninterpetedrhs)let_ty_map=Type.Tbl.create16letinit_ty_map()=Type.Tbl.add_ty_mapType.prop[T.true_;T.false_]letrecenum_bool_funs~ty=assert(Iter.for_all(funty->Type.is_funty||Type.is_propty)(Type.Seq.subty));letinsert_defining_clausesidsymarg_combstable=List.iteri(funiarg_comb->letlhs=T.appsymarg_combinletrhs=table.(i)inletlits=[Literal.mk_eqlhsrhs]inletproof=Proof.Step.define_internalid[]inletres=C.create~penalty:1~trail:Trail.emptylitsproofinUtil.debugf~section2"defining: @[%a@]@."(funk->kC.ppres);Env.add_passive(Iter.singletonres))(arg_combs)inletcreate_membersarg_msret_m=assert(not(CCList.is_emptyret_m));letarg_combinations=CCList.cartesian_productarg_msinletarg_comb_num=List.fold_left(funacca->acc*(List.lengtha))1arg_msinletfun_table=CCArray.createarg_comb_num(List.hdret_m)inletiter_funs()=letrecauxik=ifi==arg_comb_numthenkfun_tableelse(List.iter(funx->fun_table.(i)<-x;aux(i+1)k)ret_m)inaux0inletprefix="finite_domain_fun"initer_funs()|>Iter.map(funtable->let((id,id_ty),fresh_sym)=Term.mk_fresh_skolem~prefix[]tyininsert_defining_clausesidfresh_symarg_combinationstable;(* let stm = definition_stream id fresh_sym arg_combinations table in
let stm_res = Env.Stm.make ~penalty:(1) ~parents:[] (stm) in
Env.StmQ.add (Env.get_stm_queue ()) stm_res; *)Util.debugf~section2"declaring %a"(funk->kID.ppid);fresh_sym)|>Iter.to_listinifType.Tbl.length_ty_map==0theninit_ty_map();tryType.Tbl.find_ty_maptywithNot_found->letargs,ret=Type.open_funtyinletarg_members=List.map(funty->enum_bool_funs~ty)argsinletret_members=enum_bool_funs~ty:retinletnew_members=create_membersarg_membersret_membersinType.Tbl.add_ty_maptynew_members;Env.Ctx.declare_syms(List.map(funt->T.head_exnt,T.tyt)new_members);Util.debugf~section2"members of type @[%a@]@. >@[%a@]"(funk->kType.ppty(CCList.ppT.pp)new_members);new_membersletestimate_num_clausessignlimitf=letexceptionTooManyClausesinletcheck_cl_sizesize=ifsize>limitthenraiseTooManyClauses;sizeinletrecauxsignf=matchT.viewfwith|T.AppBuiltin(Not,[f])->aux(notsign)f|T.AppBuiltin(And,l)->ifsignthensum_lsignlelseprod_lsignl|T.AppBuiltin(Or,l)->ifsignthenprod_lsignlelsesum_lsignl|T.AppBuiltin(Imply,[a;b])->ifsignthenprod_ltrue[T.Form.not_a;b]elsesum_ltrue[a;T.Form.not_b]|T.AppBuiltin((Eq|Equiv|Neq|Xor)ashd,([_;a;b]|[a;b]))whenType.is_prop(T.tya)->ifBuiltin.equalEqhd||Builtin.equalEquivhdthen(auxtrue(T.Form.and_(T.Form.or_(T.Form.not_a)b)(T.Form.or_(T.Form.not_b)a)))else(auxtrue(T.Form.and_(T.Form.or_(T.Form.not_a)(T.Form.not_b))(T.Form.or_ab)))|T.AppBuiltin((ForallConst|ExistsConst),[_;body])->let_,body=T.open_funbodyinauxsignbody|_->1andsum_lsignxs=List.fold_left(funaccf->check_cl_size@@acc+auxsignf)0xsandprod_lsignxs=List.fold_left(funaccf->check_cl_size@@(acc*(auxsignf)))1xsintryletestimate=auxsignfinUtil.debugf~section1"estimate(%b, @[%a@])=@[%d@]@."(funk->ksignT.ppfestimate);truewithTooManyClauses->Util.debugf~section1"estimate(%b, @[%a@])=too many@."(funk->ksignT.ppf);falseletcheck_size_limitssignf=letlimit=Env.flex_getk_simp_limitinUtil.debugf~section1"checking limit: %d@."(funk->klimit);Env.flex_getk_lazy_cnf_kind!=`Simp||limit<0||estimate_num_clausessignlimitfletproof~constructor~name~parentsc=constructor~rule:(Proof.Rule.mkname)(List.mapC.proof_parentparents)letrename_eq~c~should_renamelhsrhssign=assert(Type.equal(T.tylhs)(T.tyrhs));assert(Type.is_prop(T.tylhs));assert(T.is_appbuiltinlhs||T.is_appbuiltinrhs);assert(not(T.is_true_or_falselhs)||(T.is_true_or_falserhs));letyields_clausesf=matchT.viewfwith|T.AppBuiltin((Eq|Neq),[ty;_;_])->Type.is_prop(Type.of_term_unsafe(ty:>InnerTerm.t))|T.AppBuiltin(_,_)->true|_->falseinletpolarity_aware=Env.flex_getk_pa_renaminginletapp_sign=ifsignthenCCFun.idelseT.Form.not_inifEnv.flex_getk_rename_eqthen(if(yields_clauseslhs&&yields_clausesrhs)then(CCOpt.map(fun(r,d,p)->app_signr,d,p)(FR.rename_form~should_rename~polarity_aware~c(T.Form.equivlhsrhs)sign))elseifyields_clauseslhsthen(CCOpt.map(fun(r,d,p)->app_sign(T.Form.eqrrhs),d,p)(FR.rename_form~should_rename~polarity_aware:false~clhssign))elseifyields_clausesrhsthen(CCOpt.map(fun(r,d,p)->app_sign(T.Form.eqlhsr),d,p)(FR.rename_form~should_rename~polarity_aware:false~crhssign))elseNone)elseNoneletmk_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|_->Noneletclausify_quant~parent~var_offset~sign~quant_body~(quant_hd:Builtin.t)=letf=Combs.expandquant_bodyinletvar_tys,body=T.open_funfinassert(List.lengthvar_tys=1);letvar_ty=List.hdvar_tysinlethd,f=ifsignthenquant_hd,felse((ifquant_hd=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_ty(var_offset+1))else(FR.get_skolem~parent~mode:(Env.flex_getk_skolem_mode)f|>CCFun.tap(funt->CCOpt.iter(funhd_id->ID.set_payload(hd_id)(ID.Attr_skolemID.K_lazy_cnf))(T.headt)))inletexpand_quant=not@@Env.flex_getCombinators.k_enable_combinatorsinletres_t=Lambda.eta_reduce~expand_quant@@Lambda.snf@@T.appf[subst_term]inres_t,hd,subst_term,rule_nameletlazy_clausify_driver?(ignore_eq=false)?(force_clausification=false)~proof_consc=letreturnaccl=Iter.appendacc(Iter.of_listl),`Stopinletcontinueacc=acc,`Continueinleteligible_to_ignore_eq~ignore_eqlhsrhs=(not(check_eq_cnf_ordering_conditionslhsrhs))||(ignore_eq&¬(T.is_true_or_falselhs)&¬(T.is_true_or_falserhs))inUtil.debugf~section3"lazy_cnf(@[%a@])@."(funk->kC.ppc);letinit=Iter.emptyinletshould_clausifysignf=force_clausification||(Env.flex_getk_lazy_cnf_kind!=`Ignore&&check_size_limitssignf)infold_litsc|>Iter.fold_while(funacc(lhs,rhs,sign,pos)->leti,_=Ls.Pos.cutposinletlit=(C.litsc).(i)inifL.is_predicate_litlitthen(Util.debugf~section3" subformula:%d:@[%a@]"(funk->kiL.pplit);beginmatchT.viewlhswith|T.AppBuiltin(And,l)whenList.lengthl>=2&&should_clausifysignlhs->letrule_name="lazy_cnf_and"inifsignthenreturnacc@@mk_and~proof_conslci~rule_nameelsereturnacc@@mk_or~proof_cons(List.mapT.Form.not_l)ci~rule_name|T.AppBuiltin(Or,l)whenList.lengthl>=2&&should_clausifysignlhs->letrule_name="lazy_cnf_or"inifsignthenreturnacc@@mk_or~proof_conslci~rule_nameelsereturnacc@@mk_and~proof_cons(List.mapT.Form.not_l)ci~rule_name|T.AppBuiltin(Imply,[a;b])whenshould_clausifysignlhs->letrule_name="lazy_cnf_imply"inifsignthen(ifforce_clausification||Env.flex_getk_lazy_cnf_kind!=`Simp||Env.flex_getk_clausify_implicationsthenreturnacc@@mk_or~proof_cons[T.Form.not_a;b]ci~rule_nameelsecontinueacc)elsereturnacc@@mk_and~proof_cons[a;T.Form.not_b]ci~rule_name|T.AppBuiltin((Equiv|Xor)ashd,[a;b])whenshould_clausifysignlhs->lethd=ifsignthenhdelse(ifhd=EquivthenXorelseEquiv)inifeligible_to_ignore_eq~ignore_eqabthencontinueaccelse(letrule_name=CCFormat.sprintf"lazy_cnf_%s"(ifhd=Equivthen"equiv"else"xor")inifhd=Equivthen(returnacc@@(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(returnacc@@(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])whenEnv.flex_getk_lazy_cnf_kind!=`Simp||not(Env.flex_getk_inf_quant)->letvar_offset=T.Seq.max_var(C.Seq.varsc)+1inletres,hd,subst_term,rule_name=clausify_quant~parent:c~var_offset~sign~quant_body:f~quant_hd:hdinassert(Type.is_prop(T.tyres));letres_cl=mk_or~proof_cons~rule_name[res]ciinifType.returns_prop(T.tysubst_term)&&hd==ForallConstthen(assert(List.lengthres_cl==1);assert(T.is_varsubst_term);Signal.sendEnv.on_pred_var_elimination(List.hdres_cl,subst_term));letsub_ty=T.tysubst_terminifEnv.flex_getk_enum_bool_funs&&Type.Seq.has_bools_onlysub_tythen(letrepls=enum_bool_funs~ty:sub_tyinifEnv.flex_getk_replace_bool_fun_quantsthen(letbodies=List.map(funr->Lambda.eta_reduce@@Lambda.whnf(T.appf[r]))replsinreturnacc@@(ifhd==ForallConstthenmk_and~proof_cons~rule_name:"_inst_quant"bodiescielsemk_or~proof_cons~rule_name:"_inst_quant"bodiesci))elsereturnaccres_cl)elsereturnaccres_cl|_->continueaccend)elseifType.is_prop(T.tylhs)&¬(L.is_predicate_litlit)then(letrule_name=CCFormat.sprintf"lazy_cnf_%s"(ifsignthen"equiv"else"xor")inUtil.debugf~section3" subeq:%d:@[%a %s= %a@]"(funk->kiT.pplhs(ifsignthen""else"~")T.pprhs);ifeligible_to_ignore_eq~ignore_eqlhsrhs||not(check_size_limitssign(T.Form.equivlhsrhs))thencontinueaccelseifsignthen(returnacc@@(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(returnacc@@(mk_or~proof_cons~rule_name[T.Form.not_lhs;T.Form.not_rhs]ci@mk_or~proof_cons~rule_name[lhs;rhs]ci)))elsecontinueacc)(init)letclausify_quants~proof_consc=C.litsc|>CCArray.find_map_i(funi->function|Literal.Equation(lhs,_,_)aslitwhenLiteral.is_predicate_litlit->beginmatchT.viewlhswith|T.AppBuiltin((ForallConst|ExistsConst)ashd,[_;body])->letvar_offset=T.Seq.max_var(C.Seq.varsc)+1inletsign=Literal.is_positivoidlitinletres,hd,subst_term,rule_name=clausify_quant~parent:c~var_offset~sign~quant_body:body~quant_hd:hdinassert(Type.is_prop(T.tyres));letres_cl=List.hd@@mk_or~proof_cons~rule_name[res]ciinifType.returns_prop(T.tysubst_term)&&hd==ForallConstthen(assert(T.is_varsubst_term);Signal.sendEnv.on_pred_var_elimination(res_cl,subst_term));Some(res_cl)|_->Noneend|_->None)letreduce_quantifiersc=letproof_cons=Proof.Step.simp~infos:[]~tags:[Proof.Tag.T_live_cnf;Proof.Tag.T_dont_increase_depth]inclausify_quants~proof_consc|>CCOpt.map_or~default:(SimplM.return_samec)(SimplM.return_new)letrename_subformulasc=Util.debugf~section3"lazy-cnf-rename(@[%a@])@."(funk->kC.ppc);letproof_cons=Proof.Step.simp~infos:[]~tags:[Proof.Tag.T_live_cnf;Proof.Tag.T_dont_increase_depth]inletclausify_defsnew_defs=List.fold_left(funaccc->lazy_clausify_driver~ignore_eq:false~force_clausification:true~proof_consc|>Iter.to_list|>(funl->ifCCList.is_emptylthenc::accelsel@acc))[]new_defsinletshould_renamesignf=letwill_yield_clauesf=letrecaux~signf=matchT.viewfwith|T.AppBuiltin(Builtin.And,l)->(sign&&(List.lengthl>=2))||aux_lsignl|T.AppBuiltin(Builtin.Or,l)->((notsign)&&(List.lengthl>=2))||aux_lsignl|T.AppBuiltin(Builtin.(ForallConst|ExistsConst),[_;body])->aux~sign(snd(T.open_funbody))|T.AppBuiltin(Builtin.Not,[body])->aux~sign:(notsign)body|T.AppBuiltin(Builtin.Imply,[a;b])->notsign||aux~sign:(notsign)a||aux~signb|T.AppBuiltin(Builtin.(Eq|Equiv|Neq|Xor),([a;b]|[_;a;b]))->(* if it is either an equivalence(xor) which yields at
least two clauses, or a complicated higher-order
disequation (between app-vars or lambdas) in which case
it is good to hide it under renamed formula and
delay reasoning about it *)Type.is_prop(T.tya)||T.Seq.subterms~include_builtin:truef|>Iter.exists(funx->T.is_app_varx||T.is_funx)|_->falseandaux_lsign=function|[]->false|x::xs->aux~signx||aux_lsignxsinletans=aux~signfinUtil.debugf~section3"@[%a@] will%s yield clauses@."(funk->kT.ppf(ifansthen""else" not"));ansinletnum_occurences=Term.Tbl.get_or_form_counterf~default:0in(* CCFormat.printf "|@[%a@]| = %d@." T.pp f num_occurences; *)num_occurences>=Env.flex_getk_renaming_threshold&&(not(FR.is_renaming_clausec))&&will_yield_clauesfinLs.fold_eqn_simple(C.litsc)|>Iter.fold_while(fun_(lhs,rhs,sign,pos)->leti,_=Ls.Pos.cutposinletlit=(C.litsc).(i)inletproof_cons=Proof.Step.simp~infos:[]~tags:[Proof.Tag.T_live_cnf;Proof.Tag.T_dont_increase_depth]inletpolarity_aware=Env.flex_getk_pa_renaminginletshould_rename=should_renamesigninifL.is_predicate_litlit&&T.is_appbuiltinlhsthen(matchFR.rename_form~should_rename~polarity_aware~clhssignwith|Some(renamer,new_defs,parents)->Term.Tbl.remove_form_counterlhs;letrule_name="renaming"inletnew_defs=clausify_defsnew_defsinletrenamer=(ifsignthenCCFun.idelseT.Form.not_)renamerinletrenamed=mk_or~proof_cons~rule_name[renamer]c~parents:(c::parents)iinletres=renamed@new_defsinUtil.debugf~section3" @[renamed subformula %d:(@[%a@])=@. @[%a@]@]@."(funk->kiC.ppc(CCList.ppC.pp)renamed);Util.debugf~section3" new defs:@[%a@]@."(funk->k(CCList.ppC.pp)new_defs);Someres,`Stop|None->None,`Continue)elseifType.is_prop(T.tylhs)&¬(L.is_predicate_litlit)&&(T.is_appbuiltinlhs||T.is_appbuiltinrhs)then(matchrename_eq~should_rename~clhsrhssignwith|Some(renamer,new_defs,parents)->letrule_name="renaming"inletnew_defs=clausify_defsnew_defsinletrenamed=mk_or~proof_cons~rule_name[renamer]c~parents:(c::parents)iinletres=renamed@new_defsinUtil.debugf~section3" @[renamed eq %d(@[%a@]) into @[%a@]@]@."(funk->kiL.pp(C.litsc).(i)(CCList.ppC.pp)renamed);Util.debugf~section3" new defs:@[%a@]@."(funk->k(CCList.ppC.pp)new_defs);Someres,`Stop|None->None,`Continue)elseNone,`Continue)Noneletinf_quantifiersc=letproof_cons=Proof.Step.inference~infos:[]~tags:[Proof.Tag.T_live_cnf;Proof.Tag.T_dont_increase_depth]inCCOpt.map_or~default:[](func->[c])@@clausify_quants~proof_conscletclausify_eqc=letrule_name="eq_elim"infold_litsc|>Iter.fold(funacc(lhs,rhs,sign,pos)->leti,_=Ls.Pos.cutposinletlit=(C.litsc).(i)inletproof_cons=Proof.Step.inference~infos:[]~tags:[Proof.Tag.T_live_cnf;Proof.Tag.T_dont_increase_depth]inifnot(L.is_predicate_litlit)&&Type.is_prop(T.tylhs)&&check_eq_cnf_ordering_conditionslhsrhs&&check_size_limitssign(T.Form.equivlhsrhs)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)inifEnv.flex_getk_penalize_eq_cnfthen(List.iter(func->C.inc_penaltycpen_inc)new_cls);new_cls@acc)elseacc)[]|>CCFun.tap(funres->Util.debugf~section3"eq_elim(@[%a@])"(funk->kC.ppc);ifCCList.is_emptyresthen(Util.debugf~section3"=∅"CCFun.id;)else(Util.debugf~section3"=@[%a@]"(funk->k(CCList.ppC.pp)res);))letclausify_impc=letrule_name="imp_elim"infold_litsc|>Iter.fold(funacc(lhs,rhs,sign,pos)->leti,_=Ls.Pos.cutposinletlit=(C.litsc).(i)inletproof_cons=Proof.Step.inference~infos:[]~tags:[Proof.Tag.T_live_cnf;Proof.Tag.T_dont_increase_depth]inif(L.is_predicate_litlit)&&Type.is_prop(T.tylhs)&&L.is_positivoidlitthen(matchlitwith|L.Equation(lhs,rhs,true)whenT.equalT.true_rhs->beginmatchT.viewlhswith|T.AppBuiltin(Imply,[prem;concl])->(mk_or~proof_cons~rule_name[T.Form.not_prem;concl]ci)@acc|_->accend|_->acc)elseacc)[]letcnf_scopec=fold_litsc|>Iter.fold_while(fun_(lhs,rhs,sign,pos)->leti,_=Ls.Pos.cutposinletlit=(C.litsc).(i)inletproof_cons=Proof.Step.simp~infos:[]~tags:[Proof.Tag.T_live_cnf;Proof.Tag.T_dont_increase_depth]inifL.is_predicate_litlit&&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~section3"lazy_cnf_simp(@[%a@])="(funk->kC.ppc);Util.debugf~section3"@[%a@]@."(funk->k(CCList.ppC.pp)res);Util.debugf~section3"proof:@[%a@]@."(funk->k(CCList.pp(Proof.S.pp_tstp))(List.mapC.proofres));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~section3"lazy_cnf_inf(@[%a@])="(funk->kC.ppc);Util.debugf~section3"@[%a@]@."(funk->k(CCList.ppC.pp)res);)elseUtil.debugf~section3"lazy_cnf_simp(@[%a@])=Ø"(funk->kC.ppc);resletsetup()=if!enabledthen(lethandlerfc=fc;Signal.ContinueListeninginSignal.onE.ProofState.PassiveSet.on_add_clause(handler(update_form_counter~action:`Increase));Signal.onE.ProofState.ActiveSet.on_add_clause(handler(update_form_counter~action:`Increase));Signal.onE.ProofState.PassiveSet.on_remove_clause(handler(update_form_counter~action:`Decrease));Signal.onE.ProofState.ActiveSet.on_remove_clause(handler(update_form_counter~action:`Decrease));(* Env.Ctx.lost_completeness (); *)beginmatchEnv.flex_getk_lazy_cnf_kindwith|`Inf|`Ignore->Env.add_unary_inf"lazy_cnf"lazy_clausify_inf;if(Env.flex_getk_simplify_quant)then(Env.add_basic_simplifyreduce_quantifiers;)|`Simp->Env.add_unary_inf"elim eq"clausify_eq;ifnot(Env.flex_getk_clausify_implications)then(Env.add_unary_inf"inf_imp"clausify_imp);ifEnv.flex_getk_inf_quantthen(Env.add_unary_inf"inf_quant"inf_quantifiers;);Env.add_multi_simpl_rule~priority:5lazy_clausify_simpl;ifEnv.flex_getk_lazy_cnf_eagerthen(Env.add_cheap_multi_simpl_rulelazy_clausify_simpl;)end;(* ** IMPORTANT **
Due to correctly set priorioty, renaming will run before simplification *)ifEnv.flex_getk_renaming_threshold>0then(Env.add_multi_simpl_rule~priority:4rename_subformulas;ifEnv.flex_getk_lazy_cnf_eagerthen(Env.add_cheap_multi_simpl_rulerename_subformulas;));ifEnv.flex_getk_scoping!=`Offthen(Env.add_multi_simpl_rule~priority:3cnf_scope;))endlet_lazy_cnf_kind=ref`Simplet_renaming_threshold=ref8let_rename_eq=reftruelet_enum_bool_funs=reffalselet_replace_bool_fun_quant=reffalselet_scoping=ref`Offlet_skolem_mode=ref`SkolemRecyclelet_pa_renaming=reftruelet_only_eligible=reffalselet_clausify_eq_pen=reffalselet_clausify_eq_max_noninterpreted=reftruelet_clausify_impls=reftruelet_simp_limit=ref(-1)let_simp_quant=reffalselet_inf_quant=reffalseletextension=letregisterenv=letmoduleE=(valenv:Env.S)inletmoduleET=Make(E)inE.flex_addk_lazy_cnf_kind!_lazy_cnf_kind;E.flex_addk_lazy_cnf_eager!_eager_lcnf;E.flex_addk_enum_bool_funs!_enum_bool_funs;E.flex_addk_replace_bool_fun_quants!_replace_bool_fun_quant;E.flex_addk_renaming_threshold!_renaming_threshold;E.flex_addk_rename_eq!_rename_eq;E.flex_addk_scoping!_scoping;E.flex_addk_skolem_mode!_skolem_mode;E.flex_addk_pa_renaming!_pa_renaming;E.flex_addk_only_eligible!_only_eligible;E.flex_addk_penalize_eq_cnf!_clausify_eq_pen;E.flex_addk_clausify_eq_max_nonint!_clausify_eq_max_noninterpreted;E.flex_addk_simp_limit!_simp_limit;E.flex_addk_clausify_implications!_clausify_impls;E.flex_addk_simplify_quant!_simp_quant;E.flex_addk_inf_quant!_inf_quant;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-eager",Arg.Bool((:=)_eager_lcnf)," apply the rule to every newly created clause";"--lazy-cnf-only-eligible-lits",Arg.Bool((:=)_only_eligible)," apply lazy clausification only on eligible literals";"--lazy-cnf-clausify-max-eq",Arg.Bool((:=)_clausify_eq_max_noninterpreted)," enable/disable clausification of an EQ literal if max side is non-interpreted ";"--lazy-cnf-clausify-implications",Arg.Bool((:=)_clausify_impls)," apply simplifying clausification to implications";"--lazy-cnf-simp-depth-limit",Arg.Int((:=)_simp_limit)," apply simplifying clausification only to formulas that would yield less than N"^" clauses; negative value is interpreted as infinity";"--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";"--polarity-aware-renaming",Arg.Bool(funv->_pa_renaming:=v)," enable/disable polarity aware renaming (introducing clause with only one definition polarity)";"--lazy-cnf-skolem-mode",Arg.Symbol(["skolem-recycle";"skolem-fresh";"choice"],(funstr->matchstrwith|"skolem-recycle"->_skolem_mode:=`SkolemRecycle|"skolem-fresh"->_skolem_mode:=`SkolemAlwaysFresh|"choice"->_skolem_mode:=`Choice|_->assertfalse))," use lazy cnf as either simplification or inference";"--lazy-cnf-kind",Arg.Symbol(["inf";"simp";"ignore"],(funstr->matchstrwith|"inf"->_lazy_cnf_kind:=`Inf|"simp"->_lazy_cnf_kind:=`Simp|"ignore"->_lazy_cnf_kind:=`Ignore|_->assertfalse))," use lazy cnf as either simplification, inference, or let calculus clausify";"--lazy-cnf-rename-eq",Arg.Bool((:=)_rename_eq)," turn on/of renaming of boolean equalities";"--lazy-cnf-simplify-quant",Arg.Bool((:=)_simp_quant)," when non-simplifying clausification is used, clausify quantifiers in a simplifying manner";"--lazy-cnf-inf-quant",Arg.Bool((:=)_inf_quant)," when simplifying clausification is used, clausify quantifiers in a non-simplifying manner";"--enum-bool-funs",Arg.Bool((:=)_enum_bool_funs)," enumerate all functions over Boolean domain (up to the order of the problem)";"--replace-bool-quant-fun",Arg.Bool((:=)_replace_bool_fun_quant)," replace Boolean fun quantifier with all possible values";"--lazy-cnf-clausify-eq-penalty",Arg.Bool((:=)_clausify_eq_pen)," turn on/of penalizing clausification of equivalences"];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