123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183(******************************************************************************)(* *)(* Alt-Ergo: The SMT Solver For Software Verification *)(* Copyright (C) 2013-2018 --- OCamlPro SAS *)(* *)(* This file is distributed under the terms of the license indicated *)(* in the file 'License.OCamlPro'. If 'License.OCamlPro' is not *)(* present, please contact us to clarify licensing. *)(* *)(******************************************************************************)moduleMake(Th:Theory.S)=structopenOptionsopenFormatmoduleE=ExprmoduleME=E.MapmoduleSE=E.SetmoduleEx=ExplanationmoduleAtom=Satml_types.AtommoduleMA=Atom.MapmoduleSAT=Satml.Make(Th)modulePF=Satml_types.Proxy_formulatypet={sat:SAT.t;assumed:SE.t;proxies:Atom.atomME.t;inv_proxies:E.tMA.t;hcons_env:Atom.hcons_env;decisions:(int*E.t)list;pending:(E.gformula*Ex.t)listlist;}exceptionBottomofExplanation.t*E.Set.tlist*tletempty()={sat=SAT.empty();assumed=SE.empty;proxies=ME.empty;inv_proxies=MA.empty;hcons_env=Atom.empty_hcons_env();decisions=[];pending=[]}letformula_of_atomenva=tryletp=MA.findaenv.inv_proxiesinpwithNot_found->assertfalseletis_trueenvf=matchPF.get_proxy_offenv.proxieswith|Somep->assert(not(Atom.is_truep)||(Atom.levelp)>=0);if(Atom.is_truep)thenletl_ex=letr=Atom.Set.fold(funaacc->SE.add(formula_of_atomenva)acc)(SAT.reason_of_deductionp)SE.emptyinlazy(Ex.make_depsr)inSome(l_ex,Atom.levelp)elseNone|None->assertfalseletforget_decisionenvflvl=letl_ok,_=List.partition(fun(dlvl,_)->dlvl<lvl)env.decisionsinletenv={envwithdecisions=l_ok}inleta=matchPF.get_proxy_offenv.proxieswith|Somep->p|None->(* TODO *)matchPF.get_proxy_of(E.negf)env.proxieswith|Somep->p|None->assertfalseinifAtom.reasona==None&&Atom.levela>0then(* right level of f in SAT because of other decisions that may be
propagated*)SAT.cancel_untilenv.sat((Atom.levela)-1);envletreset_decisionsenv=SAT.cancel_untilenv.sat0;{envwithdecisions=[]}letget_decisionsenv=env.decisionsletdecide_auxenv(dlvl,f)=beginmatchis_trueenvf,is_trueenv(E.negf)with|None,None->beginmatchPF.get_proxy_offenv.proxieswith|Somep->SAT.decideenv.satp|None->assertfalseend|Some_,Some_->assertfalse|Some_,None->ifverbose()&&debug_sat()thenfprintffmt"!!! [dlvl=%d] %a becomes true before deciding@."dlvlE.printf;|None,Some(ex,_)->ifverbose()&&debug_sat()thenfprintffmt"!!! [dlvl=%d] %a becomes false before deciding@."dlvlE.printf;(* Satml_types.Atom.pr_atom (fst f); *)letex=Ex.union(Ex.singleton(Ex.Bjf))(Lazy.forceex)inraise(Bottom(ex,[],env))(*SAT.print_env ();*)endletassumedelayenvl=letenv={envwithpending=l::env.pending}inifdelaythenenvelseletll=List.revenv.pendinginletenv={envwithpending=[]}inletenv,pfl,cnf,new_vars=List.fold_left(funaccl->List.fold_left(fun((env,pfl,cnf,vars)asacc)({E.ff=f;_},ex)->ifSE.memfenv.assumedthenaccelseifEx.has_no_bjexthenbeginletpf,(added_proxy,inv_proxies,new_vars,cnf)=PF.mk_cnfenv.hcons_envf(env.proxies,env.inv_proxies,vars,cnf)in{envwithassumed=SE.addfenv.assumed;proxies=added_proxy;inv_proxies},[pf]::pfl,cnf,new_varsendelseacc)accl)(env,[],[],[])llinifpfl!=[]thenenvelselet()=trylet_=SAT.new_varsenv.sat~nbv:(Atom.nb_made_varsenv.hcons_env)new_vars[][]inSAT.assume_simpleenv.satcnf;SAT.assume_simpleenv.satpfl;List.iter(decide_auxenv)(List.revenv.decisions);with|Satml.Sat->assertfalse(* Uncomment if Sat.solve is called *)(* SAT.cancel_until env.sat 0;
* env *)|Satml.Unsat_->assert(Options.tableaux_cdcl()&&SAT.decision_levelenv.sat=0);raise(Bottom(Ex.empty,[],env))|Satml.Last_UIP_reasonr->letr=Atom.Set.fold(funaacc->SE.add(formula_of_atomenva)acc)rSE.emptyinraise(Bottom(Ex.make_depsr,[],env))inenvletdecideenvfdlvl=trydecide_auxenv(dlvl,f);assert(dlvl=List.lengthenv.decisions+1);{envwithdecisions=(dlvl,f)::env.decisions}with|Satml.Unsat_->assert(Options.tableaux_cdcl()&&SAT.decision_levelenv.sat=0);raise(Bottom(Ex.empty,[],env))|Satml.Last_UIP_reasonr->letr=Atom.Set.fold(funaacc->SE.add(formula_of_atomenva)acc)rSE.emptyinraise(Bottom(Ex.make_depsr,[],env))end