Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file Tseitin.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238(**************************************************************************)(* *)(* Alt-Ergo Zero *)(* *)(* Sylvain Conchon and_ Alain Mebsout *)(* Universite Paris-Sud 11 *)(* *)(* Copyright 2011. This file is distributed under the terms of the *)(* Apache Software License version 2.0 *)(* *)(**************************************************************************)moduletypeArg=Tseitin_intf.ArgmoduletypeS=Tseitin_intf.SmoduleMake(F:Tseitin_intf.Arg)=structtypecombinator=And|Or|Nottypeatom=F.ttypeid=int(* main formula type *)typet={id:id;view:view;}andview=|True|Litofatom|Combofcombinator*tlistlet[@inline]viewt=t.viewletrecppoutf=matchf.viewwith|True->Format.fprintfout"true"|Lita->F.ppouta|Comb(Not,[f])->Format.fprintfout"(@[<hv1>not %a@])"ppf|Comb(And,l)->Format.fprintfout"(@[<hv>and %a@])"(Util.pp_listpp)l|Comb(Or,l)->Format.fprintfout"(@[<hv>or %a@])"(Util.pp_listpp)l|_->assertfalseletmk_=letn=ref0infunview->incrn;{view;id=!n}let[@inline]makecombl=mk_(Comb(comb,l))let[@inline]atomp=mk_(Litp)lettrue_=mk_Trueletfalse_=mk_@@Comb(Not,[true_])letflattencombl=List.fold_left(funaccf->matchf.viewwith|Comb(c,l)whenc=comb->List.rev_appendlacc|_->f::acc)[]l(* unordered filter *)letrev_filterfl=letrecauxacc=function|[]->acc|a::tl->aux(iffathena::accelseacc)tlinaux[]llet[@inline]is_true=function{view=True;_}->true|_->falselet[@inline]is_false=function{view=Comb(Not,[{view=True;_}]);_}->true|_->falseletremove_truel=rev_filter(funx->not(is_truex))lletremove_falsel=rev_filter(funx->not(is_falsex))lletand_l=letl'=remove_true@@flattenAndlinifList.existsis_falsel'then(false_)else(matchl'with|[]->true_|[a]->a|_->makeAndl')letor_l=letl'=remove_false@@flattenOrlinifList.existsis_truel'then(true_)else(matchl'with|[]->false_|[a]->a|_->makeOrl')letrecnot_f=matchf.viewwith|Comb(Not,[g])->g|Comb(Not,_)->assertfalse|Lita->atom(F.nega)|Comb(And,l)->or_@@List.rev_mapnot_l|Comb(Or,l)->and_@@List.rev_mapnot_l|_->makeNot[f]letimplyf1f2=or_[not_f1;f2]letequivf1f2=and_[implyf1f2;implyf2f1]letxorf1f2=or_[and_[not_f1;f2];and_[f1;not_f2]]letimply_lab=or_(b::List.rev_mapnot_a)let[@inline]equalab=a.id=b.idlet[@inline]hasha=CCHash.inta.id(* table of formulas *)moduleTbl=CCHashtbl.Make(structtypenonrect=tletequal=equallethash=hashend)typecnf_res=|R_atomofatom|R_andofatomlist|R_orofatomlist|R_true|R_falsetypestate={fresh:unit->atom;tbl_and:cnf_resTbl.t;(* caching *)mutableacc_or:(atom*atomlist)list;mutableacc_and:(atom*atomlist)list;mutableproxies:atomlist;}(* build a clause by flattening (if sub-formulas have the
same combinator) and_ proxy-ing sub-formulas that have the
opposite operator. *)letcnf_under_and(st:state)(f:t):atomlistoption=letrecauxf:cnf_res=matchf.viewwith|Lita->R_atoma|True->R_true|Comb(Not,[{view=True;_}])->R_false|Comb(Not,[{view=Lita;_}])->R_atom(F.nega)|Comb((And|Or),_)->begintryTbl.findst.tbl_andfwithNot_found->letres=aux_noncachedfinTbl.addst.tbl_andfres;resend|_->Log.debugf1(funk->k"(@[cnf.bad-formula@ %a@])"ppf);assertfalseandaux_noncachedf:cnf_res=matchf.viewwith|Comb(And,l)->List.fold_left(funaccf->matchacc,auxfwith|R_false,_|_,R_false->R_false|R_andacc,R_true->R_andacc|R_andacc,R_atoma->R_and(a::acc)|R_andacc,R_andl->R_and(List.rev_appendlacc)|R_andacc,R_orl->letproxy=st.fresh()inst.acc_or<-(proxy,l)::st.acc_or;R_and(proxy::acc)|_->assertfalse)(R_and[])l|Comb(Or,l)->List.fold_left(funaccf->matchacc,auxfwith|R_true,_|_,R_true->R_true|R_oracc,R_false->R_oracc|R_oracc,R_atoma->R_or(a::acc)|R_oracc,R_orl->R_or(List.rev_appendlacc)|R_oracc,R_andl->letproxy=st.fresh()inst.acc_and<-(proxy,l)::st.acc_and;R_or(proxy::acc)|_->assertfalse)(R_or[])l|_->assertfalseinmatchauxfwith|R_atoma->Some[a]|R_orl->Somel|R_false->Some[](* empty clause *)|R_true->None(* trivial clause *)|_->assertfalseletcnf?simplify:_~fresh(f:t):atomlistlist=letst={fresh;tbl_and=Tbl.create16;acc_or=[];acc_and=[];proxies=[];}inletacc=matchf.viewwith|True->[]|Comb(Not,[{view=True;_}])->[[]]|Comb(And,l)->CCList.filter_map(cnf_under_andst)l|_->CCOpt.to_list@@cnf_under_andstfin(* encode clauses that make proxies in !acc_and equivalent to
their clause *)letacc=List.fold_left(funacc(p,l)->st.proxies<-p::st.proxies;letnp=F.negpin(* build clause [cl = l1 & l2 & ... & ln => p] where [l = [l1;l2;..]]
also add clauses [p => l1], [p => l2], etc. *)letcl,acc=List.fold_left(fun(cl,acc)a->(F.nega::cl),[np;a]::acc)([p],acc)lincl::acc)accst.acc_andin(* encore clauses that make proxies in !acc_or equivalent to
their clause *)letacc=List.fold_left(funacc(p,l)->st.proxies<-p::st.proxies;(* add clause [p => l1 | l2 | ... | ln], and_ add clauses
[l1 => p], [l2 => p], etc. *)letacc=List.fold_left(funacca->[p;F.nega]::acc)acclin(F.negp::l)::acc)accst.acc_orinaccend