1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192(* 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_ext_dec=Util.mk_stat"sup.ext_dec calls"letstat_ext_inst=Util.mk_stat"sup.ext_inst calls"letstat_clc=Util.mk_stat"sup.clc"letstat_complete_eq=Util.mk_stat"ho.complete_eq.steps"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_ext_dec=ZProf.make"sup.ext_dec"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_trigger_bool_inst=Flex_state.create_key()letk_trigger_bool_ind=Flex_state.create_key()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_ext_dec_lits=Flex_state.create_key()letk_ext_rules_max_depth=Flex_state.create_key()letk_ext_rules_kind=Flex_state.create_key()letk_use_simultaneous_sup=Flex_state.create_key()letk_unif_alg=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_complete_ho_unification=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_ho_disagremeents=Flex_state.create_key()letk_bool_demod=Flex_state.create_key()letk_immediate_simplification=Flex_state.create_key()letk_arg_cong=Flex_state.create_key()letk_bool_eq_fact=Flex_state.create_key()letk_cc_simplify=Flex_state.create_key()letk_local_rw=Flex_state.create_key()let_NO_LAMSUP=-1moduleMake(Env:Env.S):SwithmoduleEnv=Env=structmoduleEnv=EnvmoduleCtx=Env.CtxmoduleC=Env.CmodulePS=Env.ProofStatemoduleI=PS.TermIndexmoduleTermIndex=PS.TermIndexmoduleSubsumIdx=PS.SubsumptionIndexmoduleUnitIdx=PS.UnitIndexmoduleStm=Stream.Make(structmoduleCtx=CtxmoduleC=Cend)moduleStmQ=StreamQueue.Make(structmoduleStm=StmmoduleEnv=Envend)moduleBools=Booleans.Make(Env)(** {5 Stream queue} *)letk_stmq=Flex_state.create_key()let_cc_simpl=ref(Congruence.FO.create~size:256())let_stmq()=Env.flex_getk_stmq(** {5 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())let_cls_w_pred_vars=ref(Type.Map.empty)(* type --> (clause,var) *)let_trigger_bools=ref(Type.Map.empty)(* type --> boolean trigger *)let_ext_dec_from_idx=ref(ID.Map.empty)let_ext_dec_into_idx=ref(ID.Map.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()(* Given a list of streams, tries getting a single clause
from each of the streams; returns obtained clauses and
partially evaluated streams *)letforce_getting_clstreams=letrecaux((clauses,streams)asacc)=function|[]->acc|(penalty,parents,stm)::xs->beginmatchstm()with|OSeq.Nil->auxaccxs|OSeq.Cons((Somecl),stm')->aux(cl::clauses,(Stm.make~penalty~parentsstm')::streams)xs|OSeq.Cons(None,stm')->aux(clauses,(Stm.make~penalty~parentsstm')::streams)xsendinaux([],[])streamsletget_triggersc=lettrivial_triggert=letbody=snd@@T.open_funtinT.is_varbody||T.is_true_or_falsebodyinLiterals.fold_terms~ord~subterms:true~eligible:C.Eligible.always~which:`All(C.litsc)~fun_bodies:false|>Iter.filter_map(fun(t,p)->letty=Term.tytandhd=Term.head_termtinletcached_t=Subst.FO.canonize_all_varstinifnot(Term.Set.memcached_t!Higher_order.prim_enum_terms)&&Type.is_funty&&Type.returns_propty&¬(Term.is_varhd)&¬(trivial_triggert)then(Somet)elseNone)lethas_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)letinstantiate_w_bool~clause~var~trigger=assert(Type.equal(T.tyvar)(T.tytrigger));letcl_sc,trig_sc=0,1inletsubst=Subst.FO.bind'Subst.empty(T.as_var_exnvar,cl_sc)(trigger,trig_sc)inletrenaming=Subst.Renaming.create()inletlits=Literals.apply_substrenamingsubst(C.litsclause,cl_sc)inletlits=Literals.map(funt->Lambda.eta_reduce@@Lambda.snft)litsinletproof=Proof.Step.inference~rule:(Proof.Rule.mk"triggered_bool_instantiation")~tags:[Proof.Tag.T_ho;Proof.Tag.T_cannot_orphan][C.proof_parent_substrenaming(clause,cl_sc)subst]inletres=C.create_alitsproof~penalty:(C.penaltyclause)~trail:(C.trailclause)in(* CCFormat.printf "instatiate:@.c:@[%a@]@.subst:@[%a@]@.res:@[%a@]@." C.pp clause Subst.pp subst C.pp res; *)resletinst_clauses_w_triggert=lettriggers=Type.Map.get_or~default:[](T.tyt)!_trigger_boolsinifnot(CCList.mem~eq:T.equalttriggers)then(_trigger_bools:=Type.Map.update(T.tyt)(function|None->Some[t]|Someres->Some(t::res))!_trigger_bools;Type.Map.get_or~default:[](T.tyt)!_cls_w_pred_vars|>CCList.map(fun(clause,var)->instantiate_w_bool~clause~var~trigger:t))else[]letinsert_new_triggert=inst_clauses_w_triggert|>CCList.to_iter|>Env.add_passivelethandle_new_pred_var_clause(clause,var)=assert(T.is_varvar);letty=T.tyvarinType.Map.get_or~default:[]ty!_trigger_bools|>CCList.map(funtrigger->instantiate_w_bool~clause~var~trigger)|>CCList.to_iter|>Env.add_passive;_cls_w_pred_vars:=Type.Map.updatety(function|None->Some[(clause,var)]|Someres->Some((clause,var)::res))!_cls_w_pred_vars;Signal.ContinueListeninglethandle_new_skolem_sym(c,trigger)=lettrig_hd=T.head_termtriggerinassert(T.is_consttrig_hd);assert(ID.is_postcnf_skolem(T.as_const_exntrig_hd));ifC.proof_depthc<Env.flex_getk_trigger_bool_insttheninsert_new_triggertrigger;Signal.ContinueListeningletupdate_triggerscl=(* if triggered boolean instantiation is off
k_trigger_bool_inst is -1 *)ifC.proof_depthcl<Env.flex_getk_trigger_bool_instthen(letnew_triggers=(get_triggerscl)inifnot(Iter.is_emptynew_triggers)then(Iter.iterinsert_new_triggernew_triggers));Signal.ContinueListeninglettrigger_inductioncl=(* abstracts away closed subterm from the term t
by replacing it with (accordingly shifted) DB variable 0 *)letabstract~subtermt=assert(T.DB.is_closedsubterm);letrecaux~deptht=ifT.equalsubtermtthen(T.bvar~ty:(T.tysubterm)depth)else(matchT.viewtwith|T.App(hd,args)->lethd'=aux~depthhdinletargs'=List.map(aux~depth)argsinifT.equalhdhd'&&T.same_largsargs'thentelseT.apphd'args'|T.AppBuiltin(hd,args)->letargs'=List.map(aux~depth)argsinifT.same_largsargs'thentelseT.app_builtin~ty:(T.tyt)hdargs'|T.Fun_->letpref,body=T.open_funtinletbody'=aux~depth:(depth+(List.lengthpref))bodyinifT.equalbodybody'thentelseT.fun_lprefbody'|_->t)inletres=aux~depth:0tinassert(Type.equal(T.tyres)(T.tyt));ifT.equalrestthenNoneelse(Someres)inletmake_triggerslhsrhssign=letlhs_body,rhs_body=snd(Term.open_funlhs),snd(Term.open_funrhs)inletimmediate_args=if(T.is_const(T.head_termlhs_body))&&(T.is_const(T.head_termrhs_body))then(List.sort_uniqT.compare(T.argslhs_body@T.argsrhs_body))else[]inCCList.filter_map(funarg->ifT.DB.is_closedarg&¬(Type.is_tType(T.tyarg))then(matchabstract~subterm:arglhs,abstract~subterm:argrhswith|Some(lhs'),Some(rhs')->assert(Type.equal(T.tylhs')(T.tyrhs'));(* Flipping the sign that is present in conjecture,
to prove the negated conjecture using induction *)letbuild_bodysign=ifsignthenT.Form.neqelseT.Form.eqinletres=T.fun_(T.tyarg)(build_bodysignlhs'rhs')inassert(T.DB.is_closedres);Someres|_->None)elseNone)immediate_argsinifC.proof_depthcl<Env.flex_getk_trigger_bool_ind&&CCOpt.is_some(C.distance_to_goalcl)then(matchC.litsclwith|[|Literal.Equation(lhs,rhs,sign)|]->CCList.flat_mapinst_clauses_w_trigger(make_triggerslhsrhssign)|_->[])else[]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->falseletext_rule_eligiblecl=Env.flex_getk_ext_rules_max_depth<0||C.proof_depthcl<=Env.flex_getk_ext_rules_max_depth(* 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_demodin_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.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 ~section 3 "@[ Adding %a to into index %B @]" (fun k-> k T.pp t !_sup_under_lambdas); *)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)|>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)|>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)|>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 *)|>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~sign:true~eligible:(C.Eligible.paramc)(C.litsc)|>Iter.filter((fun(l,_,_,_)->not(T.equallT.false_)))|>Iter.filter(fun(l,_,_,_)->sup_from_var_headed||not(T.is_app_varl))|>Iter.fold(funtree(l,_,sign,pos)->assertsign;letwith_pos=C.WithPos.({term=l;pos;clause=c;})inftreelwith_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)->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,sign)|]whensign||T.equalrT.true_->ifEnv.flex_getk_bool_demod||signthen(letl,r=ifsignthenl,relsel,T.false_in(* do not use formulas for rewriting... can have adverse
effects on lazy cnf *)if!Lazy_cnf.enabled&&(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))elseidx|[|Lit.Equation(l,r,false)|]->fidx(l,r,false,c)|_->idxin_idx_simpl:=idx';Signal.ContinueListeningletinsert_into_ext_dec_indexindex(c,pos,t)=letkey=T.head_exntinletclause_map=ID.Map.find_optkey!indexinletclause_map=matchclause_mapwith|None->C.Tbl.create8|Someres->resinletall_pos=(try(t,pos)::(C.Tbl.findclause_mapc)with_->[(t,pos)])inC.Tbl.replaceclause_mapcall_pos;index:=ID.Map.addkeyclause_map!indexletremove_from_ext_dec_indexindex(c,_,t)=letkey=T.head_exntinletclause_map=ID.Map.find_optkey!indexinmatchclause_mapwith|None->Util.debugf~section1"all clauses allready deleted."CCFun.id|Someres->(C.Tbl.removeresc;index:=ID.Map.addkeyres!index)letupdate_ext_dec_indicesfc=letwhich,eligible=ifEnv.flex_getk_ext_dec_lits=`OnlyMaxthen`Max,C.Eligible.rescelse`All,C.Eligible.alwaysinifEnv.flex_getk_ext_rules_kind!=`Off&&ext_rule_eligiblecthen(Lits.fold_terms~vars:false~var_args:false~fun_bodies:false~ty_args:false~ord~which~subterms:true~eligible(C.litsc)|>Iter.filter(fun(t,_)->not(T.is_vart)||T.is_ho_vart)|>Iter.filter(fun(t,_)->not(T.is_var(T.head_termt))&&T.is_const(T.head_termt)&&Term.has_ho_subtermt)|>Iter.iter(fun(t,pos)->f_ext_dec_into_idx(c,pos,t));leteligible=ifEnv.flex_getk_ext_dec_lits=`OnlyMaxthenC.Eligible.paramcelseC.Eligible.alwaysinLits.fold_eqn~ord~both:true~sign:true~eligible(C.litsc)|>Iter.iter(fun(l,_,sign,pos)->assertsign;lethd,_=T.as_applinifT.is_consthd&&Term.has_ho_subtermlthen(f_ext_dec_from_idx(c,pos,l))));Signal.ContinueListeninglet()=Signal.onPS.ActiveSet.on_add_clause(func->_idx_fv:=SubsumIdx.add!_idx_fvc;ignore(_update_activeTermIndex.addc);ignore(update_triggersc);update_ext_dec_indicesinsert_into_ext_dec_indexc);Signal.onPS.ActiveSet.on_remove_clause(func->_idx_fv:=SubsumIdx.remove!_idx_fvc;ignore(update_ext_dec_indicesremove_from_ext_dec_indexc);_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~section3"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=PositioninUtil.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_posinassert(Array.for_allLiteral.no_prop_invariant(C.litsinfo.passive));assert(Array.for_allLiteral.no_prop_invariant(C.litsinfo.passive));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~section2"@[<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););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~section2"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||not(Lit.Pos.is_max_term~ordpassive_lit'passive_lit_pos)||not(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=not(Lit.Pos.is_max_term~ordpassive_lit'passive_lit_pos)inletc3=not(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(Format.sprintf"bad ordering conditions %b %b %b %b"c1c2c3c4)));(* Check for superposition at a variable *)ifinfo.sup_kind!=FluidSupthenifnot@@Env.flex_getk_sup_at_varsthenassert(not(T.is_varinfo.u_p))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_pospassive_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~section3"@[... 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~section3"... 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=PositioninUtil.incr_statstat_superposition_call;letsc_a=info.scope_activeinletsc_p=info.scope_passiveinUtil.debugf~section3"@[<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_posinletshift_vars=ifinfo.sup_kind=LambdaSupthen0else-1intryletrenaming=S.Renaming.create()inletus=info.substinletsubst=US.substusinlett'=S.FO.apply~shift_varsrenamingsubst(info.t,sc_a)inbeginmatchinfo.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||not(Lit.Pos.is_max_term~ordpassive_lit'passive_lit_pos)||not(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_varsthenassert(not(T.is_varinfo.u_p))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_pospassive_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~section3"@[... ok, conclusion@ @[%a@]@]"(funk->kC.ppnew_clause);assert(C.litsnew_clause|>Literals.vars_distinct);Somenew_clausewithExitSuperpositionreason->Util.debugf~section3"@[... 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=ZProf.enter_profprof_infer_active;(* 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~sign:true~ord~both:true~eligible(C.litsclause)|>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_profprof_infer_active;new_clausesletinfer_passive_aux~retrieve_from_index~process_retrievedclause=ZProf.enter_profprof_infer_passive;(* 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:(Env.flex_getk_sup_under_lambdas)~subterms:true~ord~which:`Max~eligible~ty_args:false(C.litsclause)|>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_profprof_infer_passive;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~sign:true~ord~both:true~eligible(C.litsclause)|>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=(* 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_profprof_infer_passive;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))clauseinletclauses,streams=force_getting_clinf_resinStmQ.add_lst(_stmq())streams;clausesletinfer_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))clauseinletclauses,streams=force_getting_clinf_resinStmQ.add_lst(_stmq())streams;clausesletinfer_active_pragmatic_homax_unifsclause=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)->letall_substs=OSeq.to_list@@OSeq.takemax_unifs@@OSeq.filter_mapCCFun.idsubstsinletres=List.map(funsubst->do_supu_pwith_possubst)all_substsinSomeres)clauseininf_res|>CCList.flatten|>List.filterCCOpt.is_some|>List.mapCCOpt.get_exnletinfer_passive_pragmatic_homax_unifsclause=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)->letall_substs=OSeq.to_list@@OSeq.takemax_unifs@@OSeq.filter_mapCCFun.idsubstsinletres=List.map(funsubst->do_supu_pwith_possubst)all_substsinSomeres)clauseininf_res|>CCList.flatten|>List.filterCCOpt.is_some|>List.mapCCOpt.get_exn(* ----------------------------------------------------------------------
* FluidSup rule (Superposition at applied variables)
* ---------------------------------------------------------------------- *)letinfer_fluidsup_activeclause=ZProf.enter_profprof_infer_fluidsup_active;(* 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~sign:true~ord~both:true~eligible(C.litsclause)|>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[]inletstm_res=List.map(fun(p,s,parents)->Stm.make~penalty:p~parentss)new_clausesinStmQ.add_lst(_stmq())stm_res;ZProf.exit_profprof_infer_fluidsup_active;[]letinfer_fluidsup_passiveclause=ZProf.enter_profprof_infer_fluidsup_passive;(* 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[]inletstm_res=List.map(fun(p,s,parents)->Stm.make~penalty:p~parentss)new_clausesinStmQ.add_lst(_stmq())stm_res;ZProf.exit_profprof_infer_fluidsup_passive;[](* ----------------------------------------------------------------------
* DupSup rule (Lightweight superposition at applied variables)
* ---------------------------------------------------------------------- *)letinfer_dupsup_activeclause=leteligible=C.Eligible.paramclauseinletnew_clauses=Lits.fold_eqn~sign:true~ord~both:true~eligible(C.litsclause)|>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_listinletstm_res=List.map(fun(p,s,parents)->Stm.make~penalty:p~parentss)new_clausesinStmQ.add_lst(_stmq())stm_res;ZProf.exit_profprof_infer_fluidsup_active;[]letinfer_dupsup_passiveclause=ZProf.enter_profprof_infer_fluidsup_passive;(* 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_listinletstm_res=List.map(fun(p,s,parents)->Stm.make~penalty:p~parentss)new_clausesinStmQ.add_lst(_stmq())stm_res;ZProf.exit_profprof_infer_fluidsup_passive;[](* ----------------------------------------------------------------------
* 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~sign:true~ord~both:true~eligible(C.litsclause)|>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~section1"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~section1"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=ZProf.enter_profprof_infer_equality_resolution;leteligible=C.Eligible.filter(funlit->not@@Lit.is_predicate_litlit)in(* iterate on those literals *)(* CCFormat.printf "eq_res(@[%a@])@." C.pp clause; *)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~section1"@[<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_profprof_infer_equality_resolution;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))clauseinletcls,stm_res=force_getting_cl(List.map(funstm->C.penaltyclause,[clause],stm)inf_res)inStmQ.add_lst(_stmq())stm_res;clsletinfer_equality_resolution_pragmatic_homax_unifsclause=letinf_res=infer_equality_resolution_aux~unify:(Env.flex_getk_unif_alg)~iterate_substs:(funsubstsdo_eq_res->(* Some (OSeq.map (CCOpt.flat_map do_eq_res) substs) *)letall_substs=OSeq.to_list@@OSeq.takemax_unifs@@OSeq.filter_mapCCFun.idsubstsinletres=List.map(funsubst->do_eq_ressubst)all_substsinSomeres)clauseininf_res|>CCList.flatten|>List.filterCCOpt.is_some|>List.mapCCOpt.get_exn(* ----------------------------------------------------------------------
* Equality Factoring rule
* ---------------------------------------------------------------------- *)moduleEqFactInfo=structtypet={clause:C.t;active_idx:int;s:T.t;t:T.t;u:T.t;v:T.t;subst:US.t;scope:int;pred_var_eq_fact:bool}end(* do the inference between given positions, if ordering conditions are respected *)letdo_eq_factoringinfo=letopenEqFactInfoinlets=info.sandt=info.tandv=info.vinletus=info.substin(* check whether subst(lit) is maximal, and not (subst(s) < subst(t)) *)letrenaming=S.Renaming.create()inletsubst=US.substusinifinfo.pred_var_eq_fact||(O.compareord(S.FO.applyrenamingsubst(s,info.scope))(S.FO.applyrenamingsubst(t,info.scope))<>Comp.Lt&&(C.is_eligible_param(info.clause,info.scope)subst~idx:info.active_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)info.active_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)lett_type_is_hos=Type.is_prop(T.tys)||Type.is_fun(T.tys)(* Given terms s and t, identify maximal common context u
such that s = u[s1,...,sn] and t = u[t1,...,tn]. Then,
if some of the disagrements are solvable by a weak
unification algorihtm (e.g., pattern or fixpoint), filter
them out and create the unifying substitution. Based on
k_ho_disagremeents at least one or all of s1...sn have
to be of functional/boolean type *)letfind_ho_disagremeents?(unify=true)(orig_s,s_sc)(orig_t,t_sc)=letopenCCFuninletexceptionStopSearchinletcounter=ref0inletcheap_unify~subst(s,s_sc)(t,t_sc)=letunif_alg=ifEnv.flex_getCombinators.k_enable_combinatorsthen(funst->Unif_subst.of_subst@@Unif.FO.unify_syn~subst:(Unif_subst.substsubst)st)elseifT.is_vars||T.is_vartthen(FixpointUnif.unify_scoped~subst~counter)elsePatternUnif.unify_scoped~subst~counterintryifnotunifythenNoneelseSome(unif_alg(s,s_sc)(t,t_sc))withPatternUnif.NotInFragment|PatternUnif.NotUnifiable|Unif.Fail->Noneinletrecauxst=ifT.equalst&&(s_sc==t_sc||T.is_grounds)then[]else(matchT.views,T.viewtwith|T.App(s_hd,s_args),T.App(t_hd,t_args)whenT.is_consts_hd->let(s_hd,s_args),(t_hd,t_args)=CCPair.map_sameT.as_app_mono(s,t)inifT.equals_hdt_hdthenaux_ls_argst_argselse[s,t]|T.App(s_hd,s_args),T.App(t_hd,t_args)whennot(T.equals_hdt_hd)&&T.is_consts_hd&&T.is_constt_hd->(* trying to find prefix subterm that is the differing context *)let(s_hd,s_args),(t_hd,t_args)=CCPair.map_sameT.as_app_mono(s,t)inletlhs,rhs,args_lhs,args_rhs=ifList.lengths_args>List.lengtht_argsthen(lettaken,dropped=CCList.take_drop(List.lengths_args-List.lengtht_args)s_argsinT.apps_hdtaken,t_hd,dropped,t_args)else(lettaken,dropped=CCList.take_drop(List.lengtht_args-List.lengths_args)t_argsins_hd,T.appt_hdtaken,s_args,dropped)inifT.same_largs_lhsargs_rhs&&s_sc==t_scthen([lhs,rhs])else[s,t]|_->[s,t])andaux_lxsys=matchxs,yswith|[],[]->[]|x::xxs,y::yys->auxxy@aux_lxxsyys|_->invalid_arg"args must be of the same length"intryifnot(Type.equal(T.tyorig_s)(T.tyorig_t))thenraiseStopSearch;ifT.equalT.true_orig_s||T.equalT.true_orig_tthenraiseStopSearch;letnorm=ifEnv.flex_getCombinators.k_enable_combinatorsthenCCFun.idelseLambda.eta_expandinletdiss=aux(normorig_s)(normorig_t)inlethd_is_vart=let_,body=T.open_funtinT.is_var@@T.head_termbodyinifCCList.is_emptydiss||List.for_all(fun(s,t)->hd_is_vars||hd_is_vart)diss||List.for_all(fun(s,_)->not@@t_type_is_hos)dissthen(raiseStopSearch);let_,_,unifscope,init_subst=ifnotunifythen(orig_s,orig_t,0,US.empty)elseUS.FO.rename_to_new_scope~counter(orig_s,s_sc)(orig_t,t_sc)inletapp_substsubst=ifnotunifythen(fun(s,_)->s)elseSubst.FO.applySubst.Renaming.none(US.substsubst)in(* Filter out the pairs that are easy to unify *)letdiss=List.fold_left(fun(dis_acc,subst)(si,ti)->letsi',ti'=CCPair.map_same(app_substsubst)((si,s_sc),(ti,t_sc))inifnot(Type.is_ground(T.tysi'))||not(Type.is_ground(T.tyti'))then((* polymorphism is currently not supported *)raiseStopSearch);matchcheap_unify~subst(si',unifscope)(ti',unifscope)with|Somesubst'->dis_acc,subst'|None->(si,ti)::dis_acc,subst)([],init_subst)(diss)in(* If no constraints are left or all of pairs are flex-flex
or all of pairs are FO then we could have done all of
this with HO unification or FO superposition *)if(CCList.is_empty(fstdiss))then(raiseStopSearch);ifEnv.flex_getk_ho_disagremeents==`AllHo&&List.exists(fun(si,_)->not(t_type_is_hosi))(fstdiss)then(raiseStopSearch);SomedisswithStopSearch->Noneletext_inst~parents(s,s_sc)(t,t_sc)=assert(not(CCList.is_emptyparents));assert(CCList.lengthparents!=2||s_sc!=t_sc);letrenaming=Subst.Renaming.create()inletapply_subst=Subst.FO.applyrenamingSubst.emptyinlets,t=apply_subst(s,s_sc),apply_subst(t,t_sc)inassert(Type.equal(T.tys)(T.tyt));assert(Type.is_fun(T.tys));letty_args,ret=Type.open_fun(T.tys)inletalpha=T.of_ty@@List.hdty_argsinletbeta=T.of_ty@@Type.arrow(List.tlty_args)retinletdiff_const=Env.flex_getHO.k_diff_constinletdiff_s_t=T.appdiff_const[alpha;beta;s;t]inlets_diff,t_diff=T.apps[diff_s_t],T.appt[diff_s_t]inletneg_lit=Lit.mk_neqs_difft_diffinletpos_lit=Lit.mk_eqstinletnew_lits=[neg_lit;pos_lit]inletproof=Proof.Step.inference(List.mapC.proof_parentparents)~rule:(Proof.Rule.mk"ext_inst")inletpenalty=List.fold_leftmax1(List.mapC.penaltyparents)inC.create~trail:(C.trail_lparents)~penaltynew_litsproofletdo_ext_inst~parents((from_t,sc_f)ass)((into_t,sc_t)ast)=matchfind_ho_disagremeents~unify:falsestwith|Some(disagreements,subst)->assert(US.is_emptysubst);letho_dis=List.filter(fun(s,t)->Type.is_fun(T.tys))disagreementsin(* assert (not (CCList.is_empty ho_dis)); *)CCList.map(fun(lhs,rhs)->ext_inst~parents(lhs,sc_f)(rhs,sc_t))ho_dis|None->[]letext_inst_or_family_eqfact_auxcl=lettry_ext_eq_fact(s,t)(u,v)idx=letsc=0inmatchfind_ho_disagremeents(s,sc)(u,sc)with|Some(disagrements,subst)->assert(not(US.has_constrsubst));letsubst=US.substsubstinletdis_lits=List.map(fun(a,b)->Lit.mk_neqab)disagrementsinletnew_lits=dis_lits@((Lit.mk_neqtv)::CCArray.except_idx(C.litscl)idx)|>CCArray.of_list|>(funlits->Literals.apply_subst(Subst.Renaming.create())subst(lits,sc))|>CCArray.to_listinletproof=Proof.Step.inference[C.proof_parentcl]~rule:(Proof.Rule.mk"ext_eqfact")inletnew_c=C.create~trail:(C.trailcl)~penalty:(C.penaltycl)new_litsproofin[new_c]|None->[]inlettry_ext_eq_factinst(s,_)(u,_)=do_ext_inst~parents:[cl](s,0)(u,0)inlettry_factorings(s,t)(u,v)idx=letext_family=if(Env.flex_getk_ext_rules_kind=`Both||Env.flex_getk_ext_rules_kind=`ExtFamily)then(try_ext_eq_fact(s,t)(u,v)idx)else[]inletext_inst=if(Env.flex_getk_ext_rules_kind=`Both||Env.flex_getk_ext_rules_kind=`ExtInst)then(try_ext_eq_factinst(s,t)(u,v))else[]inext_inst@ext_familyinletaux_eq_rest(s,t)ilits=CCList.flatten@@List.mapi(funjlit->ifi<jthen(matchlitwith|Lit.Equation(u,v,true)->try_factorings(s,t)(u,v)i@try_factorings(s,t)(v,u)i|_->[])else[])litsinletlits=CCArray.to_list(C.litscl)inletmaximal=C.eligible_param(cl,0)Subst.emptyinCCList.flatten@@List.mapi(funilit->matchlitwith|Lit.Equation(s,t,true)whenEnv.flex_getk_ext_dec_lits!=`OnlyMax||BV.getmaximali->aux_eq_rest(s,t)ilits|_->[])litsletext_eqfactgiven=ifext_rule_eligiblegiventhenZProf.with_profprof_ext_decext_inst_or_family_eqfact_auxgivenelse[]letinfer_equality_factoring_aux~unify~iterate_substsclause=ZProf.enter_profprof_infer_equality_factoring;leteligible=C.Eligible.(filter(function|Equation(_,_,true)->true|Equation(lhs,rhs,false)->T.is_app_varlhs&&T.equalrhsT.true_|l->Lit.is_posl))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_lits~var_pred_statusidxs_s_posk=letis_pred_var,pred_var_sign=var_pred_statusinArray.iteri(funilit->matchlitwith|_wheni=idx->()(* same index *)|Lit.Equation(u,v,sign)->ifnotsign&¬is_pred_varthen()else(ifis_pred_var&&T.equalT.true_vthen(ifsign==pred_var_signthen(k(u,v,unify(s,0)(u,0)))else(letu=T.Form.not_uink(u,(ifsignthenT.false_elseT.true_),unify(s,0)(u,0))))elseifsign&&((notis_pred_var)||pred_var_sign)then(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,sign,s_pos)->(* try with s=t *)assert(sign||(T.equalT.true_t&&T.is_app_vars)||(T.equalT.true_s&&T.is_app_vart));letactive_idx=Lits.Pos.idxs_posinletis_var_pred=Env.flex_getk_bool_eq_fact&&T.is_app_vars&&Type.is_prop(T.tys)&&T.equalT.true_tinletvar_pred_status=(is_var_pred,sign)infind_unifiable_lits~var_pred_statusactive_idxss_pos|>Iter.filter_map(fun(u,v,substs)->lett=(* the only way we can introduce false on the RHS of the
equation is when we flip (u = true) to
((not u) = false)... Then, we also need to flip the original
equation F x != true to F x = false, which is done in the
next two lines *)ifnot(is_var_pred)||not(T.equalT.false_v)thentelseT.false_initerate_substssubsts(funsubst->letinfo=EqFactInfo.({clause;s;t;u;v;active_idx;subst;scope=0;pred_var_eq_fact=is_var_pred})indo_eq_factoringinfo)))|>Iter.to_rev_listinZProf.exit_profprof_infer_equality_factoring;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))clauseinletcls,stm_res=force_getting_cl(List.map(funstm->C.penaltyclause,[clause],stm)inf_res)inStmQ.add_lst(_stmq())stm_res;clsletinfer_equality_factoring_pragmatic_homax_unifsclause=letinf_res=infer_equality_factoring_aux~unify:(Env.flex_getk_unif_alg)~iterate_substs:(funsubstsdo_eq_fact->(* Some (OSeq.map (CCOpt.flat_map do_eq_fact) substs) *)letall_substs=OSeq.to_list@@OSeq.takemax_unifs@@OSeq.filter_mapCCFun.idsubstsinletres=List.map(funsubst->do_eq_factsubst)all_substsinSomeres)clauseininf_res|>CCList.flatten|>List.filterCCOpt.is_some|>List.mapCCOpt.get_exn(* ----------------------------------------------------------------------
* extraction of a clause from the stream queue (HO feature)
* ---------------------------------------------------------------------- *)letextract_from_stream_queue~full()=ZProf.enter_profprof_queues;letcl=iffullthenStmQ.take_fair_anyway(_stmq())elseStmQ.take_stm_nb(_stmq())inletopt_res=CCOpt.sequence_l(List.filterCCOpt.is_somecl)inZProf.exit_profprof_queues;matchopt_reswith|None->[]|Somel->lletextract_from_stream_queue_fix_stm~full()=ZProf.enter_profprof_queues;letcl=iffullthenStmQ.take_fair_anyway(_stmq())elseStmQ.take_stm_nb_fix_stm(_stmq())inletopt_res=CCOpt.sequence_l(List.filterCCOpt.is_somecl)inZProf.exit_profprof_queues;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
*)letlazy_false=Lazy.from_valfalsetypedemod_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.
restrict is an option for restricting demodulation in positive maximal terms *)letdemod_nf?(restrict=lazy_false)(st:demod_state)ct:T.t=(* compute normal form of subterm. If restrict is true, substitutions that
are variable renamings are forbidden (since we are at root of a max term) *)letrecreduce_at_root~restricttk=(* 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_map(fun(l,r,(_,_,sign,unit_clause),subst)->letrename=Subst.Renaming.create()in(* r is the term subterm is going to be rewritten into *)assert(C.is_unit_clauseunit_clause);ifsign&&C.trail_subsumesunit_clausec&¬(C.equalunit_clausec)&&(not(Lazy.forcerestrict)||not(S.is_renamingsubst))&&(O.compareord(S.FO.applyrenamesubst(l,cur_sc))(S.FO.applyrenamesubst(r,cur_sc))=Comp.Gt)(* subst(l) > subst(r) and restriction does not apply, we can rewrite *)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);letnormt=T.normalize_bools@@Lambda.eta_reduce@@Lambda.snftinlett'=normtinletl'=norm@@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;Some(r,subst,cur_sc))elseNone)inbeginmatchstepwith|None->kt(* not found any match, normal form found *)|Some(rhs,subst,cur_sc)->(* 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(rhs:>InnerTerm.t))|>Iter.fold(funsubstv->ifS.memsubst(v,cur_sc)thensubstelseS.bindsubst(v,cur_sc)(InnerTerm.var(HVar.fresh~ty:(HVar.tyv)()),cur_sc))substin(* If not beta-reduced this can get out of hands -- *)letrhs'=Lambda.snf@@Subst.FO.applySubst.Renaming.nonesubst(rhs,cur_sc)inUtil.debugf~section3"@[<2>demod(%d):@ rewrite `@[%a@]`@ into `@[%a@]`@ resulting `@[%a@]`@ nf `@[%a@]` using %a[%d]@]"(funk->k(C.idc)T.pptT.pprhsT.pprhs'T.pp(Lambda.snfrhs')Subst.ppsubstcur_sc);(* NOTE: we retraverse the term several times, but this is simpler *)normal_form~restrictrhs'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 *)andnormal_form~restricttk=matchT.viewtwith|T.Const_->reduce_at_root~restricttk|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~restrictt'k)elsereduce_at_root~restricttk|T.Fun(ty_arg,body)->(* reduce under lambdas *)ifEnv.flex_getk_lambda_demodthennormal_form~restrict:lazy_falsebody(funbody'->letu=ifT.equalbodybody'thentelseT.fun_ty_argbody'inreduce_at_root~restrictuk)elsereduce_at_root~restricttk(* TODO: DemodExt *)|T.Var_|T.DB_->kt|T.AppBuiltin(b,l)->normal_form_ll(funl'->letu=ifT.same_lll'thentelseT.app_builtin~ty:(T.tyt)bl'inreduce_at_root~restrictuk)andnormal_form_llk=matchlwith|[]->k[]|t::tail->normal_form~restrict:lazy_falset(funt'->normal_form_ltail(funl'->k(t'::l')))innormal_form~restrictt(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(* literals that are eligible for paramodulation. *)leteligible_param=lazy(C.eligible_param(c,0)S.empty)in(* demodulate literals *)letdemod_litilit=(* strictly maximal terms might be blocked *)letstrictly_max=lazy(beginmatchlitwith|Lit.Equation(t1,t2,true)->beginmatchO.compareordt1t2with|Comp.Gt->[t1]|Comp.Lt->[t2]|_->[]end|_->[]end)in(* shall we restrict a subterm? only for max terms in positive
equations that are eligible for paramodulation.
NOTE: E's paper mentions that restrictions should occur for
literals eligible for {b resolution}, not paramodulation, but
it seems it might be a typo
*)letrestrict_termt=lazy(Lit.is_poslit&&BV.get(Lazy.forceeligible_param)i&&(* restrict max terms in positive literals eligible for resolution *)CCList.mem~eq:T.equalt(Lazy.forcestrictly_max))inLit.map(funt->demod_nf~restrict:(restrict_termt)stct)litin(* demodulate every literal *)letlits=Array.mapidemod_lit(C.litsc)inifCCList.is_emptyst.demod_clausesthen((* no rewriting performed *)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=assert(Env.flex_getk_local_rw!=`Off);letneqs,others=CCArray.fold_left(fun(neq_map,others)lit->matchlitwith|Literal.Equation(lhs,rhs,sign)->ifsign&&T.is_true_or_falserhsthen(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->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 *)endinaux~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~section1"local_rw(@[%a@]):@.@[%a@]@."(funk->kC.ppcC.ppnew_c);SimplM.return_newnew_c)letcanonize_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)letdo_ext_supfrom_cfrom_pfrom_tinto_cinto_pinto_t=letsc_f,sc_i=0,1inifType.equal(Term.tyfrom_t)(Term.tyinto_t)&¬(C.idfrom_c=C.idinto_c&&Position.equalfrom_pinto_p)then(matchfind_ho_disagremeents(from_t,sc_f)(into_t,sc_i)with|Some(disagreements,subst)->assert(not@@US.has_constrsubst);letrenaming=Subst.Renaming.create()inletsubst=US.substsubstinletlits_f=Lits.apply_substrenamingsubst(C.litsfrom_c,sc_f)inletlits_i=Lits.apply_substrenamingsubst(C.litsinto_c,sc_i)inletapp_substrenamingscoped_t=Subst.FO.applyrenamingsubstscoped_tinletnew_neq_lits=List.map(fun(arg_f,arg_i)->Lit.mk_neq(app_substrenaming(arg_f,sc_f))(app_substrenaming(arg_i,sc_i)))disagreementsinlet(i,pos_f)=Lits.Pos.cutfrom_pinletfrom_s=Lits.Pos.atlits_f(Position.argi(Position.opppos_f))inLits.Pos.replacelits_i~at:into_p~by:(from_s);letnew_lits=new_neq_lits@CCArray.except_idxlits_fi@CCArray.to_listlits_iinlettrail=C.trail_l[from_c;into_c]inletpenalty=max(C.penaltyfrom_c)(C.penaltyinto_c)inlettags=[Proof.Tag.T_ho]inletproof=Proof.Step.inference[C.proof_parent_substrenaming(from_c,sc_f)subst;C.proof_parent_substrenaming(into_c,sc_i)subst]~rule:(Proof.Rule.mk"ext_sup")~tagsinletnew_c=C.create~trail~penaltynew_litsproofinSomenew_c|None->None)elseNone(* Given a "from"-clause C \/ f t1 ... tn = s and
"into"-clause D \/ f u1 .. un (~)= v, where some of the t_i
(and consequently u_i) are of functional type, construct
a clause C \/ D \/ t1 ~= u1 \/ ... tn ~= un \/ s (~)= v.
Intuitively, we are waiting for efficient extensionality rules
to kick in and fix the problem of not being able to paramodulate
with this equation.
Currently with no restrictions or indexing. After initial evaluation,
will find ways to restrict it somehow. *)letretrieve_from_extdec_idxidxid=letcl_map=ID.Map.find_optididxinmatchcl_mapwith|None->Iter.empty|Somecl_map->C.Tbl.to_itercl_map|>Iter.flat_map(fun(c,l)->Iter.of_listl|>Iter.map(fun(t,p)->(c,t,p)))letext_sup_actgiven=ifext_rule_eligiblegiventhen(leteligible=ifEnv.flex_getk_ext_dec_lits=`OnlyMaxthenC.Eligible.paramgivenelseC.Eligible.alwaysinLits.fold_eqn~ord~both:true~sign:true~eligible(C.litsgiven)|>Iter.flat_map(fun(l,_,sign,pos)->lethd,args=T.as_applinifT.is_consthd&&T.has_ho_subtermlthen(letinf_partners=retrieve_from_extdec_idx!_ext_dec_into_idx(T.as_const_exnhd)inIter.map(fun(into_c,into_t,into_p)->do_ext_supgivenposlinto_cinto_pinto_t)inf_partners)elseIter.empty)|>Iter.filter_mapCCFun.id|>Iter.to_list)else[]letext_sup_pasgiven=ifext_rule_eligiblegiventhen(letwhich,eligible=ifEnv.flex_getk_ext_dec_lits=`OnlyMaxthen`Max,C.Eligible.resgivenelse`All,C.Eligible.alwaysinLits.fold_terms~vars:false~var_args:false~fun_bodies:false~ty_args:false~ord~which~subterms:true~eligible(C.litsgiven)|>Iter.flat_map(fun(t,p)->lethd,args=T.as_apptinifT.is_consthd&&T.has_ho_subtermtthen(letinf_partners=retrieve_from_extdec_idx!_ext_dec_from_idx(T.as_const_exnhd)inIter.map(fun(from_c,from_t,from_p)->do_ext_supfrom_cfrom_pfrom_tgivenpt)inf_partners)elseIter.empty))|>Iter.filter_mapCCFun.id|>Iter.to_listelse[]letext_inst_sup_actgiven=ifext_rule_eligiblegiventhen(leteligible=ifEnv.flex_getk_ext_dec_lits=`OnlyMaxthenC.Eligible.paramgivenelseC.Eligible.alwaysinLits.fold_eqn~ord~both:true~sign:true~eligible(C.litsgiven)|>Iter.flat_map(fun(l,_,sign,pos)->lethd,args=T.as_applinifT.is_consthd&&T.has_ho_subtermlthen(letinf_partners=retrieve_from_extdec_idx!_ext_dec_into_idx(T.as_const_exnhd)inIter.map(fun(into_c,into_t,_)->do_ext_inst~parents:[given;into_c](l,0)(into_t,1))inf_partners)elseIter.empty)|>Iter.to_list|>CCList.flatten)else[]letext_inst_sup_pasgiven=ifext_rule_eligiblegiventhen(letwhich,eligible=ifEnv.flex_getk_ext_dec_lits=`OnlyMaxthen`Max,C.Eligible.resgivenelse`All,C.Eligible.alwaysinLits.fold_terms~vars:false~var_args:false~fun_bodies:false~ty_args:false~ord~which~subterms:true~eligible(C.litsgiven)|>Iter.flat_map(fun(t,p)->lethd,args=T.as_apptinifT.is_consthd&&T.has_ho_subtermtthen(Iter.map(fun(from_c,from_t,from_p)->do_ext_inst~parents:[from_c;given](from_t,0)(t,1))(retrieve_from_extdec_idx!_ext_dec_from_idx(T.as_const_exnhd)))elseIter.empty))|>Iter.to_list|>CCList.flattenelse[]letext_eqres_auxc=leteligible=C.Eligible.alwaysinifext_rule_eligiblecthen(letres=Literals.fold_eqn(C.litsc)~eligible~ord~both:false~sign:false|>Iter.to_list|>CCList.filter_map(fun(lhs,rhs,sign,pos)->assert(sign=false);letidx=Lits.Pos.idxposinifEnv.flex_getk_ext_dec_lits!=`OnlyMax||BV.get(C.eligible_res_no_substc)idxthen(letsc=0inmatchfind_ho_disagremeents(lhs,sc)(rhs,sc)with|Some(disagremeents,subst)->letnew_neq_lits=List.map(fun(s,t)->Lit.mk_neqst)disagremeentsinleti,_=Literals.Pos.cutposinletnew_lits=(Array.of_list@@new_neq_lits@CCArray.except_idx(C.litsc)i,sc)|>Literals.apply_subst(Subst.Renaming.create())(US.substsubst)|>Array.to_listinletproof=Proof.Step.inference[C.proof_parentc]~rule:(Proof.Rule.mk"ext_eqres")inletnew_c=C.create~trail:(C.trailc)~penalty:(C.penaltyc)new_litsproofinSomenew_c|None->None)elseNone)inUtil.incr_statstat_ext_dec;res)else[]letext_inst_eqresc=leteligible=C.Eligible.alwaysinifext_rule_eligiblecthen(letres=Literals.fold_eqn(C.litsc)~eligible~ord~both:false~sign:false|>Iter.to_list|>CCList.flat_map(fun(lhs,rhs,sign,pos)->assert(sign=false);letidx=Lits.Pos.idxposinifEnv.flex_getk_ext_dec_lits!=`OnlyMax||BV.get(C.eligible_res_no_substc)idxthen(do_ext_inst~parents:[c](lhs,0)(rhs,0))else[])inUtil.incr_statstat_ext_inst;res)else[]letext_eqresgiven=ZProf.with_profprof_ext_decext_eqres_auxgiven(* complete [f = g] into [f x1…xn = g x1…xn] for each [n ≥ 1] *)letcomplete_eq_args(c:C.t):C.tlist=letvar_offset=C.Seq.varsc|>Type.Seq.max_var|>succinleteligible=C.Eligible.paramcinletaux?(start=1)~polylitslit_idxtu=letn_ty_args,ty_args,_=Type.open_poly_fun(T.tyt)inassert(n_ty_args=0);assert(ty_args<>[]);letvars=List.mapi(funity->HVar.make~ty(i+var_offset)|>T.var)ty_argsinCCList.(start--List.lengthvars)|>List.map(funprefix_len->letvars_prefix=CCList.takeprefix_lenvarsinletnew_lit=Literal.mk_eq(T.apptvars_prefix)(T.appuvars_prefix)inletnew_lits=new_lit::CCArray.except_idxlitslit_idxinletproof=Proof.Step.inference[C.proof_parentc](* THIS NAME IS USED IN HEURISTICS -- CHANGE CAREFULLY! *)~rule:(Proof.Rule.mk"ho_complete_eq")~tags:[Proof.Tag.T_ho;Proof.Tag.T_dont_increase_depth]inletpenalty=C.penaltyc+(ifpolythen1else0)inletnew_c=C.createnew_litsproof~penalty~trail:(C.trailc)inifpolythen(C.set_flagSClause.flag_poly_arg_cong_resnew_ctrue;);new_c)inletis_poly_arg_cong_res=C.get_flagSClause.flag_poly_arg_cong_rescinletnew_c=C.litsc|>Iter.of_array|>Util.seq_zipi|>Iter.filter(fun(idx,lit)->eligibleidxlit)|>Iter.flat_map_l(fun(lit_idx,lit)->matchlitwith|Literal.Equation(t,u,true)whenType.is_fun(T.tyt)->aux~poly:false(C.litsc)lit_idxtu|Literal.Equation(t,u,true)whenType.is_var(T.tyt)&¬is_poly_arg_cong_res->(* A polymorphic variable might be functional on the ground level *)letty_args=OSeq.iterate[Type.var@@HVar.fresh~ty:Type.tType()](funtypes_w->Type.var(HVar.fresh~ty:Type.tType())::types_w)inletres=ty_args|>OSeq.mapi(funarrarg_idxarrow_args->letvar=Type.as_var_exn(T.tyt)inletfunty=T.of_ty(Type.arrowarrow_args(Type.var(HVar.fresh~ty:Type.tType())))inletsubst=Unif_subst.FO.singleton(var,0)(funty,0)inletrenaming,subst=Subst.Renaming.none,Unif_subst.substsubstinletlits'=Lits.apply_substrenamingsubst(C.litsc,0)inlett'=Subst.FO.applyrenamingsubst(t,0)inletu'=Subst.FO.applyrenamingsubst(u,0)inletnew_cl=aux~poly:true~start:(arrarg_idx+1)lits'lit_idxt'u'inassert(List.lengthnew_cl==1);List.hdnew_cl)inletfirst_two,rest=OSeq.take2res,OSeq.mapCCOpt.return(OSeq.drop2res)inletstm=Stm.make~penalty:(C.penaltyc+20)~parents:[c]restinStmQ.add(_stmq())stm;OSeq.to_listfirst_two|_->[])|>Iter.to_rev_listinifnew_c<>[]then(Util.add_statstat_complete_eq(List.lengthnew_c);Util.debugf~section4"(@[complete-eq@ :clause %a@ :yields (@[<hv>%a@])@])"(funk->kC.ppc(Util.pp_list~sep:" "C.pp)new_c););new_c(** Find clauses that [given] may demodulate, add them to set *)letbackward_demodulatesetgiven=ZProf.enter_profprof_back_demodulate;letrenaming=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_profprof_back_demodulate;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|Lit.Equation(l,r,false)->Congruence.FO.mk_eqcclr|_->cc)cc(C.litsc)inletres=CCArray.exists(function|Lit.Equation(l,r,true)->(* 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_neg(C.litsc)&&CCArray.existsLit.is_pos(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(ZProf.enter_profprof_basic_simplify;Util.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.emptyinlettry_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)whennot(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_profprof_basic_simplify;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_profprof_basic_simplify;SimplM.return_newnew_clause))lethandle_distinct_constantslit=matchlitwith|Lit.Equation(l,r,sign)whenT.is_constl&&T.is_constr->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.tletpositive_simplify_reflectc=ZProf.enter_profprof_pos_simplify_reflect;(* iterate through literals and try to resolve negative ones *)letreciterate_litsacclitsclauses=matchlitswith|[]->List.revacc,clauses|(Lit.Equation(s,t,false)aslit)::lits'->beginmatchequatable_termsclausesstwith|None->(* keep literal *)iterate_lits(lit::acc)lits'clauses|Somenew_clauses->(* drop literal, remember clauses *)iterate_litsacclits'new_clausesend|lit::lits'->iterate_lits(lit::acc)lits'clauses(* try to make the terms equal using some positive unit clauses
from active_set *)andequatable_termsclausest1t2=matchT.Classic.viewt1,T.Classic.viewt2with|_whenT.equalt1t2->Someclauses(* trivial *)|T.Classic.App(f,ss),T.Classic.App(g,ts)whenID.equalfg&&List.lengthss=List.lengthts->(* try to make the terms equal directly *)beginmatchequate_rootclausest1t2with|None->(* otherwise try to make subterms pairwise equal *)letok,clauses=List.fold_left2(fun(ok,clauses)t1't2'->ifokthenmatchequatable_termsclausest1't2'with|None->false,[]|Someclauses->true,clauseselsefalse,[])(true,clauses)sstsinifokthenSomeclauseselseNone|Someclauses->Someclausesend|_->equate_rootclausest1t2(* try to solve it with a unit equality *)(* try to equate terms with a positive unit clause that match them *)andequate_rootclausest1t2=tryUnitIdx.retrieve~sign:true(!_idx_simpl,1)(t1,0)|>Iter.iter(fun(l,r,(_,_,_,c'),subst)->letapp_subt=Term.normalize_bools@@Lambda.eta_expand@@Lambda.snf@@Subst.FO.applySubst.Renaming.nonesubsttinassert(T.equal(app_sub(l,1))(app_sub(t1,0)));ifC.trail_subsumesc'c&&Term.equal(app_sub(r,1))(app_sub(t2,0))thenbegin(* t1!=t2 is refuted by l\sigma = r\sigma *)Util.debugf~section4"@[<2>equate @[%a@]@ and @[%a@]@ using @[%a@]@]"(funk->kT.ppt1T.ppt2C.ppc');raise(FoundMatch(r,c',subst))(* success *)end);None(* no match *)withFoundMatch(_r,c',subst)->Some(C.proof_parent_substSubst.Renaming.none(c',1)subst::clauses)(* success *)in(* fold over literals *)letlits,premises=iterate_lits[](C.litsc|>Array.to_list)[]inifList.lengthlits=Array.length(C.litsc)then((* no literal removed, keep c *)ZProf.exit_profprof_pos_simplify_reflect;SimplM.return_samec)else(letproof=Proof.Step.simp~rule:(Proof.Rule.mk"simplify_reflect+")(C.proof_parentc::premises)inlettrail=C.trailcandpenalty=C.penaltycinletnew_c=C.create~trail~penaltylitsproofinUtil.debugf~section3"@[@[%a@]@ pos_simplify_reflect into @[%a@]@]"(funk->kC.ppcC.ppnew_c);ZProf.exit_profprof_pos_simplify_reflect;SimplM.return_newnew_c)letnegative_simplify_reflectc=ZProf.enter_profprof_neg_simplify_reflect;(* iterate through literals and try to resolve positive ones *)letreciterate_litsacclitsclauses=matchlitswith|[]->List.revacc,clauses|(Lit.Equation(s,t,true)aslit)::lits'->beginmatchcan_refutest,can_refutetswith|None,None->(* keep literal *)iterate_lits(lit::acc)lits'clauses|Somenew_clause,_|_,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=tryUnitIdx.retrieve~sign:false(!_idx_simpl,1)(s,0)|>Iter.iter(fun(l,r,(_,_,_,c'),subst)->assert(Unif.FO.equal~subst(l,1)(s,0));Util.debugf~section3"@[neg_reflect trying to eliminate@ @[%a=%a@]@ with @[%a@]@]"(funk->kT.ppsT.pptC.ppc');ifC.trail_subsumesc'c&&Unif.FO.equal~subst(r,1)(t,0)thenbegin(* TODO: useless? *)letsubst=Unif.FO.matching~subst~pattern:(r,1)(t,0)inUtil.debugf~section3"@[neg_reflect eliminates@ @[%a=%a@]@ with @[%a@]@]"(funk->kT.ppsT.pptC.ppc');raise(FoundMatch(r,c',subst))(* success *)end);None(* no match *)withFoundMatch(_r,c',subst)->Some(C.proof_parent_substSubst.Renaming.none(c',1)subst)(* success *)in(* fold over literals *)letlits,premises=iterate_lits[](C.litsc|>Array.to_list)[]inifList.lengthlits=Array.length(C.litsc)then((* no literal removed *)ZProf.exit_profprof_neg_simplify_reflect;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_profprof_neg_simplify_reflect;SimplM.return_newnew_c)(* ----------------------------------------------------------------------
* 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~section2"(@[<hv>subsumes@ :c1 @[%a@]@ :c2 @[%a@]@ :subst %a%a@]"(funk->kLits.ppaLits.ppbSubst.ppsubstProof.pp_tags!tags);Some(subst,!tags))letsubsumes_withab=ZProf.enter_profprof_subsumption;Util.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_profprof_subsumption;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 *)ZProf.enter_profprof_eq_subsumption;Util.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_profprof_eq_subsumption;resleteq_subsumesab=CCOpt.is_some(eq_subsumes_with(a,1)(b,0))letsubsumed_by_active_setc=ZProf.enter_profprof_subsumption_set;Util.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'->C.trail_subsumesc'c&&((try_eq_subsumption&&eq_subsumes(C.litsc')(C.litsc))||subsumes(C.litsc')(C.litsc)))inZProf.exit_profprof_subsumption_set;ifresthen(Util.debugf~section2"@[<2>@[%a@]@ subsumed by active set@]"(funk->kC.ppc);Util.incr_statstat_clauses_subsumed;);resletsubsumed_in_active_setaccc=ZProf.enter_profprof_subsumption_in_set;Util.incr_statstat_subsumed_in_active_set_call;(* if c is a single unit clause *)lettry_eq_subsumption=C.is_unit_clausec&&Lit.is_pos(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_profprof_subsumption_in_set;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->matchlitwith|Lit.Equation_->acc+1|_->acc)0lits(* ----------------------------------------------------------------------
* contextual literal cutting
* ---------------------------------------------------------------------- *)(* Performs successive contextual literal cuttings *)letreccontextual_literal_cutting_recc=letopenSimplM.InfixinifArray.length(C.litsc)<=1||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=ZProf.enter_profprof_clc;letres=contextual_literal_cutting_reccinZProf.exit_profprof_clc;res(* ----------------------------------------------------------------------
* 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||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~section1"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_poslit1||Lit.is_poslit2)&&(Lit.is_neglit1||Lit.is_neglit2)));letpos_lit,neg_lit=ifLit.is_poslit1thenlit1,lit2elselit2,lit1inbeginmatchpos_lit,neg_litwith|Equation(x,y,true),Equation(lhs,rhs,sign)->fail_on(not(T.is_varx&&T.is_vary));fail_on(T.equalxy);let(hd_lhs,lhs_args),(hd_rhs,rhs_args)=CCPair.map_sameT.as_app_mono(lhs,rhs)infail_on(not(T.is_consthd_lhs&&T.is_consthd_rhs));fail_on(not(T.equalhd_lhshd_rhs));fail_on(not(List.lengthlhs_args==List.lengthrhs_args));fail_on(not((find_in_argsxlhs_args)!=(-1)||(find_in_argsxrhs_args)!=(-1)));fail_on(not((find_in_argsylhs_args)!=(-1)||(find_in_argsyrhs_args)!=(-1)));(* reorient equations so that x appears in lhs *)letlhs,rhs,lhs_args,rhs_args=iffind_in_argsxlhs_args!=-1then(lhs,rhs,lhs_args,rhs_args)else(rhs,lhs,rhs_args,lhs_args)infail_on(find_in_argsxlhs_args!=find_in_argsyrhs_args);letsame_vars,diff_eqns=List.fold_left(fun(same,diff)(s,t)->fail_on(not(T.is_vars&&T.is_vart));ifT.equalstthen(s::same,diff)else(same,(s,t)::diff))([],[])(List.combinelhs_argsrhs_args)inletsame_set=T.Set.of_listsame_varsinletdiff_lhs_set,diff_rhs_set=CCPair.map_sameT.Set.of_list(CCList.splitdiff_eqns)in(* variables in each group are unique *)fail_on(List.lengthsame_vars!=T.Set.cardinalsame_set);fail_on(List.lengthdiff_eqns!=T.Set.cardinaldiff_lhs_set);fail_on(List.lengthdiff_eqns!=T.Set.cardinaldiff_rhs_set);(* variable groups do not intersect *)fail_on(not(T.Set.is_empty(T.Set.interdiff_lhs_setdiff_rhs_set)));fail_on(not(T.Set.is_empty(T.Set.interdiff_lhs_setsame_set)));fail_on(not(T.Set.is_empty(T.Set.interdiff_rhs_setsame_set)));let(sk_id,sk_ty),inv_sk=Term.mk_fresh_skolem(List.mapT.as_var_exnsame_vars)(Type.arrow[T.tylhs](T.tyx))inletinv_sk=T.appinv_sk[lhs]inletinv_lit=[Lit.mk_eqinv_skx]inletproof=Proof.Step.inference~rule:(Proof.Rule.mk"inj_rec")[C.proof_parentc]inCtx.declaresk_idsk_ty;letnew_clause=C.create~trail:(C.trailc)~penalty:(C.penaltyc)inv_litproofinUtil.debugf~section1"Injectivity recognized: %a |---| %a"(funk->kC.ppcC.ppnew_clause);[new_clause]|_->assertfalse;end|_->assertfalse;withFail->[](* Resolve negative literals that are implied by
equational theory stored in _cc_simpl *)letcc_resolve_litscl=letis_resolvedl=matchlwith|Lit.Equation(lhs,rhs,false)whenTerm.is_groundlhs&&Term.is_groundrhs&&Congruence.FO.is_eq!_cc_simpllhsrhs->None|_->Somelinletnew_lits=CCList.filter_mapis_resolved(CCArray.to_list(C.litscl))inifCCList.lengthnew_lits!=C.lengthclthen(letstep=Proof.Step.simp~rule:(Proof.Rule.mk"cc_resolve_neg")[C.proof_parentcl]inletres=C.create~penalty:(C.penaltycl)~trail:(C.trailcl)new_litsstepinSimplM.return_newres)elseSimplM.return_samecl(* Remove the clause if it has *)letis_cc_tautologycl=letis_cc_trivial=function|Lit.Equation(lhs,rhs,true)->T.is_groundlhs&&T.is_groundrhs&&Congruence.FO.is_eq!_cc_simpllhsrhs|_->falsein(* Because literals from the passive set are also added,
then unit positive equation from the passive set can make
itself tautology when it is chosen for processing...
Two ways to avoid this:
1. Do tautology checking on non-unit clauses
2. Do the check on clauses with AVATAR asertions --
the clauses added to CC are not asserted and thus
cannot make themselves tautologies.
*)(C.lengthcl>1||not(Trail.is_empty(C.trailcl)))&&Array.existsis_cc_trivial(C.litscl)(** {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_reflectandactive_simplifyc=condensationc>>=contextual_literal_cuttingandbackward_simplifyc=letset=C.ClauseSet.emptyinbackward_demodulatesetcandredundant=subsumed_by_active_setandbackward_redundant=subsumed_in_active_setandis_trivial=is_tautologyinifEnv.flex_getk_local_rw!=`Offthen(Env.add_basic_simplifylocal_rewrite);ifEnv.flex_getk_cc_simplifythen(letinsert_into_ccc=(matchC.litscwith|[|Lit.Equation(lhs,rhs,true)|]->ifTerm.is_groundlhs&&Term.is_groundrhs&&Trail.is_empty(C.trailc)then(_cc_simpl:=Congruence.FO.mk_eq!_cc_simpllhsrhs)|_->());Signal.ContinueListeninginSignal.onEnv.ProofState.PassiveSet.on_add_clauseinsert_into_cc;Env.add_basic_simplifycc_resolve_lits;Env.add_is_trivialis_cc_tautology;);Env.flex_addk_stmq(StmQ.default());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_arg_congthen(Env.add_unary_inf"ho_complete_eq"complete_eq_args);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_trigger_bool_ind>0then(Env.add_unary_inf"trigger bool ind"trigger_induction);ifEnv.flex_getk_ext_rules_kind==`ExtFamily||Env.flex_getk_ext_rules_kind==`Boththen(Env.add_binary_inf"ext_dec_act"ext_sup_act;Env.add_binary_inf"ext_dec_pas"ext_sup_pas;Env.add_unary_inf"ext_eqres_dec"ext_eqres;);ifEnv.flex_getk_ext_rules_kind=`ExtInst||Env.flex_getk_ext_rules_kind=`Boththen(Env.add_binary_inf"ext_dec_act"ext_inst_sup_act;Env.add_binary_inf"ext_dec_pas"ext_inst_sup_pas;Env.add_unary_inf"ext_eqres_dec"ext_inst_eqres;);ifEnv.flex_getk_ext_rules_kind!=`Offthen(Env.add_unary_inf"ext_eqfact_both"ext_inst_or_family_eqfact_aux;);ifEnv.flex_getk_complete_ho_unificationthen(if(Env.flex_getk_max_infs)=-1then(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;)else(assert((Env.flex_getk_max_infs)>0);Env.add_binary_inf"superposition_passive"(infer_passive_pragmatic_ho(Env.flex_getk_max_infs));Env.add_binary_inf"superposition_active"(infer_active_pragmatic_ho(Env.flex_getk_max_infs));Env.add_unary_inf"equality_factoring"(infer_equality_factoring_pragmatic_ho(Env.flex_getk_max_infs));Env.add_unary_inf"equality_resolution"(infer_equality_resolution_pragmatic_ho(Env.flex_getk_max_infs)););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;);ifEnv.flex_getk_trigger_bool_inst>0then(Signal.onEnv.on_pred_var_eliminationhandle_new_pred_var_clause;Signal.onEnv.on_pred_skolem_introductionhandle_new_skolem_sym;);)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_demod_in_var_args=reftruelet_dot_demod_into=refNonelet_complete_ho_unification=reffalselet_switch_stream_extraction=reffalselet_fluidsup_penalty=ref9let_dupsup_penalty=ref2let_fluidsup=reftruelet_subvarsup=reftruelet_dupsup=reftruelet_trigger_bool_inst=ref(-1)let_trigger_bool_ind=ref(-1)let_recognize_injectivity=reffalselet_restrict_fluidsup=reffalselet_check_sup_at_var_cond=reftruelet_restrict_hidden_sup_at_vars=reffalselet_cc_simplify=reffalselet_local_rw=ref`Offlet_lambdasup=ref(-1)let_max_infs=ref(-1)letext_rules_max_depth=ref(-1)letext_rules_kind=ref(`Off)let_ext_dec_lits=ref`OnlyMaxlet_unif_alg=ref`NewJPFulllet_unif_level=ref`Fulllet_ground_subs_check=ref0let_solid_subsumption=reffalselet_skip_multiplier=ref2.0let_imit_first=reffalselet_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_ho_disagremeents=ref`SomeHolet_bool_demod=reffalselet_immediate_simplification=reffalselet_arg_cong=reftruelet_try_lfho_unif=reftruelet_bool_eq_fact=reftruelet_guard=ref20let_ratio=ref70let_clause_num=ref7letkey=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:=-1letregister~sup=letmoduleSup=(valsup:S)inletmoduleE=Sup.EnvinE.update_flex_state(Flex_state.addkeysup);E.flex_addk_trigger_bool_inst!_trigger_bool_inst;E.flex_addk_trigger_bool_ind!_trigger_bool_ind;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_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_ext_dec_lits!_ext_dec_lits;E.flex_addk_ext_rules_max_depth!ext_rules_max_depth;E.flex_addk_ext_rules_kind!ext_rules_kind;E.flex_addk_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_complete_ho_unification!_complete_ho_unification;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_ho_disagremeents!_ho_disagremeents;E.flex_addk_bool_demod!_bool_demod;E.flex_addk_immediate_simplification!_immediate_simplification;E.flex_addk_arg_cong!_arg_cong;E.flex_addk_bool_eq_fact!_bool_eq_fact;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_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_addStreamQueue.k_guard!_guard;E.flex_addStreamQueue.k_ratio!_ratio;E.flex_addStreamQueue.k_clause_num!_clause_num;E.flex_addk_cc_simplify!_cc_simplify;E.flex_addk_local_rw!_local_rw;letmoduleJPF=JPFull.Make(structletst=E.flex_state()end)inletmoduleJPP=PUnif.Make(structletst=E.flex_state()end)inbeginmatch!_unif_algwith|`OldJP->E.flex_addk_unif_algJP_unif.unify_scoped|`NewJPFull->E.flex_addk_unif_algJPF.unify_scoped|`NewJPPragmatic->E.flex_addk_unif_algJPP.unify_scopedend(* 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";env_actions=[action];}let()=Params.add_opts["--arg-cong",Arg.Bool(funv->_arg_cong:=v)," enable/disable ArgCong";"--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";"--demod-in-var-args",Arg.Bool(funb->_demod_in_var_args:=b)," enable demodulation in arguments of variables";"--complete-ho-unif",Arg.Bool(funb->_complete_ho_unification:=b)," enable complete higher-order unification algorithm (Jensen-Pietrzykowski)";"--switch-stream-extract",Arg.Bool(funb->_switch_stream_extraction:=b)," in ho mode, switches heuristic of clause extraction from the stream queue";"--ext-rules-max-depth",Arg.Set_intext_rules_max_depth," Sets the maximal proof depth of the clause eligible for Ext-* or ExtInst inferences";"--ext-rules",Arg.Symbol(["off";"ext-inst";"ext-family";"both"],(function|"off"->ext_rules_kind:=`Off;ext_rules_max_depth:=-1;|"ext-inst"->ext_rules_kind:=`ExtInst;|"ext-family"->ext_rules_kind:=`ExtFamily;|"both"->ext_rules_kind:=`Both|_->assertfalse))," Chooses the kind of extensionality rules to use";"--ext-decompose-lits",Arg.Symbol(["all";"max"],(funstr->_ext_dec_lits:=ifString.equalstr"all"then`Allelse`OnlyMax))," Sets the maximal number of literals clause can have for ExtDec inference.";"--ext-decompose-ho-disagreements",Arg.Symbol(["all-ho";"some-ho"],(funstr->_ho_disagremeents:=ifString.equalstr"all-ho"then`AllHoelse`SomeHo))," Perform Ext-Sup, Ext-EqFact, or Ext-EqRes rules only when all disagreements are HO"^" or when there exists a HO disagremeent";"--fluidsup-penalty",Arg.Int(funp->_fluidsup_penalty:=p)," penalty for FluidSup inferences";"--dupsup-penalty",Arg.Int(funp->_dupsup_penalty:=p)," penalty for DupSup inferences";"--bool-eq-fact",Arg.Bool((:=)_bool_eq_fact)," turn bool eq-fact on or off";"--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";"--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";"--trigger-bool-inst",Arg.Set_int_trigger_bool_inst," instantiate predicate variables with boolean terms already in the proof state. Argument is the maximal proof depth of predicate variable";"--trigger-bool-ind",Arg.Set_int_trigger_bool_ind," abstract away constants from the goal and use them to trigger axioms of induction";"--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(unif_params_to_def();`NewJPFull)elseif(String.equal"pragmatic-framework"str)then`NewJPPragmaticelseinvalid_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-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";"--cc-simplify",Arg.Bool((:=)_cc_simplify)," use cong-closure of all positive ground unit eqs to simplify the clauses";"--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"];Params.add_to_mode"ho-complete-basic"(fun()->_use_simultaneous_sup:=false;(* _local_rw := `GreenContext; *)_sup_at_vars:=true;_sup_in_var_args:=false;_sup_under_lambdas:=false;_lambda_demod:=false;_demod_in_var_args:=false;_complete_ho_unification:=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 := `AnyContext; *)_demod_in_var_args:=false;_complete_ho_unification:=true;_unif_alg:=`NewJPPragmatic;_sup_at_var_headed:=true;_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;_complete_ho_unification:=true;_unif_alg:=`NewJPFull;(* _local_rw := `AnyContext; *)_sup_at_var_headed:=true;_lambdasup:=-1;_dupsup:=false;_fluidsup:=false;);Params.add_to_mode"fo-complete-basic"(fun()->_use_simultaneous_sup:=false;_arg_cong:=false;(* _local_rw := `GreenContext *));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;_demod_in_var_args:=true;(* _local_rw := `GreenContext; *)_dupsup:=false;_complete_ho_unification:=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;);