123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639(* This file is free software, part of Zipperposition. See file "license" for more details. *)openLogtkopenLibzipperpositionmoduleBV=CCBVmoduleT=TermmoduleO=OrderingmoduleS=SubstmoduleLit=LiteralmoduleLits=LiteralsmoduleComp=ComparisonmoduleUS=Unif_substmoduleP=PositionmoduleHO=Higher_orderletsection=Util.Section.make~parent:Const.section"sup"(* flag meaning the clause has been simplified already *)letflag_simplified=SClause.new_flag()moduletypeS=Superposition_intf.S(* statistics *)letstat_basic_simplify_calls=Util.mk_stat"sup.basic_simplify calls"letstat_basic_simplify=Util.mk_stat"sup.basic_simplify"letstat_superposition_call=Util.mk_stat"sup.superposition calls"letstat_equality_resolution_call=Util.mk_stat"sup.equality_resolution calls"letstat_equality_factoring_call=Util.mk_stat"sup.equality_factoring calls"letstat_subsumption_call=Util.mk_stat"sup.subsumption_calls"letstat_eq_subsumption_call=Util.mk_stat"sup.equality_subsumption calls"letstat_eq_subsumption_success=Util.mk_stat"sup.equality_subsumption success"letstat_subsumed_in_active_set_call=Util.mk_stat"sup.subsumed_in_active_set calls"letstat_subsumed_by_active_set_call=Util.mk_stat"sup.subsumed_by_active_set calls"letstat_clauses_subsumed=Util.mk_stat"sup.num_clauses_subsumed"letstat_demodulate_call=Util.mk_stat"sup.demodulate calls"letstat_demodulate_step=Util.mk_stat"sup.demodulate steps"letstat_semantic_tautology=Util.mk_stat"sup.semantic_tautologies"letstat_condensation=Util.mk_stat"sup.condensation"letstat_clc=Util.mk_stat"sup.clc"letstat_orphan_checks=Util.mk_stat"orphan checks"letprof_demodulate=ZProf.make"sup.demodulate"letprof_back_demodulate=ZProf.make"sup.backward_demodulate"letprof_pos_simplify_reflect=ZProf.make"sup.simplify_reflect+"letprof_neg_simplify_reflect=ZProf.make"sup.simplify_reflect-"letprof_clc=ZProf.make"sup.contextual_literal_cutting"letprof_semantic_tautology=ZProf.make"sup.semantic_tautology"letprof_condensation=ZProf.make"sup.condensation"letprof_basic_simplify=ZProf.make"sup.basic_simplify"letprof_subsumption=ZProf.make"sup.subsumption"letprof_eq_subsumption=ZProf.make"sup.equality_subsumption"letprof_subsumption_set=ZProf.make"sup.forward_subsumption"letprof_subsumption_in_set=ZProf.make"sup.backward_subsumption"letprof_infer_active=ZProf.make"sup.infer_active"letprof_infer_passive=ZProf.make"sup.infer_passive"letprof_infer_fluidsup_active=ZProf.make"sup.infer_fluidsup_active"letprof_infer_fluidsup_passive=ZProf.make"sup.infer_fluidsup_passive"letprof_infer_equality_resolution=ZProf.make"sup.infer_equality_resolution"letprof_infer_equality_factoring=ZProf.make"sup.infer_equality_factoring"letprof_queues=ZProf.make"sup.queues"letk_sup_at_vars=Flex_state.create_key()letk_sup_in_var_args=Flex_state.create_key()letk_sup_under_lambdas=Flex_state.create_key()letk_sup_at_var_headed=Flex_state.create_key()letk_sup_from_var_headed=Flex_state.create_key()letk_fluidsup=Flex_state.create_key()letk_subvarsup=Flex_state.create_key()letk_dupsup=Flex_state.create_key()letk_lambdasup=Flex_state.create_key()letk_demod_in_var_args=Flex_state.create_key()letk_lambda_demod=Flex_state.create_key()letk_quant_demod=Flex_state.create_key()letk_use_simultaneous_sup=Flex_state.create_key()letk_unif_alg=Flex_state.create_key()letk_unif_module:(moduleUnifFramework.US)Flex_state.key=Flex_state.create_key()letk_fluidsup_penalty=Flex_state.create_key()letk_dupsup_penalty=Flex_state.create_key()letk_ground_subs_check=Flex_state.create_key()letk_solid_subsumption=Flex_state.create_key()letk_dot_sup_into=Flex_state.create_key()letk_dot_sup_from=Flex_state.create_key()letk_dot_simpl=Flex_state.create_key()letk_dot_demod_into=Flex_state.create_key()letk_recognize_injectivity=Flex_state.create_key()letk_ho_basic_rules=Flex_state.create_key()letk_max_infs=Flex_state.create_key()letk_switch_stream_extraction=Flex_state.create_key()letk_dont_simplify=Flex_state.create_key()letk_use_semantic_tauto=Flex_state.create_key()letk_restrict_fluidsup=Flex_state.create_key()letk_check_sup_at_var_cond=Flex_state.create_key()letk_restrict_hidden_sup_at_vars=Flex_state.create_key()letk_bool_demod=Flex_state.create_key()letk_immediate_simplification=Flex_state.create_key()letk_local_rw=Flex_state.create_key()letk_destr_eq_res=Flex_state.create_key()letk_rw_with_formulas=Flex_state.create_key()letk_pred_var_eq_fact=Flex_state.create_key()letk_force_limit=Flex_state.create_key()letk_formula_simplify_reflect=Flex_state.create_key()letk_strong_sr=Flex_state.create_key()letk_superpose_w_formulas=Flex_state.create_key()let_NO_LAMSUP=-1letget_unif_module(moduleE:Env.S):(moduleUnifFramework.US)=E.flex_getk_unif_modulemoduleMake(Env:Env.S):SwithmoduleEnv=Env=structmoduleEnv=EnvmoduleCtx=Env.CtxmoduleC=Env.CmodulePS=Env.ProofStatemoduleI=PS.TermIndexmoduleTermIndex=PS.TermIndexmoduleSubsumIdx=PS.SubsumptionIndexmoduleUnitIdx=PS.UnitIndexmoduleStm=Env.StmmoduleStmQ=Env.StmQ(** {6 Stream queue} *)let_cc_simpl=ref(Congruence.FO.create~size:256())(** {6 Index Management} *)let_idx_sup_into=ref(TermIndex.empty())let_idx_lambdasup_into=ref(TermIndex.empty())let_idx_fluidsup_into=ref(TermIndex.empty())let_idx_subvarsup_into=ref(TermIndex.empty())let_idx_dupsup_into=ref(TermIndex.empty())let_idx_sup_from=ref(TermIndex.empty())let_idx_back_demod=ref(TermIndex.empty())let_idx_fv=ref(SubsumIdx.empty())(* let _idx_fv = ref (SubsumIdx.of_signature (Ctx.signature()) ()) *)let_idx_simpl=ref(UnitIdx.empty())letidx_sup_into()=!_idx_sup_intoletidx_sup_from()=!_idx_sup_fromletidx_fv()=!_idx_fv(* Beta-Eta-Normalizes terms before comparing them. Note that the Clause
module calls Ctx.ord () independently, but clauses should be normalized
independently by simplification rules. *)letord=Ctx.ord()letforce_getting_clstreams=letrecaux((clauses,streams)asacc)=function|[]->acc|(penalty,parents,stm)::xs->letrecdrip_streamistm=letmk_stmstm=Stm.make~penalty~parentsstminifi=0thenaux(clauses,(mk_stmstm)::streams)xselse(matchstm()with|OSeq.Nil->auxaccxs|OSeq.Cons((Somecl),stm')->aux(cl::clauses,(mk_stmstm')::streams)xs|OSeq.Cons(None,stm')->drip_stream(i-1)stm')in(* let limit = max 1 ((Env.flex_get StreamQueue.k_guard) / ) in *)letlimit=Env.flex_getk_force_limitindrip_streamlimitstminaux([],[])streamslethas_bad_occurrence_elsewherecvarpos=assert(T.is_varvar);Lits.fold_terms~ord~subterms:true~eligible:C.Eligible.always~which:`All(C.litsc)|>Iter.exists(fun(t,pos')->not(Position.equalpospos')&&(* variable appears at a prefix position
somewhere else (pos ≠ pos') *)matchT.viewtwith|T.App(hd,_)->T.equalhdvar|_->false)letfluidsup_applicablecl=not(Env.flex_getk_restrict_fluidsup)||Array.length(C.litscl)<=2||(C.proof_depthcl)==0(* Syntactic overapproximation of fluid or deep terms *)letis_fluid_or_deepct=(* Fluid (1): Applied variables *)T.is_var(T.head_termt)&¬(CCList.is_empty@@T.argst)(* Fluid (2): A lambda-expression that might eta-reduce to a non-lambda-expression after substitution (overapproximated) *)||T.is_funt&¬(T.is_groundt)(* Deep: A variable also occurring in a lambda-expression or in an argument of a variable in the same clause*)||matchT.as_vartwith|Somev->Lits.fold_terms~vars:false~var_args:false~fun_bodies:false~ty_args:false~which:`All~ord~subterms:true~eligible:(fun__->true)(C.litsc)|>Iter.exists(fun(t,_)->matchT.viewtwith|App(head,args)whenT.is_varhead->Iter.exists(HVar.equalType.equalv)(args|>Iter.of_list|>Iter.flat_mapT.Seq.vars)|Fun(_,body)->Iter.exists(HVar.equalType.equalv)(T.Seq.varsbody)|_->false)|None->false(* apply operation [f] to some parts of the clause [c] just added/removed
from the active set *)let_update_activefc=(* index subterms that can be rewritten by superposition *)letsup_at_vars=Env.flex_getk_sup_at_varsinletsup_in_var_args=Env.flex_getk_sup_in_var_argsinletsup_under_lambdas=Env.flex_getk_sup_under_lambdasinletsup_at_var_headed=Env.flex_getk_sup_at_var_headedinletsup_from_var_headed=Env.flex_getk_sup_from_var_headedinletfluidsup=Env.flex_getk_fluidsupinletsubvarsup=Env.flex_getk_subvarsupinletdupsup=Env.flex_getk_dupsupinletlambdasup=Env.flex_getk_lambdasupinletdemod_in_var_args=Env.flex_getk_demod_in_var_argsinletlambda_demod=Env.flex_getk_lambda_demodinletmoduleTPSet=SClause.TPSetin_idx_sup_into:=Lits.fold_terms~vars:sup_at_vars~var_args:sup_in_var_args~fun_bodies:sup_under_lambdas~ty_args:false~ord~which:`Max~subterms:true~eligible:(C.Eligible.resc)(C.litsc)|>Iter.append(TPSet.to_iter@@C.eligible_subterms_of_boolc)|>Iter.sort_uniq~cmp:(fun(_,p1)(_,p2)->Position.comparep1p2)|>Iter.filter(fun(t,_)->(* Util.debugf ~section 3 "@[ Filtering vars %a,1 @]" (fun k-> k T.pp t); *)(not(T.is_vart)||T.is_ho_vart))(* TODO: could exclude more variables from the index:
they are not needed if they occur with the same args everywhere in the clause *)|>Iter.filter(fun(t,_)->(* Util.debugf ~section 3 "@[ Filtering vars %a,2 @]" (fun k-> k T.pp t); *)sup_at_var_headed||not(T.is_var(T.head_termt)))|>Iter.fold(funtree(t,pos)->Util.debugf~section2"inserting(into):@[@[%a@]|@[%a]@]"(funk->kC.ppcTerm.ppt);letwith_pos=C.WithPos.({term=t;pos;clause=c;})inftreetwith_pos)!_idx_sup_into;(* index subterms that can be rewritten by FluidSup *)iffluidsupthen_idx_fluidsup_into:=Lits.fold_terms~vars:true~var_args:false~fun_bodies:false~ty_args:false~ord~which:`Max~subterms:true~eligible:(C.Eligible.resc)(C.litsc)(* TODO(BOOL): How is this going to be extended for Boolean reasoning? *)|>Iter.filter(fun(t,_)->is_fluid_or_deepct)|>Iter.fold(funtree(t,pos)->letwith_pos=C.WithPos.({term=t;pos;clause=c;})inftreetwith_pos)!_idx_fluidsup_into;(* index subterms that can be rewritten by FluidSup *)ifsubvarsupthen_idx_subvarsup_into:=Lits.fold_terms~vars:true~var_args:false~fun_bodies:false~ty_args:false~ord~which:`Max~subterms:true~eligible:(C.Eligible.resc)(C.litsc)(* TODO(BOOL): How is this going to be extended for Boolean reasoning? *)|>Iter.filter(fun(t,pos)->matchT.viewtwith|T.Var_->has_bad_occurrence_elsewherectpos|T.App(hd,[_])whenT.is_varhd->has_bad_occurrence_elsewherechdpos|_->false)|>Iter.fold(funtree(t,pos)->letwith_pos=C.WithPos.({term=t;pos;clause=c;})inftreetwith_pos)!_idx_subvarsup_into;ifdupsupthen_idx_dupsup_into:=Lits.fold_terms~vars:false~var_args:false~fun_bodies:false~ty_args:false~ord~which:`Max~subterms:true~eligible:(C.Eligible.resc)(C.litsc)(* TODO(BOOL): How is this going to be extended for Boolean reasoning? *)|>Iter.filter(fun(t,_)->T.is_var(T.head_termt)&¬(CCList.is_empty@@T.argst)&&Type.is_ground(T.tyt))(* Only applied variables *)|>Iter.fold(funtree(t,pos)->letwith_pos=C.WithPos.({term=t;pos;clause=c;})inftreetwith_pos)!_idx_dupsup_into;(* index subterms that can be rewritten by LambdaSup --
the ones that can rewrite those are actually the ones
already indexed by _idx_sup_from*)iflambdasup!=_NO_LAMSUPthen_idx_lambdasup_into:=Lits.fold_terms~vars:sup_at_vars~var_args:sup_in_var_args~fun_bodies:true~ty_args:false~ord~which:`Max~subterms:true~eligible:(C.Eligible.resc)(C.litsc)(* We are going only under lambdas *)(* TODO(BOOL): Maybe add bool stuff to LambdaSup *)|>Iter.filter_map(fun(t,p)->ifnot(T.is_funt)thenNoneelse(lettyargs,body=T.open_funtinletnew_pos=List.fold_left(funp_->P.(appendp(bodystop)))ptyargsinlethd=T.head_termbodyinif(not(T.is_varbody)||T.is_ho_varbody)&&(not(T.is_consthd)||not(ID.is_skolem(T.as_const_exnhd)))&&(sup_at_var_headed||not(T.is_var(T.head_termbody)))then((*CCFormat.printf "Adding %a to LS index.\n" T.pp body; *)Some(body,new_pos))elseNone))|>Iter.fold(funtree(t,pos)->letwith_pos=C.WithPos.({term=t;pos;clause=c;})inftreetwith_pos)!_idx_lambdasup_into;(* index terms that can rewrite into other clauses *)_idx_sup_from:=Lits.fold_eqn~ord~both:true~eligible:(C.Eligible.paramc)(C.litsc)|>Iter.filter((fun(_,r,sign,_)->sign||T.equalrT.false_))|>Iter.filter((fun(l,_,_,_)->(Env.flex_getk_superpose_w_formulas)||beginmatchT.viewlwith|T.AppBuiltin((Eq|Neq),_)->false|_->not(T.is_formulal)end))|>Iter.filter(fun(l,_,_,_)->sup_from_var_headed||not(T.is_app_varl))|>Iter.fold(funtree(l,r,sign,pos)->assert(sign||T.equalrT.false_);letwith_pos=C.WithPos.({term=l;pos;clause=c;})inUtil.debugf~section2"inserting(from):@[@[%a@]|@[%a]@]"(funk->kC.ppcTerm.ppl);ftreelwith_pos)!_idx_sup_from;(* terms that can be demodulated: all subterms (but vars) *)_idx_back_demod:=(* TODO: allow demod under lambdas under certain conditions (DemodExt) *)Lits.fold_terms~vars:false~var_args:(demod_in_var_args)~fun_bodies:lambda_demod~ty_args:false~ord~subterms:true~which:`All~eligible:C.Eligible.always(C.litsc)|>Iter.fold(funtree(t,pos)->matchT.viewtwith|T.AppBuiltin(hd,[_;body])->lettree=ifBuiltin.is_quantifierhd&&Env.flex_getk_quant_demodthen(let_,unfolded=T.open_funbodyinletpos=P.(appendpos((P.arg1(P.bodyP.stop))))inletwith_pos=C.WithPos.({term=unfolded;pos;clause=c})inftreeunfoldedwith_pos)elsetreeinletwith_pos=C.WithPos.({term=t;pos;clause=c})inftreetwith_pos|_->letwith_pos=C.WithPos.({term=t;pos;clause=c})inftreetwith_pos)!_idx_back_demod;Signal.ContinueListening(* update simpl. index using the clause [c] just added or removed to
the simplification set *)let_update_simplfc=assert(CCArray.for_allLit.no_prop_invariant(C.litsc));letidx=!_idx_simplinletidx'=matchC.litscwith|[|Lit.Equation(l,r,true)|]->(* do not use formulas for rewriting... can have adverse
effects on lazy cnf *)if(not(Env.flex_getk_rw_with_formulas))&&(T.is_appbuiltinl||(T.is_appbuiltinr&¬@@T.is_true_or_falser))thenidxelse(beginmatchOrdering.compareordlrwith|Comparison.Gt->fidx(l,r,true,c)|Comparison.Lt->fidx(r,l,true,c)|Comparison.Incomparable->letidx=fidx(l,r,true,c)infidx(r,l,true,c)|Comparison.Eq->idx(* no modif *)end)|[|Lit.Equation(l,r,false)|]->fidx(l,r,false,c)|_->idxin_idx_simpl:=idx';Signal.ContinueListeninglet()=Signal.onPS.ActiveSet.on_add_clause(func->_idx_fv:=SubsumIdx.add!_idx_fvc;_update_activeTermIndex.addc);Signal.onPS.ActiveSet.on_remove_clause(func->_idx_fv:=SubsumIdx.remove!_idx_fvc;_update_activeTermIndex.removec);Signal.onPS.SimplSet.on_add_clause(_update_simplUnitIdx.add);Signal.onPS.SimplSet.on_remove_clause(_update_simplUnitIdx.remove);()(** {5 Inference Rules} *)(* ----------------------------------------------------------------------
* Superposition rule
* ---------------------------------------------------------------------- *)typesupkind=|Classic|FluidSup|LambdaSup|DupSup|SubVarSupletkind_to_str=function|Classic->"sup"|FluidSup->"fluidSup"|LambdaSup->"lambdaSup"|DupSup->"dupSup"|SubVarSup->"subVarSup"(* all the information needed for a superposition inference *)moduleSupInfo=structtypet={active:C.t;active_pos:Position.t;(* position of [s] *)scope_active:int;s:T.t;(* lhs of rule *)t:T.t;(* rhs of rule *)passive:C.t;passive_pos:Position.t;(* position of [u_p] *)passive_lit:Lit.t;scope_passive:int;u_p:T.t;(* rewritten subterm *)subst:US.t;sup_kind:supkind;}endexceptionExitSuperpositionofstring(* Checks whether we must allow superposition at variables to be complete. *)letsup_at_var_conditioninfovarreplacement=ifEnv.flex_getk_check_sup_at_var_condthen(letopenSupInfoinletus=info.substinletsubst=US.substusinletrenaming=S.Renaming.create()inletreplacement'=S.FO.applyrenamingsubst(replacement,info.scope_active)inletvar'=S.FO.applyrenamingsubst(var,info.scope_passive)inif(not(Type.is_fun(Term.tyvar'))||not(O.might_flipordvar'replacement'))then(Util.debugf~section5"Cannot flip: %a = %a"(funk->kT.ppvar'T.ppreplacement');false(* If the lhs vs rhs cannot flip, we don't need a sup at var *))else((* Check whether var occurs only with the same arguments everywhere. *)letunique_args_of_varc=C.litsc|>Lits.fold_terms~vars:true~ty_args:false~which:`All~ord~subterms:true~eligible:(fun__->true)|>Iter.fold_while(fununique_args(t,_)->ifTerm.equal(fst(T.as_appt))varthen(ifCCOpt.equal(CCList.equalT.equal)unique_args(Some(snd(T.as_appt)))then(unique_args,`Continue)(* found the same arguments of var again *)else(None,`Stop)(* different arguments of var found *))else(unique_args,`Continue)(* this term doesn't have var as head *))Noneinletunique_vars=ifEnv.flex_getHigher_order.k_prune_arg_fun!=`NoPrunethenNoneelseunique_args_of_varinfo.passiveinmatchunique_varswith|Some_->Util.debugf~section5"Variable %a has same args everywhere in %a"(funk->kT.ppvarC.ppinfo.passive);false(* If var occurs with the same arguments everywhere, we don't need sup at vars *)|None->(* Check whether Cσ is >= C[var -> replacement]σ *)(* This is notoriously hard to implement due to the scope mechanism.
Especially note that var may be of polymorphic type and subst might
map to var, which can easily cause cyclic substitutions. *)letpassive'_lits=Lits.apply_substrenamingsubst(C.litsinfo.passive,info.scope_passive)inletfresh_var=HVar.fresh~ty:(T.tyvar)()inletsubst_fresh_var=US.FO.bindUS.empty(T.as_var_exnvar,info.scope_passive)(T.varfresh_var,info.scope_passive)inletpassive_fresh_var=Lits.apply_substSubst.Renaming.none(US.substsubst_fresh_var)(C.litsinfo.passive,info.scope_passive)inletsubst_replacement=Unif.FO.bindsubst(fresh_var,info.scope_passive)(replacement,info.scope_active)inletpassive_t'_lits=Lits.apply_substrenamingsubst_replacement(passive_fresh_var,info.scope_passive)inifLits.compare_multiset~ordpassive'_litspassive_t'_lits=Comp.Gtthen(Util.debugf~section3"Sup at var condition is not fulfilled because: %a >= %a"(funk->kLits.pppassive'_litsLits.pppassive_t'_lits);false)elsetrue(* If Cσ is either <= or incomparable to C[var -> replacement]σ, we need sup at var.*)))elsefalse(* if k_check_sup_at_var_cond is false, never allow superposition at variable headed terms *)(* check for hidden superposition at variables,
e.g. superposing g x = f x into h (x b) = a to give h (f b) = a.
Returns a term only containing the concerned variable
and a term consisting of the part of info.t that unifies with the variable,
e.g. (x, f) in the example above. *)letis_hidden_sup_at_varinfo=letopenSupInfoinletactive_idx=Lits.Pos.idxinfo.active_posinbeginmatchT.viewinfo.u_pwith|T.App(head,args)->beginmatchT.as_varheadwith|Some_->(* rewritten term is variable-headed *)beginmatchT.viewinfo.s,T.viewinfo.twith|T.App(f,ss),T.App(g,tt)whenList.lengthss>=List.lengthargs&&List.lengthtt>=List.lengthargs->lets_args=Array.of_listssinlett_args=Array.of_listttinletsub_s_args=Array.subs_args(Array.lengths_args-List.lengthargs)(List.lengthargs)|>CCArray.to_listinletsub_t_args=Array.subt_args(Array.lengtht_args-List.lengthargs)(List.lengthargs)|>CCArray.to_listinifArray.lengths_args>=List.lengthargs&&Array.lengtht_args>=List.lengthargs(* Check whether the last argument(s) of s and t are equal *)&&List.for_all(fun(s,t)->T.equalst)(List.combinesub_s_argssub_t_args)(* Check whether they are all variables that occur nowhere else *)&&CCList.(Array.lengths_args-List.lengthargs--^Array.lengths_args)|>List.for_all(funidx->matchT.as_var(Array.gets_argsidx)with|Somev->(* Check whether variable occurs in previous arguments: *)not(CCArray.exists(T.var_occurs~var:v)(Array.subs_args0idx))&¬(CCArray.exists(T.var_occurs~var:v)(Array.subt_args0(Array.lengtht_args-List.lengthargs))(* Check whether variable occurs in heads: *)&¬(T.var_occurs~var:vf)&¬(T.var_occurs~var:vg)(* Check whether variable occurs in other literals: *)&¬(List.exists(Literal.var_occursv)(CCArray.except_idx(C.litsinfo.active)active_idx)))|None->false)then(* Calculate the part of t that unifies with the variable *)lett_prefix=T.appg(Array.to_list(Array.subt_args0(Array.lengtht_args-List.lengthargs)))inSome(head,t_prefix)elseNone|_->Noneend|None->Noneend|_->Noneendletdup_sup_apply_substtsc_asc_psubstrenaming=letz,args=T.as_apptinassert(T.is_varz);assert(CCList.lengthargs>=2);letu_n,t'=CCList.take_drop(List.lengthargs-1)argsinletin_passive=S.FO.applyrenamingsubst(T.appzu_n,sc_p)inlett'=S.FO.applyrenamingsubst(List.hdt',sc_a)inT.appin_passive[t'](* Helper that does one or zero superposition inference, with all
the given parameters. Clauses have a scope. *)letdo_classic_superpositioninfo=letopenSupInfoinletmoduleP=PositioninletmoduleTPS=SClause.TPSetinUtil.incr_statstat_superposition_call;letsc_a=info.scope_activeinletsc_p=info.scope_passiveinassert(InnerTerm.DB.closed(info.s:>InnerTerm.t));assert(info.sup_kind==LambdaSup||InnerTerm.DB.closed(info.u_p:T.t:>InnerTerm.t));assert(not(T.is_varinfo.u_p)||T.is_ho_varinfo.u_p||info.sup_kind=FluidSup);assert(Env.flex_getk_sup_at_var_headed||info.sup_kind=FluidSup||info.sup_kind=DupSup||info.sup_kind=SubVarSup||not(T.is_var(T.head_terminfo.u_p)));letactive_idx=Lits.Pos.idxinfo.active_posinletshift_vars=ifinfo.sup_kind=LambdaSupthen0else-1inletpassive_idx,passive_lit_pos=Lits.Pos.cutinfo.passive_posinletbool_inference=(* optimization -- if no selected subterms, do not enter eligible_subterms_of_bool *)not(CCList.is_empty(C.bool_selectedinfo.passive))&&TPS.mem(info.u_p,info.passive_pos)(C.eligible_subterms_of_boolinfo.passive)inassert(Array.for_allLiteral.no_prop_invariant(C.litsinfo.passive));assert(Array.for_allLiteral.no_prop_invariant(C.litsinfo.active));tryif(info.sup_kind=LambdaSup&&US.has_constrinfo.subst)then(raise(ExitSuperposition"Might sneak in bound vars through constraints."));letrenaming=S.Renaming.create()inletus=info.substinletsubst=US.substusinletlambdasup_vars=if(info.sup_kind=LambdaSup)then(Term.Seq.subterms~include_builtin:trueinfo.u_p|>Iter.filterTerm.is_var|>Term.Set.of_iter)elseTerm.Set.emptyinlett'=ifinfo.sup_kind!=DupSupthenS.FO.apply~shift_varsrenamingsubst(info.t,sc_a)elsedup_sup_apply_substinfo.tsc_asc_psubstrenaminginUtil.debugf~section1"@[<2>sup, kind %s(%d)@ (@[<2>%a[%d]@ @[s=%a@]@ @[t=%a, t'=%a@]@])@ \
(@[<2>%a[%d]@ @[passive_lit=%a@]@ @[p=%a@]@])@ with subst=@[%a@]@]"(funk->k(kind_to_strinfo.sup_kind)(Term.Set.cardinallambdasup_vars)C.ppinfo.activesc_aT.ppinfo.sT.ppinfo.tT.ppt'C.ppinfo.passivesc_pLit.ppinfo.passive_litPosition.ppinfo.passive_posUS.ppinfo.subst);if(info.sup_kind=LambdaSup&&T.Set.exists(funv->not@@T.DB.is_closed@@Subst.FO.apply~shift_varsrenamingsubst(v,sc_p))lambdasup_vars)then(letmsg="LambdaSup: an into free variable sneaks in bound variable"inUtil.debugf~section3"%s"(funk->kmsg);raise@@ExitSuperposition(msg););ifinfo.sup_kind=FluidSup&&Term.equal(Lambda.eta_reduce@@Lambda.snf@@t')(Lambda.eta_reduce@@Lambda.snf@@S.FO.apply~shift_varsrenamingsubst(info.s,sc_a))then(letmsg="Passive literal is trivial after substitution"inUtil.debugf~section3"%s"(funk->kmsg);raise@@ExitSuperposition(msg););(letexit_negative_tl=ExitSuperposition("negative literal must paramodulate "^"into top-level positive position")inletexit_double_sup=ExitSuperposition("superposition could be performed in a different order")inmatchinfo.passive_poswith|P.Arg(_,P.LeftP.Stop)|P.Arg(_,P.RightP.Stop)->ifT.equalt'T.false_then(if(not(Env.flex_getk_superpose_w_formulas)&¬(Lit.is_positivoid(info.passive_lit)))||(Env.flex_getk_superpose_w_formulas&¬(T.is_appbuiltininfo.s))then(raiseexit_negative_tl))elseifLit.is_positivoidinfo.passive_lit&&(* active clause will take the role of passive and that is how
we can compute the resolvent *)C.compareinfo.activeinfo.passive<0then(raiseexit_double_sup);|_->ifT.equalt'T.false_&&(not(Env.flex_getk_superpose_w_formulas)||not@@T.is_appbuiltininfo.s)thenraise@@exit_negative_tl);beginmatchinfo.passive_lit,info.passive_poswith|Lit.Equation(_,v,true),P.Arg(_,P.LeftP.Stop)|Lit.Equation(v,_,true),P.Arg(_,P.RightP.Stop)->(* are we in the specific, but no that rare, case where we
rewrite s=t using s=t (into a tautology t=t)? *)(* TODO: use Unif.FO.eq? *)letv'=S.FO.apply~shift_vars:0renamingsubst(v,sc_p)inifT.equalt'v'then(Util.debugf~section3"will yield a tautology"(funk->k);raise(ExitSuperposition"will yield a tautology");)|_->()end;if(info.sup_kind=LambdaSup)then(letvars_act=CCArray.except_idx(C.litsinfo.active)active_idx|>CCArray.of_list|>Literals.vars|>T.VarSet.of_listinletvars_pas=C.litsinfo.passive|>Literals.vars|>T.VarSet.of_listinletdbs=ref[]inletvars_bound_to_closed_termsvar_setscope=T.VarSet.iter(funv->matchSubst.FO.get_varsubst((v:>InnerTerm.tHVar.t),scope)with|Some(t,_)->dbs:=T.DB.unboundt@!dbs(* hack *)|None->())var_setinvars_bound_to_closed_termsvars_actsc_a;vars_bound_to_closed_termsvars_passc_p;ifUtil.Int_set.cardinal(Util.Int_set.of_list!dbs)>Env.flex_getk_lambdasupthen(letmsg="Too many skolems will be introduced for LambdaSup."inUtil.debugf~section3"%s"(funk->kmsg);raise(ExitSuperpositionmsg);));letsubst',new_sk=ifinfo.sup_kind=LambdaSupthenS.FO.unleak_variablessubstelsesubst,[]inletpassive_lit'=Lit.apply_subst_no_simprenamingsubst'(info.passive_lit,sc_p)inletnew_trail=C.trail_l[info.active;info.passive]inifEnv.is_trivial_trailnew_trailthenraise(ExitSuperposition"trivial trail");lets'=S.FO.apply~shift_varsrenamingsubst(info.s,sc_a)inif(O.compareords't'=Comp.Lt||(* if it was an inference into selected Bool position,
we do not reevaluate BoolSelection on the new literal set
-- in 99% of cases it is selected again,
and if it is Bool selected subterm position then for we do not
check ordering restrictions*)(notbool_inference&¬(Lit.Pos.is_max_term~ordpassive_lit'passive_lit_pos))||(notbool_inference&¬(BV.get(C.eligible_res(info.passive,sc_p)subst)passive_idx))||not(C.is_eligible_param(info.active,sc_a)subst~idx:active_idx))then(letc1=O.compareords't'=Comp.Ltinletc2=notbool_inference&¬(Lit.Pos.is_max_term~ordpassive_lit'passive_lit_pos)inletc3=notbool_inference&¬(BV.get(C.eligible_res(info.passive,sc_p)subst)passive_idx)inletc4=not(C.is_eligible_param(info.active,sc_a)subst~idx:active_idx)inraise(ExitSuperposition(CCFormat.sprintf"bad ordering conditions %b %b %b %b"c1c2c3c4)));(* Check for superposition at a variable *)ifinfo.sup_kind!=FluidSupthenifnot@@Env.flex_getk_sup_at_varsthen(if(T.is_varinfo.u_p)thenraise(ExitSuperposition("sup at var position"));)elseifT.is_varinfo.u_p&¬(sup_at_var_conditioninfoinfo.u_pinfo.t)then(Util.debugf~section3"superposition at variable"(funk->k);raise(ExitSuperposition"superposition at variable"););(* Check for hidden superposition at a variable *)ifEnv.flex_getk_restrict_hidden_sup_at_varsthen(matchis_hidden_sup_at_varinfowith|Some(var,replacement)whennot(sup_at_var_conditioninfovarreplacement)->raise(ExitSuperposition"hidden superposition at variable")|_->());(* ordering constraints are ok *)letlits_a=CCArray.except_idx(C.litsinfo.active)active_idxinletlits_p=CCArray.except_idx(C.litsinfo.passive)passive_idxin(* replace s\sigma by t\sigma in u|_p\sigma *)letnew_passive_lit=Lit.Pos.replacepassive_lit'~at:passive_lit_pos~by:t'inletc_guard=Literal.of_unif_substrenamingusin(* apply substitution to other literals *)(* Util.debugf 1 "Before unleak: %a, after unleak: %a"
(fun k -> k Subst.pp subst Subst.pp subst'); *)letnew_lits=new_passive_lit::c_guard@Lit.apply_subst_listrenamingsubst'(lits_a,sc_a)@Lit.apply_subst_listrenamingsubst'(lits_p,sc_p)inletpos_enclosing_up=Position.until_first_funpassive_lit_posinletfun_context_around_up=Subst.FO.applyrenamingsubst'(Lit.Pos.atinfo.passive_litpos_enclosing_up,sc_p)inletvars=Iter.append(T.Seq.varsfun_context_around_up)(T.Seq.varst')|>Term.VarSet.of_iter|>Term.VarSet.to_listinletskolem_decls=ref[]inletsk_with_vars=List.fold_left(funacct->letsk_decl,new_sk_vars=Term.mk_fresh_skolemvars(Term.tyt)inskolem_decls:=sk_decl::!skolem_decls;Term.Map.addtnew_sk_varsacc)Term.Map.emptynew_skinletnew_lits=List.mapi(funilit->Lit.map(funt->Term.Map.fold(funsksk_vacc->Term.replace~old:sk~by:sk_vacc)sk_with_varst)lit)new_litsinletsubst_is_ho=Subst.codomainsubst|>Iter.exists(fun(t,_)->Iter.exists(funt->T.is_funt||T.is_combt)(T.Seq.subterms~include_builtin:true(T.of_term_unsafet)))inletrule=letr=kind_to_strinfo.sup_kindinletsign=ifLit.is_positivoidpassive_lit'then"+"else"-"inProof.Rule.mk(r^sign)inCCList.iter(fun(sym,ty)->Ctx.declaresymty)!skolem_decls;lettags=(ifsubst_is_ho||info.sup_kind!=Classicthen[Proof.Tag.T_ho]else[])@Unif_subst.tagsusinletproof=Proof.Step.inference~rule~tags[C.proof_parent_substrenaming(info.active,sc_a)subst';C.proof_parent_substrenaming(info.passive,sc_p)subst']andpenalty=letpen_a=C.penaltyinfo.activeinletpen_b=C.penaltyinfo.passiveinletmax_d=max(C.proof_depthinfo.active)(C.proof_depthinfo.passive)in(ifpen_a==1&&pen_b==1then1elsepen_a+pen_b)+(ifinfo.sup_kind==Classic&&T.is_varinfo.sthen1else0)(* superposition from app var = bad, unless we are superposing into a formula *)+(ifinfo.sup_kind==Classic&&T.is_app_varinfo.sthen(ifT.is_var(T.head_terminfo.t)then2*max_delsemax(max_d-2)0)else0)+(ifinfo.sup_kind==FluidSupthenEnv.flex_getk_fluidsup_penaltyelse0)+(ifinfo.sup_kind==DupSupthenEnv.flex_getk_dupsup_penaltyelse0)+(ifinfo.sup_kind==LambdaSupthen1else0)inletnew_clause=C.create~trail:new_trail~penaltynew_litsproofin(* Format.printf "LS: %a\n" C.pp new_clause; *)Util.debugf~section1"@[... ok, conclusion@ @[%a@]@]"(funk->kC.ppnew_clause);if(not(List.for_all(Lit.for_allTerm.DB.is_closed)new_lits))then(CCFormat.printf"@[<2>sup, kind %s(%d)@ (@[<2>%a[%d]@ @[s=%a@]@ @[t=%a, t'=%a@]@])@ \
(@[<2>%a[%d]@ @[passive_lit=%a@]@ @[p=%a@]@])@ with subst=@[%a@]@]"(kind_to_strinfo.sup_kind)(Term.Set.cardinallambdasup_vars)C.ppinfo.activesc_aT.ppinfo.sT.ppinfo.tT.ppt'C.ppinfo.passivesc_pLit.ppinfo.passive_litPosition.ppinfo.passive_posUS.ppinfo.subst;assertfalse;);assert(Array.for_allLiteral.no_prop_invariant(C.litsnew_clause));ifnot(C.litsnew_clause|>Literals.vars_distinct)then(CCFormat.printf"a:@[%a@]@."C.ppinfo.active;CCFormat.printf"p:@[%a@]@."C.ppinfo.passive;CCFormat.printf"r:@[%a@]@."C.ppnew_clause;CCFormat.printf"sub:@[%a@]@."Subst.ppsubst';assertfalse;);Somenew_clausewithExitSuperpositionreason->Util.debugf~section1"... cancel, %s"(funk->kreason);None(* simultaneous superposition: when rewriting D with C \lor s=t,
replace s with t everywhere in D rather than at one place. *)letdo_simultaneous_superpositioninfo=letopenSupInfoinletmoduleP=PositioninletmoduleTPS=SClause.TPSetinUtil.incr_statstat_superposition_call;letsc_a=info.scope_activeinletsc_p=info.scope_passiveinUtil.debugf~section2"@[<hv2>simultaneous sup@ \
@[<2>active@ %a[%d]@ s=@[%a@]@ t=@[%a@]@]@ \
@[<2>passive@ %a[%d]@ passive_lit=@[%a@]@ p=@[%a@]@]@ with subst=@[%a@]@]"(funk->kC.ppinfo.activesc_aT.ppinfo.sT.ppinfo.tC.ppinfo.passivesc_pLit.ppinfo.passive_litPosition.ppinfo.passive_posUS.ppinfo.subst);assert(InnerTerm.DB.closed(info.s:>InnerTerm.t));assert(info.sup_kind==LambdaSup||InnerTerm.DB.closed(info.u_p:T.t:>InnerTerm.t));assert(not(T.is_varinfo.u_p)||T.is_ho_varinfo.u_p||info.sup_kind=FluidSup);assert(Env.flex_getk_sup_at_var_headed||info.sup_kind=FluidSup||info.sup_kind=DupSup||not(T.is_var(T.head_terminfo.u_p)));letactive_idx=Lits.Pos.idxinfo.active_posinletpassive_idx,passive_lit_pos=Lits.Pos.cutinfo.passive_posinletbool_inference=TPS.mem(info.u_p,info.passive_pos)(C.eligible_subterms_of_boolinfo.passive)inletshift_vars=ifinfo.sup_kind=LambdaSupthen0else-1intryletrenaming=S.Renaming.create()inletus=info.substinletsubst=US.substusinlett'=S.FO.apply~shift_varsrenamingsubst(info.t,sc_a)in(letexit_negative_tl=ExitSuperposition("negative literal must paramodulate "^"into top-level positive position")inletexit_double_sup=ExitSuperposition("superposition could be performed in a different order")inmatchinfo.passive_poswith|P.Arg(_,P.LeftP.Stop)|P.Arg(_,P.RightP.Stop)->ifT.equalt'T.false_&¬(Lit.is_positivoid(info.passive_lit))then(raiseexit_negative_tl)elseifLit.is_positivoidinfo.passive_lit&&(* active clause will take the role of passive and that is how
we can compute the resolvent *)C.compareinfo.activeinfo.passive<0then(raiseexit_double_sup);|_->ifT.equalt'T.false_thenraise@@exit_negative_tl);beginmatchinfo.passive_lit,info.passive_poswith|Lit.Equation(_,v,true),P.Arg(_,P.LeftP.Stop)|Lit.Equation(v,_,true),P.Arg(_,P.RightP.Stop)->(* are we in the specific, but no that rare, case where we
rewrite s=t using s=t (into a tautology t=t)? *)letv'=S.FO.apply~shift_varsrenamingsubst(v,sc_p)inifT.equalt'v'thenraise(ExitSuperposition"will yield a tautology");|_->()end;letpassive_lit'=Lit.apply_subst_no_simprenamingsubst(info.passive_lit,sc_p)inletnew_trail=C.trail_l[info.active;info.passive]inifEnv.is_trivial_trailnew_trailthenraise(ExitSuperposition"trivial trail");lets'=S.FO.apply~shift_varsrenamingsubst(info.s,sc_a)inif(O.compareords't'=Comp.Lt||(notbool_inference&¬(Lit.Pos.is_max_term~ordpassive_lit'passive_lit_pos))||(notbool_inference&¬(BV.get(C.eligible_res(info.passive,sc_p)subst)passive_idx))||not(C.is_eligible_param(info.active,sc_a)subst~idx:active_idx))thenraise(ExitSuperposition"bad ordering conditions");(* Check for superposition at a variable *)ifinfo.sup_kind!=FluidSupthenifnot@@Env.flex_getk_sup_at_varsthen(if(T.is_varinfo.u_p)thenraise(ExitSuperposition("sup at var position"));)elseifT.is_varinfo.u_p&¬(sup_at_var_conditioninfoinfo.u_pinfo.t)thenraise(ExitSuperposition"superposition at variable");(* ordering constraints are ok, build new active lits (excepted s=t) *)letlits_a=CCArray.except_idx(C.litsinfo.active)active_idxinletlits_a=Lit.apply_subst_listrenamingsubst(lits_a,sc_a)in(* build passive literals and replace u|p\sigma with t\sigma *)letu'=S.FO.apply~shift_varsrenamingsubst(info.u_p,sc_p)inassert(Type.equal(T.tyu')(T.tyt'));letlits_p=Array.to_list(C.litsinfo.passive)inletlits_p=Lit.apply_subst_listrenamingsubst(lits_p,sc_p)in(* assert (T.equal (Lits.Pos.at (Array.of_list lits_p) info.passive_pos) u'); *)letlits_p=List.map(Lit.map(funt->T.replacet~old:u'~by:t'))lits_pinletc_guard=Literal.of_unif_substrenamingusin(* build clause *)letnew_lits=c_guard@lits_a@lits_pinletrule=letr=kind_to_strinfo.sup_kindinletsign=ifLit.is_positivoidpassive_lit'then"+"else"-"inProof.Rule.mk("s_"^r^sign)inletsubst_is_ho=Subst.codomainsubst|>Iter.exists(fun(t,_)->Iter.exists(funt->T.is_funt||T.is_combt)(T.Seq.subterms~include_builtin:true(T.of_term_unsafet)))inlettags=(ifsubst_is_hothen[Proof.Tag.T_ho]else[])@Unif_subst.tagsusinletproof=Proof.Step.inference~rule~tags[C.proof_parent_substrenaming(info.active,sc_a)subst;C.proof_parent_substrenaming(info.passive,sc_p)subst]andpenalty=letpen_a=C.penaltyinfo.activeinletpen_b=C.penaltyinfo.passivein(ifpen_a==1&&pen_b==1then1elsepen_a+pen_b+1)+(ifT.is_vars'then2else0)(* superposition from var = bad *)+(ifUS.has_constrinfo.substthen1else0)inletnew_clause=C.create~trail:new_trail~penaltynew_litsproofinUtil.debugf~section2"@[... ok, conclusion@ @[%a@]@]"(funk->kC.ppnew_clause);assert(C.litsnew_clause|>Literals.vars_distinct);Somenew_clausewithExitSuperpositionreason->Util.debugf~section2"@[... cancel, %s@]"(funk->kreason);None(* choose between regular and simultaneous superposition *)letdo_superpositioninfo=letopenSupInfoinassert(info.sup_kind=DupSup||info.sup_kind=SubVarSup||Type.equal(T.tyinfo.s)(T.tyinfo.t));assert(info.sup_kind=DupSup||info.sup_kind=SubVarSup||Unif.Ty.equal~subst:(US.substinfo.subst)(T.tyinfo.s,info.scope_active)(T.tyinfo.u_p,info.scope_passive));letrenaming=Subst.Renaming.create()inletshift_vars=ifinfo.sup_kind=LambdaSupthen0else-1inlets=Subst.FO.apply~shift_varsrenaming(US.substinfo.subst)(info.s,info.scope_active)inletu_p=Subst.FO.apply~shift_varsrenaming(US.substinfo.subst)(info.u_p,info.scope_passive)inletnormt=T.normalize_bools@@Lambda.eta_expand@@Lambda.snftinifinfo.sup_kind!=SubVarSup&¬(Term.equal(norm@@s)(norm@@u_p)||US.has_constrinfo.subst)then(CCFormat.printf"@[<2>sup, kind %s@ (@[<2>%a[%d]@ @[s=%a@]@ @[t=%a@]@])@ \
(@[<2>%a[%d]@ @[passive_lit=%a@]@ @[p=%a@]@])@ with subst=@[%a@]@].\n"(kind_to_strinfo.sup_kind)C.ppinfo.activeinfo.scope_activeT.ppinfo.sT.ppinfo.tC.ppinfo.passiveinfo.scope_passiveLit.ppinfo.passive_litPosition.ppinfo.passive_posUS.ppinfo.subst;CCFormat.printf"orig_s:@[%a@]@."T.ppinfo.s;CCFormat.printf"norm_s:@[%a@]@."T.pp(norms);CCFormat.printf"orig_u_p:@[%a@]@."T.ppinfo.u_p;CCFormat.printf"norm_u_p:@[%a@]@."T.pp(normu_p);assertfalse;);ifEnv.flex_getk_use_simultaneous_sup&&info.sup_kind!=LambdaSup&&info.sup_kind!=DupSupthendo_simultaneous_superpositioninfoelsedo_classic_superpositioninfoletinfer_active_aux~retrieve_from_index~process_retrievedclause=let_span=ZProf.enter_profprof_infer_activein(* no literal can be eligible for paramodulation if some are selected.
This checks if inferences with i-th literal are needed? *)leteligible=C.Eligible.paramclausein(* do the inferences where clause is active; for this,
we try to rewrite conditionally other clauses using
non-minimal sides of every positive literal *)letnew_clauses=Lits.fold_eqn~ord~both:true~eligible(C.litsclause)|>Iter.filter(fun(_,t,sign,_)->sign||T.equaltT.false_)|>Iter.flat_map(fun(s,t,_,s_pos)->letdo_supu_pwith_possubst=(* rewrite u_p with s *)ifT.DB.is_closedu_pthenletpassive=with_pos.C.WithPos.clauseinletpassive_pos=with_pos.C.WithPos.posinletpassive_lit,_=Lits.Pos.lit_at(C.litspassive)passive_posinletinfo=SupInfo.({s;t;active=clause;active_pos=s_pos;scope_active=0;u_p;passive;passive_lit;passive_pos;scope_passive=1;subst;sup_kind=Classic})indo_superpositioninfoelseNonein(* rewrite clauses using s *)retrieve_from_index(!_idx_sup_into,1)(s,0)|>Iter.filter_map(process_retrieveddo_sup))|>Iter.to_rev_listinZProf.exit_prof_span;new_clausesletinfer_passive_aux~retrieve_from_index~process_retrievedclause=let_span=ZProf.enter_profprof_infer_passivein(* perform inference on this lit? *)leteligible=C.Eligible.(resclause)in(* do the inferences in which clause is passive (rewritten),
so we consider both negative and positive literals *)letmoduleTPSet=SClause.TPSetinletnew_clauses=Lits.fold_terms~vars:(Env.flex_getk_sup_at_vars)~var_args:(Env.flex_getk_sup_in_var_args)~fun_bodies:(Env.flex_getk_sup_under_lambdas)~subterms:true~ord~which:`Max~eligible~ty_args:false(C.litsclause)|>Iter.append(TPSet.to_iter(C.eligible_subterms_of_boolclause))|>Iter.sort_uniq~cmp:(fun(_,p1)(_,p2)->Position.comparep1p2)|>Iter.filter(fun(u_p,_)->not(T.is_varu_p)||T.is_ho_varu_p)|>Iter.filter(fun(u_p,_)->T.DB.is_closedu_p)|>Iter.filter(fun(u_p,_)->Env.flex_getk_sup_at_var_headed||not(T.is_var(T.head_termu_p)))|>Iter.flat_map(fun(u_p,passive_pos)->letpassive_lit,_=Lits.Pos.lit_at(C.litsclause)passive_posinletdo_sup_with_possubst=letactive=with_pos.C.WithPos.clauseinlets_pos=with_pos.C.WithPos.posinmatchLits.View.get_eqn(C.litsactive)s_poswith|Some(s,t,true)->letinfo=SupInfo.({s;t;active;active_pos=s_pos;scope_active=1;subst;u_p;passive=clause;passive_lit;passive_pos;scope_passive=0;sup_kind=Classic})indo_superpositioninfo|_->Nonein(* all terms that occur in an equation in the active_set
and that are potentially unifiable with u_p (u at position p) *)retrieve_from_index(!_idx_sup_from,1)(u_p,0)|>Iter.filter_map(process_retrieveddo_sup))|>Iter.to_rev_listinZProf.exit_prof_span;new_clausesletinfer_activeclause=infer_active_aux~retrieve_from_index:(I.retrieve_unifiables)~process_retrieved:(fundo_sup(u_p,with_pos,subst)->do_supu_pwith_possubst)clauseletinfer_lambdasup_fromclause=(* no literal can be eligible for paramodulation if some are selected.
This checks if inferences with i-th literal are needed? *)leteligible=C.Eligible.paramclausein(* do the inferences where clause is active; for this,
we try to rewrite conditionally other clauses using
non-minimal sides of every positive literal *)Lits.fold_eqn~ord~both:true~eligible(C.litsclause)|>Iter.filter(fun(_,t,sign,_)->sign||T.equaltT.false_)|>Iter.flat_map(fun(s,t,_,s_pos)->letdo_lambdasupu_pwith_possubst=(* rewrite u_p with s *)letpassive=with_pos.C.WithPos.clauseinletpassive_pos=with_pos.C.WithPos.posinletpassive_lit,_=Lits.Pos.lit_at(C.litspassive)passive_posinletinfo=SupInfo.({s;t;active=clause;active_pos=s_pos;scope_active=0;u_p;passive;passive_lit;passive_pos;scope_passive=1;subst;sup_kind=LambdaSup})inUtil.debugf~section10"[Trying lambdasup from %a into %a with term %a into term %a]"(funk->kC.ppclauseC.pppassiveT.ppsT.ppu_p);do_superpositioninfoinI.retrieve_unifiables(!_idx_lambdasup_into,1)(s,0)|>Iter.filter_map(fun(u_p,with_pos,subst)->do_lambdasupu_pwith_possubst))|>Iter.to_rev_listletinfer_passiveclause=infer_passive_aux~retrieve_from_index:(I.retrieve_unifiables)~process_retrieved:(fundo_sup(u_p,with_pos,subst)->do_supu_pwith_possubst)clauseletinfer_lambdasup_intoclause=let_span=ZProf.enter_profprof_infer_activein(* perform inference on this lit? *)leteligible=C.Eligible.(resclause)in(* do the inferences in which clause is passive (rewritten),
so we consider both negative and positive literals *)letnew_clauses=Lits.fold_terms~vars:(Env.flex_getk_sup_at_vars)~var_args:(Env.flex_getk_sup_in_var_args)~fun_bodies:true~subterms:true~ord~which:`Max~eligible~ty_args:false(C.litsclause)|>Iter.filter_map(fun(u_p,p)->(* we rewrite only under lambdas *)ifnot(T.is_funu_p)thenNoneelse(lettyargs,body=T.open_funu_pinlethd=T.head_termbodyinletnew_pos=List.fold_left(funp_->P.(appendp(bodystop)))ptyargsin(* we check normal superposition conditions *)if(not(T.is_varbody)||T.is_ho_varbody)&&(not(T.is_consthd)||not(ID.is_skolem(T.as_const_exnhd)))&&(Env.flex_getk_sup_at_var_headed||not(T.is_var(T.head_termbody)))thenSome(body,new_pos)elseNone))|>Iter.flat_map(fun(u_p,passive_pos)->letpassive_lit,_=Lits.Pos.lit_at(C.litsclause)passive_posinletdo_sup_with_possubst=letactive=with_pos.C.WithPos.clauseinlets_pos=with_pos.C.WithPos.posinmatchLits.View.get_eqn(C.litsactive)s_poswith|Some(s,t,true)->letinfo=SupInfo.({s;t;active;active_pos=s_pos;scope_active=1;subst;u_p;passive=clause;passive_lit;passive_pos;scope_passive=0;sup_kind=LambdaSup})inUtil.debugf~section10"[Trying lambdasup from %a into %a with term %a into term %a]"(funk->kC.ppactiveC.ppclauseT.ppsT.ppu_p);do_superpositioninfo|_->Nonein(* all terms that occur in an equation in the active_set
and that are potentially unifiable with u_p (u at position p) *)I.retrieve_unifiables(!_idx_sup_from,1)(u_p,0)|>Iter.filter_map(fun(t,p,s)->do_suptps))|>Iter.to_rev_listinZProf.exit_prof_span;new_clausesletinfer_active_complete_hoclause=letinf_res=infer_active_aux~retrieve_from_index:(I.retrieve_unifiables_complete~unif_alg:(Env.flex_getk_unif_alg))~process_retrieved:(fundo_sup(u_p,with_pos,substs)->(* let penalty = max (C.penalty clause) (C.penalty with_pos.C.WithPos.clause) in *)(* /!\ may differ from the actual penalty (by -2) *)letparents=[clause;with_pos.clause]inletp=max(C.penaltyclause)(C.penaltywith_pos.clause)inSome(p,parents,OSeq.map(CCOpt.flat_map(do_supu_pwith_pos))substs))clauseinifEnv.should_force_stream_eval()then(Env.get_finite_infs(List.map(fun(_,_,x)->x)inf_res))else(letclauses,streams=force_getting_clinf_resinStmQ.add_lst(Env.get_stm_queue())streams;clauses)letinfer_passive_complete_hoclause=letinf_res=infer_passive_aux~retrieve_from_index:(I.retrieve_unifiables_complete~unif_alg:(Env.flex_getk_unif_alg))~process_retrieved:(fundo_sup(u_p,with_pos,substs)->(* let penalty = max (C.penalty clause) (C.penalty with_pos.C.WithPos.clause) in *)(* /!\ may differ from the actual penalty (by -2) *)letparents=[clause;with_pos.clause]inletp=max(C.penaltyclause)(C.penaltywith_pos.clause)inSome(p,parents,OSeq.map(CCOpt.flat_map(do_supu_pwith_pos))substs))clauseinifEnv.should_force_stream_eval()then(Env.get_finite_infs(List.map(fun(_,_,x)->x)inf_res))else(letclauses,streams=force_getting_clinf_resinStmQ.add_lst(Env.get_stm_queue())streams;clauses)(* ----------------------------------------------------------------------
* FluidSup rule (Superposition at applied variables)
* ---------------------------------------------------------------------- *)letinfer_fluidsup_activeclause=let_span=ZProf.enter_profprof_infer_fluidsup_activein(* no literal can be eligible for paramodulation if some are selected.
This checks if inferences with i-th literal are needed? *)leteligible=C.Eligible.paramclausein(* do the inferences where clause is active; for this,
we try to rewrite conditionally other clauses using
non-minimal sides of every positive literal *)letnew_clauses=iffluidsup_applicableclausethenLits.fold_eqn~ord~both:true~eligible(C.litsclause)|>Iter.filter(fun(_,t,sign,_)->sign||T.equaltT.false_)|>Iter.flat_map(fun(s,t,_,s_pos)->I.fold!_idx_fluidsup_into(funaccu_pwith_pos->assert(is_fluid_or_deepwith_pos.C.WithPos.clauseu_p);assert(T.DB.is_closedu_p);(* Create prefix variable H and use H s = H t for superposition *)letvar_h=T.var(HVar.fresh~ty:(Type.arrow[T.tys](Type.var(HVar.fresh~ty:Type.tType())))())inleths=T.appvar_h[s]inletht=T.appvar_h[t]inletres=Env.flex_getk_unif_alg(u_p,1)(hs,0)|>OSeq.map(funosubst->osubst|>CCOpt.flat_map(funsubst->letpassive=with_pos.C.WithPos.clauseinletpassive_pos=with_pos.C.WithPos.posinletpassive_lit,_=Lits.Pos.lit_at(C.litspassive)passive_posinletinfo=SupInfo.({s=hs;t=ht;active=clause;active_pos=s_pos;scope_active=0;u_p;passive;passive_lit;passive_pos;scope_passive=1;subst;sup_kind=FluidSup})indo_superpositioninfo))inletpenalty=max(C.penaltyclause)(C.penaltywith_pos.C.WithPos.clause)+(Env.flex_getk_fluidsup_penalty)in(* /!\ may differ from the actual penalty (by -2) *)Iter.cons(penalty,res,[clause;with_pos.clause])acc)Iter.empty)|>Iter.to_rev_listelse[]inifEnv.should_force_stream_eval()then(Env.get_finite_infs(List.map(fun(_,x,_)->x)new_clauses))else(letstm_res=List.map(fun(p,s,parents)->Stm.make~penalty:p~parents(s))new_clausesinStmQ.add_lst(Env.get_stm_queue())stm_res;ZProf.exit_prof_span;[])letinfer_fluidsup_passiveclause=let_span=ZProf.enter_profprof_infer_fluidsup_passivein(* perform inference on this lit? *)leteligible=C.Eligible.(resclause)in(* do the inferences in which clause is passive (rewritten),
so we consider both negative and positive literals *)letnew_clauses=iffluidsup_applicableclausethenLits.fold_terms~vars:true~var_args:false~fun_bodies:false~subterms:true~ord~which:`Max~eligible~ty_args:false(C.litsclause)|>Iter.filter(fun(u_p,_)->is_fluid_or_deepclauseu_p)|>Iter.flat_map(fun(u_p,passive_pos)->letpassive_lit,_=Lits.Pos.lit_at(C.litsclause)passive_posinI.fold!_idx_sup_from(funacc_with_pos->letactive=with_pos.C.WithPos.clauseinlets_pos=with_pos.C.WithPos.posinletres=matchLits.View.get_eqn(C.litsactive)s_poswith|Some(s,t,true)->(* Create prefix variable H and use H s = H t for superposition *)letvar_h=T.var(HVar.fresh~ty:(Type.arrow[T.tys](Type.var(HVar.fresh~ty:Type.tType())))())inleths=T.appvar_h[s]inletht=T.appvar_h[t]inEnv.flex_getk_unif_alg(hs,1)(u_p,0)|>OSeq.map(funosubst->osubst|>CCOpt.flat_map(funsubst->letinfo=SupInfo.({s=hs;t=ht;active;active_pos=s_pos;scope_active=1;subst;u_p;passive=clause;passive_lit;passive_pos;scope_passive=0;sup_kind=FluidSup})indo_superpositioninfo))|_->assertfalseinletpenalty=max(C.penaltyclause)(C.penaltywith_pos.C.WithPos.clause)+Env.flex_getk_fluidsup_penaltyin(* /!\ may differ from the actual penalty (by -2) *)Iter.cons(penalty,res,[clause;with_pos.clause])acc)Iter.empty)|>Iter.to_rev_listelse[]inifEnv.should_force_stream_eval()then(Env.get_finite_infs(List.map(fun(_,x,_)->x)new_clauses))else(letstm_res=List.map(fun(p,s,parents)->Stm.make~penalty:p~parents(s))new_clausesinStmQ.add_lst(Env.get_stm_queue())stm_res;ZProf.exit_prof_span;[])(* ----------------------------------------------------------------------
* DupSup rule (Lightweight superposition at applied variables)
* ---------------------------------------------------------------------- *)letinfer_dupsup_activeclause=let_span=ZProf.enter_profprof_infer_activeinleteligible=C.Eligible.paramclauseinletnew_clauses=Lits.fold_eqn~ord~both:true~eligible(C.litsclause)|>Iter.filter(fun(_,t,sign,_)->sign||T.equaltT.false_)|>Iter.flat_map(fun(s,t,_,s_pos)->I.fold!_idx_dupsup_into(funaccu_pwith_pos->assert(T.is_var(T.head_termu_p));assert(T.DB.is_closedu_p);if(T.Seq.varss|>Iter.append(T.Seq.varst)|>Iter.exists(funv->Type.is_tType(HVar.tyv)))then(acc)else(letscope_passive,scope_active=0,1inlethd_up,args_up=T.as_appu_pinletarg_types=List.mapT.tyargs_upinletn=List.lengthargs_upinletvar_up=T.as_var_exnhd_upinletvar_w=HVar.fresh~ty:(Type.arrowarg_types(T.tyt))()inletvar_z=HVar.fresh~ty:(Type.arrow(arg_types@[T.tyt])(T.tyu_p))()inletdb_args=List.mapi(funity->T.bvar~ty(n-1-i))arg_typesinletterm_w,term_z=T.varvar_w,T.varvar_zinletw_db=T.appterm_wdb_argsinletz_db=T.appterm_z(db_args@[w_db])inlety_subst_val=T.fun_larg_typesz_dbinassert(T.DB.is_closedy_subst_val);letsubst_y=US.FO.bind(US.empty)(var_up,scope_passive)(y_subst_val,scope_passive)inletw_args=T.appterm_wargs_upinletw_args=Subst.FO.applySubst.Renaming.none(US.substsubst_y)(w_args,scope_passive)inletz_args=T.appterm_z(args_up@[t])inletres=Env.flex_getk_unif_alg(s,scope_active)(w_args,scope_passive)|>OSeq.map(funosubst->osubst|>CCOpt.flat_map(funsubst->letsubst=US.mergesubstsubst_yinletpassive=with_pos.C.WithPos.clauseinletpassive_pos=with_pos.C.WithPos.posinletpassive_lit,_=Lits.Pos.lit_at(C.litspassive)passive_posinletinfo=SupInfo.({s;t=z_args;active=clause;active_pos=s_pos;scope_active;u_p=w_args;passive;passive_lit;passive_pos;scope_passive;subst;sup_kind=DupSup})indo_superpositioninfo))inletpenalty=max(C.penaltyclause)(C.penaltywith_pos.C.WithPos.clause)+(Env.flex_getk_fluidsup_penalty/3)in(* /!\ may differ from the actual penalty (by -2) *)Iter.cons(penalty,res,[clause;with_pos.clause])acc))Iter.empty)|>Iter.to_rev_listinifEnv.should_force_stream_eval()then(Env.get_finite_infs(List.map(fun(_,x,_)->x)new_clauses))else(letstm_res=List.map(fun(p,s,parents)->Stm.make~penalty:p~parents(s))new_clausesinStmQ.add_lst(Env.get_stm_queue())stm_res;ZProf.exit_prof_span;[])letinfer_dupsup_passiveclause=let_span=ZProf.enter_profprof_infer_fluidsup_passivein(* perform inference on this lit? *)leteligible=C.Eligible.(resclause)in(* do the inferences in which clause is passive (rewritten),
so we consider both negative and positive literals *)letnew_clauses=Lits.fold_terms~vars:false~var_args:false~fun_bodies:false~subterms:true~ord~which:`Max~eligible~ty_args:false(C.litsclause)|>Iter.filter(fun(u_p,_)->(T.is_var(T.head_termu_p)&¬(CCList.is_empty@@T.argsu_p)&&Type.is_ground(T.tyu_p)))|>Iter.flat_map(fun(u_p,passive_pos)->letpassive_lit,_=Lits.Pos.lit_at(C.litsclause)passive_posinI.fold!_idx_sup_from(funacc_with_pos->letactive=with_pos.C.WithPos.clauseinlets_pos=with_pos.C.WithPos.posinmatchLits.View.get_eqn(C.litsactive)s_poswith|Some(s,t,true)->(if(T.Seq.varss|>Iter.append(T.Seq.varst)|>Iter.exists(funv->Type.is_tType(HVar.tyv)))then(acc)else(letscope_passive,scope_active=0,1inlethd_up,args_up=T.as_appu_pinletarg_types=List.mapT.tyargs_upinletn=List.lengthargs_upinletvar_up=T.as_var_exnhd_upinletvar_w=HVar.fresh~ty:(Type.arrowarg_types(T.tyt))()inletvar_z=HVar.fresh~ty:(Type.arrow(List.appendarg_types[(T.tyt)])(T.tyu_p))()inletdb_args=List.mapi(funity->T.bvar~ty(n-1-i))arg_typesinletterm_w,term_z=T.varvar_w,T.varvar_zinletw_db=T.appterm_wdb_argsinletz_db=T.appterm_z(List.appenddb_args[w_db])inlety_subst_val=T.fun_larg_typesz_dbinassert(T.DB.is_closedy_subst_val);letsubst_y=US.FO.bind(US.empty)(var_up,scope_passive)(y_subst_val,scope_passive)inletw_args=T.appterm_wargs_upinletw_args=Subst.FO.applySubst.Renaming.none(US.substsubst_y)(w_args,scope_passive)inletz_args=T.appterm_z(List.appendargs_up[t])inletres=Env.flex_getk_unif_alg(w_args,scope_passive)(s,scope_active)|>OSeq.map(funosubst->osubst|>CCOpt.flat_map(funsubst->letsubst=US.mergesubstsubst_yinletinfo=SupInfo.({s;t=z_args;active;active_pos=s_pos;scope_active;u_p=w_args;passive=clause;passive_lit;passive_pos;scope_passive;subst;sup_kind=DupSup})indo_superpositioninfo))inletpenalty=max(C.penaltyclause)(C.penaltywith_pos.C.WithPos.clause)+((Env.flex_getk_fluidsup_penalty)/3)in(* /!\ may differ from the actual penalty (by -2) *)Iter.cons(penalty,res,[clause;with_pos.clause])acc))|_->acc)Iter.empty)|>Iter.to_rev_listinifEnv.should_force_stream_eval()then(Env.get_finite_infs(List.map(fun(_,x,_)->x)new_clauses))else(letstm_res=List.map(fun(p,s,parents)->Stm.make~penalty:p~parents(s))new_clausesinStmQ.add_lst(Env.get_stm_queue())stm_res;ZProf.exit_prof_span;[])(* ----------------------------------------------------------------------
* SubVarSup rules
* ---------------------------------------------------------------------- *)letdo_subvarsup~active_pos~passive_pos=(* Variable names in each clause renamed apart *)letrenaming=Subst.Renaming.create()inletrename_termt=Subst.FO.applyrenamingSubst.emptytinletsc_a,sc_p=0,1inletcl_a,cl_p=C.apply_subst~renaming(active_pos.C.WithPos.clause,sc_a)Subst.empty,C.apply_subst~renaming(passive_pos.C.WithPos.clause,sc_p)Subst.emptyinlets,t=matchLits.View.get_eqn(C.litscl_a)active_pos.C.WithPos.poswith|Some(l,r,_)->l,r|_->invalid_arg"active lit must be an equation"inassert(T.is_vart||T.is_app_vart||T.is_combt);letu_p=rename_term(passive_pos.C.WithPos.term,sc_p)inletvar,args=matchT.viewu_pwith|T.Varv->v,[]|T.App(hd,[x])whenT.is_varhd->T.as_var_exnhd,[x]|_->invalid_arg"u_p must be of the form y or y s"inletz_ty=Type.arrow[T.tyt](HVar.tyvar)inletz=T.app(T.var@@HVar.fresh~ty:z_ty())[t]inletsubst=Subst.FO.bind'Subst.empty(var,0)(z,0)inletpassive_lit,_=Lits.Pos.lit_at(C.litscl_p)passive_pos.C.WithPos.posinletsup_info=SupInfo.{active=cl_a;active_pos=active_pos.C.WithPos.pos;scope_active=0;s;t=T.appzargs;passive=cl_p;passive_pos=passive_pos.C.WithPos.pos;scope_passive=0;passive_lit;u_p;subst=US.of_substsubst;sup_kind=SubVarSup}indo_superpositionsup_infoletinfer_subvarsup_activeclause=leteligible=C.Eligible.paramclauseinLits.fold_eqn~ord~both:true~eligible(C.litsclause)|>Iter.filter(fun(_,t,sign,_)->sign||T.equaltT.false_)|>Iter.filter(fun(_,t,_,_)->T.is_vart||T.is_app_vart||T.is_combt)|>Iter.flat_map(fun(s,t,_,s_pos)->(* rewrite clauses using s *)I.fold!_idx_subvarsup_into(funacc_with_pos->letactive_pos=C.WithPos.{term=s;pos=s_pos;clause}inmatchdo_subvarsup~passive_pos:with_pos~active_poswith|Somec->Util.debugf~section2"svs: @[%a@]@. @[%a@]. @[%a@]@."(funk->kC.ppclauseC.ppwith_pos.clauseC.ppc);Iter.conscacc|None->acc)Iter.empty)|>Iter.to_rev_listletinfer_subvarsup_passiveclause=leteligible=C.Eligible.(resclause)inLits.fold_terms~vars:true~var_args:false~fun_bodies:false~subterms:true~ord~which:`Max~eligible~ty_args:false(C.litsclause)|>Iter.filter(fun(t,pos)->matchT.viewtwith|T.Var_->has_bad_occurrence_elsewhereclausetpos|T.App(hd,[x])->has_bad_occurrence_elsewhereclausehdpos|_->false)|>Iter.flat_map(fun(u_p,passive_pos)->I.fold!_idx_sup_from(funacc_with_pos->letpassive_pos=C.WithPos.{term=u_p;pos=passive_pos;clause}inmatchLits.View.get_eqn(C.litswith_pos.C.WithPos.clause)with_pos.C.WithPos.poswith|Some(l,r,_)whenT.is_varr||T.is_app_varr||T.is_combr->beginmatchdo_subvarsup~passive_pos~active_pos:with_poswith|Somec->Util.debugf~section2"svs: @[%a@]@. @[%a@]. @[%a@]@."(funk->kC.ppwith_pos.clauseC.ppclauseC.ppc);Iter.conscacc|None->accend|_->acc)Iter.empty)|>Iter.to_rev_list(* ----------------------------------------------------------------------
* Equality Resolution rule
* ---------------------------------------------------------------------- *)letinfer_equality_resolution_aux~unify~iterate_substsclause=let_span=ZProf.enter_profprof_infer_equality_resolutioninleteligible=C.Eligible.filter(funlit->not@@Lit.is_predicate_litlit)in(* iterate on those literals *)letnew_clauses=Lits.fold_eqn~sign:false~ord~both:false~eligible(C.litsclause)|>Iter.filter_map(fun(l,r,_,l_pos)->letdo_eq_resus=letpos=Lits.Pos.idxl_posin(* CCFormat.printf "trying %d@." pos; *)leteligible=BV.get(C.eligible_res_no_substclause)posinifeligible(* subst(lit) is maximal, we can do the inference *)then(Util.incr_statstat_equality_resolution_call;letrenaming=Subst.Renaming.create()inletsubst=US.substusinletrule=Proof.Rule.mk"eq_res"inletnew_lits=CCArray.except_idx(C.litsclause)posinletnew_lits=Lit.apply_subst_listrenamingsubst(new_lits,0)inletc_guard=Literal.of_unif_substrenamingusinletsubst_is_ho=Subst.codomainsubst|>Iter.exists(fun(t,_)->Iter.exists(funt->T.is_funt||T.is_combt)(T.Seq.subterms~include_builtin:true(T.of_term_unsafet)))inlettags=(ifsubst_is_hothen[Proof.Tag.T_ho]else[])@Unif_subst.tagsusinlettrail=C.trailclauseinletpenalty=ifC.penaltyclause=1then1elseC.penaltyclause+1inletproof=Proof.Step.inference~rule~tags[C.proof_parent_substrenaming(clause,0)subst]inletnew_clause=C.create~trail~penalty(c_guard@new_lits)proofin(* CCFormat.printf "success: @[%a@]@." C.pp new_clause; *)Util.debugf~section2"@[<hv2>equality resolution on@ @[%a@]@ yields @[%a@],\n subst @[%a@]@]"(funk->kC.ppclauseC.ppnew_clauseUS.ppus);Somenew_clause)elseNoneinletsubsts=unify(l,0)(r,0)initerate_substssubstsdo_eq_res)|>Iter.to_rev_listinZProf.exit_prof_span;new_clausesletinfer_equality_resolutionc=infer_equality_resolution_aux~unify:(funlr->trySome(Unif.FO.unify_fulllr)withUnif.Fail->None)~iterate_substs:(funsubstsdo_eq_res->CCOpt.flat_mapdo_eq_ressubsts)cletinfer_equality_resolution_complete_hoclause=letinf_res=infer_equality_resolution_aux~unify:(Env.flex_getk_unif_alg)~iterate_substs:(funsubstsdo_eq_res->Some(OSeq.map(CCOpt.flat_mapdo_eq_res)substs))clauseinifEnv.should_force_stream_eval()then(Env.get_finite_infsinf_res)else(letcls,stm_res=force_getting_cl(List.map(funstm->C.penaltyclause,[clause],stm)inf_res)inStmQ.add_lst(Env.get_stm_queue())stm_res;cls)(* ----------------------------------------------------------------------
* Equality Factoring rule
* ---------------------------------------------------------------------- *)moduleEqFactInfo=structtypet={clause:C.t;active_idx:int;is_pred_var_eq_fact:bool;s:T.t;t:T.t;u:T.t;v:T.t;subst:US.t;scope:int;}end(* do the inference between given positions, if ordering conditions are respected *)letdo_eq_factoringinfo=letopenEqFactInfoinlets=info.sandt=info.tandv=info.vandidx=info.active_idxinletus=info.substin(* check whether subst(lit) is maximal, and not (subst(s) < subst(t)) *)letrenaming=S.Renaming.create()inletsubst=US.substusinif((Env.flex_getk_pred_var_eq_fact&&info.is_pred_var_eq_fact&&C.proof_depthinfo.clause<2&¬(T.is_true_or_falset))||(O.compareord(S.FO.applyrenamingsubst(s,info.scope))(S.FO.applyrenamingsubst(t,info.scope))<>Comp.Lt&&CCList.for_all(fun(c,i)->i=idx)(C.selected_litsinfo.clause)&&CCList.is_empty(C.bool_selectedinfo.clause)&&C.is_maxlit(info.clause,info.scope)subst~idx))then(letsubst_is_ho=Subst.codomainsubst|>Iter.exists(fun(t,_)->Iter.exists(funt->T.is_funt||T.is_combt)(T.Seq.subterms~include_builtin:true(T.of_term_unsafet)))inlettags=(ifsubst_is_hothen[Proof.Tag.T_ho]else[])@Unif_subst.tagsusinUtil.incr_statstat_equality_factoring_call;letproof=Proof.Step.inference~rule:(Proof.Rule.mk"eq_fact")~tags[C.proof_parent_substrenaming(info.clause,0)subst](* new_lits: literals of the new clause. remove active literal
and replace it by a t!=v one, and apply subst *)andnew_lits=CCArray.except_idx(C.litsinfo.clause)idxinletnew_lits=Lit.apply_subst_listrenamingsubst(new_lits,info.scope)inletc_guard=Literal.of_unif_substrenamingusinletlit'=Lit.mk_neq(S.FO.applyrenamingsubst(t,info.scope))(S.FO.applyrenamingsubst(v,info.scope))inletnew_lits=lit'::c_guard@new_litsinletpenalty=ifC.penaltyinfo.clause=1then1elseC.penaltyinfo.clause+1inletnew_clause=C.create~trail:(C.trailinfo.clause)~penaltynew_litsproofinUtil.debugf~section3"@[<hv2>equality factoring on@ @[%a@]@ yields @[%a@]@]"(funk->kC.ppinfo.clauseC.ppnew_clause);Somenew_clause)else(None)letinfer_equality_factoring_aux~unify~iterate_substsclause=let_span=ZProf.enter_profprof_infer_equality_factoringinleteligible=C.Eligible.(filterLit.eqn_sign)in(* find root terms that are unifiable with s and are not in the
literal at s_pos. Calls [k] with a position and substitution *)letfind_unifiable_litsidxs_s_posk=Array.iteri(funilit->matchlitwith|_wheni=idx->()(* same index *)|Lit.Equation(u,v,sign)->ifsignthen(k(u,v,unify(s,0)(u,0));k(v,u,unify(s,0)(v,0)))|_->()(* ignore other literals *))(C.litsclause)in(* try to do inferences with each positive literal *)letnew_clauses=Lits.fold_eqn~ord~both:true~eligible(C.litsclause)|>Iter.flat_map(fun(s,t,_,s_pos)->(* try with s=t *)letactive_idx=Lits.Pos.idxs_posinfind_unifiable_litsactive_idxss_pos|>Iter.filter_map(fun(u,v,substs)->letis_pred_var_eq_fact=(T.is_app_vars&&Type.is_prop(T.tys))||(T.is_app_varu&&Type.is_prop(T.tyu))initerate_substssubsts(funsubst->letinfo=EqFactInfo.({clause;s;t;u;v;active_idx;subst;scope=0;is_pred_var_eq_fact;})indo_eq_factoringinfo)))|>Iter.to_rev_listinZProf.exit_prof_span;new_clausesletinfer_equality_factoringc=infer_equality_factoring_aux~unify:(funst->trySome(Unif.FO.unify_fullst)withUnif.Fail->None)~iterate_substs:(funsubstdo_eq_fact->CCOpt.flat_mapdo_eq_factsubst)cletinfer_equality_factoring_complete_hoclause=letinf_res=infer_equality_factoring_aux~unify:(Env.flex_getk_unif_alg)~iterate_substs:(funsubstsdo_eq_fact->Some(OSeq.map(CCOpt.flat_mapdo_eq_fact)substs))clauseinifEnv.should_force_stream_eval()then(Env.get_finite_infsinf_res)else(letcls,stm_res=force_getting_cl(List.map(funstm->C.penaltyclause,[clause],stm)inf_res)inStmQ.add_lst(Env.get_stm_queue())stm_res;cls)(* ----------------------------------------------------------------------
* extraction of a clause from the stream queue (HO feature)
* ---------------------------------------------------------------------- *)letextract_from_stream_queue~full()=let_span=ZProf.enter_profprof_queuesinletcl=iffullthenStmQ.take_fair_anyway(Env.get_stm_queue())elseStmQ.take_stm_nb(Env.get_stm_queue())inletopt_res=CCOpt.sequence_l(List.filterCCOpt.is_somecl)inZProf.exit_prof_span;matchopt_reswith|None->[]|Somel->lletextract_from_stream_queue_fix_stm~full()=let_span=ZProf.enter_profprof_queuesinletcl=iffullthenStmQ.take_fair_anyway(Env.get_stm_queue())elseStmQ.take_stm_nb_fix_stm(Env.get_stm_queue())inletopt_res=CCOpt.sequence_l(List.filterCCOpt.is_somecl)inZProf.exit_prof_span;matchopt_reswith|None->[]|Somel->l(* ----------------------------------------------------------------------
* simplifications
* ---------------------------------------------------------------------- *)(* TODO: put forward pointers in simpl_set, to make some rewriting steps
faster? (invalidate when updated, also allows to reclaim memory) *)(* TODO: use a record with
- head
- args
- subst
so as not to rebuild intermediate terms, and also to avoid mixing
the head normal form and the substitution for (evaluated) arguments.
Might even convert rules into De Bruijn, because:
- special restriction (vars rhs ⊆ vars lhs)
- indexing on first symbol might be sufficient if matching is fast
- must rewrite matching to work on the record anyway
*)typedemod_state={mutabledemod_clauses:(C.t*Subst.t*Scoped.scope)list;(* rules used *)mutabledemod_sc:Scoped.scope;(* current scope *)}(** Compute normal form of term w.r.t active set. Clauses used to
rewrite are added to the clauses hashset. *)letdemod_nf(st:demod_state)ct:T.t=(* compute normal form of subterm. If `toplevel` is true, we need an extra check
whether the rewriting clause is smaller than the rewritten clause. *)letrecreduce_at_root~topleveltk=(* find equations l=r that match subterm *)letcur_sc=st.demod_scinassert(cur_sc>0);letstep=UnitIdx.retrieve~sign:true(!_idx_simpl,cur_sc)(t,0)|>Iter.find(fun(l,r,(_,_,sign,unit_clause),subst)->letexpand_quant=not@@Env.flex_getCombinators.k_enable_combinatorsinletnormt=Lambda.eta_reduce~expand_quant@@Lambda.snftinletnorm_bt=T.normalize_bools@@normtin(* r' is the subterm is going to be rewritten into *)letr'=norm@@Subst.FO.applySubst.Renaming.nonesubst(r,cur_sc)inassert(C.is_unit_clauseunit_clause);(* NOTE: The conditions of Schulz's "braniac" paper cannot be
justified by the standard redundancy criterion.
Instead, we check whether the rewriting clause is smaller
than the rewritten clause. *)(* Only perform the rewrite if: *)if(* - The rewriting clause is positive *)sign&&(* - The clause trails are compatible *)C.trail_subsumesunit_clausec&&(* - The clauses are distinct *)not(C.equalunit_clausec)&&(* - The rewriting clause is smaller than the rewritten clause *)(nottoplevel||C.litsc|>CCArray.exists(funlit->Lit.Seq.termslit|>Iter.exists(funs->O.compareordst==Comp.Gt))||C.litsc|>CCArray.exists(funlit->matchLiteral.View.as_eqnlitwith|Some(litl,litr,true)->T.equaltlitl&&O.compareordlitrr'==Comp.Gt||T.equaltlitr&&O.compareordlitlr'==Comp.Gt|Some(litl,litr,false)->T.equaltlitl||T.equaltlitr|None->false))&&(* - subst(l) > subst(r) *)(O.compareord(S.FO.applySubst.Renaming.nonesubst(l,cur_sc))(S.FO.applySubst.Renaming.nonesubst(r,cur_sc))=Comp.Gt)then(Util.debugf~section3"@[<hv2>demod(%d):@ @[<hv>t=%a[%d],@ l=%a[%d],@ r=%a[%d]@],@ subst=@[%a@]@]"(funk->k(C.idc)T.ppt0T.pplcur_scT.pprcur_scS.ppsubst);lett'=Lambda.eta_expand@@norm_btinletl'=Lambda.eta_expand@@norm_b@@Subst.FO.applySubst.Renaming.nonesubst(l,cur_sc)in(* sanity checks *)assert(Type.equal(T.tyl)(T.tyr));assert(T.equall't');st.demod_clauses<-(unit_clause,subst,cur_sc)::st.demod_clauses;st.demod_sc<-1+st.demod_sc;(* allocate new scope *)Util.incr_statstat_demodulate_step;(* reduce [rhs] in current scope [cur_sc] *)assert(cur_sc<st.demod_sc);(* bind variables not occurring in [rhs] to fresh ones *)letsubst=(InnerTerm.Seq.vars(r:>InnerTerm.t))|>Iter.fold(funsubstv->ifS.memsubst(v,cur_sc)thensubstelseS.bindsubst(v,cur_sc)(InnerTerm.var(HVar.fresh~ty:(HVar.tyv)()),cur_sc))substinUtil.debugf~section2"@[<2>demod(%d):@ rewrite `@[%a@]`@ into `@[%a@]`@ resulting `@[%a@]`@ nf `@[%a@]` using %a[%d]@]"(funk->k(C.idc)T.pptT.pprT.ppr'T.pp(Lambda.snfr')Subst.ppsubstcur_sc);Somer')else(Util.debugf~section2"demodulation of @[%a@] using @[%a@]=@[%a@] failed@."(funk->kT.pptT.pplT.ppr);None))inbeginmatchstepwith|None->kt(* not found any match, normal form found *)|Somer'->(* NOTE: we retraverse the term several times, but this is simpler *)normal_form~toplevelr'k(* done one rewriting step, continue *)end(* rewrite innermost-leftmost of [subst(t,scope)]. The initial scope is
0, but then we normal_form terms in which variables are really the variables
of the RHS of a previously applied rule (in context !sc); all those
variables are bound to terms in context 0
when rewriting under quantifiers whose bodies are lambdas, we need to
force lambda rewriting (force_lam_rw) to rewrite the quantifier body
*)andnormal_form~topleveltk=matchT.viewtwith|T.Const_->reduce_at_root~topleveltk|T.App(hd,l)->(* rewrite subterms in call by value. *)letrewrite_args=Env.flex_getk_demod_in_var_args||not(T.is_varhd)inifrewrite_argsthennormal_form_ll(funl'->lett'=ifT.same_lll'thentelseT.apphdl'in(* rewrite term at root *)reduce_at_root~toplevelt'k)elsereduce_at_root~topleveltk|T.Fun(ty_arg,body)->(* reduce under lambdas *)ifEnv.flex_getk_lambda_demodthennormal_form~toplevel:falsebody(funbody'->letu=ifT.equalbodybody'thentelseT.fun_ty_argbody'inreduce_at_root~topleveluk)elsereduce_at_root~topleveltk(* TODO: DemodExt *)|T.Var_|T.DB_->kt|T.AppBuiltin(Builtin.(ForallConst|ExistsConst)ashd,[_;body])->ifnot(Env.flex_getk_quant_demod)then(reduce_at_root~topleveltk)else(letmk_quant=ifhd=ForallConstthenT.Form.forallelseT.Form.existsinletvars,unfolded=T.open_funbodyinnormal_form~toplevel:falseunfolded(fununfolded'->letu=ifT.equalunfoldedunfolded'thentelsemk_quant(T.fun_lvarsunfolded')inreduce_at_root~topleveluk))|T.AppBuiltin(b,l)->normal_form_ll(funl'->letu=ifT.same_lll'thentelseT.app_builtin~ty:(T.tyt)bl'inreduce_at_root~topleveluk)andnormal_form_llk=matchlwith|[]->k[]|t::tail->normal_form~toplevel:falset(funt'->normal_form_ltail(funl'->k(t'::l')))innormal_form~toplevel:truet(funt->t)let[@inline]eq_c_subst(c1,s1,sc1)(c2,s2,sc2)=C.equalc1c2&&sc1=sc2&&Subst.equals1s2(* Demodulate the clause, with restrictions on which terms to rewrite *)letdemodulate_c=Util.incr_statstat_demodulate_call;(* state for storing proofs and scope *)letst={demod_clauses=[];demod_sc=1;}in(* demodulate every literal *)letdemod_litilit=Lit.map(funt->demod_nfstct)litinletlits=Array.mapidemod_lit(C.litsc)inifCCList.is_emptyst.demod_clausesthen((* no rewriting performed *)(* Util.debugf ~section 1 "did not demod @[%a@]@." (fun k -> k C.pp c); *)SimplM.return_samec)else(assert(not(Lits.equal_comlits(C.litsc)));(* construct new clause *)st.demod_clauses<-CCList.uniq~eq:eq_c_substst.demod_clauses;letproof=Proof.Step.simp~rule:(Proof.Rule.mk"demod")(C.proof_parentc::List.rev_map(fun(c,subst,sc)->C.proof_parent_substSubst.Renaming.none(c,sc)subst)st.demod_clauses)inlettrail=C.trailcin(* we know that demodulating rules have smaller trail *)letnew_c=C.create_a~trail~penalty:(C.penaltyc)litsproofinUtil.debugf~section3"@[<hv2>demodulate@ @[%a@]@ into @[%a@]@ using {@[<hv>%a@]}@]"(funk->letpp_c_sout(c,s,sc)=Format.fprintfout"(@[%a@ :subst %a[%d]@])"C.ppcSubst.ppsscinkC.ppcC.ppnew_c(Util.pp_listpp_c_s)st.demod_clauses);assert(C.litsnew_c|>Literals.vars_distinct);SimplM.return_newnew_c)letdemodulatec=assert(Term.VarSet.for_all(funv->HVar.idv>=0)(Literals.vars(C.litsc)|>Term.VarSet.of_list));ZProf.with_profprof_demodulatedemodulate_cletlocal_rewritec=tryassert(Env.flex_getk_local_rw!=`Off);letneqs,others=CCArray.fold_left(fun(neq_map,others)lit->matchlitwith|Literal.Equation(lhs,rhs,sign)->(* NOTE: based on the representation of the literals! *)ifsign&&T.is_true_or_falserhs&&(not(T.is_varlhs))then(letnegatet=ifT.equaltT.true_thenT.false_elseT.true_in(T.Map.addlhs(negaterhs)neq_map,others))elseifnotsignthen(matchOrdering.compareordlhsrhswith|Gt->(T.Map.addlhsrhsneq_map,others)|Lt->(T.Map.addrhslhsneq_map,others)|_->((neq_map),lit::others))else((neq_map),lit::others)|_->((neq_map),lit::others))((Term.Map.empty),[])(C.litsc)inletnormalize~restrict~neqst=letonly_green_ctx=Env.flex_getk_local_rw==`GreenContextinletrecaux~topt=(matchT.Map.gettneqswith|Somet'whennotrestrict||nottop->assert(Type.equal(T.tyt)(T.tyt'));aux~topt'|_->beginmatchT.viewtwith|T.App(hd,args)whennot(T.is_varhd)||notonly_green_ctx->lethd'=aux~top:falsehdinletargs'=List.map(aux~top:false)argsinifT.equalhdhd'&&T.same_largsargs'thentelseaux~top:false(T.apphd'args')|T.AppBuiltin(hd,args)->letargs'=List.map(aux~top:false)argsinifT.same_largsargs'thentelseaux~top:false(T.app_builtin~ty:(T.tyt)hdargs')|T.Fun_whennotonly_green_ctx->letpref,body=T.open_funtinletbody'=aux~top:falsebodyinifT.equalbodybody'thentelseT.fun_lprefbody'|_->t(* do not rewrite under lambdas *)end)inaux~top:truetinletrewritten=reffalseinletnew_lits=CCArray.map(function|Lit.Equation(lhs,rhs,sign)asl->ifsign&&T.is_true_or_falserhsthen(letlhs'=normalize~restrict:true~neqslhsinifnot(T.equallhslhs')then(rewritten:=true;Lit.mk_litlhs'rhssign)elsel)elseifnotsignthen(letlhs',rhs'=matchOrdering.compareordlhsrhswith|Gt->normalize~restrict:true~neqslhs,normalize~restrict:false~neqsrhs|Lt->normalize~restrict:false~neqslhs,normalize~restrict:true~neqsrhs|_->normalize~restrict:false~neqslhs,normalize~restrict:false~neqsrhsinifnot(T.equallhslhs')||not(T.equalrhsrhs')then(rewritten:=true;Lit.mk_litlhs'rhs'sign)elsel)else(letlhs',rhs'=normalize~restrict:false~neqslhs,normalize~restrict:false~neqsrhsinifnot(T.equallhslhs')||not(T.equalrhsrhs')then(rewritten:=true;Lit.mk_litlhs'rhs'sign)elsel)|x->x)(C.litsc)inifnot!rewrittenthenSimplM.return_samecelse(letnew_lits=CCArray.to_listnew_litsinletproof=Proof.Step.simp[C.proof_parentc]~rule:(Proof.Rule.mk"local_rewriting")inletnew_c=C.create~trail:(C.trailc)~penalty:(C.penaltyc)new_litsproofinUtil.debugf~section2"local_rw(@[%a@]):@.@[%a@]@."(funk->kC.ppcC.ppnew_c);SimplM.return_newnew_c)withInvalid_argumenterr->CCFormat.printf"err in local_rw:@[%s@]@."err;CCFormat.printf"proof: @[%a@]@."Proof.S.pp_tstp(C.proofc);CCFormat.printf"local_rw: @[%a@]@."C.ppc;Format.print_flush();assertfalseletcanonize_variablesc=letall_vars=Literals.vars(C.litsc)|>(funv->InnerTerm.VarSet.of_list(v:>InnerTerm.tHVar.tlist))inletneg_vars_renaming=Subst.FO.canonize_neg_vars~var_set:all_varsinifSubst.is_emptyneg_vars_renamingthenSimplM.return_samecelse(letnew_lits=Literals.apply_substSubst.Renaming.noneneg_vars_renaming(C.litsc,0)|>CCArray.to_listinletproof=Proof.Step.inference[C.proof_parentc]~rule:(Proof.Rule.mk"cannonize vars")inletnew_c=C.create~trail:(C.trailc)~penalty:(C.penaltyc)new_litsproofinSimplM.return_newnew_c)(** Find clauses that [given] may demodulate, add them to set *)letbackward_demodulatesetgiven=let_span=ZProf.enter_profprof_back_demodulateinletrenaming=Subst.Renaming.create()in(* find clauses that might be rewritten by l -> r *)letrecurse~orientedsetlr=I.retrieve_specializations(!_idx_back_demod,1)(l,0)|>Iter.fold(funset(_t',with_pos,subst)->letc=with_pos.C.WithPos.clausein(* subst(l) matches t' and is > subst(r), very likely to rewrite! *)if(C.trail_subsumescgiven&&(oriented||O.compareord(S.FO.applyrenamingsubst(l,0))(S.FO.applyrenamingsubst(r,0))=Comp.Gt))then(* add the clause to the set, it may be rewritten by l -> r *)C.ClauseSet.addcsetelseset)setinletset'=matchC.litsgivenwith|[|Lit.Equation(l,r,true)|]->beginmatchOrdering.compareordlrwith|Comp.Gt->recurse~oriented:truesetlr|Comp.Lt->recurse~oriented:truesetrl|_->letset'=recurse~oriented:falsesetlrinrecurse~oriented:falseset'rl(* both sides can rewrite, but we need to check ordering *)end|_->setinZProf.exit_prof_span;set'letis_tautologyc=letis_tauto=Lits.is_trivial(C.litsc)||Trail.is_trivial(C.trailc)inifis_tautothenUtil.debugf~section3"@[@[%a@]@ is a tautology@]"(funk->kC.ppc);is_tauto(* semantic tautology deletion, using a congruence closure algorithm
to see if negative literals imply some positive literal *)letis_semantic_tautology_real(c:C.t):bool=(* create the congruence closure of all negative equations of [c] *)letcc=Congruence.FO.create~size:8()inletcc=Array.fold_left(funcclit->matchlitwith(* NOTE: Based on the representation of the literals *)|Lit.Equation(l,r,true)whenT.equalrT.false_->Congruence.FO.mk_eqcclT.true_|Lit.Equation(l,r,false)->Congruence.FO.mk_eqcclr|_->cc)cc(C.litsc)inletres=CCArray.exists(function(* NOTE: Based on the representation of the literals *)|Lit.Equation(l,r,_)aslitwhenLit.is_positivoidlit->(* if l=r is implied by the congruence, then the clause is redundant *)Congruence.FO.is_eqcclr|_->false)(C.litsc)inifresthen(Util.incr_statstat_semantic_tautology;Util.debugf~section2"@[@[%a@]@ is a semantic tautology@]"(funk->kC.ppc););resletis_semantic_tautology_c=ifArray.length(C.litsc)>=2&&CCArray.existsLit.is_negativoid(C.litsc)&&CCArray.existsLit.is_positivoid(C.litsc)thenis_semantic_tautology_realcelsefalseletis_semantic_tautologyc=ZProf.with_profprof_semantic_tautologyis_semantic_tautology_cletvar_in_subst_usvsc=S.mem(US.substus)((v:T.var:>InnerTerm.tHVar.t),sc)letbasic_simplifyc=ifC.get_flagflag_simplifiedcthenSimplM.return_samecelse(let_span=ZProf.enter_profprof_basic_simplifyinUtil.incr_statstat_basic_simplify_calls;letlits=C.litscinlethas_changed=reffalseinlettags=ref[]in(* bv: literals to keep *)letbv=BV.create~size:(Array.lengthlits)truein(* eliminate absurd lits *)Array.iteri(funilit->ifLit.is_absurdlitthen(has_changed:=true;tags:=Lit.is_absurd_tagslit@!tags;BV.resetbvi))lits;(* eliminate inequations x != t *)letus=refUS.emptyinifEnv.flex_getk_destr_eq_resthen(lettry_unifit1sc1t2sc2=tryletsubst'=Unif.FO.unify_full~subst:!us(t1,sc1)(t2,sc2)inhas_changed:=true;BV.resetbvi;us:=subst';withUnif.Fail->()inArray.iteri(funilit->letcan_destr_eq_varv=not(var_in_subst_!usv0)&¬(Type.is_fun(HVar.tyv))inifBV.getbvithenmatchlitwith|Lit.Equation(l,r,false)->assert(not(T.is_true_or_falser));beginmatchT.viewl,T.viewrwith|T.Varv,_whencan_destr_eq_varv->(* eligible for destructive Equality Resolution, try to update
[subst]. Careful: in the case [X!=a | X!=b | C] we must
bind X only to [a] or [b], not unify [a] with [b].
NOTE: this also works for HO constraints for unshielded vars *)try_unifil0r0|_,T.Varvwhencan_destr_eq_varv->try_unifir0l0|_->()end|_->())lits);letnew_lits=BV.selectbvlitsinletnew_lits=ifUS.is_empty!usthennew_litselse(assert!has_changed;letsubst=US.subst!usinlettgs=US.tags!usintags:=tgs@!tags;letc_guard=Literal.of_unif_substSubst.Renaming.none!usinc_guard@Lit.apply_subst_listSubst.Renaming.nonesubst(new_lits,0))inletnew_lits=CCList.uniq~eq:Lit.equal_comnew_litsinifnot!has_changed&&List.lengthnew_lits=Array.lengthlitsthen(ZProf.exit_prof_span;C.set_flagflag_simplifiedctrue;SimplM.return_samec(* no simplification *))else(letparent=ifSubst.is_empty(US.subst!us)thenC.proof_parentcelseC.proof_parent_substSubst.Renaming.none(c,0)(US.subst!us)inletproof=Proof.Step.simp[parent]~tags:!tags~rule:(Proof.Rule.mk"simplify")inletnew_lits=ifList.existsLit.is_trivialnew_litsthen[Lit.mk_tauto]elsenew_litsinletnew_clause=C.create~trail:(C.trailc)~penalty:(C.penaltyc)new_litsproofinUtil.debugf~section3"@[<>@[%a@]@ @[<2>basic_simplifies into@ @[%a@]@]@ with @[%a@]@]"(funk->kC.ppcC.ppnew_clauseUS.pp!us);Util.incr_statstat_basic_simplify;ZProf.exit_prof_span;SimplM.return_newnew_clause))lethandle_distinct_constantslit=matchlitwith|Lit.Equation(l,r,sign)whenT.is_constl&&T.is_constr->assert(not(T.is_true_or_falser));lets1=T.head_exnlands2=T.head_exnrinifID.is_distinct_objects1&&ID.is_distinct_objects2thenifsign=(ID.equals1s2)thenSome(Lit.mk_tauto,[],[Proof.Tag.T_distinct])(* "a" = "a", or "a" != "b" *)elseSome(Lit.mk_absurd,[],[Proof.Tag.T_distinct])(* "a" = "b" or "a" != "a" *)elseNone|_->NoneexceptionFoundMatchofT.t*C.t*S.tletformula_simplify_reflectc=letq_sc,idx_sc=0,1inletused_units=refC.ClauseSet.emptyinletdo_srt=letsimplify~signlhsrhs=let(<+>)=CCOpt.(<+>)inlettop_level~sign~repllhsrhs=UnitIdx.retrieve~sign(!_idx_simpl,idx_sc)(lhs,q_sc)|>Iter.find_map(fun(_,rhs',(_,_,_,c'),subst)->ifC.trail_subsumesc'cthen(tryignore(Unif.FO.matching~subst~pattern:(rhs',idx_sc)(rhs,q_sc));used_units:=C.ClauseSet.addc'!used_units;Somereplwith_->None)elseNone)inletnestedlhsrhs=T.Seq.common_contextslhsrhs|>Iter.find_map(fun(lhs,rhs)->top_level~sign:true~repl:(ifsignthenT.true_elseT.false_)lhsrhs<+>top_level~sign:true~repl:(ifsignthenT.true_elseT.false_)rhslhs)intop_level~sign~repl:T.true_lhsrhs<+>top_level~sign:(notsign)~repl:T.false_lhsrhs<+>top_level~sign~repl:T.true_rhslhs<+>top_level~sign:(notsign)~repl:T.false_rhslhs<+>nestedlhsrhsinletrecauxt=matchT.viewtwith|T.App(hd,args)->letargs'=List.mapauxargsinifT.same_largsargs'thentelseT.apphdargs'|T.AppBuiltin((Eq|Neq|Equiv|Xor)ashd,([_;x;y]|[x;y]))whenType.is_prop(T.tyt)&&T.DB.is_closedx&&T.DB.is_closedy->let(x',y')=CCPair.map_sameaux(x,y)inassert(Type.equal(T.tyx)(T.tyx'));assert(Type.equal(T.tyy)(T.tyy'));letsign=Builtin.equalEqhd||Builtin.equalEquivhdinbeginmatchsimplify~signx'y'with|Somet->t|None->if(not((T.equalxx')&&(T.equalyy')))then(if(Builtin.equalhdEq)thenT.Form.eqx'y'elseif(Builtin.equalhdNeq)thenT.Form.neqx'y'elseT.app_builtin~ty:(T.tyt)hd[x';y'])elsetend|T.AppBuiltin(hd,args)whennot(Builtin.is_quantifierhd)->letargs'=List.mapauxargsinifT.same_largsargs'thentelseT.app_builtin~ty:(T.tyt)hdargs'|T.Fun(ty,body)->letbody'=auxbodyinifT.equalbodybody'thentelseT.fun_tybody'|_->tinauxtinifEnv.flex_getk_formula_simplify_reflect&&!Lazy_cnf.enabledthen(letlits=List.map(function|Lit.Equation(lhs,rhs,sign)->Lit.mk_lit(do_srlhs)(do_srrhs)sign|x->x)(CCArray.to_list@@C.litsc)inif(not@@C.ClauseSet.is_empty!used_units)then(letparents=List.mapC.proof_parent(C.ClauseSet.to_list!used_units)inletproof=Proof.Step.simp~rule:(Proof.Rule.mk"inner_simplify_reflect")((C.proof_parentc)::parents)inlettrail=C.trailcandpenalty=C.penaltycinletnew_c=C.create~trail~penaltylitsproofinSimplM.return_newnew_c)else(SimplM.return_samec))else(SimplM.return_samec)letequatable~sign~clst=letidx_sc,q_sc=1,0inlet(<+>)=CCOpt.(<+>)inletauxst=UnitIdx.retrieve~sign(!_idx_simpl,idx_sc)(s,q_sc)|>Iter.find_map(fun(_,rhs,(_,_,_,c'),subst)->ifC.trail_subsumesc'clthen(tryignore(Unif.FO.matching~subst~pattern:(rhs,idx_sc)(t,q_sc));Somec'with_->None)elseNone)inauxst<+>auxtsletpositive_simplify_reflectc=letdriver~is_simplifiedc=letkept_lits=CCBV.create~size:(C.lengthc)trueinletpremises=CCArray.foldi(funpremisesilit->letfind_simplifying_premiselhsrhs=beginmatchis_simplifiedlhsrhswith|Someprems->CCBV.resetkept_litsi;C.ClauseSet.unionpremisesprems|None->premisesendinmatchlitwith|Lit.Equation(lhs,rhs,false)->find_simplifying_premiselhsrhs|Lit.Equation(lhs,rhs,true)whenT.equalT.false_rhs->find_simplifying_premiselhsT.true_|_->premises)(C.ClauseSet.empty)(C.litsc)inCCOpt.return_if(not(CCBV.is_empty(CCBV.negatekept_lits)))(CCBV.selectkept_lits(C.litsc),premises)inletstrong_sr_pairlhsrhs=lettasks=Queue.create()inletexceptionCantSimplifyintryQueue.push(lhs,rhs)tasks;letpremises=refC.ClauseSet.emptyinwhilenot(Queue.is_emptytasks)dolets,t=Queue.poptasksinifnot(T.equalst)then(matchequatable~sign:true~cl:cstwith|Somecl->premises:=C.ClauseSet.addcl!premises|None->beginmatchT.views,T.viewtwith|T.App(hd_s,args_s),T.App(hd_t,args_t)whenT.is_consthd_s&&T.equalhd_shd_t->CCList.iter(funpair->Queue.pushpairtasks)(List.combineargs_sargs_t)|T.AppBuiltin(hd_s,args_s),T.AppBuiltin(hd_t,args_t)whenBuiltin.equalhd_shd_t&&CCList.lengthargs_s=CCList.lengthargs_t->CCList.iter(funpair->Queue.pushpairtasks)(List.combineargs_sargs_t)|_->raiseCantSimplifyend)done;Some!premiseswithCantSimplify->Noneinletregular_sr_pairlhsrhs=ifT.equallhsrhsthenSome(C.ClauseSet.empty)elsematchequatable~sign:true~cl:clhsrhswith|Somecl->Some(C.ClauseSet.singletoncl)|None->(T.Seq.common_contextslhsrhs|>Iter.find_map(fun(a,b)->equatable~sign:true~cl:cab)|>CCOpt.mapC.ClauseSet.singleton)inletdo_strong_sr=driver~is_simplified:strong_sr_pairinletdo_regular_sr=driver~is_simplified:regular_sr_pairinletsimplifier=ifEnv.flex_getk_strong_srthendo_strong_srelsedo_regular_srinlet_span=ZProf.enter_profprof_pos_simplify_reflectin(* iterate through literals and try to resolve negative ones *)matchsimplifiercwith|None->ZProf.exit_prof_span;SimplM.return_samec|Some(new_lits,premises)->letproof=Proof.Step.simp~rule:(Proof.Rule.mk"simplify_reflect+")(List.mapC.proof_parent(c::(C.ClauseSet.to_listpremises)))inlettrail=C.trailcandpenalty=C.penaltycinletnew_c=C.create~trail~penaltynew_litsproofinUtil.debugf~section3"@[@[%a@]@ pos_simplify_reflect into @[%a@]@]"(funk->kC.ppcC.ppnew_c);ZProf.exit_prof_span;SimplM.return_newnew_cletnegative_simplify_reflectc=let_span=ZProf.enter_profprof_neg_simplify_reflectin(* iterate through literals and try to resolve positive ones *)letreciterate_litsacclitsclauses=matchlitswith|[]->List.revacc,clauses|(Lit.Equation(s,t,true)aslit)::lits'->beginmatchcan_refutestwith|None->(* keep literal *)iterate_lits(lit::acc)lits'clauses|Somenew_clause->(* drop literal, remember clause *)iterate_litsacclits'(new_clause::clauses)end|lit::lits'->iterate_lits(lit::acc)lits'clauses(* try to remove the literal using a negative unit clause *)andcan_refutest=equatable~sign:false~cl:cst|>CCOpt.mapC.proof_parentin(* fold over literals *)letlits,premises=iterate_lits[](C.litsc|>Array.to_list)[]inifList.lengthlits=Array.length(C.litsc)then((* no literal removed *)ZProf.exit_prof_span;Util.debug~section3"neg_reflect did not simplify the clause";SimplM.return_samec)else(letproof=Proof.Step.simp~rule:(Proof.Rule.mk"simplify_reflect-")(C.proof_parentc::premises)inletnew_c=C.create~trail:(C.trailc)~penalty:(C.penaltyc)litsproofinUtil.debugf~section3"@[@[%a@]@ neg_simplify_reflect into @[%a@]@]"(funk->kC.ppcC.ppnew_c);ZProf.exit_prof_span;SimplM.return_newnew_c)typesgn=Litofbool|Eqnletflex_resolvec=letexceptionCantFlexResolveintryletsgn_map=T.Tbl.create8inif(C.lengthc==0)thenraiseCantFlexResolve;Array.iter(function|Literal.Equation(lhs,rhs,_)aslit->if(Lit.is_predicate_litlit)then(assert(T.is_true_or_falserhs);if(T.is_var(T.head_termlhs))then(lethd=T.head_termlhsinmatchT.Tbl.getsgn_maphdwith|None->T.Tbl.addsgn_maphd(Lit(Lit.is_positivoidlit))|Some(Litsgn)whensgn==Lit.is_positivoidlit->()|_->raiseCantFlexResolve)elseraiseCantFlexResolve)elseifLit.is_positivoidlitthen(raiseCantFlexResolve)else(lethd_lhs,hd_rhs=CCPair.map_sameT.head_term(lhs,rhs)inif(T.is_varhd_lhs)&&(T.is_varhd_rhs)then(matchT.Tbl.getsgn_maphd_lhs,T.Tbl.getsgn_maphd_rhswith|None,None|Some(Eqn),None|None,Some(Eqn)|Some(Eqn),Some(Eqn)->T.Tbl.replacesgn_maphd_lhsEqn;T.Tbl.replacesgn_maphd_rhsEqn;|_->raiseCantFlexResolve)elseraiseCantFlexResolve)|False->()|_->raiseCantFlexResolve)(C.litsc);letnew_cl=C.create~trail:(C.trailc)[](Proof.Step.simp~rule:(Proof.Rule.mk"flex_resolve")[C.proof_parentc])~penalty:1inSimplM.return_newnew_clwithCantFlexResolve->SimplM.return_samec(* ----------------------------------------------------------------------
* subsumption
* ---------------------------------------------------------------------- *)(** raised when a subsuming substitution is found *)exceptionSubsumptionFoundofS.t(** check that every literal in a matches at least one literal in b *)letall_lits_matchasc_absc_b=CCArray.for_all(funlita->CCArray.exists(funlitb->not(Iter.is_empty(Lit.subsumes(lita,sc_a)(litb,sc_b))))b)a(** Compare literals by subsumption difficulty
(see "towards efficient subsumption", Tammet).
We sort by increasing order, so non-ground, deep, heavy literals are
smaller (thus tested early) *)letcompare_literals_subsumptionlitalitb=CCOrd.((* ground literal is bigger *)bool(Lit.is_groundlita)(Lit.is_groundlitb)(* deep literal is smaller *)<?>(mapLit.depth(oppint),lita,litb)(* heavy literal is smaller *)<?>(mapLit.weight(oppint),lita,litb))(* replace the bitvector system by some backtracking scheme?
XXX: maybe not a good idea. the algorithm is actually quite subtle
and needs tight control over the traversal (lookahead of free
variables in next literals, see [check_vars]...) *)(** Check whether [a] subsumes [b], and if it does, return the
corresponding substitution *)letsubsumes_with_(a,sc_a)(b,sc_b):_option=(* a must not have more literals, and it must be possible to bind
all its vars during subsumption *)ifArray.lengtha>Array.lengthb||not(all_lits_matchasc_absc_b)thenNoneelse((* sort a copy of [a] by decreasing difficulty *)leta=Array.copyainlettags=ref[]in(* try to subsumes literals of b whose index are not in bv, with [subst] *)letrectry_permutationsisubstbv=ifi=Array.lengthathenraise(SubsumptionFoundsubst)elseletlita=a.(i)infind_matchedlitaisubstbv0(* find literals of b that are not bv and that are matched by lita *)andfind_matchedlitaisubstbvj=ifj=Array.lengthbthen()(* if litb is already matched, continue *)elseifBV.getbvjthenfind_matchedlitaisubstbv(j+1)else(letlitb=b.(j)inBV.setbvj;(* match lita and litb, then flag litb as used, and try with next literal of a *)letn_subst=ref0inLit.subsumes~subst(lita,sc_a)(litb,sc_b)(fun(subst',tgs)->incrn_subst;tags:=tgs@!tags;try_permutations(i+1)subst'bv);BV.resetbvj;(* some variable of lita occur in a[j+1...], try another literal of b *)if!n_subst>0&¬(check_varslita(i+1))then()(* no backtracking for litb *)elsefind_matchedlitaisubstbv(j+1))(* does some literal in a[j...] contain a variable in l or r? *)andcheck_varslitj=letvars=Lit.varslitinifvars=[]thenfalseelsetryfork=jtoArray.lengtha-1doifList.exists(funv->Lit.var_occursva.(k))varsthenraiseExitdone;falsewithExit->trueintryArray.sortcompare_literals_subsumptiona;letbv=BV.empty()intry_permutations0S.emptybv;Nonewith(SubsumptionFoundsubst)->Util.debugf~section5"(@[<hv>subsumes@ :c1 @[%a@]@ :c2 @[%a@]@ :subst %a%a@]"(funk->kLits.ppaLits.ppbSubst.ppsubstProof.pp_tags!tags);Some(subst,!tags))letsubsumes_withab=let_span=ZProf.enter_profprof_subsumptioninUtil.incr_statstat_subsumption_call;let(c_a,_),(c_b,_)=a,binletw_a=CCArray.fold(funaccl->acc+Lit.weightl)0c_ainletw_b=CCArray.fold(funaccl->acc+Lit.weightl)0c_binifw_a=w_b&&Literals.equal_comc_ac_bthenSome(Subst.empty,[])else(letres=ifw_a<=w_bthensubsumes_with_abelseNoneinZProf.exit_prof_span;res)letsubsumes_classicab=matchsubsumes_with(a,0)(b,1)with|None->false|Some_->trueletsubsumesab=letmoduleSS=SolidSubsumption.Make(structletst=Env.flex_state()end)inifnot@@Env.flex_getk_solid_subsumption||Env.flex_getCombinators.k_enable_combinatorsthensubsumes_classicabelse(trySS.subsumesabwithSolidSubsumption.UnsupportedLiteralKind->subsumes_classicab)(* anti-unification of the two terms with at most one disagreement point *)letanti_unify(t:T.t)(u:T.t):(T.t*T.t)option=matchUnif.FO.anti_unify~cut:1tuwith|Some[pair]->Somepair|_->Noneleteq_subsumes_with(a,sc_a)(b,sc_b)=(* subsume a literal using a = b *)letrecequate_lit_withablit=matchlitwith|Lit.Equation(u,v,true)whennot(T.equaluv)->equate_termsabuv|_->None(* make u=v using a=b once *)andequate_termsabuv=beginmatchanti_unifyuvwith|None->None|Some(u',v')->equate_rootabu'v'end(* check whether a\sigma = u and b\sigma = v, for some sigma;
or the commutation thereof *)andequate_rootabuv:Subst.toption=letcheck_abuv=tryifTerm.sizea>Term.sizeu||Term.sizeb>Term.sizevthenraiseUnif.Fail;letsubst=Unif.FO.matching~pattern:(a,sc_a)(u,sc_b)inletsubst=Unif.FO.matching~subst~pattern:(b,sc_a)(v,sc_b)inSomesubstwithUnif.Fail->Noneinbeginmatchcheck_abuvwith|Some_ass->s|None->check_bauvendin(* check for each literal *)let_span=ZProf.enter_profprof_eq_subsumptioninUtil.incr_statstat_eq_subsumption_call;letres=matchawith|[|Lit.Equation(s,t,true)|]->letres=CCArray.find_map(equate_lit_withst)binbeginmatchreswith|None->None|Somesubst->Util.debugf~section3"@[<2>@[%a@]@ eq-subsumes @[%a@]@ :subst %a@]"(funk->kLits.ppaLits.ppbSubst.ppsubst);Util.incr_statstat_eq_subsumption_success;Somesubstend|_->None(* only a positive unit clause unit-subsumes a clause *)inZProf.exit_prof_span;resleteq_subsumesab=CCOpt.is_some(eq_subsumes_with(a,1)(b,0))letsubsumed_by_active_setc=let_span=ZProf.enter_profprof_subsumption_setinUtil.incr_statstat_subsumed_by_active_set_call;(* if there is an equation in c, try equality subsumption *)lettry_eq_subsumption=CCArray.existsLit.is_eqn(C.litsc)in(* use feature vector indexing *)letc=ifEnv.flex_getk_ground_subs_check>0thenC.ground_clausecelsecinletres=SubsumIdx.retrieve_subsuming_c!_idx_fvc|>Iter.exists(func'->letres=C.trail_subsumesc'c&&((try_eq_subsumption&&eq_subsumes(C.litsc')(C.litsc))||subsumes(C.litsc')(C.litsc))inifresthen(Util.debugf~section2"@[<2>@[%a@]@ subsumed by @[%a@]@]"(funk->kC.ppcC.ppc');Util.incr_statstat_clauses_subsumed;);res)inZProf.exit_prof_span;resletsubsumed_in_active_setaccc=let_span=ZProf.enter_profprof_subsumption_in_setinUtil.incr_statstat_subsumed_in_active_set_call;(* if c is a single unit clause *)lettry_eq_subsumption=C.is_unit_clausec&&Lit.is_positivoid(C.litsc).(0)in(* use feature vector indexing *)letres=SubsumIdx.retrieve_subsumed_c!_idx_fvc|>Iter.fold(funresc'->ifC.trail_subsumescc'thenletc'=ifEnv.flex_getk_ground_subs_check>1thenC.ground_clausec'elsec'inletredundant=(try_eq_subsumption&&eq_subsumes(C.litsc)(C.litsc'))||subsumes(C.litsc)(C.litsc')inifredundantthen(Util.incr_statstat_clauses_subsumed;C.ClauseSet.addc'res)elsereselseres)accinZProf.exit_prof_span;res(* Number of equational lits. Used as an estimation for the difficulty of the subsumption
check for this clause. *)letnum_equationallits=Array.fold_left(funacclit->acc+(ifLit.is_predicate_litlitthen0else1))0lits(* ----------------------------------------------------------------------
* contextual literal cutting
* ---------------------------------------------------------------------- *)(* Performs successive contextual literal cuttings *)letreccontextual_literal_cutting_recc=letopenSimplM.InfixinifArray.length(C.litsc)<=1||Lits.num_equational(C.litsc)>3||Array.length(C.litsc)>8thenSimplM.return_samecelse((* do we need to try to use equality subsumption? *)lettry_eq_subsumption=CCArray.existsLit.is_eqn(C.litsc)in(* try to remove one literal from the literal array *)letremove_one_litlits=Iter.of_array_ilits|>Iter.filter(fun(_,lit)->not(Lit.is_constraintlit))|>Iter.find_map(fun(i,old_lit)->(* negate literal *)lits.(i)<-Lit.negateold_lit;(* test for subsumption *)SubsumIdx.retrieve_subsuming!_idx_fv(Lits.Seq.to_formlits)(C.trailc|>Trail.labels)|>Iter.filter(func'->C.trail_subsumesc'c)|>Iter.find_map(func'->letsubst=matchiftry_eq_subsumptiontheneq_subsumes_with(C.litsc',1)(lits,0)elseNonewith|Somes->Some(s,[])|None->subsumes_with(C.litsc',1)(lits,0)insubst|>CCOpt.map(fun(subst,tags)->(* remove the literal and recurse *)CCArray.except_idxlitsi,i,c',subst,tags))|>CCFun.tap(fun_->(* restore literal *)lits.(i)<-old_lit))inbeginmatchremove_one_lit(Array.copy(C.litsc))with|None->SimplM.return_samec(* no literal removed *)|Some(new_lits,_,c',subst,tags)->(* hc' allowed us to cut a literal *)assert(List.lengthnew_lits+1=Array.length(C.litsc));letproof=Proof.Step.simp~rule:(Proof.Rule.mk"clc")~tags[C.proof_parentc;C.proof_parent_substSubst.Renaming.none(c',1)subst]inletnew_c=C.create~trail:(C.trailc)~penalty:(C.penaltyc)new_litsproofinUtil.debugf~section3"@[<2>contextual literal cutting@ in @[%a@]@ using @[%a@]@ gives @[%a@]@]"(funk->kC.ppcC.ppc'C.ppnew_c);Util.incr_statstat_clc;(* try to cut another literal *)SimplM.return_newnew_c>>=contextual_literal_cutting_recend)letcontextual_literal_cuttingc=letres=ZProf.with_profprof_clccontextual_literal_cutting_reccinres(* ----------------------------------------------------------------------
* contraction (condensation)
* ---------------------------------------------------------------------- *)exceptionCondensedIntoofLit.tarray*S.t*Subst.Renaming.t*Proof.taglist(** performs condensation on the clause. It looks for two literals l1 and l2 of same
sign such that l1\sigma = l2, and hc\sigma \ {l2} subsumes hc. Then
hc is simplified into hc\sigma \ {l2}.
If there are too many equational literals, the simplification is disabled to
avoid pathologically expensive subsumption checks.
TODO remove this limitation after an efficient subsumption check is implemented. *)letreccondensation_recc=letopenSimplM.InfixinifArray.length(C.litsc)<=1||Lits.num_equational(C.litsc)>3||Array.length(C.litsc)>8thenSimplM.return_samecelse(* scope is used to rename literals for subsumption *)letlits=C.litscinletn=Array.lengthlitsintryfori=0ton-1doletlit=lits.(i)inforj=i+1ton-1doletlit'=lits.(j)in(* see whether [lit |= lit'], and if removing [lit] gives a clause
that subsumes c. Also try to swap [lit] and [lit']. *)letsubst_remove_lit=Lit.subsumes(lit,0)(lit',0)|>Iter.map(funs->s,i)andsubst_remove_lit'=Lit.subsumes(lit',0)(lit,0)|>Iter.map(funs->s,j)in(* potential condensing substitutions *)letsubsts=Iter.appendsubst_remove_litsubst_remove_lit'inIter.iter(fun((subst,tags),idx_to_remove)->letnew_lits=Array.sublits0(n-1)inifidx_to_remove<>n-1thennew_lits.(idx_to_remove)<-lits.(n-1);(* remove lit *)letrenaming=Subst.Renaming.create()inletnew_lits=Lits.apply_substrenamingsubst(new_lits,0)in(* check subsumption *)ifsubsumesnew_litslitsthen(raise(CondensedInto(new_lits,subst,renaming,tags))))substsdone;done;SimplM.return_samecwithCondensedInto(new_lits,subst,renaming,tags)->(* clause is simplified *)letproof=Proof.Step.simp~rule:(Proof.Rule.mk"condensation")~tags[C.proof_parent_substrenaming(c,0)subst]inletc'=C.create_a~trail:(C.trailc)~penalty:(C.penaltyc)new_litsproofinUtil.debugf~section3"@[<2>condensation@ of @[%a@] (with @[%a@])@ gives @[%a@]@]"(funk->kC.ppcS.ppsubstC.ppc');(* try to condense further *)Util.incr_statstat_condensation;SimplM.return_newc'>>=condensation_recletcondensationc=ZProf.with_profprof_condensationcondensation_reccletsubsumption_weightc=C.Seq.termsc|>Iter.fold(funacct->(T.weight~var:1~sym:(fun_->2)t)+acc)0letimmediate_subsumecimmediate=letsubsumessubsumersubsumee=(subsumption_weightsubsumer<=subsumption_weightsubsumee)&&C.trail_subsumessubsumersubsumee&&((Array.existsLit.is_eqn(C.litssubsumee)&&eq_subsumes(C.litssubsumer)(C.litssubsumee))||subsumes(C.litssubsumer)(C.litssubsumee))inletimmediate=Iter.filter(func'->not(subsumescc'))immediateinifIter.existsC.is_emptyimmediatethenNoneelse(immediate|>Iter.find_map(func'->if(subsumesc'c)then(C.mark_redundantc;Env.remove_active(Iter.singletonc);Env.remove_simpl(Iter.singletonc);Util.debugf~section2"immediate subsume @[%a@]@."(funk->kC.ppc);Somec')elseNone))|>(function|Somesubsumer->Some(Iter.singletonsubsumer)|None->Someimmediate)letis_orphanedc=letres=not(C.is_emptyc)&&C.is_orphanedcinifresthen(Util.incr_statstat_orphan_checks);resletrecognize_injectivityc=letexceptionFailin(* 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~section2"Injectivity recognized: %a |---| %a"(funk->kC.ppcC.ppnew_clause);[new_clause]|_->assertfalse;end|_->assertfalse;withFail->[]letnormalize_equalitiesc=letlits=Array.to_list(C.litsc)inletnormalized=List.mapLiteral.normalize_eqlitsinifList.existsCCOpt.is_somenormalizedthen(letnew_lits=List.mapi(funil_opt->CCOpt.get_or~default:(Array.get(C.litsc)i)l_opt)normalizedinletproof=Proof.Step.simp[C.proof_parentc]~rule:(Proof.Rule.mk"simplify nested equalities")inletnew_c=C.create~trail:(C.trailc)~penalty:(C.penaltyc)new_litsproofinSimplM.return_newnew_c)else(SimplM.return_samec)(** {2 Registration} *)(* print index into file *)let_print_idx~ffileidx=CCIO.with_outfile(funoc->letout=Format.formatter_of_out_channelocinFormat.fprintfout"@[%a@]@."fidx;flushoc)letsetup_dot_printers()=letpp_leaf__=()inCCOpt.iter(funfile->Signal.onceSignals.on_dot_output(fun()->_print_idx~f:(TermIndex.to_dotpp_leaf)file!_idx_sup_into))@@Env.flex_getk_dot_sup_into;CCOpt.iter(funfile->Signal.onceSignals.on_dot_output(fun()->_print_idx~f:(TermIndex.to_dotpp_leaf)file!_idx_sup_from))@@Env.flex_getk_dot_sup_from;CCOpt.iter(funfile->Signal.onceSignals.on_dot_output(fun()->_print_idx~f:UnitIdx.to_dotfile!_idx_simpl))@@Env.flex_getk_dot_simpl;CCOpt.iter(funfile->Signal.onceSignals.on_dot_output(fun()->_print_idx~f:(TermIndex.to_dotpp_leaf)file!_idx_back_demod))@@Env.flex_getk_dot_demod_into;()letregister()=letopenSimplM.Infixinletrw_simplifyc=canonize_variablesc>>=demodulate>>=basic_simplify>>=positive_simplify_reflect>>=negative_simplify_reflect>>=formula_simplify_reflectandactive_simplifyc=condensationc>>=contextual_literal_cuttingandbackward_simplifyc=letset=C.ClauseSet.emptyinbackward_demodulatesetcandredundant=subsumed_by_active_setandbackward_redundant=subsumed_in_active_setandis_trivial=is_tautologyinEnv.add_basic_simplifynormalize_equalities;Env.add_basic_simplifyflex_resolve;ifEnv.flex_getk_local_rw!=`Offthen(Env.add_basic_simplifylocal_rewrite);ifEnv.flex_getCombinators.k_enable_combinators&&Env.flex_getk_subvarsupthen(Env.add_binary_inf"subvarsup"infer_subvarsup_active;Env.add_binary_inf"subvarsup"infer_subvarsup_passive;);ifEnv.flex_getk_switch_stream_extractionthen(Env.add_generate~priority:0"stream_queue_extraction"extract_from_stream_queue_fix_stm)else(Env.add_generate~priority:0"stream_queue_extraction"extract_from_stream_queue);ifEnv.flex_getk_recognize_injectivitythen(Env.add_unary_inf"recognize injectivity"recognize_injectivity;);ifEnv.flex_getk_ho_basic_rulesthen(Env.add_binary_inf"superposition_passive"infer_passive_complete_ho;Env.add_binary_inf"superposition_active"infer_active_complete_ho;Env.add_unary_inf"equality_factoring"infer_equality_factoring_complete_ho;Env.add_unary_inf"equality_resolution"infer_equality_resolution_complete_ho;ifEnv.flex_getk_fluidsupthen(Env.add_binary_inf"fluidsup_passive"infer_fluidsup_passive;Env.add_binary_inf"fluidsup_active"infer_fluidsup_active;);ifEnv.flex_getk_dupsupthen(Env.add_binary_inf"dupsup_passive(into)"infer_dupsup_passive;Env.add_binary_inf"dupsup_active(from)"infer_dupsup_active;);ifEnv.flex_getk_lambdasup!=-1then(Env.add_binary_inf"lambdasup_active(from)"infer_lambdasup_from;Env.add_binary_inf"lambdasup_passive(into)"infer_lambdasup_into;);)else(Env.add_binary_inf"superposition_passive"infer_passive;Env.add_binary_inf"superposition_active"infer_active;Env.add_unary_inf"equality_factoring"infer_equality_factoring;Env.add_unary_inf"equality_resolution"infer_equality_resolution;);ifnot(Env.flex_getk_dont_simplify)then(Env.add_rw_simplifyrw_simplify;Env.add_basic_simplifycanonize_variables;Env.add_basic_simplifybasic_simplify;Env.add_active_simplifyactive_simplify;Env.add_backward_simplifybackward_simplify);Env.add_redundantredundant;Env.add_backward_redundantbackward_redundant;ifEnv.flex_getk_use_semantic_tautothenEnv.add_is_trivialis_semantic_tautology;Env.add_is_trivialis_trivial;Env.add_lit_rule"distinct_symbol"handle_distinct_constants;ifEnv.flex_getk_immediate_simplificationthen(Env.add_immediate_simpl_ruleimmediate_subsume);setup_dot_printers();()endlet_use_semantic_tauto=reftruelet_use_simultaneous_sup=reftruelet_dot_sup_into=refNonelet_dot_sup_from=refNonelet_dot_simpl=refNonelet_dont_simplify=reffalselet_sup_at_vars=reffalselet_sup_at_var_headed=reftruelet_sup_from_var_headed=reftruelet_sup_in_var_args=reftruelet_sup_under_lambdas=reftruelet_lambda_demod=reffalselet_quant_demod=reffalselet_demod_in_var_args=reftruelet_dot_demod_into=refNonelet_ho_basic_rules=reffalselet_switch_stream_extraction=reffalselet_fluidsup_penalty=ref9let_dupsup_penalty=ref2let_fluidsup=reftruelet_subvarsup=reftruelet_dupsup=reftruelet_recognize_injectivity=reffalselet_restrict_fluidsup=reffalselet_check_sup_at_var_cond=reftruelet_restrict_hidden_sup_at_vars=reffalselet_local_rw=ref`Offlet_destr_eq_res=reftruelet_lambdasup=ref(-1)let_max_infs=ref(-1)let_unif_alg=ref`NewJPFulllet_unif_level=ref`Fulllet_ground_subs_check=ref0let_solid_subsumption=reffalselet_skip_multiplier=ref4.0let_imit_first=reffalselet_unif_logop_mode=ref`Pragmaticlet_max_depth=ref2let_max_rigid_imitations=ref2let_max_app_projections=ref1let_max_elims=ref0let_max_identifications=ref0let_pattern_decider=reftruelet_fixpoint_decider=reffalselet_solid_decider=reffalselet_solidification_limit=ref3let_max_unifs_solid_ff=ref60let_use_weight_for_solid_subsumption=reffalselet_sort_constraints=reffalselet_bool_demod=reffalselet_immediate_simplification=reffalselet_try_lfho_unif=reftruelet_rw_w_formulas=reffalselet_pred_var_eq_fact=reffalselet_schedule_infs=reftruelet_force_limit=ref3let_formula_sr=reftruelet_strong_sr=reffalselet_superposition_with_formulas=reffalselet_guard=ref30let_ratio=ref100let_clause_num=ref(-1)letkey=Flex_state.create_key()letunif_params_to_def()=_max_depth:=2;_max_app_projections:=1;_max_rigid_imitations:=2;_max_identifications:=0;_max_elims:=0;_max_infs:=5letregister~sup=letmoduleSup=(valsup:S)inletmoduleE=Sup.EnvinE.update_flex_state(Flex_state.addkeysup);(* in general all unif algs in Zip are terminating, except for JP *)E.flex_addPragUnifParams.k_unif_alg_is_terminatingtrue;E.flex_addk_sup_at_vars!_sup_at_vars;E.flex_addk_sup_in_var_args!_sup_in_var_args;E.flex_addk_sup_under_lambdas!_sup_under_lambdas;E.flex_addk_sup_at_var_headed!_sup_at_var_headed;E.flex_addk_sup_from_var_headed!_sup_from_var_headed;E.flex_addk_fluidsup!_fluidsup;E.flex_addk_subvarsup!_subvarsup;E.flex_addk_dupsup!_dupsup;E.flex_addk_lambdasup!_lambdasup;E.flex_addk_quant_demod!_quant_demod;E.flex_addk_restrict_fluidsup!_restrict_fluidsup;E.flex_addk_check_sup_at_var_cond!_check_sup_at_var_cond;E.flex_addk_restrict_hidden_sup_at_vars!_restrict_hidden_sup_at_vars;E.flex_addk_demod_in_var_args!_demod_in_var_args;E.flex_addk_lambda_demod!_lambda_demod;E.flex_addk_use_simultaneous_sup!_use_simultaneous_sup;E.flex_addk_fluidsup_penalty!_fluidsup_penalty;E.flex_addk_dupsup_penalty!_dupsup_penalty;E.flex_addk_ground_subs_check!_ground_subs_check;E.flex_addk_solid_subsumption!_solid_subsumption;E.flex_addk_dot_sup_into!_dot_sup_into;E.flex_addk_dot_sup_from!_dot_sup_from;E.flex_addk_dot_simpl!_dot_simpl;E.flex_addk_dot_demod_into!_dot_demod_into;E.flex_addk_recognize_injectivity!_recognize_injectivity;E.flex_addk_ho_basic_rules!_ho_basic_rules;E.flex_addk_max_infs!_max_infs;E.flex_addk_switch_stream_extraction!_switch_stream_extraction;E.flex_addk_dont_simplify!_dont_simplify;E.flex_addk_use_semantic_tauto!_use_semantic_tauto;E.flex_addk_bool_demod!_bool_demod;E.flex_addk_immediate_simplification!_immediate_simplification;E.flex_addk_rw_with_formulas!_rw_w_formulas;E.flex_addPragUnifParams.k_max_inferences!_max_infs;E.flex_addPragUnifParams.k_skip_multiplier!_skip_multiplier;E.flex_addPragUnifParams.k_imit_first!_imit_first;E.flex_addPragUnifParams.k_logop_mode!_unif_logop_mode;E.flex_addPragUnifParams.k_max_depth!_max_depth;E.flex_addPragUnifParams.k_max_rigid_imitations!_max_rigid_imitations;E.flex_addPragUnifParams.k_max_app_projections!_max_app_projections;E.flex_addPragUnifParams.k_max_elims!_max_elims;E.flex_addPragUnifParams.k_max_identifications!_max_identifications;E.flex_addPragUnifParams.k_pattern_decider!_pattern_decider;E.flex_addPragUnifParams.k_fixpoint_decider!_fixpoint_decider;E.flex_addPragUnifParams.k_solid_decider!_solid_decider;E.flex_addPragUnifParams.k_solidification_limit!_solidification_limit;E.flex_addPragUnifParams.k_max_unifs_solid_ff!_max_unifs_solid_ff;E.flex_addPragUnifParams.k_use_weight_for_solid_subsumption!_use_weight_for_solid_subsumption;E.flex_addPragUnifParams.k_sort_constraints!_sort_constraints;E.flex_addPragUnifParams.k_try_lfho!_try_lfho_unif;E.flex_addPragUnifParams.k_schedule_inferences!_schedule_infs;E.flex_addk_pred_var_eq_fact!_pred_var_eq_fact;E.flex_addk_force_limit!_force_limit;E.flex_addk_formula_simplify_reflect!_formula_sr;E.flex_addk_superpose_w_formulas!_superposition_with_formulas;E.flex_addStreamQueue.k_guard!_guard;E.flex_addStreamQueue.k_ratio!_ratio;E.flex_addStreamQueue.k_clause_num!_clause_num;E.flex_addk_local_rw!_local_rw;E.flex_addk_destr_eq_res!_destr_eq_res;E.flex_addk_strong_sr!_strong_sr;letmoduleJPF=JPFull.Make(structletst=E.flex_state()end)inletmoduleJPP=PUnif.Make(structletst=E.flex_state()end)inE.flex_addk_unif_module(moduleJPF:UnifFramework.US);beginmatch!_unif_algwith|`OldJP->E.flex_addk_unif_algJP_unif.unify_scoped;E.flex_addPragUnifParams.k_unif_alg_is_terminatingfalse;|`NewJPFull->E.flex_addk_unif_algJPF.unify_scoped;E.flex_addPragUnifParams.k_unif_alg_is_terminatingfalse;|`NewJPPragmatic->E.flex_addk_unif_algJPP.unify_scoped;E.flex_addk_unif_module(moduleJPP:UnifFramework.US);end(* TODO: move DOT index printing into the extension *)letextension=letactionenv=letmoduleE=(valenv:Env.S)inletmoduleSup=Make(E)inregister~sup:(moduleSup:S);Sup.register();in{Extensions.defaultwithExtensions.name="superposition";prio=5;env_actions=[action];}let()=Params.add_opts["--semantic-tauto",Arg.Bool(funv->_use_semantic_tauto:=v)," enable/disable semantic tautology check";"--dot-sup-into",Arg.String(funs->_dot_sup_into:=Somes)," print superposition-into index into file";"--dot-sup-from",Arg.String(funs->_dot_sup_from:=Somes)," print superposition-from index into file";"--dot-demod",Arg.String(funs->_dot_simpl:=Somes)," print forward rewriting index into file";"--dot-demod-into",Arg.String(funs->_dot_demod_into:=Somes)," print backward rewriting index into file";"--simultaneous-sup",Arg.Bool(funb->_use_simultaneous_sup:=b)," enable/disable simultaneous superposition";"--dont-simplify",Arg.Set_dont_simplify," disable simplification rules";"--sup-at-vars",Arg.Bool(funv->_sup_at_vars:=v)," enable/disable superposition at variables under certain ordering conditions";"--sup-at-var-headed",Arg.Bool(funb->_sup_at_var_headed:=b)," enable/disable superposition at variable headed terms";"--sup-from-var-headed",Arg.Bool(funb->_sup_from_var_headed:=b)," enable/disable superposition from variable headed terms";"--sup-in-var-args",Arg.Bool(funb->_sup_in_var_args:=b)," enable/disable superposition in arguments of applied variables";"--sup-under-lambdas",Arg.Bool(funb->_sup_under_lambdas:=b)," enable/disable superposition in bodies of lambda-expressions";"--lambda-demod",Arg.Bool(funb->_lambda_demod:=b)," enable/disable demodulation in bodies of lambda-expressions";"--quant-demod",Arg.Bool(funb->_quant_demod:=b)," enable/disable demodulation in bodies of quantifiers";"--demod-in-var-args",Arg.Bool(funb->_demod_in_var_args:=b)," enable demodulation in arguments of variables";"--ho-basic-rules",Arg.Bool(funb->_ho_basic_rules:=b)," enable/disable HO version of base superposition calculus rules";"--switch-stream-extract",Arg.Bool(funb->_switch_stream_extraction:=b)," in ho mode, switches heuristic of clause extraction from the stream queue";"--fluidsup-penalty",Arg.Int(funp->_fluidsup_penalty:=p)," penalty for FluidSup inferences";"--dupsup-penalty",Arg.Int(funp->_dupsup_penalty:=p)," penalty for DupSup inferences";"--fluidsup",Arg.Bool(funb->_fluidsup:=b)," enable/disable FluidSup inferences (only effective when complete higher-order unification is enabled)";"--subvarsup",Arg.Bool((:=)_subvarsup)," enable/disable SubVarSup inferences";"--lambdasup",Arg.Int(funl->ifl<0thenraise(Util.Error("argument parsing","lambdaSup argument should be non-negative"));_lambdasup:=l)," enable LambdaSup -- argument is the maximum number of skolems introduced in an inference";"--dupsup",Arg.Bool(funv->_dupsup:=v)," enable/disable DupSup inferences";"--rw-with-formulas",Arg.Bool(funv->_rw_w_formulas:=v)," enable/disable rewriting with formulas";"--ground-before-subs",Arg.Set_int_ground_subs_check," set the level of grounding before substitution. 0 - no grounding. 1 - only active. 2 - both.";"--solid-subsumption",Arg.Bool(funv->_solid_subsumption:=v)," set solid subsumption on or off";"--recognize-injectivity",Arg.Bool(funv->_recognize_injectivity:=v)," recognize injectivity axiom and axiomatize corresponding inverse";"--restrict-fluidsup",Arg.Bool(funv->_restrict_fluidsup:=v)," enable/disable restriction of fluidSup to up to two literal or inital clauses";"--use-weight-for-solid-subsumption",Arg.Bool(funv->_use_weight_for_solid_subsumption:=v)," enable/disable superposition to and from pure variable equations";"--ho-unif-level",Arg.Symbol(["full-framework";"full";"pragmatic-framework";],(funstr->_unif_alg:=if(String.equal"full"str)then`OldJPelseif(String.equal"full-framework"str)then(`NewJPFull)elseif(String.equal"pragmatic-framework"str)then(unif_params_to_def();`NewJPPragmatic)elseinvalid_arg"unknown argument")),"set the level of HO unification";"--ho-imitation-first",Arg.Bool(funv->_imit_first:=v)," Use imitation rule before projection rule";"--ho-unif-logop-mode",Arg.Symbol(["conservative";"pragmatic";"off"],(function|"conservative"->_unif_logop_mode:=`Conservative|"pragmatic"->_unif_logop_mode:=`Pragmatic|_->_unif_logop_mode:=`Off))," Choose level of AC reasoning on logical symbols in unification algorithm";"--ho-unif-max-depth",Arg.Set_int_max_depth," set pragmatic unification max depth";"--ho-max-app-projections",Arg.Set_int_max_app_projections," set maximal number of functional type projections";"--ho-max-elims",Arg.Set_int_max_elims," set maximal number of eliminations";"--ho-max-identifications",Arg.Set_int_max_identifications," set maximal number of flex-flex identifications";"--ho-skip-multiplier",Arg.Set_float_skip_multiplier," set maximal number of flex-flex identifications";"--ho-max-rigid-imitations",Arg.Set_int_max_rigid_imitations," set maximal number of rigid imitations";"--ho-max-solidification",Arg.Set_int_solidification_limit," set maximal number of rigid imitations";"--ho-max-unifs-solid-flex-flex",Arg.Set_int_max_unifs_solid_ff," set maximal number of found unifiers for solid flex-flex pairs. -1 stands for finding the MGU";"--ho-pattern-decider",Arg.Bool(funb->_pattern_decider:=b),"turn pattern decider on or off";"--ho-solid-decider",Arg.Bool(funb->_solid_decider:=b),"turn solid decider on or off";"--ho-fixpoint-decider",Arg.Bool(funb->_fixpoint_decider:=b),"turn fixpoint decider on or off";"--max-inferences",Arg.Int(funp->_max_infs:=p)," set maximal number of inferences";"--stream-queue-guard",Arg.Set_int_guard,"set value of guard for streamQueue";"--stream-queue-ratio",Arg.Set_int_ratio,"set value of ratio for streamQueue";"--bool-demod",Arg.Bool((:=)_bool_demod)," turn BoolDemod on/off";"--schedule-inferences",Arg.Bool((:=)_schedule_infs)," schedule inferences into streams even when terminating unification is used";"--destr-eq-res",Arg.Bool((:=)_destr_eq_res)," turn destructive equality resolution on/off";"--pred-var-eq-fact",Arg.Bool((:=)_pred_var_eq_fact)," force equality factoring when one side is applied variable";"--local-rw",Arg.Symbol(["any-context";"green-context";"off"],(funopt->matchoptwith|"any-context"->_local_rw:=`AnyContext|"green-context"->_local_rw:=`GreenContext|"off"->_local_rw:=`Off|_->invalid_arg"possible arugments are: [any-context; green-context; off]"))," turn local rewriting rule on/off";"--immediate-simplification",Arg.Bool((:=)_immediate_simplification)," turn immediate simplification on/off";"--try-lfho-unif",Arg.Bool((:=)_try_lfho_unif)," if term is of the right shape, try LFHO unification before HO unification";"--stream-clause-num",Arg.Set_int_clause_num,"how many clauses to take from streamQueue; by default as many as there are streams";"--ho-sort-constraints",Arg.Bool(funb->_sort_constraints:=b),"sort constraints in unification algorithm by weight";"--check-sup-at-var-cond",Arg.Bool(funb->_check_sup_at_var_cond:=b)," enable/disable superposition at variable monotonicity check";"--restrict-hidden-sup-at-vars",Arg.Bool(funb->_restrict_hidden_sup_at_vars:=b)," enable/disable hidden superposition at variables only under certain ordering conditions";"--stream-force-limit",Arg.Int((:=)_force_limit)," number of attempts to get a clause when the stream is just created";"--formula-simplify-reflect",Arg.Bool((:=)_formula_sr)," apply simplify reflect on the formula level";"--superposition-with-formulas",Arg.Bool((:=)_superposition_with_formulas)," enable superposition from (negative) formulas into any subterm";"--strong-simplify-reflect",Arg.Bool((:=)_strong_sr)," full effort simplify reflect -- tries to find an equation for each pair of subterms";];Params.add_to_mode"ho-complete-basic"(fun()->_use_simultaneous_sup:=false;_local_rw:=`GreenContext;_destr_eq_res:=false;_unif_logop_mode:=`Conservative;_sup_at_vars:=true;_sup_in_var_args:=false;_sup_under_lambdas:=false;_lambda_demod:=false;_demod_in_var_args:=false;_ho_basic_rules:=true;_sup_at_var_headed:=false;_unif_alg:=`NewJPFull;_lambdasup:=-1;_dupsup:=false;);Params.add_to_mode"ho-pragmatic"(fun()->_use_simultaneous_sup:=false;_sup_at_vars:=true;_sup_in_var_args:=false;_sup_under_lambdas:=false;_lambda_demod:=false;_local_rw:=`GreenContext;_demod_in_var_args:=false;_ho_basic_rules:=true;_unif_alg:=`NewJPPragmatic;_sup_at_var_headed:=true;_pred_var_eq_fact:=false;_lambdasup:=-1;_dupsup:=false;_max_infs:=4;_max_depth:=2;_max_app_projections:=0;_max_rigid_imitations:=2;_max_identifications:=1;_max_elims:=0;_fluidsup:=false;);Params.add_to_mode"ho-competitive"(fun()->_use_simultaneous_sup:=false;_sup_at_vars:=true;_sup_in_var_args:=false;_sup_under_lambdas:=false;_lambda_demod:=false;_demod_in_var_args:=false;_ho_basic_rules:=true;_unif_alg:=`NewJPFull;_local_rw:=`GreenContext;_sup_at_var_headed:=true;_pred_var_eq_fact:=true;_lambdasup:=-1;_dupsup:=false;_fluidsup:=false;);Params.add_to_mode"fo-complete-basic"(fun()->_use_simultaneous_sup:=false;_local_rw:=`Off;_destr_eq_res:=false;_unif_logop_mode:=`Conservative;_schedule_infs:=false;);Params.add_to_modes["lambda-free-intensional";"lambda-free-extensional";"ho-comb-complete";"lambda-free-purify-intensional";"lambda-free-purify-extensional"](fun()->_use_simultaneous_sup:=false;_sup_in_var_args:=true;_unif_logop_mode:=`Conservative;_demod_in_var_args:=true;_local_rw:=`GreenContext;_dupsup:=false;_ho_basic_rules:=false;_destr_eq_res:=false;_lambdasup:=-1;_fluidsup:=false;);Params.add_to_modes["lambda-free-extensional";"ho-comb-complete";"lambda-free-purify-extensional"](fun()->_restrict_hidden_sup_at_vars:=true;);Params.add_to_modes["lambda-free-intensional";"lambda-free-purify-intensional"](fun()->_restrict_hidden_sup_at_vars:=false;);Params.add_to_modes["lambda-free-intensional";"lambda-free-extensional";"ho-comb-complete"](fun()->_sup_at_vars:=true;);Params.add_to_modes["lambda-free-purify-intensional";"lambda-free-purify-extensional"](fun()->_sup_at_vars:=false;_check_sup_at_var_cond:=false;);