123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544(************************************************************************)(* * The Coq Proof Assistant / The Coq Development Team *)(* v * Copyright INRIA, CNRS and contributors *)(* <O___,, * (see version control and CREDITS file for authors & dates) *)(* \VV/ **************************************************************)(* // * This file is distributed under the terms of the *)(* * GNU Lesser General Public License Version 2.1 *)(* * (see LICENSE file for the text of the license) *)(************************************************************************)openCErrorsopenUtilopenConstropenUtile(***********************************************************************
Operations on coefficients
*)moduleBigInt=structopenBig_int_Ztypet=big_intletof_int=big_int_of_intletcoef0=of_int0letof_num=Q.to_bigintletto_num=Q.of_bigintletequal=eq_big_intletlt=lt_big_intletle=le_big_intletabs=abs_big_intletplus=add_big_intletmult=mult_big_intletsub=sub_big_intletopp=minus_big_intletdiv=div_big_intletmodulo=mod_big_intletto_string=string_of_big_intlethashx=try(int_of_big_intx)withFailure_->1letpuis=power_big_int_positive_int(* a et b positifs, résultat positif *)letrecpgcdab=ifequalbcoef0thenaelseifltabthenpgcdbaelsepgcdb(moduloab)end(*
module Ent = struct
type t = Entiers.entiers
let of_int = Entiers.ent_of_int
let of_num x = Entiers.ent_of_string(Num.string_of_num x)
let to_num x = Num.num_of_string (Entiers.string_of_ent x)
let equal = Entiers.eq_ent
let lt = Entiers.lt_ent
let le = Entiers.le_ent
let abs = Entiers.abs_ent
let plus =Entiers.add_ent
let mult = Entiers.mult_ent
let sub = Entiers.moins_ent
let opp = Entiers.opp_ent
let div = Entiers.div_ent
let modulo = Entiers.mod_ent
let coef0 = Entiers.ent0
let coef1 = Entiers.ent1
let to_string = Entiers.string_of_ent
let to_int x = Entiers.int_of_ent x
let hash x =Entiers.hash_ent x
let signe = Entiers.signe_ent
let rec puis p n = match n with
0 -> coef1
|_ -> (mult p (puis p (n-1)))
(* a et b positifs, résultat positif *)
let rec pgcd a b =
if equal b coef0
then a
else if lt a b then pgcd b a else pgcd b (modulo a b)
(* signe du pgcd = signe(a)*signe(b) si non nuls. *)
let pgcd2 a b =
if equal a coef0 then b
else if equal b coef0 then a
else let c = pgcd (abs a) (abs b) in
if ((lt coef0 a)&&(lt b coef0))
||((lt coef0 b)&&(lt a coef0))
then opp c else c
end
*)(* ------------------------------------------------------------------------- *)(* ------------------------------------------------------------------------- *)typevname=stringtypeterm=|Zero|ConstofQ.t|Varofvname|Oppofterm|Addofterm*term|Subofterm*term|Mulofterm*term|Powofterm*intletconstn=ifQ.(equalzero)nthenZeroelseConstnletpow(p,i)=ifInt.equali1thenpelsePow(p,i)letadd=function(Zero,q)->q|(p,Zero)->p|(p,q)->Add(p,q)letmul=function(Zero,_)->Zero|(_,Zero)->Zero|(p,Constn)whenQ.(equalone)n->p|(Constn,q)whenQ.(equalone)n->q|(p,q)->Mul(p,q)letgen_constantn=lazy(UnivGen.constr_of_monomorphic_global(Global.env())(Coqlib.lib_refn))lettpexpr=gen_constant"plugins.ring.pexpr"letttconst=gen_constant"plugins.ring.const"letttvar=gen_constant"plugins.ring.var"letttadd=gen_constant"plugins.ring.add"letttsub=gen_constant"plugins.ring.sub"letttmul=gen_constant"plugins.ring.mul"letttopp=gen_constant"plugins.ring.opp"letttpow=gen_constant"plugins.ring.pow"lettlist=gen_constant"core.list.type"letlnil=gen_constant"core.list.nil"letlcons=gen_constant"core.list.cons"lettz=gen_constant"num.Z.type"letz0=gen_constant"num.Z.Z0"letzpos=gen_constant"num.Z.Zpos"letzneg=gen_constant"num.Z.Zneg"letpxI=gen_constant"num.pos.xI"letpxO=gen_constant"num.pos.xO"letpxH=gen_constant"num.pos.xH"letnN0=gen_constant"num.N.N0"letnNpos=gen_constant"num.N.Npos"letmkt_appnamel=mkApp(Lazy.forcename,Array.of_listl)lettlp()=mkt_apptlist[mkt_apptpexpr[Lazy.forcetz]]lettllp()=mkt_apptlist[tlp()]letmkt_posn=letrecmkt_posn=ifZ.(equalone)nthenLazy.forcepxHelseifZ.is_evennthenmkt_apppxO[mkt_posZ.(nasr1)]elsemkt_apppxI[mkt_posZ.(nasr1)]inmkt_pos(Q.to_bigintn)letmkt_nn=ifQ.(equalzero)nthenLazy.forcenN0elsemkt_appnNpos[mkt_posn]letmkt_zz=ifQ.(equalzero)zthenLazy.forcez0elseifQ.(ltzero)zthenmkt_appzpos[mkt_posz]elsemkt_appzneg[mkt_pos(Q.negz)]letrecmkt_termt=matchtwith|Zero->mkt_term(ConstQ.zero)|Constr->letn=r|>Q.num|>Q.of_bigintinmkt_appttconst[Lazy.forcetz;mkt_zn]|Varv->mkt_appttvar[Lazy.forcetz;mkt_pos(Q.of_stringv)]|Oppt1->mkt_appttopp[Lazy.forcetz;mkt_termt1]|Add(t1,t2)->mkt_appttadd[Lazy.forcetz;mkt_termt1;mkt_termt2]|Sub(t1,t2)->mkt_appttsub[Lazy.forcetz;mkt_termt1;mkt_termt2]|Mul(t1,t2)->mkt_appttmul[Lazy.forcetz;mkt_termt1;mkt_termt2]|Pow(t1,n)->ifInt.equaln0thenmkt_appttconst[Lazy.forcetz;mkt_zQ.one]elsemkt_appttpow[Lazy.forcetz;mkt_termt1;mkt_n(Q.of_intn)]letrecparse_posp=matchConstr.kindpwith|App(a,[|p2|])->ifConstr.equala(Lazy.forcepxO)thenQ.(mul(of_int2))(parse_posp2)elseQ.(addone)Q.(mul(of_int2)(parse_posp2))|_->Q.oneletparse_zz=matchConstr.kindzwith|App(a,[|p2|])->ifConstr.equala(Lazy.forcezpos)thenparse_posp2elseQ.neg(parse_posp2)|_->Q.zeroletparse_nz=matchConstr.kindzwith|App(a,[|p2|])->parse_posp2|_->Q.zeroletrecparse_termp=matchConstr.kindpwith|App(a,[|_;p2|])->ifConstr.equala(Lazy.forcettvar)thenVar(Q.to_string(parse_posp2))elseifConstr.equala(Lazy.forcettconst)thenConst(parse_zp2)elseifConstr.equala(Lazy.forcettopp)thenOpp(parse_termp2)elseZero|App(a,[|_;p2;p3|])->ifConstr.equala(Lazy.forcettadd)thenAdd(parse_termp2,parse_termp3)elseifConstr.equala(Lazy.forcettsub)thenSub(parse_termp2,parse_termp3)elseifConstr.equala(Lazy.forcettmul)thenMul(parse_termp2,parse_termp3)elseifConstr.equala(Lazy.forcettpow)thenPow(parse_termp2,Q.to_int(parse_np3))elseZero|_->Zeroletrecparse_requestlp=matchConstr.kindlpwith|App(_,[|_|])->[]|App(_,[|_;p;lp1|])->(parse_termp)::(parse_requestlp1)|_->assertfalseletset_nvars_termnvarst=letrecauxtnvars=matchtwith|Zero->nvars|Constr->nvars|Varv->letn=int_of_stringvinmaxnvarsn|Oppt1->auxt1nvars|Add(t1,t2)->auxt2(auxt1nvars)|Sub(t1,t2)->auxt2(auxt1nvars)|Mul(t1,t2)->auxt2(auxt1nvars)|Pow(t1,n)->auxt1nvarsinauxtnvars(***********************************************************************
Coefficients: recursive polynomials
*)moduleCoef=BigInt(*module Coef = Ent*)modulePoly=Polynom.Make(Coef)modulePIdeal=Ideal.Make(Poly)openPIdeal(* term to sparse polynomial
variables <=np are in the coefficients
*)letterm_pol_sparsenvarsnpt=letd=nvarsinletrecauxt=(* info ("conversion de: "^(string_of_term t)^"\n");*)letres=matchtwith|Zero->zeroP|Constr->ifQ.(equalzero)rthenzeroPelsepolconstd(Poly.Pint(Coef.of_numr))|Varv->letv=int_of_stringvinifv<=npthenpolconstd(Poly.xv)elsegendv|Oppt1->oppP(auxt1)|Add(t1,t2)->plusP(auxt1)(auxt2)|Sub(t1,t2)->plusP(auxt1)(oppP(auxt2))|Mul(t1,t2)->multP(auxt1)(auxt2)|Pow(t1,n)->puisP(auxt1)nin(* info ("donne: "^(stringP res)^"\n");*)resinletres=auxtinres(* sparse polynomial to term *)letpolrec_to_termp=letrecauxp=matchpwith|Poly.Pintn->const(Coef.to_numn)|Poly.Prec(v,coefs)->letfoldicres=add(res,mul(auxc,pow(Var(string_of_intv),i)))inArray.fold_right_ifoldcoefsZeroinauxp(* approximation of the Horner form used in the tactic ring *)letpol_sparse_to_termn2p=(* info "pol_sparse_to_term ->\n";*)letp=PIdeal.reprpinletrecauxp=matchpwith[]->constQ.zero|(a,m)::p1->letm=Ideal.Monomial.reprminletn=(Array.lengthm)-1inlet(i0,e0)=List.fold_left(fun(r,d)(a,m)->letm=Ideal.Monomial.reprminleti0=ref0infork=1tondoifm.(k)>0theni0:=kdone;ifInt.equal!i00then(r,d)elseif!i0>rthen(!i0,m.(!i0))elseifInt.equal!i0r&&m.(!i0)<dthen(!i0,m.(!i0))else(r,d))(0,0)pinifInt.equali00thenletmp=polrec_to_termainifList.is_emptyp1thenmpelseadd(mp,auxp1)elseletfold(p1,p2)(a,m)=if(Ideal.Monomial.reprm).(i0)>=e0thenbeginletm0=Array.copy(Ideal.Monomial.reprm)inlet()=m0.(i0)<-m0.(i0)-e0inletm0=Ideal.Monomial.makem0in((a,m0)::p1,p2)endelse(p1,(a,m)::p2)inlet(p1,p2)=List.fold_leftfold([],[])pinletvm=ifInt.equale01thenVar(string_of_int(i0))elsepow(Var(string_of_int(i0)),e0)inadd(mul(vm,aux(List.revp1)),aux(List.revp2))in(*info "-> pol_sparse_to_term\n";*)auxp(*
lq = [cn+m+1 n+m ...cn+m+1 1]
lci=[[cn+1 n,...,cn1 1]
...
[cn+m n+m-1,...,cn+m 1]]
removes intermediate polynomials not useful to compute the last one.
*)letremove_zeroslci=letm=List.lengthlciinletu=Array.makemfalseinletrecutilesk=(* TODO: Find a more reasonable implementation of this traversal. *)ifk>=m||u.(k)then()elselet()=u.(k)<-trueinletlc=List.nthlcikinletiteric=ifnot(PIdeal.equalczeroP)thenutiles(i+k+1)inList.iteriiterlcinlet()=utiles0inletfilteril=letfjl=ifm<=i+j+1thentrueelseu.(i+j+1)inifu.(i)thenSome(List.filterifl)elseNoneinletlr=CList.map_filter_ifilterlciininfo(fun()->Printf.sprintf"useless spolynomials: %i"(m-List.lengthlr));info(fun()->Printf.sprintf"useful spolynomials: %i "(List.lengthlr));lrlettheoremedeszerosmetadatanvarslpolp=lett1=Unix.gettimeofday()inletm=nvarsinletcert=in_idealmetadatamlpolpininfo(fun()->Printf.sprintf"time: @[%10.3f@]s"(Unix.gettimeofday()-.t1));certopenIdeal(* Remove zero polynomials and duplicates from the list of polynomials lp
Return (clp, lb)
where clp is the reduced list and lb is a list of booleans
that has the same size than lp and where true indicates an
element that has been removed
*)letclean_pollp=lett=Hashpol.create12inletfindp=tryHashpol.findtpwithNot_found->Hashpol.addtptrue;falseinletrecauxlp=matchlpwith|[]->[],[]|p::lp1->letclp,lb=auxlp1inifequalpzeroP||findpthenclp,true::lbelse(p::clp,false::lb)inauxlp(* Expand the list of polynomials lp putting zeros where the list of
booleans lb indicates there is a missing element
Warning:
the expansion is relative to the end of the list in reversed order
lp cannot have less elements than lb
*)letexpand_pollblp=letrecauxlblp=matchlbwith|[]->lp|true::lb1->zeroP::auxlb1lp|false::lb1->matchlpwith[]->assertfalse|p::lp1->p::auxlb1lp1inList.rev(auxlb(List.revlp))lettheoremedeszeros_termeslp=letnvars=List.fold_leftset_nvars_term0lpinmatchlpwith|Constsugarparam::Constnparam::lp->letnparam=Q.to_intnparamin((matchQ.to_intsugarparamwith|0->sinfo"computation without sugar";lexico:=false;|1->sinfo"computation with sugar";lexico:=false;|2->sinfo"ordre lexico computation without sugar";lexico:=true;|3->sinfo"ordre lexico computation with sugar";lexico:=true;|4->sinfo"computation without sugar, division by pairs";lexico:=false;|5->sinfo"computation with sugar, division by pairs";lexico:=false;|6->sinfo"ordre lexico computation without sugar, division by pairs";lexico:=true;|7->sinfo"ordre lexico computation with sugar, division by pairs";lexico:=true;|_->user_errPp.(str"nsatz: bad parameter"));letlvar=List.initnvars(funi->Printf.sprintf"x%i"(i+1))inletlvar=["a";"b";"c";"d";"e";"f";"g";"h";"i";"j";"k";"l";"m";"n";"o";"p";"q";"r";"s";"t";"u";"v";"w";"x";"y";"z"]@lvarin(* pour macaulay *)letmetadata={name_var=lvar}inletlp=List.map(term_pol_sparsenvarsnparam)lpinmatchlpwith|[]->assertfalse|p::lp1->letlpol=List.revlp1in(* preprocessing :
we remove zero polynomials and duplicate that are not handled by in_ideal
lb is kept in order to fix the certificate in the post-processing
*)letlpol,lb=clean_pollpolinletcert=theoremedeszerosmetadatanvarslpolpinsinfo"cert ok";letlc=cert.last_comb::List.revcert.gb_combinmatchremove_zeroslcwith|[]->assertfalse|(lq::lci)->(* post-processing : we apply the correction for the last line *)letlq=expand_pollblqin(* lci commence par les nouveaux polynomes *)letm=nvarsinletc=pol_sparse_to_termm(polconstmcert.coef)inletr=Pow(Zero,cert.power)inletlci=List.revlciin(* post-processing we apply the correction for the other lines *)letlci=List.map(expand_pollb)lciinletlci=List.map(List.map(pol_sparse_to_termm))lciinletlq=List.map(pol_sparse_to_termm)lqininfo(fun()->Printf.sprintf"number of parameters: %i"nparam);sinfo"term computed";(c,r,lci,lq))|_->assertfalse(* version avec hash-consing du certificat:
let nsatz lpol =
Hashtbl.clear Dansideal.hmon;
Hashtbl.clear Dansideal.coefpoldep;
Hashtbl.clear Dansideal.sugartbl;
Hashtbl.clear Polynomesrec.hcontentP;
init_constants ();
let lp= parse_request lpol in
let (_lp0,_p,c,r,_lci,_lq as rthz) = theoremedeszeros_termes lp in
let certif = certificat_vers_polynome_creux rthz in
let certif = hash_certif certif in
let certif = certif_term certif in
let c = mkt_term c in
info "constr computed\n";
(c, certif)
*)letnsatzlpol=letlp=parse_requestlpolinlet(c,r,lci,lq)=theoremedeszeros_termeslpinletres=[c::r::lq]@lciinletres=List.map(funlx->List.mapmkt_termlx)resinletres=List.fold_right(funltr->letltterm=List.fold_right(funtr->mkt_applcons[mkt_apptpexpr[Lazy.forcetz];t;r])lt(mkt_applnil[mkt_apptpexpr[Lazy.forcetz]])inmkt_applcons[tlp();ltterm;r])res(mkt_applnil[tlp()])insinfo"term computed";resletreturn_termt=leta=mkApp(UnivGen.constr_of_monomorphic_global(Global.env())@@Coqlib.lib_ref"core.eq.refl",[|tllp();t|])inleta=EConstr.of_constrainGeneralize.generalize[a]letnsatz_computet=letlpol=trynsatztwithIdeal.NotInIdeal->user_errPp.(str"nsatz cannot solve this problem")inreturn_termlpol