123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355(******************************************************************************)(* *)(* 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 *)(* *)(******************************************************************************)openFormatopenOptionsmoduleZ=Numbers.ZmoduleQ=Numbers.QexceptionNot_a_numexceptionMaybe_zeromoduletypeS=sigincludeSig.Xvalmult:r->r->rendmoduletypeT=sigtypertypetvalcompare:t->t->intvalequal:t->t->boolvalhash:t->intvalcreate:(Q.t*r)list->Q.t->Ty.t->tvaladd:t->t->tvalsub:t->t->tvalmult:t->t->tvalmult_const:Q.t->t->tvaladd_const:Q.t->t->tvaldiv:t->t->t*boolvalmodulo:t->t->tvalis_const:t->Q.toptionvalis_empty:t->boolvalfind:r->t->Q.tvalchoose:t->Q.t*rvalsubst:r->t->t->tvalremove:r->t->tvalto_list:t->(Q.t*r)list*Q.tvalleaves:t->rlistvalprint:Format.formatter->t->unitvaltype_info:t->Ty.tvalis_monomial:t->(Q.t*r*Q.t)optionvalppmc_denominators:t->Q.tvalpgcd_numerators:t->Q.tvalnormal_form:t->t*Q.t*Q.tvalnormal_form_pos:t->t*Q.t*Q.tvalabstract_selectors:t->(r*r)list->t*(r*r)listvalseparate_constant:t->t*Numbers.Q.tendmoduletypeEXTENDED_Polynome=sigincludeTvalextract:r->toptionvalembed:t->rendmoduleMake(X:S)=structtyper=X.rmoduleM:Map.Swithtypekey=r=Map.Make(structtypet=r(*sorted in decreasing order to comply with AC(X) order requirements*)letcomparexy=X.str_cmpyxend)typet={m:Q.tM.t;c:Q.t;ty:Ty.t}letmap_to_listm=List.rev(M.fold(funxaaliens->(a,x)::aliens)m[])exceptionOutofintletcompare_mapsl1l2=tryList.iter2(fun(a,x)(b,y)->letc=X.str_cmpxyinifc<>0thenraise(Outc);letc=Q.compareabinifc<>0thenraise(Outc))l1l2;0with|Outc->c|Invalid_arguments->assert(String.compares"List.iter2"=0);List.lengthl1-List.lengthl2letcomparep1p2=letc=Ty.comparep1.typ2.tyinifc<>0thencelsematchM.is_emptyp1.m,M.is_emptyp2.mwith|true,false->-1|false,true->1|true,true->Q.comparep1.cp2.c|false,false->letc=compare_maps(map_to_listp1.m)(map_to_listp2.m)inifc=0thenQ.comparep1.cp2.celsecletequal{m=m1;c=c1;_}{m=m2;c=c2;_}=Q.equalc1c2&&M.equalQ.equalm1m2lethashp=leth=M.fold(funkvacc->23*acc+(X.hashk)*Q.hashv)p.m(19*Q.hashp.c+17*Ty.hashp.ty)inabsh(*BISECT-IGNORE-BEGIN*)moduleDebug=structletpprintfmtp=letzero=reftrueinM.iter(funxn->lets,n,op=ifQ.equalnQ.onethen(if!zerothen""else"+"),"",""elseifQ.equalnQ.m_onethen"-","",""elseifQ.signn>0then(if!zerothen""else"+"),Q.to_stringn,"*"else"-",Q.to_string(Q.minusn),"*"inzero:=false;fprintffmt"%s%s%s%a"snopX.printx)p.m;lets,n=ifQ.signp.c>0then(if!zerothen""else"+"),Q.to_stringp.celseifQ.signp.c<0then"-",Q.to_string(Q.minusp.c)else(if!zerothen"","0"else"","")infprintffmt"%s%s"snletprintfmtp=ifOptions.term_like_pp()thenpprintfmtpelsebeginM.iter(funtn->fprintffmt"%s*%a "(Q.to_stringn)X.printt)p.m;fprintffmt"%s"(Q.to_stringp.c);fprintffmt" [%a]"Ty.printp.tyendend(*BISECT-IGNORE-END*)letprint=Debug.printletis_constp=ifM.is_emptyp.mthenSomep.celseNoneletfindxm=tryM.findxmwithNot_found->Q.zeroletcreatelcty=letm=List.fold_left(funm(n,x)->letn'=Q.addn(findxm)inifQ.signn'=0thenM.removexmelseM.addxn'm)M.emptylin{m=m;c=c;ty=ty}letaddp1p2=Options.tool_req4"TR-Arith-Poly plus";letm=M.fold(funxam->leta'=Q.add(findxm)ainifQ.signa'=0thenM.removexmelseM.addxa'm)p2.mp1.min{m=m;c=Q.addp1.cp2.c;ty=p1.ty}letmult_constnp=ifQ.signn=0then{m=M.empty;c=Q.zero;ty=p.ty}else{pwithm=M.map(Q.multn)p.m;c=Q.multnp.c}letadd_constnp={pwithc=Q.addp.cn}letmult_monomeaxp=letax={m=M.addxaM.empty;c=Q.zero;ty=p.ty}inletacx=mult_constp.caxinletm=M.fold(funxiaim->M.add(X.multxxi)(Q.multaai)m)p.macx.min{acxwithm=m}letmultp1p2=Options.tool_req4"TR-Arith-Poly mult";letp=mult_constp1.cp2inM.fold(funxap->add(mult_monomeaxp2)p)p1.mpletsubp1p2=Options.tool_req4"TR-Arith-Poly moins";letm=M.fold(funxam->leta'=Q.sub(findxm)ainifQ.signa'=0thenM.removexmelseM.addxa'm)p2.mp1.min{m=m;c=Q.subp1.cp2.c;ty=p1.ty}leteuc_mod_numc1c2=letc=Q.moduloc1c2inifQ.signc<0thenQ.addc(Q.absc2)elsecleteuc_div_numc1c2=Q.div(Q.subc1(euc_mod_numc1c2))c2letdivp1p2=Options.tool_req4"TR-Arith-Poly div";ifnot(M.is_emptyp2.m)thenraiseMaybe_zero;ifQ.signp2.c=0thenraiseDivision_by_zero;letp=mult_const(Q.divQ.onep2.c)p1inmatchM.is_emptyp.m,p.tywith|_,Ty.Treal->p,false|true,Ty.Tint->{pwithc=euc_div_nump1.cp2.c},false|false,Ty.Tint->p,true(* XXX *)|_->assertfalseletmodulop1p2=Options.tool_req4"TR-Arith-Poly mod";ifnot(M.is_emptyp2.m)thenraiseMaybe_zero;ifQ.signp2.c=0thenraiseDivision_by_zero;ifnot(M.is_emptyp1.m)thenraiseNot_a_num;{p1withc=euc_mod_nump1.cp2.c}letfindxp=M.findxp.mletis_emptyp=M.is_emptyp.mletchoosep=lettn=refNonein(*version I : prend le premier element de la table*)(tryM.iter(funxa->tn:=Some(a,x);raiseExit)p.mwithExit->());(*version II : prend le dernier element de la table i.e. le plus grand
M.iter (fun x a -> tn := Some (a, x)) p.m;*)match!tnwithSomep->p|_->raiseNot_foundletsubstxp1p2=tryleta=M.findxp2.minadd(mult_constap1){p2withm=M.removexp2.m}withNot_found->p2letremovexp={pwithm=M.removexp.m}letto_listp=map_to_listp.m,p.cmoduleSX=Set.Make(structtypet=rletcompare=X.hash_cmpend)letxs_of_listsxl=List.fold_left(funsx->SX.addxs)sxlletleavesp=lets=M.fold(funa_s->xs_of_lists(X.leavesa))p.mSX.emptyinSX.elementsslettype_infop=p.tyletis_monomialp=tryM.fold(funxar->matchrwith|None->Some(a,x,p.c)|_->raiseExit)p.mNonewithExit->Noneletppmc_denominators{m;_}=letres=M.fold(fun_cacc->Z.my_lcm(Q.denc)acc)mZ.oneinQ.abs(Q.from_zres)letpgcd_numerators{m;_}=letres=M.fold(fun_cacc->Z.my_gcd(Q.numc)acc)mZ.zeroinQ.abs(Q.from_zres)letnormal_form({m;_}asp)=ifM.is_emptymthen{pwithc=Q.zero},p.c,Q.oneelseletppcm=ppmc_denominatorspinletpgcd=pgcd_numeratorspinletp=mult_const(Q.divppcmpgcd)pin{pwithc=Q.zero},p.c,(Q.divpgcdppcm)letnormal_form_posp=letp,c,d=normal_formpintryleta,_=choosepinifQ.signa>0thenp,c,delsemult_constQ.m_onep,Q.minusc,Q.minusdwithNot_found->p,c,dletabstract_selectorspacc=letmp,acc=M.fold(funri(mp,acc)->letr,acc=X.abstract_selectorsraccinletmp=tryletj=M.findrmpinletk=Q.addijinifQ.signk=0thenM.removermpelseM.addrkmpwithNot_found->M.addrimpinmp,acc)p.m(M.empty,acc)in{pwithm=mp},accletseparate_constantt={twithc=Q.zero},t.cend