123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446(******************************************************************************)(* *)(* The Alt-Ergo theorem prover *)(* Copyright (C) 2006-2013 *)(* *)(* Sylvain Conchon *)(* Evelyne Contejean *)(* *)(* Francois Bobot *)(* Mohamed Iguernelala *)(* Stephane Lescuyer *)(* Alain Mebsout *)(* *)(* CNRS - INRIA - Universite Paris Sud *)(* *)(* This file is distributed under the terms of the Apache Software *)(* License version 2.0 *)(* *)(* ------------------------------------------------------------------------ *)(* *)(* Alt-Ergo: The SMT Solver For Software Verification *)(* Copyright (C) 2013-2018 --- OCamlPro SAS *)(* *)(* This file is distributed under the terms of the Apache Software *)(* License version 2.0 *)(* *)(******************************************************************************)openOptionsopenFormatmoduleSy=SymbolsmoduleE=ExprmoduleA=XliteralmoduleL=ListmoduleX=Shostak.CombinemoduleEx=ExplanationmoduleLR=Uf.LX(* map get |-> { set } des associations (get,set) deja splites *)moduleTmap=structincludeE.Mapletupdatetamp=tryaddt(E.Set.adda(findtmp))mpwithNot_found->addt(E.Set.singletona)mpletsplitedtamp=tryE.Set.mema(findtmp)withNot_found->falseendmoduleLRset=LR.SetmoduleConseq=Set.Make(structtypet=E.t*Ex.tletcompare(lt1,_)(lt2,_)=E.comparelt1lt2end)(* map k |-> {sem Atom} d'egalites/disegalites sur des atomes semantiques*)moduleLRmap=structincludeLR.Mapletfindkmp=tryfindkmpwithNot_found->Conseq.emptyletaddkvexmp=addk(Conseq.add(v,ex)(findkmp))mpendtypegtype={g:Expr.t;gt:Expr.t;gi:Expr.t;gty:Ty.t}moduleG:Set.Swithtypeelt=gtype=Set.Make(structtypet=gtypeletcomparet1t2=E.comparet1.gt2.gend)(* ensemble de termes "set" avec leurs arguments et leurs types *)typestype={s:E.t;st:E.t;si:E.t;sv:E.t;sty:Ty.t}moduleS:Set.Swithtypeelt=stype=Set.Make(structtypet=stypeletcomparet1t2=E.comparet1.st2.send)(* map t |-> {set(t,-,-)} qui associe a chaque tableau l'ensemble
de ses affectations *)moduleTBS=structincludeMap.Make(E)letfindkmp=tryfindkmpwithNot_found->S.empty(* add reutilise find ci-dessus *)letaddkvmp=addk(S.addv(findkmp))mpendtypet={gets:G.t;(* l'ensemble des "get" croises*)tbset:S.tTBS.t;(* map t |-> set(t,-,-) *)split:LRset.t;(* l'ensemble des case-split possibles *)conseq:Conseq.tLRmap.t;(* consequences des splits *)seen:E.Set.tTmap.t;(* combinaisons (get,set) deja splitees *)new_terms:E.Set.t;size_splits:Numbers.Q.t;}letempty_={gets=G.empty;tbset=TBS.empty;split=LRset.empty;conseq=LRmap.empty;seen=Tmap.empty;new_terms=E.Set.empty;size_splits=Numbers.Q.one;}(*BISECT-IGNORE-BEGIN*)moduleDebug=structletassumefmtla=ifdebug_arrays()&&la!=[]thenbeginfprintffmt"[Arrays.Rel] We assume@.";L.iter(fun(a,_,_,_)->fprintffmt" > %a@."LR.print(LR.makea))la;end(* unused --
let print_gets fmt = G.iter (fun t -> fprintf fmt "%a@." E.print t.g)
let print_sets fmt = S.iter (fun t -> fprintf fmt "%a@." E.print t.s)
let print_splits fmt =
LRset.iter (fun a -> fprintf fmt "%a@." LR.print a)
let print_tbs fmt =
TBS.iter (fun k v -> fprintf fmt "%a --> %a@." E.print k print_sets v)
let env fmt env =
if debug_arrays () then begin
fprintf fmt "-- gets ----------------------------------------@.";
print_gets fmt env.gets;
fprintf fmt "-- tabs of sets --------------------------------@.";
print_tbs fmt env.tbset;
fprintf fmt "-- splits --------------------------------------@.";
print_splits fmt env.split;
fprintf fmt "------------------------------------------------@."
end
*)letnew_equalitiesfmtst=ifdebug_arrays()thenbeginfprintffmt"[Arrays] %d implied equalities@."(Conseq.cardinalst);Conseq.iter(fun(a,ex)->fprintffmt" %a : %a@."E.printaEx.printex)stendletcase_splita=ifdebug_arrays()thenfprintffmt"[Arrays.case-split] %a@."LR.printaletcase_split_none()=ifdebug_arrays()thenfprintffmt"[Arrays.case-split] Nothing@."end(*BISECT-IGNORE-END*)(* met a jour gets et tbset en utilisant l'ensemble des termes donne*)letrecupdate_gets_setsacct=let{E.f;xs;ty;_}=matchE.term_viewtwith|E.Not_a_term_->assertfalse|E.Termtt->ttinletgets,tbset=List.fold_leftupdate_gets_setsaccxsinmatchSy.is_getf,Sy.is_setf,xswith|true,false,[a;i]->G.add{g=t;gt=a;gi=i;gty=ty}gets,tbset|false,true,[a;i;v]->gets,TBS.adda{s=t;st=a;si=i;sv=v;sty=ty}tbset|false,false,_->(gets,tbset)|_->assertfalse(* met a jour les composantes gets et tbset de env avec les termes
contenus dans les atomes de la *)letnew_termsenvla=letfctaccr=List.fold_left(funaccx->matchX.term_extractxwith|Somet,_->update_gets_setsacct|None,_->acc)acc(X.leavesr)inletgets,tbset=L.fold_left(funacc(a,_,_,_)->matchawith|A.Eq(r1,r2)->fct(fctaccr1)r2|A.Builtin(_,_,l)|A.Distinct(_,l)->L.fold_leftfctaccl|A.Pred(r1,_)->fctaccr1)(env.gets,env.tbset)lain{envwithgets=gets;tbset=tbset}(* mise a jour de env avec les instances
1) p => p_ded
2) n => n_ded *)letupdate_envare_eqare_distdepenvaccgisipp_dednn_ded=matchare_eqgisi,are_distgisiwith|Some(idep,_),None->letconseq=LRmap.addnn_deddepenv.conseqin{envwithconseq=conseq},Conseq.add(p_ded,Ex.uniondepidep)acc|None,Some(idep,_)->letconseq=LRmap.addpp_deddepenv.conseqin{envwithconseq=conseq},Conseq.add(n_ded,Ex.uniondepidep)acc|None,None->letsp=LRset.addpenv.splitinletconseq=LRmap.addpp_deddepenv.conseqinletconseq=LRmap.addnn_deddepconseqin{envwithsplit=sp;conseq=conseq},acc|Some_,Some_->assertfalse(*----------------------------------------------------------------------
get(set(-,-,-),-) modulo egalite
---------------------------------------------------------------------*)letget_of_setare_eqare_distgtype(env,acc)class_of=let{g=get;gt=gtab;gi=gi;gty=gty}=gtypeinL.fold_left(fun(env,acc)set->ifTmap.splitedgetsetenv.seenthen(env,acc)elseletenv={envwithseen=Tmap.updategetsetenv.seen}inlet{E.f;xs;_}=matchE.term_viewsetwith|E.Not_a_term_->assertfalse|E.Termtt->ttinmatchSy.is_setf,xswith|true,[stab;si;sv]->letxi,_=X.makegiinletxj,_=X.makesiinletget_stab=E.mk_term(Sy.OpSy.Get)[stab;gi]gtyinletp=LR.mk_eqxixjinletp_ded=E.mk_eq~iff:falsegetsvinletn=LR.mk_distinctfalse[xi;xj]inletn_ded=E.mk_eq~iff:falsegetget_stabinletdep=matchare_eqgtabsetwithSome(dep,_)->dep|None->assertfalseinletenv={envwithnew_terms=E.Set.addget_stabenv.new_terms}inupdate_envare_eqare_distdepenvaccgisipp_dednn_ded|_->(env,acc))(env,acc)(class_ofgtab)(*----------------------------------------------------------------------
set(-,-,-) modulo egalite
---------------------------------------------------------------------*)letget_from_set_are_eq_are_diststype(env,acc)class_of=letsets=L.fold_left(funacct->S.unionacc(TBS.findtenv.tbset))(S.singletonstype)(class_ofstype.st)inS.fold(fun{s=set;si=si;sv=sv;_}(env,acc)->letty_si=E.type_infosvinletget=E.mk_term(Sy.OpSy.Get)[set;si]ty_siinifTmap.splitedgetsetenv.seenthen(env,acc)elseletenv={envwithseen=Tmap.updategetsetenv.seen;new_terms=E.Set.addgetenv.new_terms}inletp_ded=E.mk_eq~iff:falsegetsvinenv,Conseq.add(p_ded,Ex.empty)acc)sets(env,acc)(*----------------------------------------------------------------------
get(t,-) and set(t,-,-) modulo egalite
---------------------------------------------------------------------*)letget_and_setare_eqare_distgtype(env,acc)class_of=let{g=get;gt=gtab;gi=gi;gty=gty}=gtypeinletsuff_sets=L.fold_left(funacct->S.unionacc(TBS.findtenv.tbset))S.empty(class_ofgtab)inS.fold(fun{s=set;st=stab;si=si;sv=sv;_}(env,acc)->ifTmap.splitedgetsetenv.seenthen(env,acc)elsebeginletenv={envwithseen=Tmap.updategetsetenv.seen}inletxi,_=X.makegiinletxj,_=X.makesiinletget_stab=E.mk_term(Sy.OpSy.Get)[stab;gi]gtyinletgt_of_st=E.mk_term(Sy.OpSy.Get)[set;gi]gtyinletp=LR.mk_eqxixjinletp_ded=E.mk_eq~iff:falsegt_of_stsvinletn=LR.mk_distinctfalse[xi;xj]inletn_ded=E.mk_eq~iff:falsegt_of_stget_stabinletdep=matchare_eqgtabstabwithSome(dep,_)->dep|None->assertfalseinletenv={envwithnew_terms=E.Set.addget_stab(E.Set.addgt_of_stenv.new_terms)}inupdate_envare_eqare_distdepenvaccgisipp_dednn_dedend)suff_sets(env,acc)(* Generer de nouvelles instantiations de lemmes *)letnew_splitsare_eqare_distenvaccclass_of=letaccu=G.fold(fungt_infoaccu->letaccu=get_of_setare_eqare_distgt_infoaccuclass_ofinget_and_setare_eqare_distgt_infoaccuclass_of)env.gets(env,acc)inTBS.fold(fun_tbsaccu->S.fold(funstypeaccu->get_from_setare_eqare_diststypeaccuclass_of)tbsaccu)env.tbsetaccu(* nouvelles disegalites par instantiation du premier
axiome d'exentionnalite *)letextensionalityaccula_class_of=List.fold_left(fun((env,acc)asaccu)(a,_,dep,_)->matchawith|A.Distinct(false,[r;s])->beginmatchX.type_infor,X.term_extractr,X.term_extractswith|Ty.Tfarray(ty_k,ty_v),(Somet1,_),(Somet2,_)->leti=E.fresh_namety_kinletg1=E.mk_term(Sy.OpSy.Get)[t1;i]ty_vinletg2=E.mk_term(Sy.OpSy.Get)[t2;i]ty_vinletd=E.mk_distinct~iff:false[g1;g2]inletacc=Conseq.add(d,dep)accinletenv={envwithnew_terms=E.Set.addg2(E.Set.addg1env.new_terms)}inenv,acc|_->accuend|_->accu)acculaletimplied_consequencesenveqsla=letspl,eqs=L.fold_left(fun(spl,eqs)(a,_,dep,_)->leta=LR.makeainletspl=LRset.remove(LR.nega)(LRset.removeaspl)inleteqs=Conseq.fold(fun(fact,ex)acc->Conseq.add(fact,Ex.unionexdep)acc)(LRmap.findaenv.conseq)eqsinspl,eqs)(env.split,eqs)lain{envwithsplit=spl},eqs(* deduction de nouvelles dis/egalites *)letnew_equalitiesenveqslaclass_of=letla=L.filter(fun(a,_,_,_)->matchawithA.Builtin_->false|_->true)lainletenv,eqs=extensionality(env,eqs)laclass_ofinimplied_consequencesenveqsla(* choisir une egalite sur laquelle on fait un case-split *)lettwo=Numbers.Q.from_int2letcase_splitenv_~for_model:_=(*if Numbers.Q.compare
(Numbers.Q.mult two env.size_splits) (max_split ()) <= 0 ||
Numbers.Q.sign (max_split ()) < 0 then*)tryleta=LR.neg(LRset.chooseenv.split)inDebug.case_splita;[LR.viewa,true,Th_util.CS(Th_util.Th_arrays,two)]withNot_found->Debug.case_split_none();[]letcount_splitsenvla=letnb=List.fold_left(funnb(_,_,_,i)->matchiwith|Th_util.CS(Th_util.Th_arrays,n)->Numbers.Q.multnbn|_->nb)env.size_splitslain{envwithsize_splits=nb}letassumeenvufla=letare_eq=Uf.are_equaluf~added_terms:trueinletare_neq=Uf.are_distinctufinletclass_of=Uf.class_ofufinletenv=count_splitsenvlain(* instantiation des axiomes des tableaux *)Debug.assumefmtla;letenv=new_termsenvlainletenv,atoms=new_splitsare_eqare_neqenvConseq.emptyclass_ofinletenv,atoms=new_equalitiesenvatomslaclass_ofin(*Debug.env fmt env;*)Debug.new_equalitiesfmtatoms;letl=Conseq.fold(fun(a,ex)l->((Sig_rel.LTerma,ex,Th_util.Other)::l))atoms[]inenv,{Sig_rel.assume=l;remove=[]}letassumeenvufla=ifOptions.timers()thentryTimers.exec_timer_startTimers.M_ArraysTimers.F_assume;letres=assumeenvuflainTimers.exec_timer_pauseTimers.M_ArraysTimers.F_assume;reswithe->Timers.exec_timer_pauseTimers.M_ArraysTimers.F_assume;raiseeelseassumeenvuflaletquery___=Noneletaddenv___=envletprint_model___=()letnew_termsenv=env.new_termsletinstantiate~do_syntactic_matching:__env__=env,[]letassume_th_elttth_elt_=matchth_elt.Expr.extendswith|Util.Arrays->failwith"This Theory does not support theories extension"|_->t