123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193(*
MSAT is free software, using the Apache license, see file LICENSE
Copyright 2015 Guillaume Bury
*)moduletypeS=Backend_intf.SmoduletypeArg=sigtypehyptypelemmatypeassumptionvalprove_hyp:Format.formatter->string->hyp->unitvalprove_lemma:Format.formatter->string->lemma->unitvalprove_assumption:Format.formatter->string->assumption->unitendmoduleMake(S:Msat.S)(A:Argwithtypehyp:=S.clauseandtypelemma:=S.clauseandtypeassumption:=S.clause)=structmoduleAtom=S.AtommoduleClause=S.ClausemoduleM=Map.Make(S.Atom)moduleC_tbl=S.Clause.TblmoduleP=S.Proofletname=Clause.nameletclause_mapc=letrecauxaccai=ifi>=Array.lengthathenaccelsebeginletname=Format.sprintf"A%d"iinaux(M.adda.(i)nameacc)a(i+1)endinauxM.empty(Clause.atomsc)0letclause_itermformatfmtclause=letauxatom=Format.fprintffmtformat(M.findatomm)inArray.iteraux(Clause.atomsclause)letelim_duplicatefmtgoalhyp_=(** Printing info comment in coq *)Format.fprintffmt"(* Eliminating doublons. Goal : %s ; Hyp : %s *)@\n"(namegoal)(namehyp);(** Prove the goal: intro the atoms, then use them with the hyp *)letm=clause_mapgoalinFormat.fprintffmt"pose proof @[<hov>(fun %a=>@ %s%a) as %s@].@\n"(clause_iterm"%s@ ")goal(namehyp)(clause_iterm"@ %s")hyp(namegoal)letresolution_auxmah1h2fmt()=Format.fprintffmt"%s%a"(nameh1)(funfmt->Array.iter(funb->ifb==athenbeginFormat.fprintffmt"@ (fun p =>@ %s%a)"(nameh2)(funfmt->(Array.iter(func->ifAtom.equalc(Atom.nega)thenFormat.fprintffmt"@ (fun np => np p)"elseFormat.fprintffmt"@ %s"(M.findcm))))(Clause.atomsh2)endelseFormat.fprintffmt"@ %s"(M.findbm)))(Clause.atomsh1)letresolutionfmtgoalhyp1hyp2atom=leta=Atom.absatominleth1,h2=ifArray.exists(Atom.equala)(Clause.atomshyp1)thenhyp1,hyp2else(assert(Array.exists(Atom.equala)(Clause.atomshyp2));hyp2,hyp1)in(** Print some debug info *)Format.fprintffmt"(* Clausal resolution. Goal : %s ; Hyps : %s, %s *)@\n"(namegoal)(nameh1)(nameh2);(** Prove the goal: intro the axioms, then perform resolution *)ifArray.length(Clause.atomsgoal)=0then(letm=M.emptyinFormat.fprintffmt"exact @[<hov 1>(%a)@].@\n"(resolution_auxmah1h2)();false)else(letm=clause_mapgoalinFormat.fprintffmt"pose proof @[<hov>(fun %a=>@ %a)@ as %s.@]@\n"(clause_iterm"%s@ ")goal(resolution_auxmah1h2)()(namegoal);true)(* Count uses of hypotheses *)letincr_usehc=leti=tryC_tbl.findhcwithNot_found->0inC_tbl.addhc(i+1)letdecr_usehc=leti=C_tbl.findhc-1inassert(i>=0);let()=C_tbl.addhciini<=0letclearfmtc=Format.fprintffmt"clear %s."(namec)letrecclean_auxfmt=function|[]->()|[x]->Format.fprintffmt"%a@\n"clearx|x::((_::_)asr)->Format.fprintffmt"%a@ %a"clearxclean_auxrletcleanhfmtl=matchList.filter(decr_useh)lwith|[]->()|l'->Format.fprintffmt"(* Clearing unused clauses *)@\n%a"clean_auxl'letprove_nodetfmtnode=letclause=node.P.conclusioninmatchnode.P.stepwith|P.Hypothesis_->A.prove_hypfmt(nameclause)clause|P.Assumption->A.prove_assumptionfmt(nameclause)clause|P.Lemma_->A.prove_lemmafmt(nameclause)clause|P.Duplicate(p,l)->letc=P.conclusionpinlet()=elim_duplicatefmtclauseclincleantfmt[c]|P.Hyper_reshr->let(p1,p2,a)=P.res_of_hyper_reshrinletc1=P.conclusionp1inletc2=P.conclusionp2inifresolutionfmtclausec1c2athencleantfmt[c1;c2]letcount_usesp=leth=C_tbl.create128inletaux()node=List.iter(funp'->incr_usehP.(conclusionp'))(P.parentsnode.P.step)inlet()=P.foldaux()pinh(* Here the main idea is to always try and have exactly
one goal to prove, i.e False. So each *)letppfmtp=leth=count_usespinletaux()node=Format.fprintffmt"%a"(prove_nodeh)nodeinFormat.fprintffmt"(* Coq proof generated by mSAT*)@\n";P.foldaux()pendmoduleSimple(S:Msat.S)(A:Argwithtypehyp=S.formulalistandtypelemma:=S.lemmaandtypeassumption:=S.formula)=Make(S)(structmoduleP=S.Proof(* Some helpers *)letlit=S.Atom.formulaletget_assumptionc=matchS.Clause.atoms_lcwith|[x]->x|_->assertfalseletget_lemmac=matchP.expand(P.provec)with|{P.step=P.Lemmap;_}->p|_->assertfalseletprove_hypfmtnamec=A.prove_hypfmtname(List.maplit(S.Clause.atoms_lc))letprove_lemmafmtnamec=A.prove_lemmafmtname(get_lemmac)letprove_assumptionfmtnamec=A.prove_assumptionfmtname(lit(get_assumptionc))end)