12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122(* This file is free software, part of Zipperposition. See file "license" for more details. *)openLogtkopenLibzipperpositionmoduleBV=CCBVmoduleT=TermmoduleO=OrderingmoduleS=SubstmoduleLit=LiteralmoduleLits=LiteralsmoduleComp=ComparisonmoduleUS=Unif_substmoduleP=Positionletsection=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_clc=Util.mk_stat"sup.clc"letprof_demodulate=Util.mk_profiler"sup.demodulate"letprof_back_demodulate=Util.mk_profiler"sup.backward_demodulate"letprof_pos_simplify_reflect=Util.mk_profiler"sup.simplify_reflect+"letprof_neg_simplify_reflect=Util.mk_profiler"sup.simplify_reflect-"letprof_clc=Util.mk_profiler"sup.contextual_literal_cutting"letprof_semantic_tautology=Util.mk_profiler"sup.semantic_tautology"letprof_condensation=Util.mk_profiler"sup.condensation"letprof_basic_simplify=Util.mk_profiler"sup.basic_simplify"letprof_subsumption=Util.mk_profiler"sup.subsumption"letprof_eq_subsumption=Util.mk_profiler"sup.equality_subsumption"letprof_subsumption_set=Util.mk_profiler"sup.forward_subsumption"letprof_subsumption_in_set=Util.mk_profiler"sup.backward_subsumption"letprof_infer_active=Util.mk_profiler"sup.infer_active"letprof_infer_passive=Util.mk_profiler"sup.infer_passive"letprof_ext_dec=Util.mk_profiler"sup.ext_dec"letprof_infer_fluidsup_active=Util.mk_profiler"sup.infer_fluidsup_active"letprof_infer_fluidsup_passive=Util.mk_profiler"sup.infer_fluidsup_passive"letprof_infer_equality_resolution=Util.mk_profiler"sup.infer_equality_resolution"letprof_infer_equality_factoring=Util.mk_profiler"sup.infer_equality_factoring"letk_trigger_bool_inst=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_true_false=Flex_state.create_key()letk_sup_at_var_headed=Flex_state.create_key()letk_fluidsup=Flex_state.create_key()letk_dupsup=Flex_state.create_key()letk_lambdasup=Flex_state.create_key()letk_sup_w_pure_vars=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_max_lits_ext_dec=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_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()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(Stm)moduleBools=Booleans.Make(Env)moduleSS=SolidSubsumption.Make(structletst=Env.flex_state()end)(** {6 Stream queue} *)typequeue={q:StmQ.t;}let_stmq={q=StmQ.default();}(** {6 Index Management} *)let_idx_sup_into=ref(TermIndex.empty())let_idx_lambdasup_into=ref(TermIndex.empty())let_idx_fluidsup_into=ref(TermIndex.empty())let_idx_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(C.ClauseSet.empty)let_trigger_bools=ref(Term.Set.empty)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()letpred_varsc=(* instantiate only variables in eligible lits *)leteligible=C.Eligible.rescinletlits=CCArray.mapi(funilit->(i,lit))(C.litsc)|>CCArray.filter_map(fun(i,lit)->ifeligibleilitthenSomelitelseNone)inCCList.to_seq(Literals.varslits)|>Iter.filter(funv->letty=HVar.tyvinType.is_funty&&Type.returns_propty)|>Iter.to_listletget_triggersc=lettrivial_triggert=T.is_const(T.head_termt)||T.is_var(snd@@T.open_funt)inLiterals.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)lethandle_pred_var_instc=ifC.proof_depthc<Env.flex_getk_trigger_bool_instthen(ifnot(CCList.is_empty(pred_varsc))then(_cls_w_pred_vars:=C.ClauseSet.addc!_cls_w_pred_vars;);_trigger_bools:=Term.Set.add_seq!_trigger_bools(get_triggersc););Signal.ContinueListeningletfluidsup_applicablecl=not(Env.flex_getk_restrict_fluidsup)||Array.length(C.litscl)<=2||(C.proof_depthcl)==0(* Syntactic overapproximation of fluid or deep terms *)letis_fluid_or_deepct=(* Fluid (1): Applied variables *)T.is_var(T.head_termt)&¬(CCList.is_empty@@T.argst)(* Fluid (2): A lambda-expression that might eta-reduce to a non-lambda-expression after substitution (overapproximated) *)||T.is_funt&¬(T.is_groundt)(* Deep: A variable also occurring in a lambda-expression or in an argument of a variable in the same clause*)||matchT.as_vartwith|Somev->Lits.fold_terms~vars:false~var_args:false~fun_bodies:false~ty_args:false~which:`All~ord~subterms:true~eligible:(fun__->true)(C.litsc)|>Iter.exists(fun(t,_)->matchT.viewtwith|App(head,args)whenT.is_varhead->Iter.exists(HVar.equalType.equalv)(args|>Iter.of_list|>Iter.flat_mapT.Seq.vars)|Fun(_,body)->Iter.exists(HVar.equalType.equalv)(T.Seq.varsbody)|_->false)|None->false(* apply operation [f] to some parts of the clause [c] just added/removed
from the active set *)let_update_activefc=(* index subterms that can be rewritten by superposition *)letsup_at_vars=Env.flex_getk_sup_at_varsinletsup_in_var_args=Env.flex_getk_sup_in_var_argsinletsup_under_lambdas=Env.flex_getk_sup_under_lambdasinletsup_t_f=Env.flex_getk_sup_true_falseinletsup_at_var_headed=Env.flex_getk_sup_at_var_headedinletfluidsup=Env.flex_getk_fluidsupinletdupsup=Env.flex_getk_dupsupinletlambdasup=Env.flex_getk_lambdasupinletsup_with_pure_vars=Env.flex_getk_sup_w_pure_varsinletdemod_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); *)(sup_t_f||not(Term.is_true_or_falset))&&(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;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,r,_,_)->(sup_with_pure_vars||not(Term.is_varl)||not(Term.is_varr))&&(sup_t_f||not(Term.is_true_or_falsel)))|>Iter.filter((fun(l,_,_,_)->not(T.equallT.false_)))|>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,true)|]->beginmatchOrdering.compareordlrwith|Comparison.Gt->fidx(l,r,true,c)|Comparison.Lt->assert(not(T.is_true_or_falser));fidx(r,l,true,c)|Comparison.Incomparable->assert(T.is_var(T.head_terml)||not(T.is_true_or_falsel));letidx=fidx(l,r,true,c)infidx(r,l,true,c)|Comparison.Eq->idx(* no modif *)end|[|Lit.Equation(l,r,false)|]->assert(not(T.equalrT.true_||T.equalrT.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.alwaysinifC.proof_depthc<=Env.flex_getk_max_lits_ext_decthen(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((* CCFormat.printf "adding %a to ext_dec index.\n" T.pp l; *)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(handle_pred_var_instc);update_ext_dec_indicesinsert_into_ext_dec_indexc);Signal.onPS.ActiveSet.on_remove_clause(func->_idx_fv:=SubsumIdx.remove!_idx_fvc;_cls_w_pred_vars:=C.ClauseSet.removec!_cls_w_pred_vars;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);()(** {6 Inference Rules} *)(* ----------------------------------------------------------------------
* Superposition rule
* ---------------------------------------------------------------------- *)typesupkind=|Classic|FluidSup|LambdaSup|DupSupletkind_to_str=function|Classic->"sup"|FluidSup->"fluidSup"|LambdaSup->"lambdaSup"|DupSup->"dupSup"(* 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=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 Cσ is >= C[var -> replacement]σ *)tryletpassive'_lits=Lits.apply_substrenamingsubst(C.litsinfo.passive,info.scope_passive)inletsubst_t=Unif.FO.bind_or_updatesubst(T.as_var_exnvar,info.scope_passive)(replacement,info.scope_active)inletpassive_t'_lits=Lits.apply_substrenamingsubst_t(C.litsinfo.passive,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.*)withUnif.Fail->true(* occurs check failed, do the inference -- check with Alex.*))letdup_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||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));tryUtil.debugf~section3"@[<2>sup, kind %s@ (@[<2>%a[%d]@ @[s=%a@]@ @[t=%a@]@])@ \
(@[<2>%a[%d]@ @[passive_lit=%a@]@ @[p=%a@]@])@ with subst=@[%a@]@].\n"(funk->k(kind_to_strinfo.sup_kind)C.ppinfo.activesc_aT.ppinfo.sT.ppinfo.tC.ppinfo.passivesc_pLit.ppinfo.passive_litPosition.ppinfo.passive_posUS.ppinfo.subst);letrenaming=S.Renaming.create()inletus=info.substinletsubst=US.substusinletlambdasup_vars=if(info.sup_kind=LambdaSup)then(Term.Seq.subtermsinfo.u_p|>Iter.filterTerm.is_var|>Term.Set.of_seq)elseTerm.Set.emptyinlett'=ifinfo.sup_kind!=DupSupthenS.FO.apply~shift_varsrenamingsubst(info.t,sc_a)elsedup_sup_apply_substinfo.tsc_asc_psubstrenaminginUtil.debugf~section1"@[<2>sup, kind %s(%d)@ (@[<2>%a[%d]@ @[s=%a@]@ @[t=%a, t'=%a@]@])@ \
(@[<2>%a[%d]@ @[passive_lit=%a@]@ @[p=%a@]@])@ with subst=@[%a@]@]"(funk->k(kind_to_strinfo.sup_kind)(Term.Set.cardinallambdasup_vars)C.ppinfo.activesc_aT.ppinfo.sT.ppinfo.tT.ppt'C.ppinfo.passivesc_pLit.ppinfo.passive_litPosition.ppinfo.passive_posUS.ppinfo.subst);if(info.sup_kind=LambdaSup&&T.Set.exists(funv->not@@T.DB.is_closed@@Subst.FO.applyrenamingsubst(v,sc_p))lambdasup_vars)then(Util.debugf~section3"LambdaSup -- an into free variable sneaks in bound variable"(funk->k);raise@@ExitSuperposition("LambdaSup -- an into free variable sneaks in bound variable"););beginmatchinfo.passive_lit,info.passive_poswith|Lit.Equation(_,v,true),P.Arg(_,P.LeftP.Stop)|Lit.Equation(v,_,true),P.Arg(_,P.RightP.Stop)->(* are we in the specific, but no that rare, case where we
rewrite s=t using s=t (into a tautology t=t)? *)(* TODO: use Unif.FO.eq? *)letv'=S.FO.apply~shift_vars:0renamingsubst(v,sc_p)inifT.equalt'v'then(Util.debugf~section3"will yield a tautology"(funk->k);raise(ExitSuperposition"will yield a tautology");)|_->()end;if(info.sup_kind=LambdaSup)then(letvars_a=CCArray.except_idx(C.litsinfo.active)active_idx|>CCArray.of_list|>Literals.vars|>T.VarSet.of_listinletvars_p=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_setin(* I am going crazy from different castings *)vars_bound_to_closed_termsvars_asc_a;vars_bound_to_closed_termsvars_psc_p;ifUtil.Int_set.cardinal(Util.Int_set.of_list!dbs)>Env.flex_getk_lambdasupthen(Util.debugf~section3"Too many skolems will be introduced for LambdaSup."(funk->k);raise(ExitSuperposition"Too many skolems will be introduced for LambdaSup.");));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))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)then(Util.debugf~section3"superposition at variable"(funk->k);raise(ExitSuperposition"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)in(* For some reason type comparison does not work. *)letpos_enclosing_up=Position.until_first_funpassive_lit_posinletaround_up=Subst.FO.applyrenamingsubst'(Lit.Pos.atinfo.passive_litpos_enclosing_up,sc_p)inletvars=Iter.append(T.Seq.varsaround_up)(T.Seq.varst')|>Term.VarSet.of_seq|>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->(* For polymorphism -- will apply type substitution. *)letscope=ifi<(List.lengthc_guard+List.lengthlits_a)thensc_aelsesc_pinletsk=S.FO.applyrenamingsubst(sk,scope)inTerm.replace~old:sk~by:sk_vacc)sk_with_varst)lit)new_litsinifList.exists(funlit->Lit.Seq.termslit|>Iter.exists(funt->not(Lambda.is_properly_encodedt)))new_litsthen(raise(ExitSuperposition"improperly formed quantified expressions."););letsubst_has_lams=Subst.codomainsubst|>Iter.exists(fun(t,_)->Iter.existsT.is_fun(T.Seq.subterms(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_has_lamsthen[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=max(C.penaltyinfo.active)(C.penaltyinfo.passive)+(ifT.is_vars'then2else0)(* superposition from var = bad *)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);assert(List.for_all(Lit.for_allTerm.DB.is_closed)new_lits);assert(Array.for_allLiteral.no_prop_invariant(C.litsnew_clause));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_has_lams=Subst.codomainsubst|>Iter.exists(fun(t,_)->Iter.existsT.is_fun(T.Seq.subterms(T.of_term_unsafet)))inlettags=(ifsubst_has_lamsthen[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=max(C.penaltyinfo.active)(C.penaltyinfo.passive)+(ifT.is_vars'then2else0)(* superposition from var = bad *)inletnew_clause=C.create~trail:new_trail~penaltynew_litsproofinUtil.debugf~section3"@[... ok, conclusion@ @[%a@]@]"(funk->kC.ppnew_clause);Somenew_clausewithExitSuperpositionreason->Util.debugf~section3"@[... cancel, %s@]"(funk->kreason);None(* choose between regular and simultaneous superposition *)letdo_superpositioninfo=letopenSupInfoinassert(info.sup_kind=DupSup||Type.equal(T.tyinfo.s)(T.tyinfo.t));assert(info.sup_kind=DupSup||Unif.Ty.equal~subst:(US.substinfo.subst)(T.tyinfo.s,info.scope_active)(T.tyinfo.u_p,info.scope_passive));letrenaming=Subst.Renaming.create()inlets=Subst.FO.applyrenaming(US.substinfo.subst)(info.s,info.scope_active)inletu_p=Subst.FO.applyrenaming(US.substinfo.subst)(info.u_p,info.scope_passive)inassert(Term.equal(Lambda.eta_reduce@@Lambda.snf@@s)(Lambda.eta_reduce@@Lambda.snf@@u_p)||US.has_constrinfo.subst);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=Util.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.filter(fun(l,r,_,_)->(Env.flex_getk_sup_w_pure_vars||not(Term.is_varl)||not(Term.is_varr))&&(Env.flex_getk_sup_true_false||not(Term.is_true_or_falsel)))|>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_listinUtil.exit_profprof_infer_active;new_clausesletinfer_passive_aux~retrieve_from_index~process_retrievedclause=Util.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_listinUtil.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_listinUtil.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)->letpenalty=max(C.penaltyclause)(C.penaltywith_pos.C.WithPos.clause)in(* /!\ may differ from the actual penalty (by -2) *)Some(penalty,OSeq.map(CCOpt.flat_map(do_supu_pwith_pos))substs))clauseinletstm_res=List.map(fun(p,s)->Stm.make~penalty:ps)inf_resinStmQ.add_lst_stmq.qstm_res;[]letinfer_passive_complete_hoclause=letinf_res=infer_passive_aux~retrieve_from_index:(I.retrieve_unifiables_complete~unif_alg:(Env.flex_getk_unif_alg))~process_retrieved:(fundo_sup(u_p,with_pos,substs)->letpenalty=max(C.penaltyclause)(C.penaltywith_pos.C.WithPos.clause)in(* /!\ may differ from the actual penalty (by -2) *)Some(penalty,OSeq.map(CCOpt.flat_map(do_supu_pwith_pos))substs))clauseinletstm_res=List.map(fun(p,s)->Stm.make~penalty:ps)inf_resinStmQ.add_lst_stmq.qstm_res;[]letinfer_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=Util.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)acc)Iter.empty)|>Iter.to_rev_listelse[]inletstm_res=List.map(fun(p,s)->Stm.make~penalty:ps)new_clausesinStmQ.add_lst_stmq.qstm_res;Util.exit_profprof_infer_fluidsup_active;[]letinfer_fluidsup_passiveclause=Util.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)acc)Iter.empty)|>Iter.to_rev_listelse[]inletstm_res=List.map(fun(p,s)->Stm.make~penalty:ps)new_clausesinStmQ.add_lst_stmq.qstm_res;Util.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);(* Create prefix variable H and use H s = H t for superposition *)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(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_penaltyin(* /!\ may differ from the actual penalty (by -2) *)Iter.cons(penalty,res)acc))Iter.empty)|>Iter.to_rev_listinletstm_res=List.map(fun(p,s)->Stm.make~penalty:ps)new_clausesinStmQ.add_lst_stmq.qstm_res;Util.exit_profprof_infer_fluidsup_active;[]letinfer_dupsup_passiveclause=Util.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_penaltyin(* /!\ may differ from the actual penalty (by -2) *)Iter.cons(penalty,res)acc))|_->acc)Iter.empty)|>Iter.to_rev_listinletstm_res=List.map(fun(p,s)->Stm.make~penalty:ps)new_clausesinStmQ.add_lst_stmq.qstm_res;Util.exit_profprof_infer_fluidsup_passive;[](* ----------------------------------------------------------------------
* Equality Resolution rule
* ---------------------------------------------------------------------- *)letinfer_equality_resolution_aux~unify~iterate_substsclause=Util.enter_profprof_infer_equality_resolution;leteligible=C.Eligible.alwaysin(* iterate on those literals *)letnew_clauses=Lits.fold_eqn~sign:false~ord~both:false~eligible(C.litsclause)|>Iter.filter_map(fun(l,r,_,l_pos)->letdo_eq_resus=letpos=Lits.Pos.idxl_posinifBV.get(C.eligible_res_no_substclause)pos(* 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_has_lams=Subst.codomainsubst|>Iter.exists(fun(t,_)->Iter.existsT.is_fun(T.Seq.subterms(T.of_term_unsafet)))inlettags=(ifsubst_has_lamsthen[Proof.Tag.T_ho]else[])@Unif_subst.tagsusinlettrail=C.trailclauseandpenalty=C.penaltyclauseinletproof=Proof.Step.inference~rule~tags[C.proof_parent_substrenaming(clause,0)subst]inletnew_clause=C.create~trail~penalty(c_guard@new_lits)proofinUtil.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_listinUtil.exit_profprof_infer_equality_resolution;new_clausesletinfer_equality_resolution=infer_equality_resolution_aux~unify:(funlr->trySome(Unif.FO.unify_fulllr)withUnif.Fail->None)~iterate_substs:(funsubstsdo_eq_res->CCOpt.flat_mapdo_eq_ressubsts)letinfer_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))clauseinletpenalty=C.penaltyclauseinletstm_res=List.map(Stm.make~penalty:penalty)inf_resinStmQ.add_lst_stmq.qstm_res;[]letinfer_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;}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.substusinifO.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_idxthen(letsubst_has_lams=Subst.codomainsubst|>Iter.exists(fun(t,_)->Iter.existsT.is_fun(T.Seq.subterms(T.of_term_unsafet)))inlettags=(ifsubst_has_lamsthen[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_litsinletnew_clause=C.create~trail:(C.trailinfo.clause)~penalty:(C.penaltyinfo.clause)new_litsproofinUtil.debugf~section3"@[<hv2>equality factoring on@ @[%a@]@ yields @[%a@]@]"(funk->kC.ppinfo.clauseC.ppnew_clause);Somenew_clause)elseNoneletext_eqfact_decompose_auxcl=lettry_ext_eq_fact(s,t)(u,v)idx=let(s_hd,s_args),(u_hd,u_args)=CCPair.map_sameT.as_app(s,u)inifnot(T.equals_hdu_hd)&&Type.equal(T.tys)(T.tyu)&&List.lengths_args=List.lengthu_args&&List.for_all(fun(s,t)->Term.equalst)(CCList.combines_argsu_args)then(letnew_lits=Lit.mk_neqs_hdu_hd::Lit.mk_neqtv::CCArray.except_idx(C.litscl)idxinletproof=Proof.Step.inference[C.proof_parentcl]~rule:(Proof.Rule.mk"ext_eqfact_decompose")inletnew_c=C.create~trail:(C.trailcl)~penalty:(C.penaltycl)new_litsproofin[new_c])else[]inletaux_eq_rest(s,t)ilits=List.mapi(funjlit->ifi<jthen(matchlitwith|Lit.Equation(u,v,true)->try_ext_eq_fact(s,t)(u,v)i@try_ext_eq_fact(s,t)(v,u)i|_->[])else[])lits|>CCList.flatteninletlits=CCArray.to_list(C.litscl)inList.mapi(funilit->matchlitwith|Lit.Equation(s,t,true)->aux_eq_rest(s,t)ilits|_->[])lits|>CCList.flattenletpred_var_instantiationctrigger_set=letp_vars=pred_varscinletsubsts=CCList.flat_map(funv->letres=ref[]in(* no really efficient way without turning set to list *)Term.Set.iter(funt->letvar_ty=HVar.tyvandt_ty=Term.tytinifType.is_groundvar_ty&&Type.is_groundt_ty&&Type.equalvar_tyt_tythen(letsubst=Subst.FO.bind'Subst.empty(v,0)(t,1)inres:=subst::!res;))trigger_set;!res)p_varsinIter.of_listsubsts|>Iter.map(funsub->letrenaming=Subst.Renaming.create()inletnew_lits=Lits.apply_substrenamingsub(C.litsc,0)inlettrail=C.trailcinletpenalty=C.penaltycinletrule=Proof.Rule.mk"instantiate_w_trigger"inlettags=[Proof.Tag.T_ho]inletproof=Proof.Step.inference~tags~rule[C.proof_parent_substrenaming(c,0)sub]inletnew_clause=C.create~trail~penalty(CCArray.to_listnew_lits)proofin(* CCFormat.printf "[BOOL_INST: %a, %a => %a].\n" C.pp c Subst.pp sub C.pp new_clause; *)assert(C.Seq.termsc|>Iter.for_allT.DB.is_closed);assert(C.Seq.termsnew_clause|>Iter.for_allT.DB.is_closed);new_clause)|>Iter.to_listletinstantiate_with_triggersc=ifC.proof_depthc<Env.flex_getk_trigger_bool_instthen(pred_var_instantiationc!_trigger_bools)else[]lettrigger_insantiationc=ifC.proof_depthc<Env.flex_getk_trigger_bool_instthen(lettriggers=Term.Set.of_seq@@get_triggerscinletres=ref[]inC.ClauseSet.iter(funold_c->res:=pred_var_instantiationold_ctriggers@!res)!_cls_w_pred_vars;!res)else[]letext_eqfact_decomposegiven=ifProof.Step.inferences_performed(C.proof_stepgiven)<Env.flex_getk_max_lits_ext_decthenUtil.with_profprof_ext_decext_eqfact_decompose_auxgivenelse[]letinfer_equality_factoring_aux~unify~iterate_substsclause=Util.enter_profprof_infer_equality_factoring;leteligible=C.Eligible.(filterLit.is_pos)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,true)->(* positive equation *)ifT.equalvT.false_&¬is_pred_varthen()else(ifis_pred_var&&T.is_true_or_falsevthen(assert(T.is_true_or_falsepred_var_sign);ifT.equalvpred_var_signthen(k(u,v,unify(s,0)(u,0)))else(letu=T.Form.not_uink(u,pred_var_sign,unify(s,0)(u,0))))else(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~sign:true~ord~both:true~eligible(C.litsclause)|>Iter.flat_map(fun(s,t,_,s_pos)->(* try with s=t *)letactive_idx=Lits.Pos.idxs_posinletis_var_pred=T.is_var(T.head_terms)&&Type.is_prop(T.tys)&&T.is_true_or_falsetinifnot@@Env.flex_getk_sup_true_false&&T.is_true_or_falsesthenIter.empty(* disable factoring from false*)elseifT.equaltT.false_&¬is_var_predthenIter.emptyelse(letvar_pred_status=(is_var_pred,t)infind_unifiable_lits~var_pred_statusactive_idxss_pos)|>Iter.filter_map(fun(u,v,substs)->iterate_substssubsts(funsubst->letinfo=EqFactInfo.({clause;s;t;u;v;active_idx;subst;scope=0;})indo_eq_factoringinfo)))|>Iter.to_rev_listinUtil.exit_profprof_infer_equality_factoring;new_clausesletinfer_equality_factoring=infer_equality_factoring_aux~unify:(funst->trySome(Unif.FO.unify_fullst)withUnif.Fail->None)~iterate_substs:(funsubstdo_eq_fact->CCOpt.flat_mapdo_eq_factsubst)letinfer_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))clauseinletpenalty=C.penaltyclauseinletstm_res=List.map(Stm.make~penalty:penalty)inf_resinStmQ.add_lst_stmq.qstm_res;[]letinfer_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()=letcl=iffullthen[StmQ.take_first_anyway_stmq.q]elseStmQ.take_stm_nb_stmq.qinletopt_res=CCOpt.sequence_l(List.filterCCOpt.is_somecl)inmatchopt_reswith|None->[]|Somel->lletextract_from_stream_queue_fix_stm~full()=letcl=iffullthen[StmQ.take_first_anyway_stmq.q]elseStmQ.take_stm_nb_fix_stm_stmq.qinletopt_res=CCOpt.sequence_l(List.filterCCOpt.is_somecl)inmatchopt_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.equalunit_clausec)&&(not(Lazy.forcerestrict)||not(S.is_renamingsubst))&&C.trail_subsumesunit_clausec&&(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:@ @[<hv>t=%a[%d],@ l=%a[%d],@ r=%a[%d]@],@ subst=@[%a@]@]"(funk->kT.ppt0T.pplcur_scT.pprcur_scS.ppsubst);lett'=Lambda.eta_reduce@@Lambda.snftinletl'=Lambda.eta_reduce@@Lambda.snf@@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);Util.debugf~section3"@[<2>demod:@ rewrite `@[%a@]`@ into `@[%a@]`@ using %a[%d]@]"(funk->kT.pptT.pprhsSubst.ppsubstcur_sc);(* NOTE: we retraverse the term several times, but this is simpler *)letrhs=Subst.FO.applySubst.Renaming.nonesubst(rhs,cur_sc)innormal_form~restrictrhsk(* 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);(* Assertion against variable clashes *)(* Not sure if this assertion is in place -- maybe Zip renames the vars afterwards
TODO: INVESTIGATE!!!
*)(* Lits.vars (C.lits new_c)
|> CCList.map (fun v -> (HVar.id v))
|> (fun vars -> assert (CCList.length (CCList.uniq ~eq:CCInt.equal vars) == CCList.length vars)); *)(* return simplified clause *)SimplM.return_newnew_c)letdemodulatec=assert(Term.VarSet.for_all(funv->HVar.idv>=0)(Literals.vars(C.litsc)|>Term.VarSet.of_list));Util.with_profprof_demodulatedemodulate_cletcanonize_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_decfrom_cfrom_pfrom_tinto_cinto_pinto_t=letsc_f,sc_i=0,1inletrenaming=Subst.Renaming.create()inlet(hd_f,args_f),(hd_i,args_i)=Term.as_appfrom_t,Term.as_appinto_tinifType.equal(Term.tyfrom_t)(Term.tyinto_t)&&List.lengthargs_f=List.lengthargs_i&¬(C.idfrom_c=C.idinto_c&&Position.equalfrom_pinto_p)then((* Renaming variables apart *)letargs_f=List.map(funt->Subst.FO.applyrenamingSubst.empty(t,sc_f))args_finletargs_i=List.map(funt->Subst.FO.applyrenamingSubst.empty(t,sc_i))args_iinletcombined=CCList.combineargs_fargs_iinifT.equalhd_fhd_i&&T.is_consthd_f&&List.for_all(fun(s,t)->Type.equal(T.tys)(T.tyt))combinedthen(ifList.exists(fun(s,t)->(* otherwise they would be unifyible *)not(T.is_var(T.head_terms))&¬(T.is_var(T.head_termt)))combinedthen(letlits_f=Lits.apply_substrenamingSubst.empty(C.litsfrom_c,sc_f)inletlits_i=Lits.apply_substrenamingSubst.empty(C.litsinto_c,sc_i)inletnew_neq_lits=List.map(fun(arg_f,arg_i)->Lit.mk_neqarg_farg_i)combinedinlet(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.empty;C.proof_parent_substrenaming(into_c,sc_i)Subst.empty]~rule:(Proof.Rule.mk"ext_decompose")~tagsinletnew_c=C.create~trail~penaltynew_litsproofinSomenew_c)elseNone)elseNone)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_seqcl_map|>Iter.flat_map(fun(c,l)->Iter.of_listl|>Iter.map(fun(t,p)->(c,t,p)))letext_decompose_actgiven=ifC.lengthgiven<=Env.flex_getk_max_lits_ext_decthen(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_decgivenposlinto_cinto_pinto_t)inf_partners)elseIter.empty)|>Iter.filter_mapCCFun.id|>Iter.to_list)else[]letext_decompose_pasgiven=ifC.lengthgiven<=Env.flex_getk_max_lits_ext_decthen(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_decfrom_cfrom_pfrom_tgivenpt)inf_partners)elseIter.empty))|>Iter.filter_mapCCFun.id|>Iter.to_listelse[]letext_eqres_decompose_auxc=leteligible=C.Eligible.neginifC.proof_depthc<Env.flex_getk_max_lits_ext_decthen(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);let(l_hd,l_args),(r_hd,r_args)=CCPair.map_sameT.as_app(lhs,rhs)inifnot(T.equall_hdr_hd)&&List.lengthl_args=List.lengthr_args&&List.for_all(fun(s,t)->Type.equal(Term.tys)(Term.tyt))(CCList.combinel_argsr_args)&&(List.for_all(fun(s,t)->Term.equalst)(CCList.combinel_argsr_args))then(letnew_neq_lits=((l_hd,r_hd)::CCList.combinel_argsr_args)|>CCList.filter_map(fun(arg_f,arg_i)->ifnot(T.equalarg_farg_i)thenSome(Lit.mk_neqarg_farg_i)elseNone)inleti,_=Literals.Pos.cutposinletnew_lits=new_neq_lits@CCArray.except_idx(C.litsc)iinletproof=Proof.Step.inference[C.proof_parentc]~rule:(Proof.Rule.mk"ext_eqres_decompose")inletnew_c=C.create~trail:(C.trailc)~penalty:(C.penaltyc)new_litsproofinSomenew_c)elseNone)inUtil.incr_statstat_ext_dec;res)else[]letext_eqres_decomposegiven=Util.with_profprof_ext_decext_eqres_decompose_auxgiven(** Find clauses that [given] may demodulate, add them to set *)letbackward_demodulatesetgiven=Util.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((oriented||O.compareord(S.FO.applyrenamingsubst(l,0))(S.FO.applyrenamingsubst(r,0))=Comp.Gt)&&C.trail_subsumescgiven)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|_->setinUtil.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(* registering equations of the form ~ P as negative equations P = true *)|Lit.Equation(p,t,true)whenT.equaltT.false_->Congruence.FO.mk_eqccpT.true_|_->cc)cc(C.litsc)inletres=CCArray.exists(function(* making sure we do not catch equations of the form P = false
that are interpreted as negative equations P = true *)|Lit.Equation(l,r,true)whennot(T.equalrT.false_)->(* 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=Util.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(Util.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)->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|Lit.Equation(l,r,true)whenType.is_prop(T.tyl)->beginmatchT.viewl,T.viewrwith|(T.AppBuiltin(Builtin.True,[]),T.Varx|T.Varx,T.AppBuiltin(Builtin.True,[]))whennot(var_in_subst_!usx0)->(* [C or x=true ---> C[x:=false]] *)begintryletsubst'=US.FO.bind!us(x,0)(T.false_,0)inhas_changed:=true;BV.resetbvi;us:=subst';withUnif.Fail->()end|_->()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(Util.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;Util.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=Util.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)->assert(Unif.FO.equal~subst(l,1)(t1,0));ifUnif.FO.equal~subst(r,1)(t2,0)&&C.trail_subsumesc'cthenbegin(* 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 *)Util.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);Util.exit_profprof_pos_simplify_reflect;SimplM.return_newnew_c)letnegative_simplify_reflectc=Util.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');ifUnif.FO.equal~subst(r,1)(t,0)&&C.trail_subsumesc'cthenbegin(* 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 *)Util.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);Util.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=Util.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_abelseNoneinUtil.exit_profprof_subsumption;res)letsubsumesab=matchsubsumes_with(a,0)(b,1)with|None->false|Some_->true(* 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 *)Util.enter_profprof_eq_subsumption;Util.incr_statstat_eq_subsumption_call;letres=matchawith|[|Lit.Equation(s,t,true)|]->letres=CCArray.find(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 *)inUtil.exit_profprof_eq_subsumption;resleteq_subsumesab=CCOpt.is_some(eq_subsumes_with(a,1)(b,0))letsubsumed_by_active_setc=Util.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_clausecelsecinletsubsumesab=ifnot@@Env.flex_getk_solid_subsumptionthensubsumesabelse(trySS.subsumesabwithSolidSubsumption.UnsupportedLiteralKind->subsumesab)inletres=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)))inUtil.exit_profprof_subsumption_set;ifresthen(Util.debugf~section1"@[<2>@[%a@]@ subsumed by active set@]"(funk->kC.ppc);Util.incr_statstat_clauses_subsumed;);resletsubsumed_in_active_setaccc=Util.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 *)letsubsumesab=ifnot@@Env.flex_getk_solid_subsumptionthensubsumesabelse(trySS.subsumesabwithSolidSubsumption.UnsupportedLiteralKind->subsumesab)inletres=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)accinUtil.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.inference~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=Util.enter_profprof_clc;letres=contextual_literal_cutting_reccinUtil.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=Util.with_profprof_condensationcondensation_reccletrecognize_injectivityc=ifC.lengthc==2then(letpos_lit=CCArray.find_idxLit.is_pos(C.litsc)inletneg_lit=CCArray.find_idxLit.is_neg(C.litsc)intrylet_,pos_lit=CCOpt.get_exnpos_litinlet_,neg_lit=CCOpt.get_exnneg_litinmatchpos_litwith|Equation(x,y,true)->ifTerm.is_varx&&Term.is_vary&¬(Term.equalxy)then(matchneg_litwith|Equation(l,r,false)->lethd_l,hd_r=CCPair.map_sameTerm.head_term(l,r)inifTerm.is_consthd_l&&Term.is_consthd_r&&Term.equalhd_lhd_rthen(letcovered_l=Term.max_coverl[Somex]inletcovered_r=Term.max_coverr[Somey]inifTerm.equalcovered_lcovered_rthen(letty=Type.arrow[Term.tyl](Term.tyx)inletsk_vars=Term.varscovered_l|>Term.VarSet.to_listinlet(sk_id,sk_ty),sk_term=Term.mk_fresh_skolemsk_varstyinletinverse_x=Term.appsk_term[l]inletinverse_lit=[Lit.mk_eqinverse_xx]inletproof=Proof.Step.inference~rule:(Proof.Rule.mk"inverse recognition")[C.proof_parentc]inCtx.declaresk_idsk_ty;letnew_clause=C.create~trail:(C.trailc)~penalty:(C.penaltyc)inverse_litproofinUtil.debugf~section1"Injectivity recognized: %a |---| %a"(funk->kC.ppcC.ppnew_clause);(* Format.printf "Injectivity recognized: %a |---| %a" C.pp c C.pp new_clause; *)[new_clause])else[])else[]|_->[](* predicate *))else[]|_->assertfalsewithInvalid_argument_->[])else[](** {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_tautologyinifnot@@Env.flex_getk_sup_w_pure_varsthen(Env.Ctx.lost_completeness());ifEnv.flex_getk_recognize_injectivitythen(Env.add_unary_inf"recognize injectivity"recognize_injectivity;);ifEnv.flex_getk_max_lits_ext_dec!=0then(Env.add_binary_inf"ext_dec_act"ext_decompose_act;Env.add_binary_inf"ext_dec_pas"ext_decompose_pas;Env.add_unary_inf"ext_eqres_dec"ext_eqres_decompose;Env.add_unary_inf"ext_eqfact_dec"ext_eqfact_decompose;);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(Env.add_unary_inf"trigger_pred_var active"trigger_insantiation;Env.add_unary_inf"trigger_pred_var passive"instantiate_with_triggers;);if(List.existsCCFun.id[Env.flex_getk_fluidsup;Env.flex_getk_dupsup;Env.flex_getk_lambdasup!=-1;Env.flex_getk_max_infs=-1])then(ifEnv.flex_getk_switch_stream_extractionthenEnv.add_generate"stream_queue_extraction"extract_from_stream_queue_fix_stmelseEnv.add_generate"stream_queue_extraction"extract_from_stream_queue;))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;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_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_ord_in_normal_form=reffalselet_fluidsup_penalty=ref0let_fluidsup=reftruelet_dupsup=reftruelet_trigger_bool_inst=ref(-1)let_recognize_injectivity=reffalselet_sup_with_pure_vars=reftruelet_restrict_fluidsup=reffalselet_lambdasup=ref(-1)let_max_infs=ref(-1)letmax_lits_ext_dec=ref0let_ext_dec_lits=ref`OnlyMaxlet_unif_alg=ref`NewJPFulllet_unif_level=ref`Fulllet_ground_subs_check=ref0let_sup_t_f=reftruelet_solid_subsumption=reffalselet_skip_multiplier=ref35.0let_imit_first=reffalselet_max_depth=ref3let_max_rigid_imitations=ref3let_max_app_projections=ref1let_max_elims=ref1let_max_identifications=ref1let_pattern_decider=reftruelet_fixpoint_decider=reffalselet_solid_decider=reffalselet_solidification_limit=ref5let_max_unifs_solid_ff=ref20let_use_weight_for_solid_subsumption=reffalseletkey=Flex_state.create_key()letunif_params_to_def()=_max_depth:=2;_max_app_projections:=1;_max_rigid_imitations:=1;_max_identifications:=1;_max_elims:=1;_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_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_true_false!_sup_t_f;E.flex_addk_sup_at_var_headed!_sup_at_var_headed;E.flex_addk_fluidsup!_fluidsup;E.flex_addk_dupsup!_dupsup;E.flex_addk_lambdasup!_lambdasup;E.flex_addk_sup_w_pure_vars!_sup_with_pure_vars;E.flex_addk_restrict_fluidsup!_restrict_fluidsup;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_max_lits_ext_dec!max_lits_ext_dec;E.flex_addk_use_simultaneous_sup!_use_simultaneous_sup;E.flex_addk_fluidsup_penalty!_fluidsup_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_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;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["--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-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";"--ord-in-normal-form",Arg.Bool(funv->_ord_in_normal_form:=v)," compare intermediate terms in calculus rules in beta-normal-eta-long form";"--ext-decompose",Arg.Set_intmax_lits_ext_dec," Sets the maximal number of literals clause can have for ExtDec inference.";"--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.";"--fluidsup-penalty",Arg.Int(funp->_fluidsup_penalty:=p)," penalty for FluidSup inferences";"--fluidsup",Arg.Bool(funb->_fluidsup:=b)," enable/disable FluidSup inferences (only effective when complete higher-order unification is enabled)";"--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";"--sup-with-pure-vars",Arg.Bool(funv->_sup_with_pure_vars:=v)," enable/disable superposition to and from pure variable equations";"--restrict-fluidsup",Arg.Bool(funv->_restrict_fluidsup:=v)," enable/disable restriction of fluidSup to up to two literal or inital clauses";"--sup-with-true-false",Arg.Bool(funv->(_sup_t_f:=v))," enable/disable superposition, eq-res and eq-fact with true/false";"--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";"--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"];Params.add_to_mode"ho-complete-basic"(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;_ord_in_normal_form:=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;_demod_in_var_args:=false;_complete_ho_unification:=true;_unif_alg:=`NewJPPragmatic;_ord_in_normal_form:=true;_sup_at_var_headed:=true;_lambdasup:=-1;_dupsup:=false;_max_infs:=5;_max_depth:=3;_max_app_projections:=0;_max_identifications:=1;_max_elims:=1;_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;_ord_in_normal_form:=true;_sup_at_var_headed:=true;_lambdasup:=-1;_dupsup:=false;_max_infs:=10;_max_depth:=6;_max_app_projections:=1;_max_identifications:=1;_max_elims:=1;_fluidsup:=false;);Params.add_to_mode"fo-complete-basic"(fun()->_use_simultaneous_sup:=false;)