123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748(* This file is free software, part of Zipperposition. See file "license" for more details. *)(** {1 boolean subterms} *)openLogtkopenLibzipperpositionmoduleBV=CCBVmoduleT=TermmoduleLit=LiteralmoduleUS=Unif_substmoduleLits=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"letstat_ext_dec=Util.mk_stat"sup.ext_dec calls"letstat_ext_inst=Util.mk_stat"sup.ext_inst calls"letprof_eq_res=ZProf.make"ho.eq_res"letprof_eq_res_syn=ZProf.make"ho.eq_res_syntactic"letprof_ext_dec=ZProf.make"sup.ext_dec"letprof_ho_unif=ZProf.make"ho.unif"letstat_complete_eq=Util.mk_stat"ho.complete_eq.steps"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_choice_axiom_penalty=Flex_state.create_key()letk_instantiate_choice_ax=Flex_state.create_key()letk_elim_leibniz_eq=Flex_state.create_key()letk_elim_andrews_eq=Flex_state.create_key()letk_elim_andrews_eq_simpl=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_generalize_choice_trigger=Flex_state.create_key()letk_prim_enum_add_var=Flex_state.create_key()letk_prim_enum_early_bird=Flex_state.create_key()letk_resolve_flex_flex=Flex_state.create_key()letk_arg_cong=Flex_state.create_key()letk_arg_cong_simpl=Flex_state.create_key()letk_ext_dec_lits=Flex_state.create_key()letk_ext_rules_max_depth=Flex_state.create_key()letk_ext_rules_kind=Flex_state.create_key()letk_ho_disagremeents=Flex_state.create_key()letk_add_ite_axioms=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)moduleStm=E.StmmoduleStmQ=E.StmQmoduleFR=E.FormRename(* 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())let_ext_dec_from_idx=ref(ID.Map.empty)let_ext_dec_into_idx=ref(ID.Map.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])|_->Noneletext_pos_general?(all_lits=false)(c:C.t):C.tlist=leteligible=ifall_litsthenC.Eligible.alwayselseC.Eligible.paramcinletexpand_quant=not@@Env.flex_getCombinators.k_enable_combinatorsin(* 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_reduce~expand_quantt)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=letget_new_litslhsrhs=letcalc_skolemlhsrhs=let(pref_l,body_l),(pref_r,body_r)=CCPair.map_sameT.open_fun(lhs,rhs)inassert(CCList.equalType.equalpref_lpref_r);assert(not(CCList.is_emptypref_l));lethd_var,rest_vars=CCList.hd_tlpref_linletbody=T.fun_hd_var@@CCList.fold_right(funtybody->T.Form.exists(T.fun_tybody))rest_vars(T.Form.neqbody_lbody_r)inassert(T.DB.is_closedbody);FR.get_skolem~parent:c~mode:`SkolemRecyclebodyinassert(Type.is_fun(T.tylhs));letlhs,rhs=CCPair.map_sameCombs.expand(lhs,rhs)inletrecauxacclhsrhs=assert(Type.equal(T.tylhs)(T.tyrhs));ifnot(Type.is_fun(T.tylhs))thenaccelse(letsk=calc_skolemlhsrhsinletpenalty=ifList.length(fst@@Type.open_fun(T.tylhs))=1then0else1inletlhs',rhs'=CCPair.map_same(funhd->Lambda.whnf@@T.apphd[sk])(lhs,rhs)inletnew_lit=Lit.mk_neqlhs'rhs'inaux((new_lit,penalty)::acc)lhs'rhs')inaux[]lhsrhsinletmk_clause~lits~penalty=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.create~penalty:(C.penaltyc+penalty)~trail:(C.trailc)(CCArray.to_listlits)proofinUtil.debugf1~section"NegExt: @[%a@] => @[%a@].\n"(funk->kC.ppcC.ppnew_c);Util.incr_statstat_neg_ext;new_cinleteligible=C.Eligible.rescinletnew_lits_map=IntMap.to_list@@CCArray.foldi(funnew_litsidxlit->matchlitwith|Literal.Equation(lhs,rhs,false)wheneligibleidxlit&&Type.is_fun@@T.tylhs->IntMap.addidx(get_new_litslhsrhs)new_lits|_->new_lits)IntMap.empty(C.litsc)inletcompute_resultslits_map=letlit_arr=CCArray.copy(C.litsc)inletrecauxpenalty=function|[]->[mk_clause~lits:lit_arr~penalty]|(idx,repls)::rest->CCList.flat_map(fun(repl,p)->lit_arr.(idx)<-repl;aux(penalty+p)rest)replsinaux0lits_mapinifCCList.is_emptynew_lits_mapthen[]elsecompute_resultsnew_lits_mapletneg_ext_simpl(c:C.t):C.tSimplM.t=letis_eligible=C.Eligible.alwaysinletapplied_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')letord=Ctx.ord()letext_rule_eligiblecl=Env.flex_getk_ext_rules_max_depth<0||C.proof_depthcl<Env.flex_getk_ext_rules_max_depthletupdate_ext_dec_indicesfc=letord=Ctx.ord()inletwhich,eligible=ifEnv.flex_getk_ext_dec_lits=`OnlyMaxthen`Max,C.Eligible.rescelse`All,C.Eligible.alwaysinifEnv.flex_getk_ext_rules_kind!=`Off&&ext_rule_eligiblecthen(Lits.fold_terms~vars:false~var_args:false~fun_bodies:false~ty_args:false~ord~which~subterms:true~eligible(C.litsc)|>Iter.filter(fun(t,_)->not(T.is_vart)||T.is_ho_vart)|>Iter.filter(fun(t,_)->not(T.is_var(T.head_termt))&&T.is_const(T.head_termt)&&Term.has_ho_subtermt)|>Iter.iter(fun(t,pos)->f_ext_dec_into_idx(c,pos,t));leteligible=ifEnv.flex_getk_ext_dec_lits=`OnlyMaxthenC.Eligible.paramcelseC.Eligible.alwaysinLits.fold_eqn~ord~both:true~sign:true~eligible(C.litsc)|>Iter.iter(fun(l,_,sign,pos)->assertsign;lethd,_=T.as_applinifT.is_consthd&&Term.has_ho_subtermlthen(f_ext_dec_from_idx(c,pos,l))));Signal.ContinueListeninglett_type_is_hos=Type.is_prop(T.tys)||Type.is_fun(T.tys)(* Given terms s and t, identify maximal common context u
such that s = u[s1,...,sn] and t = u[t1,...,tn]. Then,
if some of the disagrements are solvable by a weak
unification algorihtm (e.g., pattern or fixpoint), filter
them out and create the unifying substitution. Based on
k_ho_disagremeents at least one or all of s1...sn have
to be of functional/boolean type *)letfind_ho_disagremeents?(unify=true)(orig_s,s_sc)(orig_t,t_sc)=letopenCCFuninletexceptionStopSearchinletcounter=ref0inletcheap_unify~subst(s,s_sc)(t,t_sc)=letunif_alg=ifEnv.flex_getCombinators.k_enable_combinatorsthen(funst->Unif_subst.of_subst@@Unif.FO.unify_syn~subst:(Unif_subst.substsubst)st)elseifT.is_vars||T.is_vartthen(FixpointUnif.unify_scoped~subst~counter)elsePatternUnif.unify_scoped~subst~counterintryifnotunifythenNoneelseSome(unif_alg(s,s_sc)(t,t_sc))withPatternUnif.NotInFragment|PatternUnif.NotUnifiable|Unif.Fail->Noneinletrecfind_diss~topst=letreturn~topres=iftopthen[]elseresinifT.equalst&&(s_sc==t_sc||T.is_grounds)then[]else(matchT.views,T.viewtwith|T.App(s_hd,s_args),T.App(t_hd,t_args)whenT.is_consts_hd->let(s_hd,s_args),(t_hd,t_args)=CCPair.map_sameT.as_app_mono(s,t)inifT.equals_hdt_hdthenfind_diss_ls_argst_argselsereturn~top[s,t]|T.App(s_hd,s_args),T.App(t_hd,t_args)whennot(T.equals_hdt_hd)&&T.is_consts_hd&&T.is_constt_hd->(* trying to find prefix subterm that is the differing context *)let(s_hd,s_args),(t_hd,t_args)=CCPair.map_sameT.as_app_mono(s,t)inletlhs,rhs,args_lhs,args_rhs=ifList.lengths_args>List.lengtht_argsthen(lettaken,dropped=CCList.take_drop(List.lengths_args-List.lengtht_args)s_argsinT.apps_hdtaken,t_hd,dropped,t_args)else(lettaken,dropped=CCList.take_drop(List.lengtht_args-List.lengths_args)t_argsins_hd,T.appt_hdtaken,s_args,dropped)inifT.same_largs_lhsargs_rhs&&s_sc==t_scthen([lhs,rhs])elsereturn~top[s,t]|_->return~top[s,t])andfind_diss_lxsys=matchxs,yswith|[],[]->[]|x::xxs,y::yys->find_diss~top:falsexy@find_diss_lxxsyys|_->invalid_arg"args must be of the same length"intryifnot(Type.equal(T.tyorig_s)(T.tyorig_t))thenraiseStopSearch;ifT.is_true_or_falseorig_s||T.is_true_or_falseorig_tthenraiseStopSearch;letnorm=ifEnv.flex_getCombinators.k_enable_combinatorsthenCCFun.idelseLambda.eta_expandinletdiss=find_diss~top:true(normorig_s)(normorig_t)inlethd_is_vart=let_,body=T.open_funtinT.is_var@@T.head_termbodyinifCCList.is_emptydiss||List.for_all(fun(s,t)->hd_is_vars||hd_is_vart)diss||List.for_all(fun(s,_)->not@@t_type_is_hos)dissthen(raiseStopSearch);let_,_,unifscope,init_subst=ifnotunifythen(orig_s,orig_t,0,US.empty)elseUS.FO.rename_to_new_scope~counter(orig_s,s_sc)(orig_t,t_sc)inletapp_substsubst=ifnotunifythen(fun(s,_)->s)elseSubst.FO.applySubst.Renaming.none(US.substsubst)inletinit_subst=Unif.Ty.unify_syn~subst:(US.substinit_subst)((T.ty(app_substinit_subst(orig_s,s_sc))),unifscope)((T.ty(app_substinit_subst(orig_t,t_sc))),unifscope)in(* Filter out the pairs that are easy to unify *)letdiss=List.fold_left(fun(dis_acc,subst)(si,ti)->letsi',ti'=CCPair.map_same(app_substsubst)((si,s_sc),(ti,t_sc))inifnot(Type.is_ground(T.tysi'))||not(Type.is_ground(T.tyti'))then((* polymorphism is currently not supported *)raiseStopSearch);letapp_tyrstysc=Subst.Ty.applyrs(ty,sc)inmatchcheap_unify~subst(si',unifscope)(ti',unifscope)with|Somesubst'->assert(letr=Subst.Renaming.create()inlets=Unif_subst.substsubst'inType.equal(app_tyrs(T.tysi')unifscope)(app_tyrs(T.tyti')unifscope));dis_acc,subst'|None->assert(letr=Subst.Renaming.create()inlets=Unif_subst.substsubstinType.equal(app_tyrs(T.tysi)s_sc)(app_tyrs(T.tyti)t_sc));(si,ti)::dis_acc,subst)([],US.of_substinit_subst)(diss)in(* If no constraints are left or all of pairs are flex-flex
or all of pairs are FO then we could have done all of
this with HO unification or FO superposition *)if(CCList.is_empty(fstdiss))then(raiseStopSearch);ifEnv.flex_getk_ho_disagremeents==`AllHo&&List.exists(fun(si,_)->not(t_type_is_hosi))(fstdiss)then(raiseStopSearch);SomedisswithStopSearch->None|Unif.Fail->Noneletext_inst~parents(s,s_sc)(t,t_sc)=assert(not(CCList.is_emptyparents));assert(CCList.lengthparents!=2||s_sc!=t_sc);letrenaming=Subst.Renaming.create()inletapply_subst=Subst.FO.applyrenamingSubst.emptyinlets,t=apply_subst(s,s_sc),apply_subst(t,t_sc)inassert(Type.equal(T.tys)(T.tyt));assert(Type.is_fun(T.tys));letty_args,ret=Type.open_fun(T.tys)inletalpha=T.of_ty@@List.hdty_argsinletbeta=T.of_ty@@Type.arrow(List.tlty_args)retinletdiff_const=Env.flex_getk_diff_constinletdiff_s_t=T.appdiff_const[alpha;beta;s;t]inlets_diff,t_diff=T.apps[diff_s_t],T.appt[diff_s_t]inletneg_lit=Lit.mk_neqs_difft_diffinletpos_lit=Lit.mk_eqstinletnew_lits=[neg_lit;pos_lit]inletproof=Proof.Step.inference(List.mapC.proof_parentparents)~rule:(Proof.Rule.mk"ext_inst")inletpenalty=List.fold_leftmax1(List.mapC.penaltyparents)inC.create~trail:(C.trail_lparents)~penaltynew_litsproofletdo_ext_inst~parents((from_t,sc_f)ass)((into_t,sc_t)ast)=matchfind_ho_disagremeents~unify:falsestwith|Some(disagreements,subst)->assert(US.is_emptysubst);letho_dis=List.filter(fun(s,t)->Type.is_fun(T.tys))disagreementsin(* assert (not (CCList.is_empty ho_dis)); *)CCList.map(fun(lhs,rhs)->ext_inst~parents(lhs,sc_f)(rhs,sc_t))ho_dis|None->[]letext_inst_or_family_eqfactcl=lettry_ext_eq_fact(s,t)(u,v)idx=letsc=0inmatchfind_ho_disagremeents(s,sc)(u,sc)with|Some(disagrements,subst)->assert(not(US.has_constrsubst));letsubst=US.substsubstinletdis_lits=List.map(fun(a,b)->Lit.mk_neqab)disagrementsinletnew_lits=dis_lits@((Lit.mk_neqtv)::CCArray.except_idx(C.litscl)idx)|>CCArray.of_list|>(funlits->Literals.apply_subst(Subst.Renaming.create())subst(lits,sc))|>CCArray.to_listinletproof=Proof.Step.inference[C.proof_parentcl]~rule:(Proof.Rule.mk"ext_eqfact")in(* ext_eqfact is rarely used *)letnew_c=C.create~trail:(C.trailcl)~penalty:(C.penaltycl+(C.proof_depthcl))new_litsproofin[new_c]|None->[]inlettry_ext_eq_factinst(s,_)(u,_)=do_ext_inst~parents:[cl](s,0)(u,0)inlettry_factorings(s,t)(u,v)idx=letext_family=if(Env.flex_getk_ext_rules_kind=`Both||Env.flex_getk_ext_rules_kind=`ExtFamily)then(try_ext_eq_fact(s,t)(u,v)idx)else[]inletext_inst=if(Env.flex_getk_ext_rules_kind=`Both||Env.flex_getk_ext_rules_kind=`ExtInst)then(try_ext_eq_factinst(s,t)(u,v))else[]inext_inst@ext_familyinletaux_eq_rest(s,t)ilits=CCList.flatten@@List.mapi(funjlit->ifi<jthen(matchlitwith|Lit.Equation(u,v,_)whenLit.is_positivoidlit->try_factorings(s,t)(u,v)i@try_factorings(s,t)(v,u)i|_->[])else[])litsinletlits=CCArray.to_list(C.litscl)inletmaximal=C.eligible_param(cl,0)Subst.emptyinCCList.flatten@@List.mapi(funilit->matchlitwith|Lit.Equation(s,t,_)whenLit.is_positivoidlit&&(Env.flex_getk_ext_dec_lits!=`OnlyMax||BV.getmaximali)->aux_eq_rest(s,t)ilits|_->[])lits(* Given a "from"-clause C \/ f t1 ... tn = s and
"into"-clause D \/ f u1 .. un (~)= v, where some of the t_i
(and consequently u_i) are of functional type, construct
a clause C \/ D \/ t1 ~= u1 \/ ... tn ~= un \/ s (~)= v.
Intuitively, we are waiting for efficient extensionality rules
to kick in and fix the problem of not being able to paramodulate
with this equation.
Currently with no restrictions or indexing. After initial evaluation,
will find ways to restrict it somehow. *)letretrieve_from_extdec_idxidxid=letcl_map=ID.Map.find_optididxinmatchcl_mapwith|None->Iter.empty|Somecl_map->C.Tbl.to_itercl_map|>Iter.flat_map(fun(c,l)->Iter.of_listl|>Iter.map(fun(t,p)->(c,t,p)))letdo_ext_supfrom_cfrom_pfrom_tinto_cinto_pinto_t=letsc_f,sc_i=0,1inifType.equal(Term.tyfrom_t)(Term.tyinto_t)&¬(C.idfrom_c=C.idinto_c&&Position.equalfrom_pinto_p)then(matchfind_ho_disagremeents(from_t,sc_f)(into_t,sc_i)with|Some(disagreements,subst)->assert(not@@US.has_constrsubst);letrenaming=Subst.Renaming.create()inletsubst=US.substsubstinletlits_f=Lits.apply_substrenamingsubst(C.litsfrom_c,sc_f)inletlits_i=Lits.apply_substrenamingsubst(C.litsinto_c,sc_i)inletapp_substrenamingscoped_t=Subst.FO.applyrenamingsubstscoped_tinletnew_neq_lits=List.map(fun(arg_f,arg_i)->Lit.mk_neq(app_substrenaming(arg_f,sc_f))(app_substrenaming(arg_i,sc_i)))disagreementsinlet(i,pos_f)=Lits.Pos.cutfrom_pinletfrom_s=Lits.Pos.atlits_f(Position.argi(Position.opppos_f))inLits.Pos.replacelits_i~at:into_p~by:(from_s);letnew_lits=new_neq_lits@CCArray.except_idxlits_fi@CCArray.to_listlits_iinlettrail=C.trail_l[from_c;into_c]inletpenalty=max(C.penaltyfrom_c)(C.penaltyinto_c)inlettags=[Proof.Tag.T_ho]inletproof=Proof.Step.inference[C.proof_parent_substrenaming(from_c,sc_f)subst;C.proof_parent_substrenaming(into_c,sc_i)subst]~rule:(Proof.Rule.mk"ext_sup")~tagsinletnew_c=C.create~trail~penaltynew_litsproofinSomenew_c|None->None)elseNoneletext_sup_actgiven=ifext_rule_eligiblegiventhen(leteligible=ifEnv.flex_getk_ext_dec_lits=`OnlyMaxthenC.Eligible.paramgivenelseC.Eligible.alwaysinLits.fold_eqn~ord~both:true~sign:true~eligible(C.litsgiven)|>Iter.flat_map(fun(l,_,sign,pos)->lethd,args=T.as_applinifT.is_consthd&&T.has_ho_subtermlthen(letinf_partners=retrieve_from_extdec_idx!_ext_dec_into_idx(T.as_const_exnhd)inIter.map(fun(into_c,into_t,into_p)->do_ext_supgivenposlinto_cinto_pinto_t)inf_partners)elseIter.empty)|>Iter.filter_mapCCFun.id|>Iter.to_list)else[]letext_sup_pasgiven=ifext_rule_eligiblegiventhen(letwhich,eligible=ifEnv.flex_getk_ext_dec_lits=`OnlyMaxthen`Max,C.Eligible.resgivenelse`All,C.Eligible.alwaysinLits.fold_terms~vars:false~var_args:false~fun_bodies:false~ty_args:false~ord~which~subterms:true~eligible(C.litsgiven)|>Iter.flat_map(fun(t,p)->lethd,args=T.as_apptinifT.is_consthd&&T.has_ho_subtermtthen(letinf_partners=retrieve_from_extdec_idx!_ext_dec_from_idx(T.as_const_exnhd)inIter.map(fun(from_c,from_t,from_p)->do_ext_supfrom_cfrom_pfrom_tgivenpt)inf_partners)elseIter.empty))|>Iter.filter_mapCCFun.id|>Iter.to_listelse[]letext_inst_sup_actgiven=ifext_rule_eligiblegiventhen(leteligible=ifEnv.flex_getk_ext_dec_lits=`OnlyMaxthenC.Eligible.paramgivenelseC.Eligible.alwaysinLits.fold_eqn~ord~both:true~sign:true~eligible(C.litsgiven)|>Iter.flat_map(fun(l,_,sign,pos)->lethd,args=T.as_applinifT.is_consthd&&T.has_ho_subtermlthen(letinf_partners=retrieve_from_extdec_idx!_ext_dec_into_idx(T.as_const_exnhd)inIter.map(fun(into_c,into_t,_)->do_ext_inst~parents:[given;into_c](l,0)(into_t,1))inf_partners)elseIter.empty)|>Iter.to_list|>CCList.flatten)else[]letext_inst_sup_pasgiven=ifext_rule_eligiblegiventhen(letwhich,eligible=ifEnv.flex_getk_ext_dec_lits=`OnlyMaxthen`Max,C.Eligible.resgivenelse`All,C.Eligible.alwaysinLits.fold_terms~vars:false~var_args:false~fun_bodies:false~ty_args:false~ord~which~subterms:true~eligible(C.litsgiven)|>Iter.flat_map(fun(t,p)->lethd,args=T.as_apptinifT.is_consthd&&T.has_ho_subtermtthen(Iter.map(fun(from_c,from_t,from_p)->do_ext_inst~parents:[from_c;given](from_t,0)(t,1))(retrieve_from_extdec_idx!_ext_dec_from_idx(T.as_const_exnhd)))elseIter.empty))|>Iter.to_list|>CCList.flattenelse[]letext_eqres_auxc=leteligible=C.Eligible.alwaysinifext_rule_eligiblecthen(letres=Literals.fold_eqn(C.litsc)~eligible~ord~both:false~sign:false|>Iter.to_list|>CCList.filter_map(fun(lhs,rhs,sign,pos)->assert(sign=false);letidx=Lits.Pos.idxposinifEnv.flex_getk_ext_dec_lits!=`OnlyMax||BV.get(C.eligible_res_no_substc)idxthen(letsc=0inmatchfind_ho_disagremeents(lhs,sc)(rhs,sc)with|Some(disagremeents,subst)->letnew_neq_lits=List.map(fun(s,t)->Lit.mk_neqst)disagremeentsinleti,_=Literals.Pos.cutposinletnew_lits=(Array.of_list@@new_neq_lits@CCArray.except_idx(C.litsc)i,sc)|>Literals.apply_subst(Subst.Renaming.create())(US.substsubst)|>Array.to_listinletproof=Proof.Step.inference[C.proof_parentc]~rule:(Proof.Rule.mk"ext_eqres")inletnew_c=C.create~trail:(C.trailc)~penalty:(C.penaltyc)new_litsproofinSomenew_c|_->None)elseNone)inUtil.incr_statstat_ext_dec;res)else[]letext_inst_eqresc=leteligible=C.Eligible.alwaysinifext_rule_eligiblecthen(letres=Literals.fold_eqn(C.litsc)~eligible~ord~both:false~sign:false|>Iter.to_list|>CCList.flat_map(fun(lhs,rhs,sign,pos)->assert(sign=false);letidx=Lits.Pos.idxposinifEnv.flex_getk_ext_dec_lits!=`OnlyMax||BV.get(C.eligible_res_no_substc)idxthen(do_ext_inst~parents:[c](lhs,0)(rhs,0))else[])inUtil.incr_statstat_ext_inst;res)else[]letext_eqresgiven=ZProf.with_profprof_ext_decext_eqres_auxgivenletinsert_into_ext_dec_indexindex(c,pos,t)=letkey=T.head_exntinletclause_map=ID.Map.find_optkey!indexinletclause_map=matchclause_mapwith|None->C.Tbl.create8|Someres->resinletall_pos=(try(t,pos)::(C.Tbl.findclause_mapc)with_->[(t,pos)])inC.Tbl.replaceclause_mapcall_pos;index:=ID.Map.addkeyclause_map!indexletremove_from_ext_dec_indexindex(c,_,t)=letkey=T.head_exntinletclause_map=ID.Map.find_optkey!indexinmatchclause_mapwith|None->Util.debugf~section1"all clauses allready deleted."CCFun.id|Someres->(C.Tbl.removeresc;index:=ID.Map.addkeyres!index)(* 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,_)whenLiteral.is_predicate_litlit->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,Literal.is_positivoidlit)::set,(ifLiteral.is_positivoidlitthen[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~add_var:(Env.flex_getk_prim_enum_add_var)~enum_cache:(Env.flex_getk_prim_enum_terms)~signature:(Ctx.signature())~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)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|T.AppBuiltin(Builtin.ChoiceConst,l)->CCList.lengthl==2&&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_litsproofinletchoice_of_tyty=assert(Type.is_funty);letargs,_=Type.open_funtyinletalpha_to_prop=List.hdargsinassert(Type.is_funalpha_to_prop);letalpha=List.hd(fst(Type.open_funalpha_to_prop))inletres=T.app_builtinBuiltin.ChoiceConst~ty[T.of_tyalpha]inresin(* def_clause is the clause that defined the symbol hd *)letgenerate_instances_of_hd~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[choice_of_tyhd_ty,None]elsel)inCCList.flat_map(fun(hd,def_clause)->generate_instances_of_hd~def_clausehdarg)choice_ops)else(matchTerm.Map.find_opthd!choice_opswith|Somedef_clause->generate_instances_of_hd~def_clausehdarg|None->[])|T.AppBuiltin(ChoiceConst,[ty_arg;ch_arg])->letty=Type.arrow[T.tych_arg](T.tyt)inlethd=T.app_builtin~tyChoiceConst[ty_arg]ingenerate_instances_of_hd~def_clause:Nonehdch_arg|_->assert(false)inletres=C.Seq.termsc|>Iter.flat_map(Term.Seq.subterms~include_builtin:true)|>Iter.filteris_choice_subterm|>Iter.flat_map_lbuild_choice_inst|>Iter.to_listinifnot(CCList.is_emptyres)then(Util.debugf~section1"inst(@[%a@])=@.@[%a@]@."(funk->kC.ppc(CCList.ppC.pp)res););res(* 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,_,_)whenLiteral.is_negativoidl&&Literal.is_predicate_litl&&T.is_app_varlhs->beginmatchT.viewlhswith|T.App(hd,[var])whenT.is_varvar->Somehd|_->Noneend|_->Noneinletextract_p_choice_ppl=matchlwith|Literal.Equation(lhs,_,_)whenLiteral.is_positivoidl&&Literal.is_predicate_litl->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,_,pos)->leti,_=Literals.Pos.cutposinletlit=(C.litsc).(i)inifLiteral.is_predicate_litlit&&Term.is_app_varlhsthen(letvar_hd=Term.as_var_exn(Term.head_termlhs)inletsign=Literal.is_positivoidlitinifsignthen(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_parent_substSubst.Renaming.none(c,0)subst])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[]letelim_andrews_eq_?(proof_constructor=Proof.Step.inference)c=letord=Env.ord()inleteligible=C.Eligible.alwaysinLits.fold_eqn~both:false~ord~eligible(C.litsc)|>Iter.fold(funcmd_list(lhs,rhs,_,pos)->leti,_=Lits.Pos.cutposinletlit=(C.litsc).(i)inifLit.is_predicate_litlit&&T.is_app_varlhsthen(lethd,args=T.as_applhsinassert(T.is_varhd);letlam_pref,_=Type.open_fun(T.tyhd)inletreturnij=letmk_dbidx=letty=List.nthlam_prefidxinletidx=(List.lengthlam_pref)-idx-1inT.bvar~tyidxinletmk_body~signij=sign(mk_dbi)(mk_dbj)inletsign=ifLit.is_positivoidlitthenT.Form.neqelseT.Form.eqinletsubst_t=T.fun_llam_pref(mk_body~signij)inletvar=T.as_var_exnhdinSome(Subst.FO.bind'Subst.empty(var,0)(subst_t,0))in(CCList.filter_mapCCFun.id@@CCList.flat_map_i(funiarg_i->CCList.mapi(funjarg_j->ifj>i&&T.equalarg_iarg_jthenreturnijelseNone)args)args)@cmd_list)elsecmd_list)([])|>List.map(funsubst->letrule=Proof.Rule.mk"elim_andrews_eq"inlettags=[Proof.Tag.T_ho]inletproof=Some(proof_constructor~rule~tags[C.proof_parentc])inC.apply_subst~proof(c,0)subst)letelim_andrews_equalityc=ifC.proof_depthc<Env.flex_getk_elim_andrews_eqthen(elim_andrews_eq_c)else[]letelim_andrews_equality_simplsc=ifC.proof_depthc<Env.flex_getk_elim_andrews_eqthen(letres=elim_andrews_eq_cinCCOpt.return_if(not(CCList.is_emptyres))res)elseNoneletpp_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<>[]);let_span=ZProf.enter_profprof_ho_unifinletr=ho_unif_real_cpairsothersinZProf.exit_prof_span;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~expand_quant:(not@@Env.flex_getCombinators.k_enable_combinators)~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.trivialletmk_choice_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.Ctx.declarechoice_idchoice_type;Env.C.create~penalty:(Env.flex_getk_choice_axiom_penalty)~trail:Trail.emptylitsProof.Step.trivialletmk_ite_clauses()=letite_id=ID.make("zf_ite")inletalpha=Type.var(HVar.make~ty:Type.tType0)inletite_ty=Type.arrow[Type.prop;alpha;alpha]alphainletite_const=Term.const~ty:ite_tyite_idinletx=Term.var(HVar.make~ty:alpha1)inlety=Term.var(HVar.make~ty:alpha2)inletif_t=T.appite_const[T.true_;x;y]inletif_f=T.appite_const[T.false_;x;y]inletif_t_cl=C.create~penalty:1~trail:Trail.empty[Lit.mk_eqif_tx]Proof.Step.trivialinletif_f_cl=C.create~penalty:1~trail:Trail.empty[Lit.mk_eqif_fy]Proof.Step.trivialinEnv.Ctx.declareite_idite_ty;Iter.of_list[if_t_cl;if_f_cl]letearly_bird_prim_enumclvar=assert(T.is_varvar);letoffset=C.Seq.varscl|>T.Seq.max_var|>succinletmode=Env.flex_getk_ho_prim_modeinletadd_var=Env.flex_getk_prim_enum_add_varinletsc=0inHO_unif.enum_prop~enum_cache:(Env.flex_getk_prim_enum_terms)~add_var~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.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_passiveletrecognize_injectivityc=letexceptionFailinletmoduleLit=Literalin(* avoiding cascading if-then-elses *)letfail_oncondition=ifconditionthenraiseFailinletfind_in_argsvarargs=fst@@CCOpt.get_or~default:(-1,T.true_)(CCList.find_idx(T.equalvar)args)intryfail_on(C.lengthc!=2);matchC.litscwith|[|lit1;lit2|]->fail_on(not((Lit.is_positivoidlit1||Lit.is_positivoidlit2)&&(Lit.is_negativoidlit1||Lit.is_negativoidlit2)));letpos_lit,neg_lit=ifLit.is_positivoidlit1thenlit1,lit2elselit2,lit1inbeginmatchpos_lit,neg_litwith|Equation(x,y,true),Equation(lhs,rhs,sign)->fail_on(not(T.is_varx&&T.is_vary));fail_on(T.equalxy);let(hd_lhs,lhs_args),(hd_rhs,rhs_args)=CCPair.map_sameT.as_app_mono(lhs,rhs)infail_on(not(T.is_consthd_lhs&&T.is_consthd_rhs));fail_on(not(T.equalhd_lhshd_rhs));fail_on(not(List.lengthlhs_args==List.lengthrhs_args));fail_on(not((find_in_argsxlhs_args)!=(-1)||(find_in_argsxrhs_args)!=(-1)));fail_on(not((find_in_argsylhs_args)!=(-1)||(find_in_argsyrhs_args)!=(-1)));(* reorient equations so that x appears in lhs *)letlhs,rhs,lhs_args,rhs_args=iffind_in_argsxlhs_args!=-1then(lhs,rhs,lhs_args,rhs_args)else(rhs,lhs,rhs_args,lhs_args)infail_on(find_in_argsxlhs_args!=find_in_argsyrhs_args);letsame_vars,diff_eqns=List.fold_left(fun(same,diff)(s,t)->fail_on(not(T.is_vars&&T.is_vart));ifT.equalstthen(s::same,diff)else(same,(s,t)::diff))([],[])(List.combinelhs_argsrhs_args)inletsame_set=T.Set.of_listsame_varsinletdiff_lhs_set,diff_rhs_set=CCPair.map_sameT.Set.of_list(CCList.splitdiff_eqns)in(* variables in each group are unique *)fail_on(List.lengthsame_vars!=T.Set.cardinalsame_set);fail_on(List.lengthdiff_eqns!=T.Set.cardinaldiff_lhs_set);fail_on(List.lengthdiff_eqns!=T.Set.cardinaldiff_rhs_set);(* variable groups do not intersect *)fail_on(not(T.Set.is_empty(T.Set.interdiff_lhs_setdiff_rhs_set)));fail_on(not(T.Set.is_empty(T.Set.interdiff_lhs_setsame_set)));fail_on(not(T.Set.is_empty(T.Set.interdiff_rhs_setsame_set)));let(sk_id,sk_ty),inv_sk=Term.mk_fresh_skolem(List.mapT.as_var_exnsame_vars)(Type.arrow[T.tylhs](T.tyx))inletinv_sk=T.appinv_sk[lhs]inletinv_lit=[Lit.mk_eqinv_skx]inletproof=Proof.Step.inference~rule:(Proof.Rule.mk"inj_rec")[C.proof_parentc]inCtx.declaresk_idsk_ty;letnew_clause=C.create~trail:(C.trailc)~penalty:(C.penaltyc)inv_litproofinUtil.debugf~section1"Injectivity recognized: %a |---| %a"(funk->kC.ppcC.ppnew_clause);[new_clause]|_->assertfalse;end|_->assertfalse;withFail->[](* 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.paramcinletaux?(start=1)~polylitslit_idxtu=letn_ty_args,ty_args,_=Type.open_poly_fun(T.tyt)inassert(n_ty_args=0);assert(ty_args<>[]);letvars=List.mapi(funity->T.var@@HVar.make~ty(i+var_offset))ty_argsinCCList.(start--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](* THIS NAME IS USED IN HEURISTICS -- CHANGE CAREFULLY! *)~rule:(Proof.Rule.mk"ho_complete_eq")~tags:[Proof.Tag.T_ho;Proof.Tag.T_dont_increase_depth]inletpenalty=C.penaltyc+(ifpolythen1else0)inletnew_c=C.createnew_litsproof~penalty~trail:(C.trailc)inifpolythen(C.set_flagSClause.flag_poly_arg_cong_resnew_ctrue;);new_c)inletis_poly_arg_cong_res=C.get_flagSClause.flag_poly_arg_cong_rescinletnew_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~poly:false(C.litsc)lit_idxtu|Literal.Equation(t,u,true)whenType.is_var(T.tyt)&¬is_poly_arg_cong_res->(* A polymorphic variable might be functional on the ground level *)letty_args=OSeq.iterate[Type.var@@HVar.fresh~ty:Type.tType()](funtypes_w->Type.var(HVar.fresh~ty:Type.tType())::types_w)inletres=ty_args|>OSeq.mapi(funarrarg_idxarrow_args->letvar=Type.as_var_exn(T.tyt)inletfunty=T.of_ty(Type.arrowarrow_args(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)inletnew_cl=aux~poly:true~start:(arrarg_idx+1)lits'lit_idxt'u'inassert(List.lengthnew_cl==1);List.hdnew_cl)inletfirst_two,rest=OSeq.take2res,OSeq.mapCCOpt.return(OSeq.drop2res)inletstm=Stm.make~penalty:(C.penaltyc+20)~parents:[c]restinStmQ.add(Env.get_stm_queue())stm;OSeq.to_listfirst_two|_->[])|>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_cletarg_cong_simplc=letvar_offset=ref(C.Seq.varsc|>Type.Seq.max_var|>succ)inletsimplified=reffalseinletnew_lits=Array.map(function|Lit.Equation(lhs,rhs,sign)whensign&&Type.is_fun(T.tylhs)->lettyargs=fst(Type.open_fun(T.tylhs))insimplified:=true;letvars=List.map(funty->incrvar_offset;T.var@@HVar.make~ty(!var_offset))tyargsinletlhs',rhs'=T.applhsvars,T.apprhsvarsinLit.mk_eqlhs'rhs'|x->x)(C.litsc)inifnot!simplifiedthenSimplM.return_samecelse(letproof=Proof.Step.simp~rule:(Proof.Rule.mk"arg_cong_simpl")[C.proof_parentc]inSimplM.return_new(C.create_a~penalty:(C.penaltyc)~trail:(C.trailc)new_litsproof))typefixed_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_clauseendlet()=Signal.onE.ProofState.ActiveSet.on_add_clause(func->update_ext_dec_indicesinsert_into_ext_dec_indexc);Signal.onE.ProofState.ActiveSet.on_remove_clause(func->update_ext_dec_indicesremove_from_ext_dec_indexc)letsetup()=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();if(Env.flex_getk_neg_ext_as_simpl)then(Env.add_unary_simplifyneg_ext_simpl;)elseif(Env.flex_getk_neg_ext)then(Env.add_unary_inf"neg_ext"neg_ext);ifEnv.flex_getk_ext_rules_kind==`ExtFamily||Env.flex_getk_ext_rules_kind==`Boththen(Env.add_binary_inf"ext_dec_act"ext_sup_act;Env.add_binary_inf"ext_dec_pas"ext_sup_pas;Env.add_unary_inf"ext_eqres_dec"ext_eqres;);ifEnv.flex_getk_ext_rules_kind=`ExtInst||Env.flex_getk_ext_rules_kind=`Boththen(Env.add_binary_inf"ext_dec_act"ext_inst_sup_act;Env.add_binary_inf"ext_dec_pas"ext_inst_sup_pas;Env.add_unary_inf"ext_eqres_dec"ext_inst_eqres;);ifEnv.flex_getk_ext_rules_kind!=`Offthen(Env.add_unary_inf"ext_eqfact_both"ext_inst_or_family_eqfact;);ifEnv.flex_getk_arg_cong_simplthen(Env.add_basic_simplifyarg_cong_simpl;)elseifEnv.flex_getk_arg_congthen(Env.add_unary_inf"ho_complete_eq"complete_eq_args);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_elim_andrews_eq>0then(ifEnv.flex_getk_elim_andrews_eq_simplthen(Env.add_multi_simpl_rule~priority:100elim_andrews_equality_simpls)elseEnv.add_unary_inf"ho_elim_leibniz_eq"elim_andrews_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_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->Env.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));Signal.onceEnv.on_start(fun()->ifEnv.flex_getk_ext_axiomthen(Env.ProofState.PassiveSet.add(Iter.singleton(mk_extensionality_clause())));ifEnv.flex_getk_choice_axiomthen(Env.ProofState.PassiveSet.add(Iter.singleton(mk_choice_clause())));ifEnv.flex_getk_add_ite_axiomsthen(Env.ProofState.PassiveSet.add(mk_ite_clauses()));));()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_choice_axiom_penalty=ref1let_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_elim_andrews_eq=ref(-1)let_elim_andrews_eq_simpl=ref(false)let_prune_arg_fun=ref`NoPrunelet_check_lambda_free=ref`Falseletprim_enum_terms=refTerm.Set.emptylet_simple_projection=ref(-1)let_simple_projection_md=ref2let_purify_applied_vars=ref`Nonelet_eta=ref`Reducelet_generalize_choice_trigger=reffalselet_prim_enum_simpl=reffalselet_prim_enum_add_var=reffalselet_prim_enum_early_bird=reffalselet_resolve_flex_flex=reffalselet_ground_app_vars=ref`Offlet_arg_cong=reftruelet_arg_cong_simpl=reffalseletext_rules_max_depth=ref(-1)letext_rules_kind=ref(`Off)let_ext_dec_lits=ref`Alllet_ho_disagremeents=ref`SomeHolet_ite_axioms=reffalseletextension=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_choice_axiom_penalty!_choice_axiom_penalty;E.flex_addk_instantiate_choice_ax!_instantiate_choice_ax;E.flex_addk_elim_leibniz_eq!_elim_leibniz_eq;E.flex_addk_elim_andrews_eq!_elim_andrews_eq;E.flex_addk_elim_andrews_eq_simpl!_elim_andrews_eq_simpl;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_generalize_choice_trigger!_generalize_choice_trigger;E.flex_addk_prim_enum_add_var!_prim_enum_add_var;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;E.flex_addk_arg_cong!_arg_cong;E.flex_addk_arg_cong_simpl!_arg_cong_simpl;E.flex_addk_ho_disagremeents!_ho_disagremeents;E.flex_addk_ext_dec_lits!_ext_dec_lits;E.flex_addk_ext_rules_max_depth!ext_rules_max_depth;E.flex_addk_ext_rules_kind!ext_rules_kind;E.flex_addk_add_ite_axioms!_ite_axioms;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);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.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";"--arg-cong",Arg.Bool(funv->_arg_cong:=v)," enable/disable ArgCong";"--arg-cong-simpl",Arg.Bool(funv->_arg_cong_simpl:=v)," enable/disable ArgCong as a simplification rule";"--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-add-var",Arg.Bool((:=)_prim_enum_add_var)," turn an instantiation %x. t into %x. (F x | t)";"--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-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-choice-axiom-penalty",Arg.Int(funv->_choice_axiom_penalty:=v)," choice axiom penalty";"--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-elim-andrews",Arg.String(funv->matchvwith|"inf"->_elim_andrews_eq:=max_int|"off"->_elim_andrews_eq:=-1|_->matchCCInt.of_stringvwith|None->invalid_arg"number expected for --ho-elim-leibniz"|Somex->_elim_andrews_eq:=x)," enable/disable treatment of Andrews equality. inf enables it for infinte depth of clauses"^"; off disables it; number enables it for a given depth of clause";"--ho-elim-andrews-simpl",Arg.Bool((:=)_elim_andrews_eq_simpl)," use Andrews equality replacement as simplification ";"--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-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)";"--ext-rules-max-depth",Arg.Set_intext_rules_max_depth," Sets the maximal proof depth of the clause eligible for Ext-* or ExtInst inferences";"--ext-rules",Arg.Symbol(["off";"ext-inst";"ext-family";"both"],(function|"off"->ext_rules_kind:=`Off;ext_rules_max_depth:=-1;|"ext-inst"->ext_rules_kind:=`ExtInst;|"ext-family"->ext_rules_kind:=`ExtFamily;|"both"->ext_rules_kind:=`Both|_->assertfalse))," Chooses the kind of extensionality rules to use";"--ite-axioms",Arg.Bool((:=)_ite_axioms)," include if-then-else definition axioms";"--ext-decompose-lits",Arg.Symbol(["all";"max"],(funstr->_ext_dec_lits:=ifString.equalstr"all"then`Allelse`OnlyMax))," Sets the maximal number of literals clause can have for ExtDec inference.";"--ext-decompose-ho-disagreements",Arg.Symbol(["all-ho";"some-ho"],(funstr->_ho_disagremeents:=ifString.equalstr"all-ho"then`AllHoelse`SomeHo))," Perform Ext-Sup, Ext-EqFact, or Ext-EqRes rules only when all disagreements are HO"^" or when there exists a HO disagremeent";];Params.add_to_mode"ho-complete-basic"(fun()->enabled_:=true;def_unfold_enabled_:=false;force_enabled_:=true;_ext_axiom:=true;_choice_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;_arg_cong:=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;