123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461(* 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_complete_eq=Util.mk_stat"ho.complete_eq.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"letstat_neg_cong_fun=Util.mk_stat"ho.neg_cong_fun_success"letprof_eq_res=Util.mk_profiler"ho.eq_res"letprof_eq_res_syn=Util.mk_profiler"ho.eq_res_syntactic"letprof_ho_unif=Util.mk_profiler"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_neg_cong_fun=Flex_state.create_key()letk_instantiate_choice_ax=Flex_state.create_key()letk_elim_leibniz_eq=Flex_state.create_key()letk_unif_max_depth=Flex_state.create_key()letk_prune_arg_fun=Flex_state.create_key()letk_prim_enum_terms=Flex_state.create_key()typeprune_kind=[`NoPrune|`OldPrune|`PruneAllCovers|`PruneMaxCover]moduletypeS=sigmoduleEnv:Env.SmoduleC:moduletypeofEnv.C(** {6 Registration} *)valsetup:unit->unit(** Register rules in the environment *)endletk_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:[`Full|`Neg|`None|`Pragmatic|`TF]Flex_state.key=Flex_state.create_key()letk_ho_prim_max_penalty:intFlex_state.key=Flex_state.create_key()moduleMake(E:Env.S):SwithmoduleEnv=E=structmoduleEnv=EmoduleC=Env.CmoduleCtx=Env.Ctx(* 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)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)inFormat.printf"@[EP: @[%a@] => @[%a@]@].\n"C.ppcC.ppnew_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_clauses(* complete [f = g] into [f x1…xn = g x1…xn] for each [n ≥ 1] *)letcomplete_eq_args(c:C.t):C.tlist=letvar_offset=C.Seq.varsc|>Type.Seq.max_var|>succinleteligible=C.Eligible.paramcinletauxlitslit_idxtu=letn_ty_args,ty_args,_=Type.open_poly_fun(T.tyt)inassert(n_ty_args=0);assert(ty_args<>[]);letvars=List.mapi(funity->HVar.make~ty(i+var_offset)|>T.var)ty_argsinCCList.(1--List.lengthvars)|>List.map(funprefix_len->letvars_prefix=CCList.takeprefix_lenvarsinletnew_lit=Literal.mk_eq(T.apptvars_prefix)(T.appuvars_prefix)inletnew_lits=new_lit::CCArray.except_idxlitslit_idxinletproof=Proof.Step.inference[C.proof_parentc]~rule:(Proof.Rule.mk"ho_complete_eq")~tags:[Proof.Tag.T_ho]inletnew_c=C.createnew_litsproof~penalty:(C.penaltyc)~trail:(C.trailc)innew_c)inletnew_c=C.litsc|>Iter.of_array|>Util.seq_zipi|>Iter.filter(fun(idx,lit)->eligibleidxlit)|>Iter.flat_map_l(fun(lit_idx,lit)->matchlitwith|Literal.Equation(t,u,true)whenType.is_fun(T.tyt)->aux(C.litsc)lit_idxtu|Literal.Equation(t,u,true)whenType.is_var(T.tyt)->(* A polymorphic variable might be functional on the ground level *)letvar=Type.as_var_exn(T.tyt)inletfunty=T.of_ty(Type.arrow[Type.var(HVar.fresh~ty:Type.tType())](Type.var(HVar.fresh~ty:Type.tType())))inletsubst=Unif_subst.FO.singleton(var,0)(funty,0)inletrenaming,subst=Subst.Renaming.none,Unif_subst.substsubstinletlits'=Lits.apply_substrenamingsubst(C.litsc,0)inlett'=Subst.FO.applyrenamingsubst(t,0)inletu'=Subst.FO.applyrenamingsubst(u,0)inauxlits'lit_idxt'u'|_->[])|>Iter.to_rev_listinifnew_c<>[]then(Util.add_statstat_complete_eq(List.lengthnew_c);Util.debugf~section4"(@[complete-eq@ :clause %a@ :yields (@[<hv>%a@])@])"(funk->kC.ppc(Util.pp_list~sep:" "C.pp)new_c););new_cletneg_cong_fun(c:C.t):C.tlist=letfind_diffsst=letrecloopst=let(hd_s,args_s),(hd_t,args_t)=T.as_apps,T.as_apptinifT.is_consthd_s&&T.is_consthd_tthen(ifT.equalhd_shd_tthen(letzipped=CCList.combineargs_sargs_tinletzipped=List.filter(fun(a_s,a_t)->not(T.equala_sa_t))zippedinifList.lengthzipped=1then(lets,t=List.hdzippedinloopst)elsezipped)else[(s,t)])else[(s,t)]inlet(hd_s,_),(hd_t,_)=T.as_apps,T.as_apptinifT.is_consthd_s&&T.is_consthd_t&&T.equalhd_shd_tthen(letdiffs=loopstinifList.for_all(fun(s,t)->Type.equal(T.tys)(T.tyt))diffsthendiffselse[](* because of polymorphism, it might be possible
that terms will not be of the same type,
and that will give rise to wrong term applications*))else[]inletis_eligible=C.Eligible.alwaysinC.litsc|>CCArray.mapi(funil->matchlwith|Literal.Equation(lhs,rhs,false)whenis_eligibleil->letsubterms=find_diffslhsrhsinassert(List.for_all(fun(s,t)->Type.equal(T.tys)(T.tyt))subterms);ifnot(CCList.is_emptysubterms)&&List.exists(fun(l,_)->Type.is_fun(T.tyl)||Type.is_prop(T.tyl))subtermsthenletsubterms_lit=CCList.map(fun(l,r)->letfree_vars=T.VarSet.union(T.varsl)(T.varsr)|>T.VarSet.to_listinletarg_types=Type.expected_args@@T.tylinifCCList.is_emptyarg_typesthenLiteral.mk_neqlrelse(letskolem_decls=ref[]inletskolems=List.map(funty->letsk,res=T.mk_fresh_skolemfree_varstyinskolem_decls:=sk::!skolem_decls;res)arg_typesindeclare_skolems!skolem_decls;Literal.mk_neq(T.applskolems)(T.apprskolems)))subtermsinletnew_lits=CCList.flat_map(fun(j,x)->ifi!=jthen[x]elsesubterms_lit)(C.litsc|>Array.mapi(funjx->(j,x))|>Array.to_list)inletproof=Proof.Step.inference[C.proof_parentc]~rule:(Proof.Rule.mk"neg_cong_fun")~tags:[Proof.Tag.T_ho]inletnew_c=C.createnew_litsproof~penalty:(C.penaltyc)~trail:(C.trailc)inUtil.incr_statstat_neg_cong_fun;Somenew_celseNone|_->None)|>CCArray.filter_map(funx->x)|>CCArray.to_listletneg_ext(c:C.t):C.tlist=letis_eligible=C.Eligible.rescinC.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.varslinletskolem_decls=ref[]inletnew_lits=CCList.map(fun(j,x)->ifi!=jthenxelse(letskolems=List.map(funty->letsk,res=T.mk_fresh_skolemfree_varstyinskolem_decls:=sk::!skolem_decls;res)arg_typesinLiteral.mk_neq(T.applhsskolems)(T.apprhsskolems)))(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]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(c:C.t):C.tlist=(* find unshielded predicate vars *)letfind_vars():_HVar.tIter.t=Literals.vars(C.litsc)|>CCList.to_seq|>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:(Literal.tlist*(T.tlist*bool)list)option=tryArray.fold_left(fun(others,set)lit->beginmatchlitwith|Literal.Equation(lhs,rhs,true)whenT.equalrhsT.true_||T.equalrhsT.false_->letf,args=T.as_applhsinletsign=T.equalrhsT.true_inbeginmatchT.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|_->lit::others,setend|_->lit::others,setend)([],[])(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)->(* 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~section5"(@[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=CCList.product(funargs_posargs_neg->letargs_pos=Subst.FO.apply_lrenamingsubst(args_pos,0)inletargs_neg=Subst.FO.apply_lrenamingsubst(args_neg,0)inList.map2Literal.mk_eqargs_posargs_neg)pos_argsneg_args|>List.flatteninl1@l2inletproof=Proof.Step.inference~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_~(mode)(c:C.t):C.tlist=letfree_vars=Literals.vars(C.litsc)|>T.VarSet.of_listin(* set of variables to refine (only those occurring in "interesting" lits) *)letvars=Literals.fold_lits~eligible:C.Eligible.always(C.litsc)|>Iter.mapfst|>Iter.flat_mapLiteral.Seq.terms|>Iter.flat_mapT.Seq.subterms|>Iter.filter(funt->Type.is_prop(T.tyt))|>Iter.filter_map(funt->lethd=T.head_termtinbeginmatchT.as_varhd,Type.arity(T.tyhd)with|Somev,Type.Arity(0,n)whenn>0&&Type.returns_prop(T.tyhd)&&T.VarSet.memvfree_vars->Somev|_->Noneend)|>T.VarSet.of_seq(* unique *)inifnot(T.VarSet.is_emptyvars)then(Util.debugf~section5"(@[<hv2>ho.refine@ :clause %a@ :terms {@[%a@]}@])"(funk->kC.ppc(Util.pp_seqT.pp_var)(T.VarSet.to_seqvars)););letsc_c=0inletoffset=C.Seq.varsc|>T.Seq.max_var|>succinbeginvars|>T.VarSet.to_seq|>Iter.flat_map_l(funv->HO_unif.enum_prop~enum_cache:(Env.flex_getk_prim_enum_terms)~mode~offset(v,sc_c))|>Iter.map(fun(subst,penalty)->letrenaming=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)in(* CCFormat.printf "[Prim_enum:] @[%a@]\n=>\n@[%a@].\n" C.pp c C.pp new_c; *)Util.debugf~section3"(@[<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[]letchoice_ops=refTerm.Set.emptyletnew_choice_counter=ref0letinsantiate_choice?(inst_vars=true)?(choice_ops=choice_ops)c=letmax_var=C.Seq.varsc|>Iter.mapHVar.id|>Iter.max|>CCOpt.get_or~default:0inletis_choice_subtermt=matchT.viewtwith|T.App(hd,[arg])whenT.is_varhd||Term.Set.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))inletapplied_to_0=T.Form.not_(Lambda.whnf(T.appt[T.bvar~ty:arg_ty0]))inletres=T.fun_arg_tyapplied_to_0inassert(T.DB.is_closedres);resinletchoice_inst_of_hdhdarg=letarg_ty=Term.tyarginletty=List.hd(Type.expected_argsarg_ty)inletx=T.var_of_int~ty(max_var+1)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.pparginletproof=Proof.Step.inference~rule:(Proof.Rule.mk("inst_choice"^arg_str))[]inC.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.Set.addnew_ch_const!choice_ops;new_ch_constinletbuild_choice_instt=matchT.viewtwith|T.App(hd,[arg])->ifTerm.is_varhd&&inst_varsthen(lethd_ty=Term.tyhdinletchoice_ops=Term.Set.filter(funt->Type.equal(Term.tyt)hd_ty)!choice_ops|>Term.Set.to_list|>(funl->ifCCList.is_emptylthen[new_choice_ophd_ty]elsel)inCCList.flat_map(funhd->[choice_inst_of_hdhdarg;choice_inst_of_hdhd(neg_triggerarg)])choice_ops)elseifTerm.Set.memhd!choice_opsthen([choice_inst_of_hdhdarg;choice_inst_of_hdhd(neg_triggerarg)])else[]|_->assert(false)inC.Seq.termsc|>Iter.flat_mapTerm.Seq.subterms|>Iter.filteris_choice_subterm|>Iter.flat_map_lbuild_choice_inst|>Iter.to_listletrecognize_choice_opsc=letextract_not_p_xl=matchlwith|Literal.Equation(lhs,rhs,true)whenT.equalT.false_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&&T.is_app_varlhs->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->choice_ops:=Term.Set.addsym!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.Set.singletonsym))pas_cl))inEnv.add_passivenew_cls;C.mark_redundantc;true|None->falseend|None->false)elsefalseletelim_leibniz_equalityc=ifC.proof_depthc<Env.flex_getk_elim_leibniz_eqthen(letord=Env.ord()inleteligible=C.Eligible.alwaysinletpos_pred_vars,neg_pred_vars,occurences=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&&sign&&Term.is_true_or_falserhsthen(letvar_hd=Term.as_var_exn(Term.head_termlhs)inifTerm.equalT.true_rhsthen(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.Step.inference~rule~tags[C.proof_parentc])inSome(C.apply_subst~proof(c,0)subst)))(CCList.mapi(funiarg->(i,arg))args))else[])(Term.Map.to_listoccurences))in(* CCFormat.printf "Elim Leibniz eq:@ @[%a@].\n" C.pp c;
CCFormat.printf "Pos/neg vars:@ @[%a@].\n" (Term.VarSet.pp HVar.pp) pos_neg_vars;
CCFormat.printf "Res:@ @[%a@].\n" (CCList.pp C.pp) res); *)res)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<>[]);Util.enter_profprof_ho_unif;letr=ho_unif_real_cpairsothersinUtil.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')(* rule for eta-expansion *)leteta_normalizet=(* assert (T.DB.is_closed t); *)lett'=Ctx.eta_normalizetinif(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)letextensionality_clause=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_idinletx=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.trivialtypefixed_arg_status=|AlwaysofT.t(* This argument is always the given term in all occurences *)|Varies(* This argument contains different terms in differen occurrences *)typedupl_arg_status=|AlwaysSameAsofint(* This argument is always the same as some other argument across occurences (links to the next arg with this property) *)|Unique(* This argument is not always the same as some other argument across occurences *)(** 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->Lambda.eta_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?*)letsetup()=ifnot(Env.flex_getk_enabled)then(Util.debug~section1"HO rules disabled";)else(Util.debug~section1"setup HO rules";Env.Ctx.lost_completeness();Env.add_unary_inf"ho_complete_eq"complete_eq_args;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;letho_norm=(funt->t|>beta_reduce|>(funopt->matchoptwithNone->eta_normalizet|Somet'->matcheta_normalizet'withNone->Somet'|Somett->Somett))inEnv.set_ho_normalization_ruleho_norm;Ordering.normalize:=(funt->CCOpt.get_or~default:t(ho_normt));if(Env.flex_getk_neg_cong_fun)then(Env.add_unary_inf"neg_cong_fun"neg_cong_fun);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;);ifEnv.flex_getk_enable_ho_unifthen(Env.add_unary_inf"ho_unif"ho_unif;);beginmatchEnv.flex_getk_ho_prim_modewith|`None->()|mode->Env.add_unary_inf"ho_prim_enum"(prim_enum~mode);end;ifEnv.flex_getk_ext_axiomthenEnv.ProofState.PassiveSet.add(Iter.singletonextensionality_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=ref1(* FUDGE *)letset_prim_mode_=letl=["neg",`Neg;"full",`Full;"pragmatic",`Pragmatic;"tf",`TF;"none",`None;]inletset_s=prim_mode_:=List.assocslinArg.Symbol(List.mapfstl,set_)letst_contains_ho(st:(_,_,_)Statement.t):bool=letis_non_atomic_tyty=letn_ty_vars,args,_=Type.open_poly_funtyinn_ty_vars>0||args<>[]in(* is there a HO variable? *)lethas_ho_var()=Statement.Seq.termsst|>Iter.flat_mapT.Seq.vars|>Iter.exists(funv->is_non_atomic_ty(HVar.tyv))(* is there a HO symbol? *)andhas_ho_sym()=Statement.Seq.ty_declsst|>Iter.exists(fun(_,ty)->Type.orderty>1)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_neg_cong_fun=reffalselet_instantiate_choice_ax=reffalselet_elim_leibniz_eq=ref(-1)let_unif_max_depth=ref11let_prune_arg_fun=ref`NoPruneletprim_enum_terms=refTerm.Set.emptyletextension=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_neg_cong_fun!_neg_cong_fun;E.flex_addk_instantiate_choice_ax!_instantiate_choice_ax;E.flex_addk_elim_leibniz_eq!_elim_leibniz_eq;E.flex_addk_unif_max_depth!_unif_max_depth;E.flex_addk_prune_arg_fun!_prune_arg_fun;E.flex_addk_prim_enum_termsprim_enum_terms;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_seqvec|>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.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];}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-neg-cong-fun",Arg.Bool(funv->_neg_cong_fun:=v),"enable NegCongFun";"--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-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.Int(funv->_elim_leibniz_eq:=v)," enable/disable treatment of Leibniz equality";"--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 ho definition unfolding";"--ho-ext-axiom-penalty",Arg.Int(funp->_ext_axiom_penalty:=p)," penalty for extensionality axiom";];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:=false;_neg_ext_as_simpl:=false;_ext_pos:=true;_ext_pos_all_lits:=false;prim_mode_:=`None;_elim_pred_var:=false;_neg_cong_fun:=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;_neg_cong_fun:=false;enable_unif_:=false;_prune_arg_fun:=`PruneMaxCover;);Params.add_to_mode"ho-competitive"(fun()->enabled_:=true;def_unfold_enabled_:=true;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;_neg_cong_fun:=false;enable_unif_:=false;_prune_arg_fun:=`PruneMaxCover;);Params.add_to_mode"fo-complete-basic"(fun()->enabled_:=false;);Extensions.registerextension;