1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909(* This file is free software, part of Zipperposition. See file "license" for more details. *)(** {1 boolean subterms} *)openLogtkopenLibzipperpositionmoduleBV=CCBVmoduleT=TermmoduleLits=LiteralsmoduleIntSet=Set.Make(CCInt)moduleIntMap=Util.Int_mapletsection=Util.Section.make~parent:Const.section"ho"letstat_eq_res=Util.mk_stat"ho.eq_res.steps"letstat_eq_res_syntactic=Util.mk_stat"ho.eq_res_syntactic.steps"letstat_ext_neg_lit=Util.mk_stat"ho.extensionality-.steps"letstat_ext_pos=Util.mk_stat"ho.extensionality+.steps"letstat_beta=Util.mk_stat"ho.beta_reduce.steps"letstat_eta_normalize=Util.mk_stat"ho.eta_normalize.steps"letstat_prim_enum=Util.mk_stat"ho.prim_enum.steps"letstat_elim_pred=Util.mk_stat"ho.elim_pred.steps"letstat_ho_unif=Util.mk_stat"ho.unif.calls"letstat_ho_unif_steps=Util.mk_stat"ho.unif.steps"letstat_neg_ext=Util.mk_stat"ho.neg_ext_success"letprof_eq_res=ZProf.make"ho.eq_res"letprof_eq_res_syn=ZProf.make"ho.eq_res_syntactic"letprof_ho_unif=ZProf.make"ho.unif"letk_ext_pos=Flex_state.create_key()letk_ext_pos_all_lits=Flex_state.create_key()letk_ext_axiom=Flex_state.create_key()letk_choice_axiom=Flex_state.create_key()letk_elim_pred_var=Flex_state.create_key()letk_ext_neg_lit=Flex_state.create_key()letk_neg_ext=Flex_state.create_key()letk_neg_ext_as_simpl=Flex_state.create_key()letk_ext_axiom_penalty=Flex_state.create_key()letk_instantiate_choice_ax=Flex_state.create_key()letk_elim_leibniz_eq=Flex_state.create_key()letk_prune_arg_fun=Flex_state.create_key()letk_prim_enum_terms=Flex_state.create_key()letk_simple_projection=Flex_state.create_key()letk_simple_projection_md=Flex_state.create_key()letk_check_lambda_free=Flex_state.create_key()letk_purify_applied_vars=Flex_state.create_key()letk_eta=Flex_state.create_key()letk_diff_const=Flex_state.create_key()letk_use_diff_for_neg_ext=Flex_state.create_key()letk_generalize_choice_trigger=Flex_state.create_key()letk_prim_enum_simpl=Flex_state.create_key()letk_prim_enum_early_bird=Flex_state.create_key()letk_resolve_flex_flex=Flex_state.create_key()typeprune_kind=[`NoPrune|`OldPrune|`PruneAllCovers|`PruneMaxCover]moduletypeS=sigmoduleEnv:Env.SmoduleC:moduletypeofEnv.C(** {5 Registration} *)valsetup:unit->unit(** Register rules in the environment *)valprim_enum_tf:Env.C.t->Env.C.tlistendletk_some_ho:boolFlex_state.key=Flex_state.create_key()letk_enabled:boolFlex_state.key=Flex_state.create_key()letk_enable_def_unfold:boolFlex_state.key=Flex_state.create_key()letk_enable_ho_unif:boolFlex_state.key=Flex_state.create_key()letk_ho_prim_mode:[`Combinators|`And|`Or|`Neg|`Quants|`Eq|`TF|`Full|`Pragmatic|`Simple|`None]Flex_state.key=Flex_state.create_key()letk_ho_prim_max_penalty:intFlex_state.key=Flex_state.create_key()letk_ground_app_vars:[`Off|`Fresh|`All]Flex_state.key=Flex_state.create_key()moduleMake(E:Env.S):SwithmoduleEnv=E=structmoduleEnv=EmoduleC=Env.CmoduleCtx=Env.CtxmoduleCombs=Combinators.Make(E)(* index for ext-neg, to ensure α-equivalent negative equations have the same skolems *)moduleFV_ext_neg_lit=FV_tree.Make(structtypet=Literal.t*T.tlist(* lit -> skolems *)letcompare=CCOrd.(pairLiteral.compare(listT.compare))letto_lits(l,_)=Iter.return(Literal.Conv.to_forml)letlabels_=Util.Int_set.emptyend)letidx_ext_neg_lit_:FV_ext_neg_lit.tref=ref(FV_ext_neg_lit.empty())(* retrieve skolems for this literal, if any *)letfind_skolems_(lit:Literal.t):T.tlistoption=FV_ext_neg_lit.retrieve_alpha_equiv_c!idx_ext_neg_lit_(lit,[])|>Iter.find_map(fun(lit',skolems)->letsubst=Literal.variant(lit',0)(lit,1)|>Iter.headinbeginmatchsubstwith|Some(subst,_)->letskolems=List.map(funt->Subst.FO.applySubst.Renaming.nonesubst(t,0))skolemsinSomeskolems|None->Noneend)letremove_ff_constraintsc=letmoduleVS=Term.VarSetin(* assumes literal is negative flex-flex lit *)letextract_hd_vars=function|Literal.Equation(lhs,rhs,false)->VS.of_list[T.as_var_exn(T.head_termlhs);T.as_var_exn(T.head_termrhs)]|_->assertfalseinletis_neg_ff=function|Literal.Equation(lhs,rhs,false)->T.is_var(T.head_termlhs)&&T.is_var(T.head_termrhs)|_->falsein(* variable is blocked if it is not flex-flex or if it appears as variable head
in the literal where blocked occurrs as well *)letblocked_vars=CCArray.filter(funl->not@@is_neg_ffl)(C.litsc)|>Literals.vars|>VS.of_listin(* ad-hoc union find with two equivalence classes -- shares variables
with blocked_vars or not -- used to compute whether var is blocked or not*)letvars_to_remove,_=CCArray.fold(fun((allowed,bl)asacc)lit->matchlitwith|Literal.Equation(lhs,rhs,false)whenis_neg_fflit->letl_var,r_var=CCPair.map_same(funt->T.as_var_exn(T.head_termt))(lhs,rhs)inifnot(VS.meml_varbl)&¬(VS.memr_varbl)then((VS.add_listallowed[l_var;r_var]),bl)else(ifVS.meml_varallowed||VS.memr_varallowedthen(VS.empty,VS.add_list(VS.unionallowedbl)[l_var;r_var])else(allowed,VS.add_listbl[l_var;r_var]))|_->acc)(VS.empty,blocked_vars)(C.litsc)inifVS.is_emptyvars_to_removethen(SimplM.return_samec)else(letnew_lits=CCArray.to_list(C.litsc)|>CCList.filter_map(funlit->ifis_neg_fflitthen(letc_vars=extract_hd_varslitinifVS.subsetc_varsvars_to_removethenNoneelseSomelit)elseSomelit)inletproof=Proof.Step.simp~tags:[Proof.Tag.T_ho]~rule:(Proof.Rule.mk"remove_ff_constraints")[C.proof_parentc]inletcl=C.create~penalty:(C.penaltyc)~trail:(C.trailc)new_litsproofinSimplM.return_newcl)letrecdeclare_skolems=function|[]->()|(sym,id)::rest->Ctx.declaresymid;declare_skolemsrest(* negative extensionality rule:
[f != g] where [f : a -> b] becomes [f k != g k] for a fresh parameter [k] *)letext_neg_lit(lit:Literal.t):_option=matchlitwith|Literal.Equation(f,g,false)whenType.is_fun(T.tyf)&¬(T.is_varf)&¬(T.is_varg)&¬(T.equalfg)->letn_ty_params,ty_args,_=Type.open_poly_fun(T.tyf)inassert(n_ty_params=0);letparams=matchfind_skolems_litwith|Somel->l|None->(* create new skolems, parametrized by free variables *)letvars=Literal.varslitinletskolems=ref[]inletl=List.map(funty->letsk,res=T.mk_fresh_skolemvarstyinskolems:=sk::!skolems;res)ty_argsin(* save list *)declare_skolems!skolems;idx_ext_neg_lit_:=FV_ext_neg_lit.add!idx_ext_neg_lit_(lit,l);linletnew_lit=Literal.mk_neq(T.appfparams)(T.appgparams)inUtil.incr_statstat_ext_neg_lit;Util.debugf~section4"(@[ho_ext_neg_lit@ :old `%a`@ :new `%a`@])"(funk->kLiteral.pplitLiteral.ppnew_lit);Some(new_lit,[],[Proof.Tag.T_ho;Proof.Tag.T_ext])|_->None(* positive extensionality `m x = n x --> m = n` *)letext_pos?(only_unit=true)(c:C.t):C.tlist=(* CCFormat.printf "EP: %b\n" only_unit; *)letis_eligible=C.Eligible.alwaysinifnotonly_unit||C.litsc|>CCArray.length=1thenC.litsc|>CCArray.mapi(funil->letl=Literal.map(funt->Lambda.eta_reduce~full:truet)linmatchlwith|Literal.Equation(t1,t2,true)whenis_eligibleil->letf1,l1=T.as_appt1inletf2,l2=T.as_appt2inbeginmatchList.revl1,List.revl2with|last1::l1,last2::l2->beginmatchT.viewlast1,T.viewlast2with|T.Varx,T.VarywhenHVar.equalType.equalxy&¬(Type.is_tType(HVar.tyx))&&Iter.of_list[Iter.doubletonf1f2;Iter.of_listl1;Iter.of_listl2]|>Iter.flatten|>Iter.flat_mapT.Seq.vars|>Iter.for_all(funv'->not(HVar.equalType.equalv'x))->(* it works! *)letnew_lit=Literal.mk_eq(T.appf1(List.revl1))(T.appf2(List.revl2))inletnew_lits=C.litsc|>CCArray.to_list|>List.mapi(funjl->ifi=jthennew_litelsel)inletproof=Proof.Step.inference[C.proof_parentc]~rule:(Proof.Rule.mk"ho_ext_pos")~tags:[Proof.Tag.T_ho;Proof.Tag.T_ext]inletnew_c=C.createnew_litsproof~penalty:(C.penaltyc)~trail:(C.trailc)in(* Format.printf "@[EP: @[%a@] => @[%a@]@].\n" C.pp c C.pp new_c; *)(* Format.force_newline (); *)Util.incr_statstat_ext_pos;Util.debugf~section4"(@[ext_pos@ :clause %a@ :yields %a@])"(funk->kC.ppcC.ppnew_c);Somenew_c|_,_->Noneend|_->Noneend|_->None)|>CCArray.filter_map(funx->x)|>CCArray.to_listelse[]letext_pos_general?(all_lits=false)(c:C.t):C.tlist=leteligible=ifall_litsthenC.Eligible.alwayselseC.Eligible.paramcin(* Remove recursively variables at the end of the literal t = s if possible.
e.g. ext_pos_lit (f X Y) (g X Y) other_lits = [f X = g X, f = g]
if X and Y do not appear in other_lits *)letrecext_pos_littsother_lits=letf,tt=T.as_apptinletg,ss=T.as_appsinbeginmatchList.revtt,List.revsswith|last_t::tl_rev_t,last_s::tl_rev_s->ifT.equallast_tlast_s&¬(T.is_typelast_t)thenmatchT.as_varlast_twith|Somev->ifnot(T.var_occurs~var:vf)&¬(T.var_occurs~var:vg)&¬(List.exists(T.var_occurs~var:v)tl_rev_t)&¬(List.exists(T.var_occurs~var:v)tl_rev_s)&¬(List.exists(Literal.var_occursv)other_lits)then(letbutlast=(funl->CCList.take(List.lengthl-1)l)inlett'=T.appf(butlasttt)inlets'=T.appg(butlastss)inLiteral.mk_eqt's'::ext_pos_litt's'other_lits)else[]|None->[]else[]|_->[]endinletnew_clauses=(* iterate over all literals eligible for paramodulation *)C.litsc|>Iter.of_array|>Util.seq_zipi|>Iter.filter(fun(idx,lit)->eligibleidxlit)|>Iter.flat_map_l(fun(lit_idx,lit)->letlit=Literal.map(funt->Lambda.eta_reducet)litinmatchlitwith|Literal.Equation(t,s,true)->ext_pos_litts(CCArray.except_idx(C.litsc)lit_idx)|>Iter.of_list|>Iter.flat_map_l(funnew_lit->(* create a clause with new_lit instead of lit *)letnew_lits=new_lit::CCArray.except_idx(C.litsc)lit_idxinletproof=Proof.Step.inference[C.proof_parentc]~rule:(Proof.Rule.mk"ho_ext_pos_general")~tags:[Proof.Tag.T_ho;Proof.Tag.T_ext]inletnew_c=C.createnew_litsproof~penalty:(C.penaltyc)~trail:(C.trailc)in[new_c])|>Iter.to_list|_->[])|>Iter.to_rev_listinifnew_clauses<>[]then(Util.debugf~section4"(@[ext-pos-general-eq@ :clause %a@ :yields (@[<hv>%a@])@])"(funk->kC.ppc(Util.pp_list~sep:" "C.pp)new_clauses););new_clausesletneg_ext(c:C.t):C.tlist=letdiff_const=Env.flex_getk_diff_constinletrecapp_diff_exhaustivelyst=function|alpha::beta::[]->letdiff_s_t=T.appdiff_const[T.of_tyalpha;T.of_tybeta;s;t]inT.apps[diff_s_t],T.appt[diff_s_t]|alpha::((beta::rest)asxs)->assert(not@@CCList.is_emptyrest);letrest',ret=CCList.take_drop(List.lengthrest-1)restinassert(List.lengthret=1);letnew_beta=Type.arrow(beta::rest')(List.hdret)inletdiff_s_t=T.appdiff_const[T.of_tyalpha;T.of_tynew_beta;s;t]inapp_diff_exhaustively(T.apps[diff_s_t])(T.appt[diff_s_t])xs|_->invalid_arg"argument must be a function type"inletis_eligible=C.Eligible.rescinC.litsc|>CCArray.mapi(funil->matchlwith|Literal.Equation(lhs,rhs,false)whenis_eligibleil&&Type.is_fun@@T.tylhs->letarg_types,ret_ty=Type.open_fun(T.tylhs)inletfree_vars=Literal.varslinletskolem_decls=ref[]inletnew_lits=CCList.map(fun(j,x)->ifi!=jthenxelse(letlhs,rhs=ifEnv.flex_getk_use_diff_for_neg_extthen(app_diff_exhaustivelylhsrhs(arg_types@[ret_ty]))else(letskolems=List.map(funty->letsk,res=T.mk_fresh_skolemfree_varstyinskolem_decls:=sk::!skolem_decls;res)arg_typesinT.applhsskolems,T.apprhsskolems)inLiteral.mk_neqlhsrhs))(C.litsc|>Array.mapi(funjx->(j,x))|>Array.to_list)indeclare_skolems!skolem_decls;letproof=Proof.Step.inference[C.proof_parentc]~rule:(Proof.Rule.mk"neg_ext")~tags:[Proof.Tag.T_ho;Proof.Tag.T_ext;Proof.Tag.T_dont_increase_depth]inletnew_c=C.createnew_litsproof~penalty:(C.penaltyc)~trail:(C.trailc)inUtil.debugf1~section"NegExt: @[%a@] => @[%a@].\n"(funk->kC.ppcC.ppnew_c);Util.incr_statstat_neg_ext;Somenew_c|_->None)|>CCArray.filter_map(funx->x)|>CCArray.to_listletneg_ext_simpl(c:C.t):C.tSimplM.t=letis_eligible=C.Eligible.rescinletapplied_neg_ext=reffalseinletnew_lits=C.litsc|>CCArray.mapi(funil->matchlwith|Literal.Equation(lhs,rhs,false)whenis_eligibleil&&Type.is_fun@@T.tylhs->letarg_types=Type.expected_args@@T.tylhsinletfree_vars=Literal.varsl|>T.VarSet.of_list|>T.VarSet.to_listinletskolem_decls=ref[]inletskolems=List.map(funty->letsk,res=T.mk_fresh_skolemfree_varstyinskolem_decls:=sk::!skolem_decls;res)arg_typesinapplied_neg_ext:=true;declare_skolems!skolem_decls;Literal.mk_neq(T.applhsskolems)(T.apprhsskolems)|_->l)inifnot!applied_neg_extthenSimplM.return_samecelse(letproof=Proof.Step.simp[C.proof_parentc]~rule:(Proof.Rule.mk"neg_ext_simpl")~tags:[Proof.Tag.T_ho;Proof.Tag.T_ext]inletc'=C.create_a~trail:(C.trailc)~penalty:(C.penaltyc)new_litsproofin(* CCFormat.printf "[NE_simpl]: @[%a@] => @[%a@].\n" C.pp c C.pp c'; *)SimplM.return_newc')(* try to eliminate a predicate variable in one fell swoop *)letelim_pred_variable?(proof_constructor=Proof.Step.inference)(c:C.t):C.tlist=(* find unshielded predicate vars *)letfind_vars():_HVar.tIter.t=Literals.vars(C.litsc)|>CCList.to_iter|>Iter.filter(funv->(Type.is_prop@@Type.returns@@HVar.tyv)&¬(Literals.is_shieldedv(C.litsc)))(* find all constraints on [v], also returns the remaining literals.
returns None if some constraints contains [v] itself. *)andgather_litsv=tryArray.fold_left(fun(others,set,pos_lits)lit->beginmatchlitwith|Literal.Equation(lhs,rhs,sign)whenT.equalrhsT.true_->letf,args=T.as_applhsinbeginmatchT.viewfwith|T.VarqwhenHVar.equalType.equalvq->(* found an occurrence *)ifList.exists(T.var_occurs~var:v)argsthen(raiseExit;(* [P … t[v] …] is out of scope *));others,(args,sign)::set,(ifsignthen[lit]else[])@pos_lits|_->lit::others,set,pos_litsend|_->lit::others,set,pos_litsend)([],[],[])(C.litsc)|>CCOpt.returnwithExit->Nonein(* try to eliminate [v], if it doesn't occur in its own arguments *)lettry_elim_varv:_option=(* gather constraints on [v] *)beginmatchgather_litsvwith|None|Some(_,[],_)->None|Some(other_lits,constr_l,pos_lits)->(* gather positive/negative args *)letpos_args,neg_args=CCList.partition_map(fun(args,sign)->ifsignthen`Leftargselse`Rightargs)constr_lin(* build substitution used for this inference *)letsubst=letsome_tup=matchpos_args,neg_argswith|tup::_,_|_,tup::_->tup|[],[]->assertfalseinletoffset=C.Seq.varsc|>T.Seq.max_var|>succinletvars=List.mapi(funit->HVar.make~ty:(T.tyt)(i+offset))some_tupinletvars_t=List.mapT.varvarsinletbody=neg_args|>List.map(funtup->assert(List.lengthtup=List.lengthvars);List.map2T.Form.eqvars_ttup|>T.Form.and_l)|>T.Form.or_linUtil.debugf~section1"(@[elim-pred-with@ (@[@<1>λ @[%a@].@ %a@])@])"(funk->k(Util.pp_list~sep:" "Type.pp_typed_var)varsT.ppbody);Util.incr_statstat_elim_pred;lett=T.fun_of_fvarsvarsbodyinSubst.FO.of_list[((v:>InnerTerm.tHVar.t),0),(t,0)]in(* build new clause *)letrenaming=Subst.Renaming.create()inletnew_lits=letl1=Literal.apply_subst_listrenamingsubst(other_lits,0)inletl2=Literal.apply_subst_listrenamingsubst(pos_lits,0)inl1@l2inletproof=proof_constructor~rule:(Proof.Rule.mk"ho_elim_pred")~tags:[Proof.Tag.T_ho][C.proof_parent_substrenaming(c,0)subst]inletnew_c=C.createnew_litsproof~penalty:(C.penaltyc)~trail:(C.trailc)inUtil.debugf~section3"(@[<2>elim_pred_var %a@ :clause %a@ :yields %a@])"(funk->kT.pp_varvC.ppcC.ppnew_c);Somenew_cendinbeginfind_vars()|>Iter.filter_maptry_elim_var|>Iter.to_rev_listend(* maximum penalty on clauses to perform Primitive Enum on *)letmax_penalty_prim_=Env.flex_getk_ho_prim_max_penalty(* rule for primitive enumeration of predicates [P t1…tn]
(using ¬ and ∧ and =) *)letprim_enum_?(proof_constructor=Proof.Step.inference)~(mode)(c:C.t):C.tlist=(* set of variables to refine (only those occurring in "interesting" lits) *)letvars=Literals.fold_eqn~both:false~ord:(Ctx.ord())~eligible:(C.Eligible.always)(C.litsc)|>Iter.flat_map_l(fun(l,r,_,_)->letextract_vart=let_,body=T.open_funtinmatchT.viewbodywith|T.Varx->Somex|T.App(hd,_)whenT.is_varhd->Some(T.as_var_exnhd)|_->NoneinCCOpt.to_list(extract_varl)@CCOpt.to_list(extract_varr))|>Iter.filter(funv->Type.returns_prop@@HVar.tyv)|>T.VarSet.of_iter(* unique *)inifnot(T.VarSet.is_emptyvars)then(Util.debugf~section1"(@[<hv2>ho.refine@ :clause %a@ :terms {@[%a@]}@])"(funk->kC.ppc(Util.pp_iterT.pp_var)(T.VarSet.to_itervars)););letsc_c=0inletoffset=C.Seq.varsc|>T.Seq.max_var|>succinbeginvars|>T.VarSet.to_iter|>Iter.flat_map_l(funv->HO_unif.enum_prop~enum_cache:(Env.flex_getk_prim_enum_terms)~signature:(Ctx.signature())~mode~offset(v,sc_c))|>Iter.map(fun(subst,penalty)->letpenalty=ifEnv.flex_getk_prim_enum_simplthen0elsepenaltyinletrenaming=Subst.Renaming.create()inletlits=Literals.apply_substrenamingsubst(C.litsc,sc_c)inletproof=Proof.Step.inference~rule:(Proof.Rule.mk"ho.refine")~tags:[Proof.Tag.T_ho][C.proof_parent_substrenaming(c,sc_c)subst]inletnew_c=C.create_alitsproof~penalty:(C.penaltyc+penalty)~trail:(C.trailc)inUtil.debugf~section1"(@[<hv2>ho.refine@ :from %a@ :subst %a@ :yields %a@])"(funk->kC.ppcSubst.ppsubstC.ppnew_c);Util.incr_statstat_prim_enum;new_c)|>Iter.to_rev_listendletprim_enum~(mode)c=ifC.proof_depthc<max_penalty_prim_thenprim_enum_~modecelse[](* prim_enum_ ~mode c *)letprim_enum_tfc=prim_enum_~mode:`TFcletchoice_ops=refTerm.Map.emptyletnew_choice_counter=ref0letinsantiate_choice?(proof_constructor=Proof.Step.inference)?(inst_vars=true)?(choice_ops=choice_ops)c=letmax_var=ref((C.Seq.varsc|>Iter.mapHVar.id|>Iter.max|>CCOpt.get_or~default:0)+1)inletis_choice_subtermt=matchT.viewtwith|T.App(hd,[arg])whenT.is_varhd||Term.Map.memhd!choice_ops->letty=T.tyarginType.is_funty&&List.length(Type.expected_argsty)=1&&Type.equal(Term.tyt)(List.hd(Type.expected_argsty))&&Type.returns_propty&&T.DB.is_closedt|_->falseinletneg_triggert=assert(T.DB.is_closedt);letarg_ty=List.hd(Type.expected_args(T.tyt))inletnegated=T.Form.not_(Lambda.whnf(T.appt[T.bvar~ty:arg_ty0]))inletres=T.fun_arg_tynegatedinassert(T.DB.is_closedres);resinletgeneralize_triggert=assert(T.DB.is_closedt);letarg_ty=List.hd(Type.expected_args(T.tyt))inletapplied_to_0=Lambda.whnf(T.appt[T.bvar~ty:arg_ty0])inletty=Type.arrow[Type.prop]Type.propinletfresh_var=T.var@@HVar.fresh_cnt~counter:max_var~ty()inletres=T.fun_arg_ty(T.appfresh_var[applied_to_0])inassert(T.DB.is_closedres);resinletchoice_inst_of_hd~def_clausehdarg=letarg_ty=Term.tyarginletty=List.hd(Type.expected_argsarg_ty)inletx=T.var@@HVar.fresh_cnt~counter:max_var~ty()inletchoice_x=Lambda.whnf(T.apparg[x])inletchoice_arg=Lambda.snf(T.apparg[T.apphd[arg]])inletnew_lits=[Literal.mk_propchoice_xfalse;Literal.mk_propchoice_argtrue]inletarg_str=CCFormat.sprintf"(%a)"T.TPTP.pparginletparents=matchdef_clausewith|Somedef->[C.proof_parentdef;C.proof_parentc]|None->[C.proof_parentc]inletproof=proof_constructor~tags:[Proof.Tag.T_cannot_orphan]~rule:(Proof.Rule.mk("inst_choice"^arg_str))parentsinC.create~penalty:1~trail:Trail.emptynew_litsproofinletnew_choice_opty=letchoice_ty_name="#_choice_"^CCInt.to_string(CCRef.get_then_incrnew_choice_counter)inletnew_ch_id=ID.makechoice_ty_nameinletnew_ch_const=T.constnew_ch_id~tyinCtx.add_signature(Signature.declare(C.Ctx.signature())new_ch_idty);Util.debugf1"new choice for type %a: %a(%a).\n"(funk->kType.pptyT.ppnew_ch_constType.pp(T.tynew_ch_const));choice_ops:=Term.Map.addnew_ch_constNone!choice_ops;new_ch_constin(* def_clause is the clause that defined the symbol hd *)letgenerate_instances~def_clausehdarg=choice_inst_of_hd~def_clausehdarg::choice_inst_of_hd~def_clausehd(neg_triggerarg)::(ifnot@@Env.flex_getk_generalize_choice_triggerthen[]else[choice_inst_of_hd~def_clausehd(generalize_triggerarg)])inletbuild_choice_instt=matchT.viewtwith|T.App(hd,[arg])->ifTerm.is_varhd&&inst_varsthen(lethd_ty=Term.tyhdinletchoice_ops=Term.Map.filter(funt_->Type.equal(Term.tyt)hd_ty)!choice_ops|>Term.Map.to_list|>(funl->ifCCList.is_emptylthen[new_choice_ophd_ty,None]elsel)inCCList.flat_map(fun(hd,def_clause)->generate_instances~def_clausehdarg)choice_ops)else(matchTerm.Map.find_opthd!choice_opswith|Somedef_clause->generate_instances~def_clausehdarg|None->[])|_->assert(false)inC.Seq.termsc|>Iter.flat_map(Term.Seq.subterms~include_builtin:true)|>Iter.filteris_choice_subterm|>Iter.flat_map_lbuild_choice_inst|>Iter.to_list(* Given a clause C, project all its applied variables to base-type arguments
if there is a variable occurrence in which at least one of base-type arguments is
not a bound variable.
Penalty of the resulting clause is penalty of the original clause + penalty_inc *)letsimple_projection~penalty_inc~max_depthc=ifC.proof_depthc>max_depththen[]else(C.Seq.termsc|>Iter.flat_map(Term.Seq.subterms~include_builtin:true~ignore_head:true)|>Iter.fold(funvar_mapsubterm->matchT.viewsubtermwith|T.App(hd,args)whenT.is_varhd&&List.exists(funt->not(Type.is_fun(T.tyt))&¬(T.is_bvart))args->letvar_arg_tys,var_ret_ty=Type.open_fun(T.tyhd)inassert(not(Type.is_funvar_ret_ty));letnew_bindings=CCList.foldi(funaccidxarg->letarg_ty=T.tyarginifType.is_groundarg_ty&&Type.equalarg_tyvar_ret_tythen(letdb=T.bvar~ty:arg_ty(List.lengthvar_arg_tys-1-idx)inletbinding=T.fun_lvar_arg_tysdbinTerm.Set.addbindingacc)elseacc)Term.Set.emptyargsinletold_bindings=Term.Map.get_orhd~default:Term.Set.emptyvar_mapinTerm.Map.addhd(Term.Set.unionold_bindingsnew_bindings)var_map|_->var_map)Term.Map.empty|>(funvar_map->Term.Map.fold(funvarbindingsacc->letvar=Term.as_var_exnvarinTerm.Set.fold(funbindingacc->letsubst=(Subst.FO.bind'Subst.empty(var,0)(binding,0))inletproof=Some(Proof.Step.inference~rule:(Proof.Rule.mk"simp.projection")~tags:[Proof.Tag.T_ho][C.proof_parent_substSubst.Renaming.none(c,0)subst])inletres=C.apply_subst~penalty_inc:(Somepenalty_inc)~proof(c,0)substinres::acc)bindingsacc)var_map[]))letrecognize_choice_opsc=letextract_not_p_xl=matchlwith|Literal.Equation(lhs,rhs,false)whenT.equalT.true_rhs&&T.is_app_varlhs->beginmatchT.viewlhswith|T.App(hd,[var])whenT.is_varvar->Somehd|_->Noneend|_->Noneinletextract_p_choice_ppl=matchlwith|Literal.Equation(lhs,rhs,true)whenT.equalT.true_rhs->beginmatchT.viewlhswith|T.App(hd,[ch_p])whenT.equalhdp->beginmatchT.viewch_pwith|T.App(sym,[var])whenT.is_constsym&&T.equalvarp->Somesym|_->Noneend|_->Noneend|_->NoneinifC.lengthc==2then(letpx=CCArray.find_mapextract_not_p_x(C.litsc)inmatchpxwith|Somep->letp_ch_p=CCArray.find_map(extract_p_choice_pp)(C.litsc)inbeginmatchp_ch_pwith|Somesym->ifnot(Term.Map.memsym!choice_ops)then(choice_ops:=Term.Map.addsym(Somec)!choice_ops;letnew_cls=Env.get_active()|>Iter.flat_map_l(funpas_cl->ifC.idpas_cl=C.idcthen[]else(insantiate_choice~inst_vars:false~choice_ops:(ref(Term.Map.singletonsym(Somec)))pas_cl))|>Iter.mapCombs.maybe_conv_lamsinEnv.add_passivenew_cls);C.mark_redundantc;true|None->falseend|None->false)elsefalseletelim_leibniz_eq_?(proof_constructor=Proof.Step.inference)c=letord=Env.ord()inleteligible=C.Eligible.alwaysinletpos_pred_vars,neg_pred_vars,occurrences=Lits.fold_eqn~both:false~ord~eligible(C.litsc)|>Iter.fold(fun(pos_vs,neg_vs,occ)(lhs,rhs,sign,_)->ifType.is_prop(Term.tylhs)&&Term.is_app_varlhs&&T.equalT.true_rhsthen(letvar_hd=Term.as_var_exn(Term.head_termlhs)inifsignthen(Term.VarSet.addvar_hdpos_vs,neg_vs,Term.Map.addlhstrueocc)else(pos_vs,Term.VarSet.addvar_hdneg_vs,Term.Map.addlhsfalseocc))else(pos_vs,neg_vs,occ))(Term.VarSet.empty,Term.VarSet.empty,Term.Map.empty)inletpos_neg_vars=Term.VarSet.interpos_pred_varsneg_pred_varsinletres=ifTerm.VarSet.is_emptypos_neg_varsthen[]else(CCList.flat_map(fun(t,sign)->lethd,args=T.as_apptinletvar_hd=T.as_var_exnhdinifTerm.VarSet.mem(Term.as_var_exnhd)pos_neg_varsthen(lettyargs,_=Type.open_fun(Term.tyhd)inletn=List.lengthtyargsinCCList.filter_map(fun(i,arg)->ifT.var_occurs~var:var_hdargthenNoneelse(letbody=(ifsignthenT.Form.neqelseT.Form.eq)arg(T.bvar~ty:(T.tyarg)(n-i-1))inletsubs_term=T.fun_ltyargsbodyin(letcached_t=Subst.FO.canonize_all_varssubs_terminE.flex_addk_prim_enum_terms(ref(Term.Set.addcached_t!(Env.flex_getk_prim_enum_terms))));letsubst=Subst.FO.bind'(Subst.empty)(var_hd,0)(subs_term,0)inletrule=Proof.Rule.mk("elim_leibniz_eq_"^(ifsignthen"+"else"-"))inlettags=[Proof.Tag.T_ho]inletproof=Some(proof_constructor~rule~tags[C.proof_parentc])inSome(C.apply_subst~proof(c,0)subst)))(CCList.mapi(funiarg->(i,arg))args))else[])(Term.Map.to_listoccurrences))inresletelim_leibniz_equalityc=ifC.proof_depthc<Env.flex_getk_elim_leibniz_eqthen(elim_leibniz_eq_c)else[]letpp_pairs_out=letopenCCFormatinFormat.fprintfout"(@[<hv>%a@])"(Util.pp_list~sep:" "@@hvbox@@HO_unif.pp_pair)(* perform HO unif on [pairs].
invariant: [C.lits c = pairs @ other_lits] *)letho_unif_real_cpairsother_lits:C.tlist=Util.debugf~section5"(@[ho_unif.try@ :pairs (@[<hv>%a@])@ :other_lits %a@])"(funk->kpp_pairs_pairs(Util.pp_list~sep:" "Literal.pp)other_lits);Util.incr_statstat_ho_unif;letoffset=C.Seq.varsc|>T.Seq.max_var|>succinbeginHO_unif.unif_pairs?fuel:None(pairs,0)~offset|>List.map(fun(new_pairs,us,penalty,renaming)->letsubst=Unif_subst.substusinletc_guard=Literal.of_unif_substrenamingusinletnew_pairs=List.map(fun(env,t,u)->assert(env==[]);Literal.mk_constrainttu)new_pairsandother_lits=Literal.apply_subst_listrenamingsubst(other_lits,0)inletall_lits=c_guard@new_pairs@other_litsinletproof=Proof.Step.inference~rule:(Proof.Rule.mk"ho_unif")~tags:[Proof.Tag.T_ho][C.proof_parent_substrenaming(c,0)subst]inletnew_c=C.createall_litsproof~trail:(C.trailc)~penalty:(C.penaltyc+penalty)inUtil.debugf~section5"(@[ho_unif.step@ :pairs (@[%a@])@ :subst %a@ :yields %a@])"(funk->kpp_pairs_pairsSubst.ppsubstC.ppnew_c);Util.incr_statstat_ho_unif_steps;new_c)end(* HO unification of constraints *)letho_unif(c:C.t):C.tlist=ifC.litsc|>CCArray.existsLiteral.is_ho_constraintthen((* separate constraints from the rest *)letpairs,others=C.litsc|>Array.to_list|>CCList.partition_map(function|Literal.Equation(t,u,false)aslitwhenLiteral.is_ho_constraintlit->`Left([],t,u)|lit->`Rightlit)inassert(pairs<>[]);ZProf.enter_profprof_ho_unif;letr=ho_unif_real_cpairsothersinZProf.exit_profprof_ho_unif;r)else[](* rule for β-reduction *)letbeta_reducet=(* assert (T.DB.is_closed t); *)lett'=Lambda.snftinif(T.equaltt')then(Util.debugf~section50"(@[beta_reduce `%a`@ failed `@])"(funk->kT.ppt);None)else(Util.debugf~section50"(@[beta_reduce `%a`@ :into `%a`@])"(funk->kT.pptT.ppt');Util.incr_statstat_beta;(* assert (T.DB.is_closed t'); *)Somet')leteta_normalize()=matchEnv.flex_getk_etawith|`Reduce->Lambda.eta_reduce~full:true|`Expand->Lambda.eta_expand|`None->(funt->t)(* rule for eta-expansion/reduction *)leteta_normalizet=(* assert (T.DB.is_closed t); *)lett'=eta_normalize()tinif(T.equaltt')then(Util.debugf~section50"(@[eta_normalize `%a`@ failed `@])"(funk->kT.ppt);None)else(Util.debugf~section50"(@[eta_normalize `%a`@ :into `%a`@])"(funk->kT.pptT.ppt');Util.incr_statstat_eta_normalize;(* assert (T.DB.is_closed t'); *)Somet')moduleTVar=structtypet=Type.tHVar.tletequal=HVar.equalType.equallethash=HVar.hashletcompare=HVar.compareType.compareendmoduleVarTermMultiMap=CCMultiMap.Make(TVar)(Term)moduleVTbl=CCHashtbl.Make(TVar)letmk_diff_const()=letdiff_id=ID.make("zf_ext_diff")inID.set_payloaddiff_id(ID.Attr_skolemID.K_normal);(* make the arguments of diff mandatory *)letalpha_var=HVar.make~ty:Type.tType0inletalpha=Type.varalpha_varinletbeta_var=HVar.make~ty:Type.tType1inletbeta=Type.varbeta_varinletalpha_to_beta=Type.arrow[alpha]betainletdiff_type=Type.forall_fvars[alpha_var;beta_var](Type.arrow[alpha_to_beta;alpha_to_beta]alpha)inletdiff=Term.const~ty:diff_typediff_idinEnv.Ctx.declarediff_iddiff_type;Env.flex_addk_diff_constdiffletmk_extensionality_clause()=letdiff=Env.flex_getk_diff_constinletalpha_var=HVar.make~ty:Type.tType0inletalpha=Type.varalpha_varinletbeta_var=HVar.make~ty:Type.tType1inletbeta=Type.varbeta_varinletalpha_to_beta=Type.arrow[alpha]betainletx=Term.var(HVar.make~ty:alpha_to_beta2)inlety=Term.var(HVar.make~ty:alpha_to_beta3)inletx_diff=Term.appx[Term.appdiff[T.of_tyalpha;T.of_tybeta;x;y]]inlety_diff=Term.appy[Term.appdiff[T.of_tyalpha;T.of_tybeta;x;y]]inletlits=[Literal.mk_eqxy;Literal.mk_neqx_diffy_diff]inEnv.C.create~penalty:(Env.flex_getk_ext_axiom_penalty)~trail:Trail.emptylitsProof.Step.trivialletchoice_clause=letchoice_id=ID.make("zf_choice")inletalpha_var=HVar.make~ty:Type.tType0inletalpha=Type.varalpha_varinletalpha_to_prop=Type.arrow[alpha]Type.propinletchoice_type=Type.arrow[alpha_to_prop]alphainletchoice=Term.const~ty:choice_typechoice_idinletp=Term.var(HVar.make~ty:alpha_to_prop1)inletx=Term.var(HVar.make~ty:alpha2)inletpx=Term.appp[x]in(* p x *)letp_choice=Term.appp[Term.appchoice[p]](* p (choice p) *)in(* ~ (p x) | p (choice p) *)letlits=[Literal.mk_proppxfalse;Literal.mk_propp_choicetrue]inEnv.C.create~penalty:1~trail:Trail.emptylitsProof.Step.trivialletearly_bird_prim_enumclvar=assert(T.is_varvar);letoffset=C.Seq.varscl|>T.Seq.max_var|>succinletmode=Env.flex_getk_ho_prim_modeinletsc=0inHO_unif.enum_prop~enum_cache:(Env.flex_getk_prim_enum_terms)~signature:(Ctx.signature())~mode~offset(T.as_var_exnvar,sc)|>CCList.map(fun(subst,p)->letrenaming=Subst.Renaming.create()inletlits=Literals.apply_substrenamingsubst(C.litscl,sc)inletlits=Literals.map(funt->Lambda.eta_reduce@@Lambda.snft)litsinletproof=Proof.Step.inference~rule:(Proof.Rule.mk"ho.refine.early.bird")~tags:[Proof.Tag.T_ho;Proof.Tag.T_cannot_orphan][C.proof_parent_substrenaming(cl,sc)subst]inletres=C.create_alitsproof~penalty:(C.penaltycl+(max(p-1)0))~trail:(C.trailcl)inletres=Combs.maybe_conv_lamsresin(* CCFormat.printf "orig:@[%a@]@.subst:@[%a@]@.res:@[%a@]@." C.pp cl Subst.pp subst C.pp res; *)res)|>CCList.to_iter|>Env.add_passivetypefixed_arg_status=|AlwaysofT.t(* This argument is always the given term in all occurrences *)|Varies(* This argument contains different terms in differen occurrences *)typedupl_arg_status=|AlwaysSameAsofint(* This argument is always the same as some other argument across occurrences (links to the next arg with this property) *)|Unique(* This argument is not always the same as some other argument across occurrences *)(** Removal of fixed/duplicate arguments of variables.
- If within a clause, there exists a variable F that's always applied
to at least i arguments and the ith argument is always the same DB-free term,
we can systematically remove the argument (and repair F's type).
- If within a clause, there exist a variable F, and indices i < j
such that all occurrences of F are applied to at least j arguments and the
ith argument is syntactically same as the jth argument, we can
systematically remove the ith argument (and repair F's type accordingly).
*)letprune_arg_oldc=letstatus:(fixed_arg_status*dupl_arg_status)listVTbl.t=VTbl.create8inC.litsc|>Literals.fold_terms~vars:true~ty_args:false~which:`All~ord:Ordering.none~subterms:true~eligible:(fun__->true)|>Iter.iter(fun(t,_)->lethead,args=T.as_apptinmatchT.as_varheadwith|Somevar->beginmatchVTbl.getstatusvarwith|Somevar_status->(* We have seen this var before *)letupdate_fasfasarg=matchfaswith|Alwaysu->ifT.equaluargthenAlwaysuelseVaries|Varies->Variesinletrecupdate_dasdasarg=matchdaswith|AlwaysSameAsj->begintryifT.equal(List.nthargsj)argthenAlwaysSameAsjelseupdate_das(snd(List.nthvar_statusj))(List.nthargsj)withFailure_->Uniqueend|Unique->Uniquein(* Shorten the lists to have equal lengths. Arguments positions are only interesting if they appear behind every occurrence of a var.*)letminlen=min(List.lengthvar_status)(List.lengthargs)inletargs=CCList.takeminlenargsinletvar_status=CCList.takeminlenvar_statusinVTbl.replacestatusvar(CCList.map(fun((fas,das),arg)->update_fasfasarg,update_dasdasarg)(List.combinevar_statusargs))|None->(* First time to encounter this var *)letreccreate_var_status?(i=0)args:(fixed_arg_status*dupl_arg_status)list=matchargswith|[]->[]|arg::args'->letfas=ifT.DB.is_closedargthenAlwaysargelseVariesin(* Find next identical argument *)letdas=matchCCList.find_idx((Term.equal)arg)args'with|Some(j,_)->AlwaysSameAs(i+j+1)|None->Uniquein(fas,das)::create_var_status~i:(i+1)args'inVTbl.addstatusvar(create_var_statusargs)end|None->();());letsubst=VTbl.to_liststatus|>CCList.filter_map(fun(var,var_status)->assert(not(Type.is_tType(HVar.tyvar)));letty_args,ty_return=Type.open_fun(HVar.tyvar)inletkeep=var_status|>CCList.map(fun(fas,das)->(* Keep argument if this is true: *)fas==Varies&&das==Unique)inifCCList.for_all((=)true)keepthenNoneelse((* Keep argument if var_status list is not long enough (This happens when the argument does not appear for some occurrence of var): *)letkeep=CCList.(appendkeep(replicate(lengthty_args-lengthkeep)true))in(* Create substitution: *)letty_args'=ty_args|>CCList.combinekeep|>CCList.filterfst|>CCList.mapsndinletvar'=HVar.castvar~ty:(Type.arrowty_args'ty_return)inletbvars=CCList.combinekeepty_args|>List.mapi(funi(k,ty)->k,T.bvar~ty(List.lengthty_args-i-1))|>CCList.filterfst|>CCList.mapsndinletreplacement=T.fun_lty_args(T.app(T.varvar')bvars)inSome((var,0),(replacement,1))))|>Subst.FO.of_list'inifSubst.is_emptysubstthenSimplM.return_samecelse(letrenaming=Subst.Renaming.noneinletnew_lits=Lits.apply_substrenamingsubst(C.litsc,0)inletproof=Proof.Step.simp~rule:(Proof.Rule.mk"prune_arg")~tags:[Proof.Tag.T_ho][C.proof_parent_substrenaming(c,0)subst]inletc'=C.create_a~trail:(C.trailc)~penalty:(C.penaltyc)new_litsproofinUtil.debugf~section3"@[<>@[%a@]@ @[<2>prune_arg into@ @[%a@]@]@ with @[%a@]@]"(funk->kC.ppcC.ppc'Subst.ppsubst);SimplM.return_newc')(* TODO: Simplified flag like in first-order? Profiler?*)letprune_arg~all_coversc=letget_covers?(current_sets=[])headargs=letty_args,_=Type.open_fun(T.tyhead)inletmissing=CCList.replicate(List.lengthty_args-List.lengthargs)Noneinletargs_opt=List.mapi(funia_i->assert(Term.DB.is_closeda_i);assert(CCList.is_emptycurrent_sets||List.lengthcurrent_sets=(List.lengthargs+List.lengthmissing));ifCCList.is_emptycurrent_sets||not(Term.Set.is_empty(List.nthcurrent_setsi))then(Some(List.mapi(funja_j->ifi=jthenNoneelseSomea_j)args))elseNone(* ignoring onself *))args@missinginletres=List.mapi(funiarg_opt->ifi<List.lengthargsthen(lett=List.nthargsiinbeginmatcharg_optwith|Somearg_l->letres_l=ifall_coversthenT.cover_with_termstarg_lelse[t;T.max_covertarg_l]inT.Set.of_listres_l|None->Term.Set.emptyend)elseTerm.Set.empty)args_optinresinletstatus=VTbl.create8inletfree_vars=Literals.vars(C.litsc)|>T.VarSet.of_listinC.litsc|>Literals.map(funt->Combs.expandt)(* to make sure that DB indices are everywhere the same *)|>Literals.fold_terms~vars:true~ty_args:false~which:`All~ord:Ordering.none~subterms:true~eligible:(fun__->true)|>Iter.iter(fun(t,_)->lethead,_=T.as_apptinmatchT.as_varheadwith|SomevarwhenT.VarSet.memvarfree_vars->beginmatchVTbl.getstatusvarwith|Some(current_sets,created_sk)->lett,new_sk=T.DB.skolemize_loosely_boundtinletnew_skolems=T.IntMap.bindingsnew_sk|>List.mapsnd|>Term.Set.of_listinletcovers=get_covers~current_setshead(T.argst)inassert(List.lengthcurrent_sets=List.lengthcovers);letpaired=CCList.combinecurrent_setscoversinletres=List.map(fun(o,n)->Term.Set.interon)pairedinVTbl.replacestatusvar(res,Term.Set.unioncreated_sknew_skolems);|None->lett',created_sk=T.DB.skolemize_loosely_boundtinletcreated_sk=T.IntMap.bindingscreated_sk|>List.mapsnd|>Term.Set.of_listinVTbl.addstatusvar(get_covershead(T.argst'),created_sk);end|_->();());letsubst=VTbl.to_liststatus|>CCList.filter_map(fun(var,(args,skolems))->letremoved=refIntSet.emptyinletn=List.lengthargsinletkeep=List.mapi(funiarg_set->letarg_l=Term.Set.to_listarg_setinletarg_l=List.filter(funt->List.for_all(funidx->not@@IntSet.memidx!removed)(T.DB.unboundt)&&T.Seq.subtermst|>Iter.for_all(funsubt->not@@Term.Set.memsubtskolems))arg_linletres=CCList.is_emptyarg_linifnotresthenremoved:=IntSet.add(n-i-1)!removed;res)argsinifCCList.for_all((=)true)keepthenNoneelse(letty_args,ty_return=Type.open_fun(HVar.tyvar)inletty_args'=CCList.combinekeepty_args|>CCList.filterfst|>CCList.mapsndinletvar'=HVar.castvar~ty:(Type.arrowty_args'ty_return)inletbvars=CCList.combinekeepty_args|>List.mapi(funi(k,ty)->k,T.bvar~ty(List.lengthty_args-i-1))|>CCList.filterfst|>CCList.mapsndinletreplacement=T.fun_lty_args(T.app(T.varvar')bvars)inSome((var,0),(replacement,1))))|>Subst.FO.of_list'inifSubst.is_emptysubstthenSimplM.return_samecelse(letrenaming=Subst.Renaming.noneinletnew_lits=Lits.apply_substrenamingsubst(C.litsc,0)inletproof=Proof.Step.simp~rule:(Proof.Rule.mk"prune_arg_fun")~tags:[Proof.Tag.T_ho][C.proof_parent_substrenaming(c,0)subst]inletc'=C.create_a~trail:(C.trailc)~penalty:(C.penaltyc)new_litsproofinUtil.debugf~section3"@[<>@[%a@]@ @[<2>prune_arg_fun into@ @[%a@]@]@ with @[%a@]@]"(funk->kC.ppcC.ppc'Subst.ppsubst);SimplM.return_newc')(* TODO: Simplified flag like in first-order? Profiler?*)letgroundings=Type.Tbl.create32letground_app_vars~modec=assert(mode!=`Off);letapp_var=C.Seq.varsc|>Iter.filter(funv->Type.is_fun(HVar.tyv)&&Type.is_ground(HVar.tyv))|>Iter.headinletget_groundingsvar=letintroduce_new_constty=let(f_id,f_ty),f=Term.mk_fresh_skolem[]tyinC.Ctx.add_signature(Signature.declare(C.Ctx.signature())f_idf_ty);finletty=T.tyvarinmatchmodewith|`Off->[]|`Fresh->[Type.Tbl.get_or_addgroundings~f:introduce_new_const~k:ty]|`All->letids=Signature.find_by_type(C.Ctx.signature())tyinifnot(ID.Set.is_emptyids)thenList.map(Term.const~ty)(ID.Set.to_listids)else[Type.Tbl.get_or_addgroundings~f:introduce_new_const~k:ty]inCCOpt.map(funv->letinstrepl=assert(T.is_groundrepl);letsubst=Subst.FO.bind'Subst.empty(v,0)(repl,0)inletrenaming=Subst.Renaming.noneinletp=Proof.Step.simp~rule:(Proof.Rule.mk"ground_app_vars")~tags:[Proof.Tag.T_ho][C.proof_parent_substrenaming(c,0)subst]inletres=C.apply_subst~renaming~proof:(Somep)(c,0)substin(* CCFormat.printf "grond: @[%a@] => @[%a@]@." C.pp c C.pp res;
CCFormat.printf "proof: @[%a@]@." Proof.S.pp_tstp (C.proof res); *)resinList.mapinst(get_groundings(T.varv)))app_varletprim_enum_simpl~modec=ifC.proof_depthc<max_penalty_prim_then((* Primitive enumeration will replace the original clause with
instances. This will chage the shape of the clause and disable some
instantiating rules (e.g. choice and Leibniz equality removal).
Therefore, we should apply these rules as part of this
destrutive simplification.
*)letproof_constructor=Proof.Step.simpinifEnv.flex_getk_instantiate_choice_ax&&recognize_choice_opscthenNoneelse(letother_insts=(ifEnv.flex_getk_instantiate_choice_axthen(insantiate_choice~proof_constructorc)else[])@(ifC.proof_depthc<Env.flex_getk_elim_leibniz_eqthenelim_leibniz_eq_~proof_constructorcelse[])@(ifEnv.flex_getk_elim_pred_varthenelim_pred_variable~proof_constructorcelse[])inletres=other_insts@prim_enum_~proof_constructor~modecinifCCList.is_emptyresthenNoneelseSomeres))elseNone(* Purify variables
- if they occur applied and unapplied ("int" mode).
- if they occur with differen argumetns ("ext" mode).
Example: g X = X a \/ X a = b becomes g X = Y a \/ Y a = b \/ X != Y.
Literals with only a variable on both sides are not affected. *)letpurify_applied_variablec=(* set of new literals *)letnew_lits=ref[]inletadd_lit_lit=new_lits:=lit::!new_litsin(* cache for term headed by variable -> replacement variable *)letcache_replacement_=T.Tbl.create8in(* cache for variable -> untouched term (the first term we encounter with a certain variable as head) *)letcache_untouched_=VTbl.create8in(* index of the next fresh variable *)letvaridx=Literals.Seq.terms(C.litsc)|>Iter.flat_mapT.Seq.vars|>T.Seq.max_var|>succ|>CCRef.createin(* variable used to purify a term *)letreplacement_vart=tryT.Tbl.findcache_replacement_twithNot_found->lethead,_=T.as_apptinletty=T.tyheadinletv=T.var_of_int~ty(CCRef.get_then_incrvaridx)inletlit=Literal.mk_neqvheadinadd_lit_lit;T.Tbl.addcache_replacement_tv;vin(* We make the variables of two (variable-headed) terms different if they are
in different classes.
For extensional variable purification, two terms are only in the same class
if they are identical.
For intensional variable purification, two terms are in the same class if
they are both unapplied variables or both applied variables. *)letsame_classt1t2=assert(T.is_var(fst(T.as_appt1)));assert(T.is_var(fst(T.as_appt2)));ifEnv.flex_getk_purify_applied_vars==`ExtthenT.equalt1t2else(assert(Env.flex_getk_purify_applied_vars==`Int);matchT.viewt1,T.viewt2with|T.Varx,T.VarywhenHVar.equalType.equalxy->true|T.App(f,_),T.App(g,_)whenT.equalfg->true|_->false)in(* Term should not be purified if
- this is the first term we encounter with this variable as head or
- it is equal to the first term encountered with this variable as head *)letshould_purifytv=tryifsame_classt(VTbl.findcache_untouched_v)then(Util.debugf~section5"Leaving untouched: %a"(funk->kT.ppt);false)else(Util.debugf~section5"To purify: %a"(funk->kT.ppt);true)withNot_found->VTbl.addcache_untouched_vt;Util.debugf~section5"Add untouched term: %a"(funk->kT.ppt);falsein(* purify a term *)letrecpurify_termt=lethead,args=T.as_apptinletres=matchT.as_varheadwith|Somev->ifshould_purifytvthen((* purify *)Util.debugf~section5"@[Purifying: %a.@ Untouched is: %a@]"(funk->kT.pptT.pp(VTbl.findcache_untouched_v));letv'=replacement_vartinassert(Type.equal(HVar.tyv)(T.tyv'));T.appv'(List.mappurify_termargs))else((* dont purify *)T.apphead(List.mappurify_termargs))|None->(* dont purify *)T.apphead(List.mappurify_termargs)inassert(Type.equal(T.tyres)(T.tyt));resin(* purify a literal *)letpurify_litlit=(* don't purify literals with only a variable on both sides *)ifLiteral.for_allT.is_varlitthenlitelseLiteral.mappurify_termlitin(* try to purify *)letlits'=Array.mappurify_lit(C.litsc)inbeginmatch!new_litswith|[]->SimplM.return_samec|_::_->(* replace! *)letall_lits=!new_lits@(Array.to_listlits')inletparent=C.proof_parentcinletproof=Proof.Step.simp~rule:(Proof.Rule.mk"ho.purify_applied_variable")~tags:[Proof.Tag.T_ho][parent]inletnew_clause=(C.create~trail:(C.trailc)~penalty:(C.penaltyc)all_litsproof)inUtil.debugf~section5"@[<hv2>Purified:@ Old: %a@ New: %a@]"(funk->kC.ppcC.ppnew_clause);SimplM.return_newnew_clauseendletsetup()=mk_diff_const();ifnot(Env.flex_getk_enabled)then(Util.debug~section1"HO rules disabled";)else(Util.debug~section1"setup HO rules";Env.Ctx.lost_completeness();ifEnv.flex_getk_resolve_flex_flexthen(Env.add_basic_simplifyremove_ff_constraints);ifEnv.flex_getk_ground_app_vars!=`Offthen(letmode=Env.flex_getk_ground_app_varsinE.add_cheap_multi_simpl_rule(ground_app_vars~mode);E.add_multi_simpl_rule~priority:1000(ground_app_vars~mode));ifEnv.flex_getk_elim_pred_varthenEnv.add_unary_inf"ho_elim_pred_var"elim_pred_variable;ifEnv.flex_getk_ext_neg_litthenEnv.add_lit_rule"ho_ext_neg_lit"ext_neg_lit;ifEnv.flex_getk_elim_leibniz_eq>0then(Env.add_unary_inf"ho_elim_leibniz_eq"elim_leibniz_equality);ifEnv.flex_getk_instantiate_choice_axthen(Env.add_redundantrecognize_choice_ops;Env.add_unary_inf"inst_choice"insantiate_choice;);ifEnv.flex_getk_ext_posthen(Env.add_unary_inf"ho_ext_pos"(ext_pos_general~all_lits:(Env.flex_getk_ext_pos_all_lits)););(* removing unfolded clauses *)ifEnv.flex_getk_enable_def_unfoldthen(Env.add_clause_conversion(func->matchStatement.get_rw_rulecwith|Some_->E.CR_drop|None->E.CR_skip));beginmatchEnv.flex_getk_prune_arg_funwith|`PruneMaxCover->Env.add_unary_simplify(prune_arg~all_covers:false);|`PruneAllCovers->Env.add_unary_simplify(prune_arg~all_covers:true);|`OldPrune->Env.add_unary_simplifyprune_arg_old;|`NoPrune->();end;ifEnv.flex_getCombinators.k_enable_combinatorsthen(Env.set_ho_normalization_rule"comb-normalize"Combinators_base.comb_normalize;)else(letho_norm=(funt->t|>beta_reduce|>(funopt->matchoptwithNone->eta_normalizet|Somet'->matcheta_normalizet'withNone->Somet'|Somett->Somett))inEnv.set_ho_normalization_rule"ho_norm"ho_norm);if(Env.flex_getk_neg_ext)then(Env.add_unary_inf"neg_ext"neg_ext)elseif(Env.flex_getk_neg_ext_as_simpl)then(Env.add_unary_simplifyneg_ext_simpl;);if(Env.flex_getk_purify_applied_vars!=`None)then(Env.add_unary_simplifypurify_applied_variable);ifEnv.flex_getk_enable_ho_unifthen(Env.add_unary_inf"ho_unif"ho_unif;);ifEnv.flex_getk_simple_projection>=0then(letpenalty_inc=Env.flex_getk_simple_projectioninletmax_depth=Env.flex_getk_simple_projection_mdinEnv.add_unary_inf"simple_projection"(simple_projection~penalty_inc~max_depth););ifnot(Env.flex_getk_prim_enum_early_bird)then(beginmatchEnv.flex_getk_ho_prim_modewith|`None->()|mode->ifEnv.flex_getk_prim_enum_simplthen(Env.add_single_step_multi_simpl_rule(prim_enum_simpl~mode))elseEnv.add_unary_inf"ho_prim_enum"(prim_enum~mode);end)else(Signal.onEnv.on_pred_var_elimination(fun(cl,var)->early_bird_prim_enumclvar;Signal.ContinueListening));ifEnv.flex_getk_ext_axiomthenEnv.ProofState.PassiveSet.add(Iter.singleton(mk_extensionality_clause()));ifEnv.flex_getk_choice_axiomthenEnv.ProofState.PassiveSet.add(Iter.singletonchoice_clause););()endletenabled_=reftrueletdef_unfold_enabled_=reffalseletforce_enabled_=reffalseletenable_unif_=reffalse(* this unification seems very buggy, had to turn it off *)letprim_mode_=ref`Negletprim_max_penalty=ref2(* FUDGE *)letset_prim_mode_=letl=["and",`And;"or",`Or;"neg",`Neg;"eq",`Eq;"quants",`Quants;"tf",`TF;"combs",`Combinators;"full",`Full;"pragmatic",`Pragmatic;"simple",`Simple;"none",`None;]inletset_s=prim_mode_:=List.assocslinArg.Symbol(List.mapfstl,set_)(* detection of HO statements *)letst_contains_ho(st:(_,_,_)Statement.t):bool=letis_non_atomic_tyty=letn_ty_vars,args,_=Type.open_poly_funtyinn_ty_vars>0||args<>[]andhas_prop_in_argsty=letn_ty_vars,args,_=Type.open_poly_funtyinList.existsType.contains_propargsin(* is there a HO variable? Any variable with a type that is
Prop or just not an atomic type is. *)lethas_ho_var()=Statement.Seq.termsst|>Iter.flat_mapT.Seq.vars|>Iter.mapHVar.ty|>Iter.exists(funty->is_non_atomic_tyty||Type.contains_propty)(* is there a HO symbol?
means the symbol has a higher-order, or contains Prop in a sub-position
of an argument. *)andhas_ho_sym()=Statement.Seq.ty_declsst|>Iter.exists(fun(_,ty)->Type.orderty>1||has_prop_in_argsty)andhas_ho_eq()=Statement.Seq.formsst|>Iter.exists(func->c|>List.exists(function|SLiteral.Eq(t,u)|SLiteral.Neq(t,u)->T.is_ho_at_roott||T.is_ho_at_rootu||is_non_atomic_ty(T.tyt)|_->false))inhas_ho_sym()||has_ho_var()||has_ho_eq()let_ext_pos=reftruelet_ext_pos_all_lits=reffalselet_ext_axiom=reffalselet_choice_axiom=reffalselet_elim_pred_var=reftruelet_ext_neg_lit=reffalselet_neg_ext=reftruelet_neg_ext_as_simpl=reffalselet_ext_axiom_penalty=ref5let_huet_style=reffalselet_cons_elim=reftruelet_imit_first=reffalselet_compose_subs=reffalselet_var_solve=reffalselet_instantiate_choice_ax=reffalselet_elim_leibniz_eq=ref(-1)let_prune_arg_fun=ref`NoPrunelet_check_lambda_free=ref`Falseletprim_enum_terms=refTerm.Set.emptylet_oracle_composer=ref(OSeq.merge:>(Logtk.Subst.toptionOSeq.tOSeq.t->Logtk.Subst.toptionOSeq.t))let_simple_projection=ref(-1)let_simple_projection_md=ref2let_purify_applied_vars=ref`Nonelet_eta=ref`Reducelet_use_diff_for_neg_ext=reffalselet_generalize_choice_trigger=reffalselet_prim_enum_simpl=reffalselet_prim_enum_early_bird=reffalselet_resolve_flex_flex=reffalselet_ground_app_vars=ref`Offletextension=letregisterenv=letmoduleE=(valenv:Env.S)inE.flex_addk_ext_pos!_ext_pos;E.flex_addk_ext_pos_all_lits!_ext_pos_all_lits;E.flex_addk_ext_axiom!_ext_axiom;E.flex_addk_choice_axiom!_choice_axiom;E.flex_addk_elim_pred_var!_elim_pred_var;E.flex_addk_ext_neg_lit!_ext_neg_lit;E.flex_addk_neg_ext!_neg_ext;E.flex_addk_neg_ext_as_simpl!_neg_ext_as_simpl;E.flex_addk_ext_axiom_penalty!_ext_axiom_penalty;E.flex_addk_instantiate_choice_ax!_instantiate_choice_ax;E.flex_addk_elim_leibniz_eq!_elim_leibniz_eq;E.flex_addk_prune_arg_fun!_prune_arg_fun;E.flex_addk_prim_enum_termsprim_enum_terms;E.flex_addk_simple_projection!_simple_projection;E.flex_addk_simple_projection_md!_simple_projection_md;E.flex_addk_check_lambda_free!_check_lambda_free;E.flex_addk_purify_applied_vars!_purify_applied_vars;E.flex_addk_eta!_eta;E.flex_addk_use_diff_for_neg_ext!_use_diff_for_neg_ext;E.flex_addk_generalize_choice_trigger!_generalize_choice_trigger;E.flex_addk_prim_enum_simpl!_prim_enum_simpl;E.flex_addk_prim_enum_early_bird!_prim_enum_early_bird;E.flex_addk_resolve_flex_flex!_resolve_flex_flex;E.flex_addk_ground_app_vars!_ground_app_vars;ifE.flex_getk_check_lambda_free=`OnlythenE.flex_addSaturate.k_abort_after_fragment_checktrue;ifE.flex_getk_check_lambda_free!=`FalsethenE.add_fragment_check(func->E.C.Seq.termsc|>Iter.for_allTerm.in_lfho_fragment);Signal.on_everyE.on_start(fun()->ifnot!Unif._unif_boolthenprint_endline("To remain in the chosen logic fragment, "^"unification with booleans has been disabled."));ifE.flex_getk_some_ho||!force_enabled_then(letmoduleET=Make(E)inET.setup())(* check if there are HO variables *)andcheck_hovecstate=letis_ho=CCVector.to_itervec|>Iter.existsst_contains_hoinifis_hothen(Util.debug~section2"problem is HO");if!def_unfold_enabled_then((* let new_vec = *)CCVector.iter(func->matchStatement.get_rw_rulecwithSome(sym,r)->Util.debugf~section1"@[<2> Adding constant def rule: `@[%a@]`@]"(funk->kRewrite.Rule.ppr);Rewrite.Defined_cst.declare_or_addsymr;|_->())vec(*vec in*));state|>Flex_state.addk_some_hois_ho|>Flex_state.addk_enabled!enabled_|>Flex_state.addPragUnifParams.k_oracle_composer!_oracle_composer|>Flex_state.addk_enable_def_unfold!def_unfold_enabled_|>Flex_state.addk_enable_ho_unif(!enabled_&&!enable_unif_)|>Flex_state.addk_ho_prim_mode(if!enabled_then!prim_mode_else`None)|>Flex_state.addk_ho_prim_max_penalty!prim_max_penaltyin{Extensions.defaultwithExtensions.name="ho";post_cnf_actions=[check_ho];env_actions=[register];}letpurify_opt=letset_n=_purify_applied_vars:=ninletl=["ext",`Ext;"int",`Int;"none",`None]inArg.Symbol(List.mapfstl,funs->set_(List.assocsl))leteta_opt=letset_n=_eta:=ninletl=["reduce",`Reduce;"expand",`Expand;"none",`None]inArg.Symbol(List.mapfstl,funs->set_(List.assocsl))let()=Options.add_opts["--ho",Arg.Bool(funb->enabled_:=b)," enable/disable HO reasoning";"--force-ho",Arg.Bool(funb->force_enabled_:=b)," enable/disable HO reasoning even if the problem is first-order";"--ho-unif",Arg.Bool(funv->enable_unif_:=v)," enable full HO unification";"--ho-elim-pred-var",Arg.Bool(funb->_elim_pred_var:=b)," disable predicate variable elimination";"--ho-prim-enum",set_prim_mode_," set HO primitive enum mode";"--ho-prim-max",Arg.Set_intprim_max_penalty," max penalty for HO primitive enum";"--ho-prim-enum-simpl",Arg.Bool((:=)_prim_enum_simpl)," use primitive enumeration as simplification rule";"--ho-prim-enum-early-bird",Arg.Bool((:=)_prim_enum_early_bird)," use early-bird primitive enumeration (requires lazy CNF)";"--ho-resolve-flex-flex",Arg.Bool((:=)_resolve_flex_flex)," eagerly remove non-essential flex-flex constraints";"--ho-oracle-composer",Arg.Symbol(["merge";"fair"],(funs->ifs="merge"then_oracle_composer:=(OSeq.merge:>(Logtk.Subst.toptionOSeq.tOSeq.t->Logtk.Subst.toptionOSeq.t))else_oracle_composer:=UnifFramework.take_fair))," choose either OSeq.merge or Unif.take_fair as the composer";"--ho-ext-axiom",Arg.Bool(funv->_ext_axiom:=v)," enable/disable extensionality axiom";"--ho-choice-axiom",Arg.Bool(funv->_choice_axiom:=v)," enable choice axiom";"--ho-ext-pos",Arg.Bool(funv->_ext_pos:=v)," enable/disable positive extensionality rule";"--ho-neg-ext",Arg.Bool(funv->_neg_ext:=v)," turn NegExt on or off";"--ho-neg-ext-simpl",Arg.Bool(funv->_neg_ext_as_simpl:=v)," turn NegExt as simplification rule on or off";"--ho-ext-pos-all-lits",Arg.Bool(funv->_ext_pos_all_lits:=v)," turn ExtPos on for all or only eligible literals";"--ho-prune-arg",Arg.Symbol(["all-covers";"max-covers";"old-prune";"off"],(funs->ifs="all-covers"then_prune_arg_fun:=`PruneAllCoverselseifs="max-covers"then_prune_arg_fun:=`PruneMaxCoverelseifs="old-prune"then_prune_arg_fun:=`OldPruneelse_prune_arg_fun:=`NoPrune))," choose arg prune mode";"--ho-ext-neg-lit",Arg.Bool(funv->_ext_neg_lit:=v)," enable/disable negative extensionality rule on literal level [?]";"--ho-elim-leibniz",Arg.String(funv->matchvwith|"inf"->_elim_leibniz_eq:=max_int|"off"->_elim_leibniz_eq:=-1|_->matchCCInt.of_stringvwith|None->invalid_arg"number expected for --ho-elim-leibniz"|Somex->_elim_leibniz_eq:=x)," enable/disable treatment of Leibniz equality. inf enables it for infinte depth of clauses"^"; off disables it; number enables it for a given depth of clause";"--ho-def-unfold",Arg.Bool(funv->def_unfold_enabled_:=v)," enable ho definition unfolding";"--ho-choice-inst",Arg.Bool(funv->_instantiate_choice_ax:=v)," enable heuristic Hilbert choice instantiation";"--ho-simple-projection",Arg.Int(funv->_simple_projection:=v)," enable simple projection instantiation."^" positive argument is increase in clause penalty for the conclusion; "^" negative argument turns the inference off";"--ho-simple-projection-max-depth",Arg.Set_int_simple_projection_md," sets the max depth for simple projection";"--ho-ext-axiom-penalty",Arg.Int(funp->_ext_axiom_penalty:=p)," penalty for extensionality axiom";"--ho-purify",purify_opt," enable purification of applied variables: 'ext' purifies"^" whenever a variable is applied to different arguments."^" 'int' purifies whenever a variable appears applied and unapplied.";"--ho-eta",eta_opt," eta-expansion/reduction";"--ground-app-vars",Arg.Symbol(["off";"fresh";"all"],(funkind->matchkindwith|"off"->_ground_app_vars:=`Off|"fresh"->_ground_app_vars:=`Fresh|"all"->_ground_app_vars:=`All|_->assertfalse))," ground all applied variables to either all constants of the right type in signature or a fresh constant";"--ho-use-diff-for-neg-ext",Arg.Bool((:=)_use_diff_for_neg_ext)," use diff constant for NegExt rule instead of fresh skolem";"--ho-generalize-choice-trigger",Arg.Bool((:=)_generalize_choice_trigger)," apply choice trigger to a fresh variable";"--check-lambda-free",Arg.Symbol(["true";"false";"only"],funs->matchswith|"true"->_check_lambda_free:=`True|"only"->_check_lambda_free:=`Only|_->_check_lambda_free:=`False),"check whether problem belongs to lambda-free ('only' will abort after the check)";];Params.add_to_mode"ho-complete-basic"(fun()->enabled_:=true;def_unfold_enabled_:=false;force_enabled_:=true;_ext_axiom:=true;_ext_neg_lit:=false;_neg_ext:=true;_neg_ext_as_simpl:=false;_ext_pos:=true;_ext_pos_all_lits:=false;prim_mode_:=`None;_elim_pred_var:=false;enable_unif_:=false;_prune_arg_fun:=`PruneMaxCover;);Params.add_to_mode"ho-pragmatic"(fun()->enabled_:=true;def_unfold_enabled_:=false;force_enabled_:=true;_ext_axiom:=false;_ext_neg_lit:=false;_neg_ext:=true;_neg_ext_as_simpl:=false;_ext_pos:=true;_ext_pos_all_lits:=true;prim_mode_:=`None;_elim_pred_var:=true;enable_unif_:=false;_prune_arg_fun:=`PruneMaxCover;);Params.add_to_mode"ho-competitive"(fun()->enabled_:=true;def_unfold_enabled_:=false;force_enabled_:=true;_ext_axiom:=false;_ext_neg_lit:=false;_neg_ext:=true;_neg_ext_as_simpl:=false;_ext_pos:=true;_ext_pos_all_lits:=true;prim_mode_:=`None;_elim_pred_var:=true;enable_unif_:=false;_prune_arg_fun:=`PruneMaxCover;);Params.add_to_mode"ho-comb-complete"(fun()->enabled_:=true;def_unfold_enabled_:=false;_resolve_flex_flex:=false;force_enabled_:=true;_ext_axiom:=false;_ext_neg_lit:=false;_neg_ext:=true;_neg_ext_as_simpl:=false;_ext_pos:=true;_ext_pos_all_lits:=true;prim_mode_:=`None;_elim_pred_var:=true;enable_unif_:=false;_prune_arg_fun:=`NoPrune;Unif._allow_pattern_unif:=false;_eta:=`None);Params.add_to_mode"fo-complete-basic"(fun()->enabled_:=false;_resolve_flex_flex:=false;Unif._allow_pattern_unif:=false;Unif._unif_bool:=false;);Params.add_to_modes["lambda-free-intensional";"lambda-free-extensional";"lambda-free-purify-intensional";"lambda-free-purify-extensional"](fun()->enabled_:=true;enable_unif_:=false;_resolve_flex_flex:=false;force_enabled_:=true;_elim_pred_var:=false;_neg_ext_as_simpl:=false;_prune_arg_fun:=`NoPrune;prim_mode_:=`None;_check_lambda_free:=`True;Unif._allow_pattern_unif:=false;Unif._unif_bool:=false;_eta:=`None;);Params.add_to_modes["lambda-free-extensional";"lambda-free-purify-extensional"](fun()->_ext_axiom:=true;_neg_ext:=true;_ext_pos:=true;_ext_pos_all_lits:=true;);Params.add_to_modes["lambda-free-intensional";"lambda-free-purify-intensional"](fun()->_ext_axiom:=false;_neg_ext:=false;_ext_pos:=false;_ext_pos_all_lits:=false;);Params.add_to_mode"lambda-free-purify-intensional"(fun()->_purify_applied_vars:=`Int);Params.add_to_mode"lambda-free-purify-extensional"(fun()->_purify_applied_vars:=`Ext);Extensions.registerextension;