root / pobysoPythonSage / src / sageSLZ / sagePolynomialOperations.sage @ 98
Historique | Voir | Annoter | Télécharger (21,83 ko)
1 |
load "/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageMatrixOperations.sage" |
---|---|
2 |
print "sagePolynomialOperations loading..." |
3 |
def spo_add_polynomial_coeffs_to_matrix_row(pMonomials, |
4 |
pCoefficients, |
5 |
knownMonomials, |
6 |
protoMatrixRows, |
7 |
columnsWidth=0): |
8 |
""" |
9 |
For a given polynomial (under the form of monomials and coefficents lists), |
10 |
add the coefficients of the protoMatrix (a list of proto matrix rows). |
11 |
Coefficients are added to the protoMatrix row in the order imposed by the |
12 |
monomials discovery list (the knownMonomials list) built as construction |
13 |
goes on. |
14 |
As a bonus, data can be printed out for a visual check. |
15 |
pMonomials : the list of the monomials coming form some polynomial; |
16 |
pCoefficients : the list of the corresponding coefficients to add to |
17 |
the protoMatrix in the exact same order as the monomials; |
18 |
knownMonomials : the list of the already knonw monomials; |
19 |
protoMatrixRows: a list of lists, each one holding the coefficients of the |
20 |
monomials |
21 |
columnWith : the width, in characters, of the displayed column ; if 0, |
22 |
do not display anything. |
23 |
""" |
24 |
# We have started with the smaller degrees in the first variable. |
25 |
pMonomials.reverse() |
26 |
pCoefficients.reverse() |
27 |
# New empty proto matrix row. |
28 |
protoMatrixRowCoefficients = [] |
29 |
# We work according to the order of the already known monomials |
30 |
# No known monomials yet: add the pMonomials to knownMonomials |
31 |
# and add the coefficients to the proto matrix row. |
32 |
if len(knownMonomials) == 0: |
33 |
for pmIdx in xrange(0, len(pMonomials)): |
34 |
knownMonomials.append(pMonomials[pmIdx]) |
35 |
protoMatrixRowCoefficients.append(pCoefficients[pmIdx]) |
36 |
if columnsWidth != 0: |
37 |
monomialAsString = str(pCoefficients[pmIdx]) + " " + \ |
38 |
str(pMonomials[pmIdx]) |
39 |
print monomialAsString, " " * \ |
40 |
(columnsWidth - len(monomialAsString)), |
41 |
# There are some known monomials. We search for them in pMonomials and |
42 |
# add their coefficients to the proto matrix row. |
43 |
else: |
44 |
for knownMonomialIndex in xrange(0,len(knownMonomials)): |
45 |
# We lazily use an exception here since pMonomials.index() function |
46 |
# may fail throwing the ValueError exception. |
47 |
try: |
48 |
indexInPmonomials = \ |
49 |
pMonomials.index(knownMonomials[knownMonomialIndex]) |
50 |
if columnsWidth != 0: |
51 |
monomialAsString = str(pCoefficients[indexInPmonomials]) + \ |
52 |
" " + str(knownMonomials[knownMonomialIndex]) |
53 |
print monomialAsString, " " * \ |
54 |
(columnsWidth - len(monomialAsString)), |
55 |
# Add the coefficient to the proto matrix row and delete the \ |
56 |
# known monomial from the current pMonomial list |
57 |
#(and the corresponding coefficient as well). |
58 |
protoMatrixRowCoefficients.append(pCoefficients[indexInPmonomials]) |
59 |
del pMonomials[indexInPmonomials] |
60 |
del pCoefficients[indexInPmonomials] |
61 |
# The knownMonomials element is not in pMonomials |
62 |
except ValueError: |
63 |
protoMatrixRowCoefficients.append(0) |
64 |
if columnsWidth != 0: |
65 |
monomialAsString = "0" + " "+ \ |
66 |
str(knownMonomials[knownMonomialIndex]) |
67 |
print monomialAsString, " " * \ |
68 |
(columnsWidth - len(monomialAsString)), |
69 |
# End for knownMonomialKey loop. |
70 |
# We now append the remaining monomials of pMonomials to knownMonomials |
71 |
# and the corresponding coefficients to proto matrix row. |
72 |
for pmIdx in xrange(0, len(pMonomials)): |
73 |
knownMonomials.append(pMonomials[pmIdx]) |
74 |
protoMatrixRowCoefficients.append(pCoefficients[pmIdx]) |
75 |
if columnsWidth != 0: |
76 |
monomialAsString = str(pCoefficients[pmIdx]) + " " \ |
77 |
+ str(pMonomials[pmIdx]) |
78 |
print monomialAsString, " " * \ |
79 |
(columnsWidth - len(monomialAsString)), |
80 |
# End for pmIdx loop. |
81 |
# Add the new list row elements to the proto matrix. |
82 |
protoMatrixRows.append(protoMatrixRowCoefficients) |
83 |
if columnsWidth != 0: |
84 |
|
85 |
# End spo_add_polynomial_coeffs_to_matrix_row |
86 |
|
87 |
def spo_expression_as_string(powI, powT, powP, alpha): |
88 |
""" |
89 |
Computes a string version of the i^k + t^l + p^m + N^n expression for |
90 |
output. |
91 |
""" |
92 |
expressionAsString ="" |
93 |
if powI != 0: |
94 |
expressionAsString += "i^" + str(powI) |
95 |
if powT != 0: |
96 |
if len(expressionAsString) != 0: |
97 |
expressionAsString += " * " |
98 |
expressionAsString += "t^" + str(powT) |
99 |
if powP != 0: |
100 |
if len(expressionAsString) != 0: |
101 |
expressionAsString += " * " |
102 |
expressionAsString += "p^" + str(powP) |
103 |
if (alpha - powP) != 0 : |
104 |
if len(expressionAsString) != 0: |
105 |
expressionAsString += " * " |
106 |
expressionAsString += "N^" + str(alpha - powP) |
107 |
return(expressionAsString) |
108 |
# End spo_expression_as_string. |
109 |
|
110 |
def spo_norm(poly, p=2): |
111 |
""" |
112 |
Behaves more or less (no infinity defined) as the norm for the |
113 |
univariate polynomials. |
114 |
Quoting the Sage documentation: |
115 |
Definition: For integer p, the p-norm of a polynomial is the pth root of |
116 |
the sum of the pth powers of the absolute values of the coefficients of |
117 |
the polynomial. |
118 |
|
119 |
""" |
120 |
# TODO: check the arguments (for p see below).. |
121 |
norm = 0 |
122 |
# For infinity norm. |
123 |
if p == Infinity: |
124 |
for coefficient in poly.coefficients(): |
125 |
coefficientAbs = coefficient.abs() |
126 |
if coefficientAbs > norm: |
127 |
norm = coefficientAbs |
128 |
return norm |
129 |
# TODO: check here the value of p |
130 |
# p must be an integer. |
131 |
if int(p) != p: |
132 |
return None |
133 |
# p must be >= 1. |
134 |
if p < 1: |
135 |
return None |
136 |
# For 1 norm. |
137 |
if p == 1: |
138 |
for coefficient in poly.coefficients(): |
139 |
norm += coefficient.abs() |
140 |
return norm |
141 |
# For other norms |
142 |
for coefficient in poly.coefficients(): |
143 |
norm += (coefficient^p).abs() |
144 |
return pow(norm, 1/p) |
145 |
# end spo_norm |
146 |
|
147 |
def spo_polynomial_to_proto_matrix(p, pRing, alpha, N, columnsWidth=0): |
148 |
""" |
149 |
From a (bivariate) polynomial and some other parameters build a proto |
150 |
matrix (an array of "rows") to be converted into a "true" matrix and |
151 |
eventually by reduced by fpLLL. |
152 |
The matrix is such as those found in Boneh-Durphee and Stehl?. |
153 |
|
154 |
Parameters |
155 |
---------- |
156 |
p: the (bivariate) polynomial; |
157 |
pRing: the ring over which p is defined; |
158 |
alpha: |
159 |
N: |
160 |
columsWidth: if == 0, no information is displayed, otherwise data is |
161 |
printed in colums of columnsWitdth width. |
162 |
""" |
163 |
knownMonomials = [] |
164 |
protoMatrixRows = [] |
165 |
polynomialsList = [] |
166 |
pVariables = p.variables() |
167 |
iVariable = pVariables[0] |
168 |
tVariable = pVariables[1] |
169 |
polynomialAtPower = pRing(1) |
170 |
currentPolynomial = pRing(1) |
171 |
pIdegree = p.degree(pVariables[0]) |
172 |
pTdegree = p.degree(pVariables[1]) |
173 |
currentIdegree = currentPolynomial.degree(iVariable) |
174 |
nAtPower = N^alpha |
175 |
nAtAlpha = nAtPower |
176 |
polExpStr = "" |
177 |
# We work from p^0 * N^alpha to p^alpha * N^0 |
178 |
for pPower in xrange(0, alpha + 1): |
179 |
# pPower == 0 is a special case. We introduce all the monomials but one |
180 |
# in i and those in t necessary to be able to introduce |
181 |
# p. We arbitrary choose to introduce the highest degree monomial in i |
182 |
# with p. We also introduce all the mixed i^k * t^l monomials with |
183 |
# k < p.degree(i) and l <= p.degree(t). |
184 |
# Mixed terms introduction is necessary here before we start "i shifts" |
185 |
# in the next iteration. |
186 |
if pPower == 0: |
187 |
# Notice that i^pIdegree is excluded as the bound of the xrange is |
188 |
# pIdegree |
189 |
for iPower in xrange(0, pIdegree): |
190 |
for tPower in xrange(0, pTdegree + 1): |
191 |
if columnsWidth != 0: |
192 |
polExpStr = spo_expression_as_string(iPower, |
193 |
tPower, |
194 |
pPower, |
195 |
alpha) |
196 |
print "->", polExpStr |
197 |
currentExpression = iVariable^iPower * \ |
198 |
tVariable^tPower * nAtAlpha |
199 |
# polynomialAtPower == 1 here. Next line should be commented |
200 |
# out but it does not work! Some conversion problem? |
201 |
currentPolynomial = pRing(currentExpression) |
202 |
polynomialsList.append(polExpStr) |
203 |
pMonomials = currentPolynomial.monomials() |
204 |
pCoefficients = currentPolynomial.coefficients() |
205 |
spo_add_polynomial_coeffs_to_matrix_row(pMonomials, |
206 |
pCoefficients, |
207 |
knownMonomials, |
208 |
protoMatrixRows, |
209 |
columnsWidth) |
210 |
# End tPower. |
211 |
# End for iPower. |
212 |
else: # pPower > 0: (p^1..p^alpha) |
213 |
# This where we introduce the p^pPower * N^(alpha-pPower) |
214 |
# polynomial. |
215 |
# This step could technically be fused as the first iteration |
216 |
# of the next loop (with iPower starting at 0). |
217 |
# We set it apart for clarity. |
218 |
if columnsWidth != 0: |
219 |
polExpStr = spo_expression_as_string(0, 0, pPower, alpha) |
220 |
print "->", polExpStr |
221 |
currentPolynomial = polynomialAtPower * nAtPower |
222 |
polynomialsList.append(polExpStr) |
223 |
pMonomials = currentPolynomial.monomials() |
224 |
pCoefficients = currentPolynomial.coefficients() |
225 |
spo_add_polynomial_coeffs_to_matrix_row(pMonomials, |
226 |
pCoefficients, |
227 |
knownMonomials, |
228 |
protoMatrixRows, |
229 |
columnsWidth) |
230 |
|
231 |
# The i^iPower * p^pPower polynomials: they add i^k monomials to |
232 |
# p^pPower up to k < pIdegree * pPower. This only introduces i^k |
233 |
# monomials since mixed terms (that were introduced at a previous |
234 |
# stage) are only shifted to already existing |
235 |
# ones. p^pPower is "shifted" to higher degrees in i as far as |
236 |
# possible, one step short of the degree in i of p^(pPower+1) . |
237 |
# These "pure" i^k monomials can only show up with i multiplications. |
238 |
for iPower in xrange(1, pIdegree): |
239 |
if columnsWidth != 0: |
240 |
polExpStr = spo_expression_as_string(iPower, \ |
241 |
0, \ |
242 |
pPower, \ |
243 |
alpha) |
244 |
print "->", polExpStr |
245 |
currentExpression = i^iPower * nAtPower |
246 |
currentPolynomial = pRing(currentExpression) * polynomialAtPower |
247 |
polynomialsList.append(polExpStr) |
248 |
pMonomials = currentPolynomial.monomials() |
249 |
pCoefficients = currentPolynomial.coefficients() |
250 |
spo_add_polynomial_coeffs_to_matrix_row(pMonomials, \ |
251 |
pCoefficients, \ |
252 |
knownMonomials, \ |
253 |
protoMatrixRows, \ |
254 |
columnsWidth) |
255 |
# End for iPower |
256 |
# We want now to introduce a t * p^pPower polynomial. But before |
257 |
# that we must introduce some mixed monomials. |
258 |
# This loop is no triggered before pPower == 2. |
259 |
# It introduces a first set of high i degree mixed monomials. |
260 |
for iPower in xrange(1, pPower): |
261 |
tPower = pPower - iPower + 1 |
262 |
if columnsWidth != 0: |
263 |
polExpStr = spo_expression_as_string(iPower * pIdegree, |
264 |
tPower, |
265 |
0, |
266 |
alpha) |
267 |
print "->", polExpStr |
268 |
currentExpression = i^(iPower * pIdegree) * t^tPower * nAtAlpha |
269 |
currentPolynomial = pRing(currentExpression) |
270 |
polynomialsList.append(polExpStr) |
271 |
pMonomials = currentPolynomial.monomials() |
272 |
pCoefficients = currentPolynomial.coefficients() |
273 |
spo_add_polynomial_coeffs_to_matrix_row(pMonomials, |
274 |
pCoefficients, |
275 |
knownMonomials, |
276 |
protoMatrixRows, |
277 |
columnsWidth) |
278 |
# End for iPower |
279 |
# |
280 |
# This is the mixed monomials main loop. It introduces: |
281 |
# - the missing mixed monomials needed before the |
282 |
# t^l * p^pPower * N^(alpha-pPower) polynomial; |
283 |
# - the t^l * p^pPower * N^(alpha-pPower) itself; |
284 |
# - for each of i^k * t^l * p^pPower * N^(alpha-pPower) polynomials: |
285 |
# - the the missing mixed monomials needed polynomials, |
286 |
# - the i^k * t^l * p^pPower * N^(alpha-pPower) itself. |
287 |
# The t^l * p^pPower * N^(alpha-pPower) is introduced when |
288 |
# |
289 |
for iShift in xrange(0, pIdegree): |
290 |
# When pTdegree == 1, the following loop only introduces |
291 |
# a single new monomial. |
292 |
#print "++++++++++" |
293 |
for outerTpower in xrange(1, pTdegree + 1): |
294 |
# First one high i degree mixed monomial. |
295 |
iPower = iShift + pPower * pIdegree |
296 |
if columnsWidth != 0: |
297 |
polExpStr = spo_expression_as_string(iPower, |
298 |
outerTpower, |
299 |
0, |
300 |
alpha) |
301 |
print "->", polExpStr |
302 |
currentExpression = i^iPower * t^outerTpower * nAtAlpha |
303 |
currentPolynomial = pRing(currentExpression) |
304 |
polynomialsList.append(polExpStr) |
305 |
pMonomials = currentPolynomial.monomials() |
306 |
pCoefficients = currentPolynomial.coefficients() |
307 |
spo_add_polynomial_coeffs_to_matrix_row(pMonomials, |
308 |
pCoefficients, |
309 |
knownMonomials, |
310 |
protoMatrixRows, |
311 |
columnsWidth) |
312 |
#print "+++++" |
313 |
# At iShift == 0, the following innerTpower loop adds |
314 |
# duplicate monomials, since no extra i^l * t^k is needed |
315 |
# before introducing the |
316 |
# i^iShift * t^outerPpower * p^pPower * N^(alpha-pPower) |
317 |
# polynomial. |
318 |
# It introduces smaller i degree monomials than the |
319 |
# one(s) added previously (no pPower multiplication). |
320 |
# Here the exponent of t decreases as that of i increases. |
321 |
# This conditional is not entered before pPower == 1. |
322 |
# The innerTpower loop does not produce anything before |
323 |
# pPower == 2. We keep it anyway for other configuration of |
324 |
# p. |
325 |
if iShift > 0: |
326 |
iPower = pIdegree + iShift |
327 |
for innerTpower in xrange(pPower, 1, -1): |
328 |
if columnsWidth != 0: |
329 |
polExpStr = spo_expression_as_string(iPower, |
330 |
innerTpower, |
331 |
0, |
332 |
alpha) |
333 |
currentExpression = \ |
334 |
i^(iPower) * t^(innerTpower) * nAtAlpha |
335 |
currentPolynomial = pRing(currentExpression) |
336 |
polynomialsList.append(polExpStr) |
337 |
pMonomials = currentPolynomial.monomials() |
338 |
pCoefficients = currentPolynomial.coefficients() |
339 |
spo_add_polynomial_coeffs_to_matrix_row(pMonomials, |
340 |
pCoefficients, |
341 |
knownMonomials, |
342 |
protoMatrixRows, |
343 |
columnsWidth) |
344 |
iPower += pIdegree |
345 |
# End for innerTpower |
346 |
# End of if iShift > 0 |
347 |
# When iShift == 0, just after each of the |
348 |
# p^pPower * N^(alpha-pPower) polynomials has |
349 |
# been introduced (followed by a string of |
350 |
# i^k * p^pPower * N^(alpha-pPower) polynomials) a |
351 |
# t^l * p^pPower * N^(alpha-pPower) is introduced here. |
352 |
# |
353 |
# Eventually, the following section introduces the |
354 |
# i^iShift * t^outerTpower * p^iPower * N^(alpha-iPower) |
355 |
# polynomials. |
356 |
if columnsWidth != 0: |
357 |
polExpStr = spo_expression_as_string(iShift, |
358 |
outerTpower, |
359 |
pPower, |
360 |
alpha) |
361 |
print "->", polExpStr |
362 |
currentExpression = i^iShift * t^outerTpower * nAtPower |
363 |
currentPolynomial = pRing(currentExpression) * polynomialAtPower |
364 |
polynomialsList.append(polExpStr) |
365 |
pMonomials = currentPolynomial.monomials() |
366 |
pCoefficients = currentPolynomial.coefficients() |
367 |
spo_add_polynomial_coeffs_to_matrix_row(pMonomials, |
368 |
pCoefficients, |
369 |
knownMonomials, |
370 |
protoMatrixRows, |
371 |
columnsWidth) |
372 |
# End for outerTpower |
373 |
#print "++++++++++" |
374 |
# End for iShift |
375 |
polynomialAtPower *= p |
376 |
nAtPower /= N |
377 |
# End for pPower loop |
378 |
return ((protoMatrixRows, knownMonomials, polynomialsList)) |
379 |
# End spo_polynomial_to_proto_matrix |
380 |
|
381 |
def spo_proto_to_column_matrix(protoMatrixColumns, \ |
382 |
knownMonomialsList, \ |
383 |
boundVar1, \ |
384 |
boundVar2): |
385 |
""" |
386 |
Create a column (each row holds the coefficients of one monomial) matrix. |
387 |
|
388 |
Parameters |
389 |
---------- |
390 |
protoMatrixColumns: a list of coefficient lists. |
391 |
""" |
392 |
numColumns = len(protoMatrixColumns) |
393 |
if numColumns == 0: |
394 |
return None |
395 |
# The last column holds has the maximum length. |
396 |
numRows = len(protoMatrixColumns[numColumns-1]) |
397 |
if numColumns == 0: |
398 |
return None |
399 |
baseMatrix = matrix(ZZ, numRows, numColumns) |
400 |
for colIndex in xrange(0, numColumns): |
401 |
for rowIndex in xrange(0, len(protoMatrixColumns[colIndex])): |
402 |
if protoMatrixColumns[colIndex][rowIndex] != 0: |
403 |
baseMatrix[rowIndex, colIndex] = \ |
404 |
protoMatrixColumns[colIndex][rowIndex] * \ |
405 |
knownMonomialsList[rowIndex](boundVar1, boundVar2) |
406 |
return baseMatrix |
407 |
# End spo_proto_to_column_matrix. |
408 |
# |
409 |
def spo_proto_to_row_matrix(protoMatrixRows, \ |
410 |
knownMonomialsList, \ |
411 |
boundVar1, \ |
412 |
boundVar2): |
413 |
""" |
414 |
Create a row (each column holds the evaluation one monomial at boundVar1 and |
415 |
boundVar2 values) matrix. |
416 |
|
417 |
Parameters |
418 |
---------- |
419 |
protoMatrixRows: a list of coefficient lists. |
420 |
""" |
421 |
numRows = len(protoMatrixRows) |
422 |
if numRows == 0: |
423 |
return None |
424 |
# The last row is the longest one. |
425 |
numColumns = len(protoMatrixRows[numRows-1]) |
426 |
if numColumns == 0: |
427 |
return None |
428 |
baseMatrix = matrix(ZZ, numRows, numColumns) |
429 |
for rowIndex in xrange(0, numRows): |
430 |
for colIndex in xrange(0, len(protoMatrixRows[rowIndex])): |
431 |
if protoMatrixRows[rowIndex][colIndex] != 0: |
432 |
baseMatrix[rowIndex, colIndex] = \ |
433 |
protoMatrixRows[rowIndex][colIndex] * \ |
434 |
knownMonomialsList[colIndex](boundVar1,boundVar2) |
435 |
#print rowIndex, colIndex, |
436 |
#print protoMatrixRows[rowIndex][colIndex], |
437 |
#print knownMonomialsList[colIndex](boundVar1,boundVar2) |
438 |
return baseMatrix |
439 |
# End spo_proto_to_row_matrix. |
440 |
# |
441 |
print "\t...sagePolynomialOperations loaded" |