123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342(************************************************************************)(* * The Rocq Prover / The Rocq Development Team *)(* v * Copyright INRIA, CNRS and contributors *)(* <O___,, * (see version control and CREDITS file for authors & dates) *)(* \VV/ **************************************************************)(* // * This file is distributed under the terms of the *)(* * GNU Lesser General Public License Version 2.1 *)(* * (see LICENSE file for the text of the license) *)(************************************************************************)openLtac_pluginopenCErrorsopenUtilopenTermopenConstropenContextopenProof_searchopenContext.Named.DeclarationmoduleSearch=structopenPptypeposition=intlistletmsg_with_position(p:position)s=matchpwith|[]->()|_::_->letpp=Proof_search.ppsinletrecpp_rec=function|[]->mt()|[i]->inti|i::l->pp_recl++str"."++intiinFeedback.msg_debug(h(pp_recp)++pp)letpuship=matchpwith[]->[]|_::_->i::pletdepth_first?(debug=false)s=letrecexploreps=let()=msg_with_positionpsinifProof_search.successsthenselseexplore_many1p(Proof_search.branchings)andexplore_manyip=function|[]->raiseNot_found|[s]->explore(puship)s|s::l->tryexplore(puship)swithNot_found->explore_many(succi)plinletpos=ifdebugthen[1]else[]inexplorepossendletforcecountlazc=incrcount;Lazy.forcelazcletstep_count=ref0letnode_count=ref0letli_False=lazy(destInd(UnivGen.constr_of_monomorphic_global(Global.env())@@Rocqlib.lib_ref"core.False.type"))letli_and=lazy(destInd(UnivGen.constr_of_monomorphic_global(Global.env())@@Rocqlib.lib_ref"core.and.type"))letli_or=lazy(destInd(UnivGen.constr_of_monomorphic_global(Global.env())@@Rocqlib.lib_ref"core.or.type"))letgen_constantn=lazy(UnivGen.constr_of_monomorphic_global(Global.env())(Rocqlib.lib_refn))letl_xI=gen_constant"num.pos.xI"letl_xO=gen_constant"num.pos.xO"letl_xH=gen_constant"num.pos.xH"letl_empty=gen_constant"plugins.rtauto.empty"letl_push=gen_constant"plugins.rtauto.push"letl_Reflect=gen_constant"plugins.rtauto.Reflect"letl_Atom=gen_constant"plugins.rtauto.Atom"letl_Arrow=gen_constant"plugins.rtauto.Arrow"letl_Bot=gen_constant"plugins.rtauto.Bot"letl_Conjunct=gen_constant"plugins.rtauto.Conjunct"letl_Disjunct=gen_constant"plugins.rtauto.Disjunct"letl_Ax=gen_constant"plugins.rtauto.Ax"letl_I_Arrow=gen_constant"plugins.rtauto.I_Arrow"letl_E_Arrow=gen_constant"plugins.rtauto.E_Arrow"letl_D_Arrow=gen_constant"plugins.rtauto.D_Arrow"letl_E_False=gen_constant"plugins.rtauto.E_False"letl_I_And=gen_constant"plugins.rtauto.I_And"letl_E_And=gen_constant"plugins.rtauto.E_And"letl_D_And=gen_constant"plugins.rtauto.D_And"letl_I_Or_l=gen_constant"plugins.rtauto.I_Or_l"letl_I_Or_r=gen_constant"plugins.rtauto.I_Or_r"letl_E_Or=gen_constant"plugins.rtauto.E_Or"letl_D_Or=gen_constant"plugins.rtauto.D_Or"letspecial_whdenvsigmac=Reductionops.clos_whd_flagsRedFlags.allenvsigmacletspecial_nfenvsigmac=Reductionops.clos_norm_flagsRedFlags.betaiotazetaenvsigmactypeatom_env={mutablenext:int;mutableenv:(constr*int)list}letmake_atomatom_envterm=letterm=EConstr.Unsafe.to_constrtermintrylet(_,i)=List.find(fun(t,_)->Constr.equaltermt)atom_env.envinAtomiwithNot_found->leti=atom_env.nextinatom_env.env<-(term,i)::atom_env.env;atom_env.next<-i+1;Atomiletrecmake_formenvsigmaatom_envterm=letopenEConstrinletopenVarsinletnormalize=special_nfenvsigmainletcciterm=special_whdenvsigmaterminmatchEConstr.kindsigmaccitermwithProd(_,a,b)->ifnoccurnsigma1b&&Retyping.get_sort_family_ofenvsigmaa==InPropthenletfa=make_formenvsigmaatom_envainletfb=make_formenvsigmaatom_envbinArrow(fa,fb)elsemake_atomatom_env(normalizeterm)|Cast(a,_,_)->make_formenvsigmaatom_enva|Ind(ind,_)->ifEnviron.QInd.equalenvind(fst(Lazy.forceli_False))thenBotelsemake_atomatom_env(normalizeterm)|App(hd,argv)whenInt.equal(Array.lengthargv)2->begintryletind,_=destIndsigmahdinifEnviron.QInd.equalenvind(fst(Lazy.forceli_and))thenletfa=make_formenvsigmaatom_envargv.(0)inletfb=make_formenvsigmaatom_envargv.(1)inConjunct(fa,fb)elseifEnviron.QInd.equalenvind(fst(Lazy.forceli_or))thenletfa=make_formenvsigmaatom_envargv.(0)inletfb=make_formenvsigmaatom_envargv.(1)inDisjunct(fa,fb)elsemake_atomatom_env(normalizeterm)withDestKO->make_atomatom_env(normalizeterm)end|_->make_atomatom_env(normalizeterm)letrecmake_hypsenvsigmaatom_envlenv=function[]->[]|LocalDef(_,body,typ)::rest->make_hypsenvsigmaatom_env(typ::body::lenv)rest|LocalAssum(id,typ)::rest->lethrec=make_hypsenvsigmaatom_env(typ::lenv)restinifList.exists(func->Termops.local_occur_varsigmaid.binder_namec)lenv||(Retyping.get_sort_family_ofenvsigmatyp!=InProp)thenhrecelse(id,make_formenvsigmaatom_envtyp)::hrecletrecbuild_posn=ifn<=1thenforcenode_countl_xHelseifInt.equal(nland1)0thenmkApp(forcenode_countl_xO,[|build_pos(nasr1)|])elsemkApp(forcenode_countl_xI,[|build_pos(nasr1)|])letrecbuild_form=functionAtomn->mkApp(forcenode_countl_Atom,[|build_posn|])|Arrow(f1,f2)->mkApp(forcenode_countl_Arrow,[|build_formf1;build_formf2|])|Bot->forcenode_countl_Bot|Conjunct(f1,f2)->mkApp(forcenode_countl_Conjunct,[|build_formf1;build_formf2|])|Disjunct(f1,f2)->mkApp(forcenode_countl_Disjunct,[|build_formf1;build_formf2|])letrecdecalk=function[]->k|(start,delta)::rest->ifk>startthenk-deltaelsedecalkrestletadd_popsizedpops=matchpopswith[]->[size+d,d]|(_,sum)::_->(size+sum,sum+d)::popsletrecbuild_proofpopssize=functionAxi->mkApp(forcestep_countl_Ax,[|build_pos(decalipops)|])|I_Arrowp->mkApp(forcestep_countl_I_Arrow,[|build_proofpops(size+1)p|])|E_Arrow(i,j,p)->mkApp(forcestep_countl_E_Arrow,[|build_pos(decalipops);build_pos(decaljpops);build_proofpops(size+1)p|])|D_Arrow(i,p1,p2)->mkApp(forcestep_countl_D_Arrow,[|build_pos(decalipops);build_proofpops(size+2)p1;build_proofpops(size+1)p2|])|E_Falsei->mkApp(forcestep_countl_E_False,[|build_pos(decalipops)|])|I_And(p1,p2)->mkApp(forcestep_countl_I_And,[|build_proofpopssizep1;build_proofpopssizep2|])|E_And(i,p)->mkApp(forcestep_countl_E_And,[|build_pos(decalipops);build_proofpops(size+2)p|])|D_And(i,p)->mkApp(forcestep_countl_D_And,[|build_pos(decalipops);build_proofpops(size+1)p|])|I_Or_l(p)->mkApp(forcestep_countl_I_Or_l,[|build_proofpopssizep|])|I_Or_r(p)->mkApp(forcestep_countl_I_Or_r,[|build_proofpopssizep|])|E_Or(i,p1,p2)->mkApp(forcestep_countl_E_Or,[|build_pos(decalipops);build_proofpops(size+1)p1;build_proofpops(size+1)p2|])|D_Or(i,p)->mkApp(forcestep_countl_D_Or,[|build_pos(decalipops);build_proofpops(size+2)p|])|Pop(d,p)->build_proof(add_popsizedpops)sizepletbuild_envgamma=List.fold_right(fun(p,_)e->mkApp(forcenode_countl_push,[|mkProp;p;e|]))gamma.env(mkApp(forcenode_countl_empty,[|mkProp|]))let{Goptions.get=verbose}=Goptions.declare_bool_option_and_ref~key:["Rtauto";"Verbose"]~value:false()let{Goptions.get=check}=Goptions.declare_bool_option_and_ref~key:["Rtauto";"Check"]~value:false()openPpletrtauto_tac=Proofview.Goal.enterbeginfungl->lethyps=Proofview.Goal.hypsglinletconcl=Proofview.Goal.conclglinletenv=Proofview.Goal.envglinletsigma=Proofview.Goal.sigmaglinRocqlib.check_required_library["Stdlib";"rtauto";"Rtauto"];letgamma={next=1;env=[]}inlet()=ifRetyping.get_sort_family_ofenvsigmaconcl!=InPropthenuser_err(Pp.str"Goal should be in Prop.")inletglf=make_formenvsigmagammaconclinlethyps=make_hypsenvsigmagamma[concl]hypsinletformula=List.fold_left(fungl(_,f)->Arrow(f,gl))glfhypsinletdebug=matchTacinterp.get_debug()with|Tactic_debug.DebugOn0->true|_->falseinletsearch_funs=Search.depth_first~debugsinlet()=beginreset_info();ifverbose()thenFeedback.msg_info(str"Starting proof-search ...");endinletsearch_start_time=System.get_time()inletprf=tryproject(search_fun(init_state[]formula))withNot_found->user_err(Pp.str"rtauto couldn't find a proof.")inletsearch_end_time=System.get_time()inlet()=ifverbose()thenbeginFeedback.msg_info(str"Proof tree found in "++System.fmt_time_differencesearch_start_timesearch_end_time);pp_info();Feedback.msg_info(str"Building proof term ... ")endinletbuild_start_time=System.get_time()inlet()=step_count:=0;node_count:=0inletmain=mkApp(forcenode_countl_Reflect,[|build_envgamma;build_formformula;build_proof[]0prf|])inletterm=applistcmain(List.rev_map(fun(id,_)->mkVarid.binder_name)hyps)inletbuild_end_time=System.get_time()inlet()=ifverbose()thenbeginFeedback.msg_info(str"Proof term built in "++System.fmt_time_differencebuild_start_timebuild_end_time++fnl()++str"Proof size : "++int!step_count++str" steps"++fnl()++str"Proof term size : "++int(!step_count+!node_count)++str" nodes (constants)"++fnl()++str"Giving proof term to Rocq ... ")endinlettac_start_time=System.get_time()inletterm=EConstr.of_constrterminletresult=ifcheck()thenTactics.exact_checktermelseTactics.exact_no_checkterminlettac_end_time=System.get_time()inlet()=ifcheck()thenFeedback.msg_info(str"Proof term type-checking is on");ifverbose()thenFeedback.msg_info(str"Internal tactic executed in "++System.fmt_time_differencetac_start_timetac_end_time)inresultend