2 /* -------------------------------------- */
4 isListCertLess(lhs,rhs) :=
5 isListLess(first(lhs),first(rhs));
8 /* Order Isolating with certificates List */
9 isListCertSort(isListCert) :=
10 sort(isListCert,isListCertLess);
13 subInterval(checkSub,bigInt) :=
14 is(first(checkSub)>=first(bigInt) and
15 second(checkSub)<=second(bigInt));
17 subIntervalInSet(intSet,bigInt) :=
24 while not(found) and i<= length(intSet) do
26 if subInterval(part(intSet,i),bigInt) then
37 /* Yun's square free decomposition algorithm */
38 squareFreeFactor(pol,var) :=
42 g : gcd(pol,diff(pol,var),var),
46 d : ratexpand(diff(pol,var)/g-diff(c,var)),
47 while not(degree(c,var)=0) do
52 d : ratexpand(d/q-diff(c,var))
59 bernsteinSplitWithZ(bcoeff,l,r,m) :=
67 i,j,nnorm,dnorm,ratnorm],
70 ratnorm : (r-m)/(r-l),
72 dnorm : denom(ratnorm),
74 b : make_array('any,p+1),
78 bern_first : [dnorm^p * b[0]],
79 bern_second : [dnorm^p * b[p]],
85 b[j] : nnorm*b[j] + (dnorm-nnorm)*b[j+1],
87 bern_first : endcons(dnorm^(p-i) * b[0],bern_first),
89 bern_second : cons(dnorm^(p-i)*b[p-i],bern_second)
93 return([bern_first,bern_second])
99 bernsteinMerge(lhs,rhs):=
100 block([extB,normfact,lhsNorm],
102 extB:bernsteinSplitWithZ(lhs[3],lhs[1][1],lhs[1][2],rhs[1][2])[1],
104 degP: length(lhs[3])-1,
107 middlePoint :rhs[1][2],
109 ratnorm : (rightEnd-middlePoint)/(rightEnd-leftEnd),
110 dnorm : denom(ratnorm),
112 if signChanges(extB)=0 then
113 return([[lhs[1][1],rhs[1][2]],lhs[2],extB/dnorm^degP])
120 /* It compresses a certificate by checking the positivity */
121 /* on adjacient intervals */
122 /* resList contains items of the form */
123 /* [[leftEnd,rightEnd],normFact,bernCoeff]] */
125 compressCertificate(certList) :=
126 block([isList,resList,extBCoeff,firstItem,secondItem,degP,lhsNorm,
127 dnorm,ratnorm,leftEnd,rightEnd,middlePoint,merged],
128 degP: length(certList[1][3]),
131 while (length(isList)>1) do
133 firstItem : first(isList),
134 secondItem : second(isList),
136 merged:bernsteinMerge(firstItem,secondItem),
138 if not(merged=false) then
140 extBCoeff: merged[3],
141 lhsNorm: lst_gcd(extBCoeff),
143 isList : rest(isList,2),
145 isList : cons(merged,isList)
150 resList : append(resList,[first(isList)]),
155 if length(isList)=1 then
156 resList : endcons(first(isList),resList),
162 /* Certification of positivity for a square free polynomial and */
163 /* for a polynomial with no roots in the considered interval */
164 deCasteljauNoCheckCertificateBetween(pol,var,
166 block([sfList,sfCert,i,j,intUnion,noCertificate,
167 searchLeftEnd:search_interval[1],
168 searchRightEnd:search_interval[2],
170 degP:degree(pol,var),
171 res,bernIntSet,item,bernInt,noSubInt,
172 bcoeff,normFact,bsplit,leftEnd,rightEnd,middlePoint,bCoeff,
173 lhsSplit, lhsNorm, rhsSplit, rhsNorm, ratnorm, dnorm, certificate,sgnCh],
177 bCoeff : bernsteinCoeffList(pol,var,searchLeftEnd,searchRightEnd),
179 normFact : apply(sarag_lcm,map(denom,bCoeff)),
180 bCoeff : normFact*bCoeff,
181 bernIntSet : [[search_interval,normFact,bCoeff]],
184 while not(bernIntSet=[]) and certificate do
186 item : first(bernIntSet),
187 bernIntSet : rest(bernIntSet),
189 bernInt : first(item),
190 normFact : second(item),
191 bCoeff : third(item),
193 leftEnd : first(bernInt),
194 rightEnd : second(bernInt),
196 if first(bCoeff)=0 then
204 if last(bCoeff)=0 then
212 if first(bCoeff)*last(bCoeff)<0 then
215 res:[0,[leftEnd,rightEnd]],
221 sgnCh:signChanges(bCoeff),
222 if sgnCh=0 and certificate then
224 res : endcons([[leftEnd,rightEnd],normFact,bCoeff],res)
228 middlePoint : (leftEnd+rightEnd)/2,
229 bsplit : bernsteinSplitWithZ(bCoeff,leftEnd,rightEnd,middlePoint),
231 lhsSplit : first(bsplit),
232 lhsNorm : lst_gcd(lhsSplit),
234 rhsSplit : second(bsplit),
235 rhsNorm : lst_gcd(rhsSplit),
237 ratnorm : (rightEnd-middlePoint)/(rightEnd-leftEnd),
238 dnorm : denom(ratnorm),
240 bernIntSet : endcons([[leftEnd,middlePoint],
241 normFact/lhsNorm*dnorm^degP,
242 lhsSplit/lhsNorm],bernIntSet),
243 bernIntSet : endcons([[middlePoint,rightEnd],
244 normFact/rhsNorm*dnorm^degP,
245 rhsSplit/rhsNorm],bernIntSet)
251 if COMPRESS_CERTIFICATE then
252 return([sg,compressCertificate(isListCertSort(res))])
254 return([sg,isListCertSort(res)])
261 /* Certification of positivity for a generic polynomial */
262 deCasteljauCertificateBetween(pol,var,search_interval) :=
263 block([sqFreeCert,sfCert,i,j,intUnion,noCertificate,
264 res,sqFree,item,bernInt,noSubInt,
265 bcoeff,normFact,bsplit,leftEnd,rightEnd,middlePoint,exPol, searchLeftEnd, searchRightEnd],
268 searchLeftEnd : first(search_interval),
269 searchRightEnd : second(search_interval),
271 sqFree: SQUARE_FREE_ALGORITHM(exPol,var),
272 sqFreeCert: deCasteljauNoCheckCertificateBetween(sqFree,var,
275 if first(sqFreeCert)=0 then
278 return([0,sqFreeCert[2],sqFree])
282 deCasteljauNoCheckCertificateBetween(exPol,var,
290 localBernsteinProof(poly,var,local_cert,printFlag):=
291 block([cert_sgn,sgnCh,bernCoeffList,i, verifySum],
293 sgnCh:signChanges(local_cert[3]),
294 bernCoeffList: (1/local_cert[2])*(local_cert[3]),
297 cert_sgn:sgn(local_cert[3][1])
304 sprint("It has a zero in ",local_cert[1])
306 print("because in this interval it has "),
307 print("the following Bernstein coefficients ",
316 sprint("It is positive in ",local_cert[1])
318 print("because in this interval it has "),
320 print("the following Bernstein coefficients ",
329 sprint("It is negative in ",local_cert[1])
331 print("because in this interval it has "),
332 print("the following Bernstein coefficients ",
336 print("as we see below: "),
337 for i: 0 thru length(bernCoeffList) - 2 do
339 print(bernCoeffList[i+1], bernstein(length(bernCoeffList)-1,i, local_cert[1][1], local_cert[1][2],var), "+")
341 print(bernCoeffList[length(bernCoeffList)], bernstein(length(bernCoeffList) - 1, length(bernCoeffList) - 1, local_cert[1][1], local_cert[1][2],var), "="),
342 for i: 0 thru length(bernCoeffList) - 2 do
344 print(bernCoeffList[i+1] * ratsimp(bernstein(length(bernCoeffList)-1,i, local_cert[1][1], local_cert[1][2],var)), "+")
346 print(bernCoeffList[length(bernCoeffList)] * ratsimp(bernstein(length(bernCoeffList) - 1, length(bernCoeffList) - 1, local_cert[1][1], local_cert[1][2],var)), "="),
348 for i: 0 thru length(bernCoeffList) - 1 do
350 verifySum : verifySum + bernCoeffList[i+1] * ratsimp(bernstein(length(bernCoeffList)-1,i, local_cert[1][1], local_cert[1][2],var))
352 print(ratsimp(verifySum))
358 bernsteinProof(poly,var,search_interval,cert):=
364 sprint("The polynomial ", exPol, " has a zero in ",
365 search_interval, "."),
366 if length(cert[2])= 1 then /* root found */
367 print("In fact it is zero for ", var, " = ", cert[2][1])
371 if expand(cert[3])=exPol then
372 ( /* square-free, interval found */
374 print("In fact it has value ",
375 subst(cert[2][1], var, exPol), " for ", var, " = ", cert[2][1]),
376 print("and it has value ",
377 subst(cert[2][2], var, exPol), " for ", var, " = ", cert[2][2])
380 ( /* non-square-free, interval found */
382 print("In fact its square-free part ", cert[3]),
383 print("has value ", subst(cert[2][1],var,cert[3]),
384 " for ", var, " = ", cert[2][1]),
385 print("and has value ",
386 subst(cert[2][2],var,cert[3])," for ", var, " = ", cert[2][2])
393 sprint("The polynomial ", exPol, " is positive in ",
395 if length(cert[2])>1 then
398 print("In fact we have that: "),
399 for i: 1 thru length(cert[2]) do
402 localBernsteinProof(poly,var,cert[2][i],true)
406 localBernsteinProof(poly,var,cert[2][1],false)
410 sprint("The polynomial ", exPol, " is negative in ",
412 if length(cert[2])>1 then
415 print("In fact we have: "),
416 for i: 1 thru length(cert[2]) do
419 localBernsteinProof(poly,var,cert[2][i],true)
423 localBernsteinProof(poly,var,cert[2][1],false)
430 return(length(cert[2]))
434 certificateProofBetween(pol,var, search_interval):=
435 bernsteinProof(pol,var,search_interval, certificateBetween(pol,var,search_interval));
439 certificateProof([args]):=
440 if length(args)=2 then
441 certificateProofBetween(args[1],args[2],
442 [DEFAULT_LEFT_END, DEFAULT_RIGHT_END])
444 certificateProofBetween(args[1],args[2], args[3]);