root / pobysoPythonSage / src / sageSLZ / sagePolynomialOperations.sage @ 109
Historique | Voir | Annoter | Télécharger (34,39 ko)
1 | 74 | storres | load "/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageMatrixOperations.sage" |
---|---|---|---|
2 | 87 | storres | print "sagePolynomialOperations loading..." |
3 | 106 | storres | def spo_add_polynomial_coeffs_to_matrix_row(poly, |
4 | 83 | storres | knownMonomials, |
5 | 83 | storres | protoMatrixRows, |
6 | 83 | storres | columnsWidth=0): |
7 | 80 | storres | """ |
8 | 106 | storres | For a given polynomial , |
9 | 80 | storres | add the coefficients of the protoMatrix (a list of proto matrix rows). |
10 | 80 | storres | Coefficients are added to the protoMatrix row in the order imposed by the |
11 | 80 | storres | monomials discovery list (the knownMonomials list) built as construction |
12 | 80 | storres | goes on. |
13 | 83 | storres | As a bonus, data can be printed out for a visual check. |
14 | 106 | storres | poly : the polynomial; in argument; |
15 | 106 | storres | knownMonomials : the list of the already known monomials; will determine |
16 | 106 | storres | the order of the coefficients appending to a row; in-out |
17 | 106 | storres | argument (new monomials may be discovered and then |
18 | 106 | storres | appended the the knowMonomials list); |
19 | 80 | storres | protoMatrixRows: a list of lists, each one holding the coefficients of the |
20 | 106 | storres | monomials of a polynomial; in-out argument: a new row is |
21 | 106 | storres | added at each call; |
22 | 80 | storres | columnWith : the width, in characters, of the displayed column ; if 0, |
23 | 106 | storres | do not display anything; in argument. |
24 | 80 | storres | """ |
25 | 106 | storres | pMonomials = poly.monomials() |
26 | 106 | storres | pCoefficients = poly.coefficients() |
27 | 80 | storres | # We have started with the smaller degrees in the first variable. |
28 | 80 | storres | pMonomials.reverse() |
29 | 80 | storres | pCoefficients.reverse() |
30 | 80 | storres | # New empty proto matrix row. |
31 | 80 | storres | protoMatrixRowCoefficients = [] |
32 | 80 | storres | # We work according to the order of the already known monomials |
33 | 80 | storres | # No known monomials yet: add the pMonomials to knownMonomials |
34 | 80 | storres | # and add the coefficients to the proto matrix row. |
35 | 80 | storres | if len(knownMonomials) == 0: |
36 | 80 | storres | for pmIdx in xrange(0, len(pMonomials)): |
37 | 80 | storres | knownMonomials.append(pMonomials[pmIdx]) |
38 | 80 | storres | protoMatrixRowCoefficients.append(pCoefficients[pmIdx]) |
39 | 80 | storres | if columnsWidth != 0: |
40 | 80 | storres | monomialAsString = str(pCoefficients[pmIdx]) + " " + \ |
41 | 80 | storres | str(pMonomials[pmIdx]) |
42 | 80 | storres | print monomialAsString, " " * \ |
43 | 80 | storres | (columnsWidth - len(monomialAsString)), |
44 | 80 | storres | # There are some known monomials. We search for them in pMonomials and |
45 | 80 | storres | # add their coefficients to the proto matrix row. |
46 | 80 | storres | else: |
47 | 80 | storres | for knownMonomialIndex in xrange(0,len(knownMonomials)): |
48 | 80 | storres | # We lazily use an exception here since pMonomials.index() function |
49 | 80 | storres | # may fail throwing the ValueError exception. |
50 | 80 | storres | try: |
51 | 80 | storres | indexInPmonomials = \ |
52 | 80 | storres | pMonomials.index(knownMonomials[knownMonomialIndex]) |
53 | 80 | storres | if columnsWidth != 0: |
54 | 80 | storres | monomialAsString = str(pCoefficients[indexInPmonomials]) + \ |
55 | 80 | storres | " " + str(knownMonomials[knownMonomialIndex]) |
56 | 80 | storres | print monomialAsString, " " * \ |
57 | 80 | storres | (columnsWidth - len(monomialAsString)), |
58 | 80 | storres | # Add the coefficient to the proto matrix row and delete the \ |
59 | 80 | storres | # known monomial from the current pMonomial list |
60 | 80 | storres | #(and the corresponding coefficient as well). |
61 | 80 | storres | protoMatrixRowCoefficients.append(pCoefficients[indexInPmonomials]) |
62 | 80 | storres | del pMonomials[indexInPmonomials] |
63 | 80 | storres | del pCoefficients[indexInPmonomials] |
64 | 80 | storres | # The knownMonomials element is not in pMonomials |
65 | 80 | storres | except ValueError: |
66 | 80 | storres | protoMatrixRowCoefficients.append(0) |
67 | 80 | storres | if columnsWidth != 0: |
68 | 80 | storres | monomialAsString = "0" + " "+ \ |
69 | 80 | storres | str(knownMonomials[knownMonomialIndex]) |
70 | 80 | storres | print monomialAsString, " " * \ |
71 | 80 | storres | (columnsWidth - len(monomialAsString)), |
72 | 80 | storres | # End for knownMonomialKey loop. |
73 | 80 | storres | # We now append the remaining monomials of pMonomials to knownMonomials |
74 | 80 | storres | # and the corresponding coefficients to proto matrix row. |
75 | 80 | storres | for pmIdx in xrange(0, len(pMonomials)): |
76 | 80 | storres | knownMonomials.append(pMonomials[pmIdx]) |
77 | 80 | storres | protoMatrixRowCoefficients.append(pCoefficients[pmIdx]) |
78 | 80 | storres | if columnsWidth != 0: |
79 | 80 | storres | monomialAsString = str(pCoefficients[pmIdx]) + " " \ |
80 | 80 | storres | + str(pMonomials[pmIdx]) |
81 | 80 | storres | print monomialAsString, " " * \ |
82 | 80 | storres | (columnsWidth - len(monomialAsString)), |
83 | 80 | storres | # End for pmIdx loop. |
84 | 80 | storres | # Add the new list row elements to the proto matrix. |
85 | 80 | storres | protoMatrixRows.append(protoMatrixRowCoefficients) |
86 | 80 | storres | if columnsWidth != 0: |
87 | 80 | storres | |
88 | 83 | storres | # End spo_add_polynomial_coeffs_to_matrix_row |
89 | 80 | storres | |
90 | 109 | storres | def spo_get_coefficient_for_monomial(monomialsList, coefficientsList, monomial): |
91 | 109 | storres | """ |
92 | 109 | storres | Get, for a polynomial, the coefficient for a given monomial. |
93 | 109 | storres | The polynomial is given as two lists (monomials and coefficients as |
94 | 109 | storres | return by the respective methods ; indexes of the two lists must match). |
95 | 109 | storres | If the monomial is not found, 0 is returned. |
96 | 109 | storres | """ |
97 | 109 | storres | monomialIndex = 0 |
98 | 109 | storres | for mono in monomialsList: |
99 | 109 | storres | if mono == monomial: |
100 | 109 | storres | return coefficientsList[monomialIndex] |
101 | 109 | storres | monomialIndex += 1 |
102 | 109 | storres | return 0 |
103 | 109 | storres | # End spo_get_coefficient_for_monomial. |
104 | 109 | storres | |
105 | 109 | storres | |
106 | 105 | storres | def spo_expression_as_string(powI, powT, powP, powN): |
107 | 80 | storres | """ |
108 | 80 | storres | Computes a string version of the i^k + t^l + p^m + N^n expression for |
109 | 80 | storres | output. |
110 | 80 | storres | """ |
111 | 80 | storres | expressionAsString ="" |
112 | 80 | storres | if powI != 0: |
113 | 80 | storres | expressionAsString += "i^" + str(powI) |
114 | 80 | storres | if powT != 0: |
115 | 80 | storres | if len(expressionAsString) != 0: |
116 | 80 | storres | expressionAsString += " * " |
117 | 80 | storres | expressionAsString += "t^" + str(powT) |
118 | 80 | storres | if powP != 0: |
119 | 80 | storres | if len(expressionAsString) != 0: |
120 | 80 | storres | expressionAsString += " * " |
121 | 80 | storres | expressionAsString += "p^" + str(powP) |
122 | 105 | storres | if (powN) != 0 : |
123 | 80 | storres | if len(expressionAsString) != 0: |
124 | 80 | storres | expressionAsString += " * " |
125 | 105 | storres | expressionAsString += "N^" + str(powN) |
126 | 80 | storres | return(expressionAsString) |
127 | 80 | storres | # End spo_expression_as_string. |
128 | 80 | storres | |
129 | 87 | storres | def spo_norm(poly, p=2): |
130 | 81 | storres | """ |
131 | 81 | storres | Behaves more or less (no infinity defined) as the norm for the |
132 | 81 | storres | univariate polynomials. |
133 | 107 | storres | Quoting Sage documentation: |
134 | 107 | storres | "Definition: For integer p, the p-norm of a polynomial is the pth root of |
135 | 81 | storres | the sum of the pth powers of the absolute values of the coefficients of |
136 | 107 | storres | the polynomial." |
137 | 87 | storres | |
138 | 81 | storres | """ |
139 | 87 | storres | # TODO: check the arguments (for p see below).. |
140 | 81 | storres | norm = 0 |
141 | 87 | storres | # For infinity norm. |
142 | 87 | storres | if p == Infinity: |
143 | 87 | storres | for coefficient in poly.coefficients(): |
144 | 87 | storres | coefficientAbs = coefficient.abs() |
145 | 87 | storres | if coefficientAbs > norm: |
146 | 87 | storres | norm = coefficientAbs |
147 | 87 | storres | return norm |
148 | 87 | storres | # TODO: check here the value of p |
149 | 107 | storres | # p must be a positive integer >= 1. |
150 | 107 | storres | if p < 1 or (not p in ZZ): |
151 | 94 | storres | return None |
152 | 87 | storres | # For 1 norm. |
153 | 87 | storres | if p == 1: |
154 | 87 | storres | for coefficient in poly.coefficients(): |
155 | 87 | storres | norm += coefficient.abs() |
156 | 87 | storres | return norm |
157 | 87 | storres | # For other norms |
158 | 81 | storres | for coefficient in poly.coefficients(): |
159 | 103 | storres | norm += coefficient.abs()^p |
160 | 87 | storres | return pow(norm, 1/p) |
161 | 81 | storres | # end spo_norm |
162 | 81 | storres | |
163 | 100 | storres | def spo_polynomial_to_proto_matrix(p, alpha, N, columnsWidth=0): |
164 | 74 | storres | """ |
165 | 83 | storres | From a (bivariate) polynomial and some other parameters build a proto |
166 | 87 | storres | matrix (an array of "rows") to be converted into a "true" matrix and |
167 | 83 | storres | eventually by reduced by fpLLL. |
168 | 102 | storres | The matrix is such as those found in Boneh-Durphee and Stehlé. |
169 | 74 | storres | |
170 | 83 | storres | Parameters |
171 | 83 | storres | ---------- |
172 | 87 | storres | p: the (bivariate) polynomial; |
173 | 87 | storres | pRing: the ring over which p is defined; |
174 | 74 | storres | alpha: |
175 | 74 | storres | N: |
176 | 83 | storres | columsWidth: if == 0, no information is displayed, otherwise data is |
177 | 83 | storres | printed in colums of columnsWitdth width. |
178 | 74 | storres | """ |
179 | 100 | storres | pRing = p.parent() |
180 | 77 | storres | knownMonomials = [] |
181 | 77 | storres | protoMatrixRows = [] |
182 | 92 | storres | polynomialsList = [] |
183 | 74 | storres | pVariables = p.variables() |
184 | 74 | storres | iVariable = pVariables[0] |
185 | 76 | storres | tVariable = pVariables[1] |
186 | 87 | storres | polynomialAtPower = pRing(1) |
187 | 87 | storres | currentPolynomial = pRing(1) |
188 | 74 | storres | pIdegree = p.degree(pVariables[0]) |
189 | 74 | storres | pTdegree = p.degree(pVariables[1]) |
190 | 87 | storres | currentIdegree = currentPolynomial.degree(iVariable) |
191 | 105 | storres | nAtAlpha = N^alpha |
192 | 105 | storres | nAtPower = nAtAlpha |
193 | 92 | storres | polExpStr = "" |
194 | 74 | storres | # We work from p^0 * N^alpha to p^alpha * N^0 |
195 | 74 | storres | for pPower in xrange(0, alpha + 1): |
196 | 76 | storres | # pPower == 0 is a special case. We introduce all the monomials but one |
197 | 78 | storres | # in i and those in t necessary to be able to introduce |
198 | 76 | storres | # p. We arbitrary choose to introduce the highest degree monomial in i |
199 | 76 | storres | # with p. We also introduce all the mixed i^k * t^l monomials with |
200 | 77 | storres | # k < p.degree(i) and l <= p.degree(t). |
201 | 78 | storres | # Mixed terms introduction is necessary here before we start "i shifts" |
202 | 78 | storres | # in the next iteration. |
203 | 74 | storres | if pPower == 0: |
204 | 78 | storres | # Notice that i^pIdegree is excluded as the bound of the xrange is |
205 | 78 | storres | # pIdegree |
206 | 74 | storres | for iPower in xrange(0, pIdegree): |
207 | 74 | storres | for tPower in xrange(0, pTdegree + 1): |
208 | 77 | storres | if columnsWidth != 0: |
209 | 92 | storres | polExpStr = spo_expression_as_string(iPower, |
210 | 76 | storres | tPower, |
211 | 76 | storres | pPower, |
212 | 105 | storres | alpha-pPower) |
213 | 92 | storres | print "->", polExpStr |
214 | 74 | storres | currentExpression = iVariable^iPower * \ |
215 | 91 | storres | tVariable^tPower * nAtAlpha |
216 | 78 | storres | # polynomialAtPower == 1 here. Next line should be commented |
217 | 78 | storres | # out but it does not work! Some conversion problem? |
218 | 91 | storres | currentPolynomial = pRing(currentExpression) |
219 | 106 | storres | polynomialsList.append(currentPolynomial) |
220 | 74 | storres | pMonomials = currentPolynomial.monomials() |
221 | 74 | storres | pCoefficients = currentPolynomial.coefficients() |
222 | 83 | storres | spo_add_polynomial_coeffs_to_matrix_row(pMonomials, |
223 | 83 | storres | pCoefficients, |
224 | 83 | storres | knownMonomials, |
225 | 83 | storres | protoMatrixRows, |
226 | 83 | storres | columnsWidth) |
227 | 78 | storres | # End tPower. |
228 | 78 | storres | # End for iPower. |
229 | 77 | storres | else: # pPower > 0: (p^1..p^alpha) |
230 | 78 | storres | # This where we introduce the p^pPower * N^(alpha-pPower) |
231 | 77 | storres | # polynomial. |
232 | 77 | storres | # This step could technically be fused as the first iteration |
233 | 77 | storres | # of the next loop (with iPower starting at 0). |
234 | 77 | storres | # We set it apart for clarity. |
235 | 77 | storres | if columnsWidth != 0: |
236 | 105 | storres | polExpStr = spo_expression_as_string(0, 0, pPower, alpha-pPower) |
237 | 92 | storres | print "->", polExpStr |
238 | 77 | storres | currentPolynomial = polynomialAtPower * nAtPower |
239 | 106 | storres | polynomialsList.append(currentPolynomial) |
240 | 77 | storres | pMonomials = currentPolynomial.monomials() |
241 | 77 | storres | pCoefficients = currentPolynomial.coefficients() |
242 | 83 | storres | spo_add_polynomial_coeffs_to_matrix_row(pMonomials, |
243 | 83 | storres | pCoefficients, |
244 | 83 | storres | knownMonomials, |
245 | 83 | storres | protoMatrixRows, |
246 | 83 | storres | columnsWidth) |
247 | 77 | storres | |
248 | 77 | storres | # The i^iPower * p^pPower polynomials: they add i^k monomials to |
249 | 77 | storres | # p^pPower up to k < pIdegree * pPower. This only introduces i^k |
250 | 77 | storres | # monomials since mixed terms (that were introduced at a previous |
251 | 77 | storres | # stage) are only shifted to already existing |
252 | 77 | storres | # ones. p^pPower is "shifted" to higher degrees in i as far as |
253 | 77 | storres | # possible, one step short of the degree in i of p^(pPower+1) . |
254 | 77 | storres | # These "pure" i^k monomials can only show up with i multiplications. |
255 | 77 | storres | for iPower in xrange(1, pIdegree): |
256 | 87 | storres | if columnsWidth != 0: |
257 | 92 | storres | polExpStr = spo_expression_as_string(iPower, \ |
258 | 87 | storres | 0, \ |
259 | 87 | storres | pPower, \ |
260 | 87 | storres | alpha) |
261 | 92 | storres | print "->", polExpStr |
262 | 77 | storres | currentExpression = i^iPower * nAtPower |
263 | 87 | storres | currentPolynomial = pRing(currentExpression) * polynomialAtPower |
264 | 106 | storres | polynomialsList.append(currentPolynomial) |
265 | 77 | storres | pMonomials = currentPolynomial.monomials() |
266 | 77 | storres | pCoefficients = currentPolynomial.coefficients() |
267 | 87 | storres | spo_add_polynomial_coeffs_to_matrix_row(pMonomials, \ |
268 | 87 | storres | pCoefficients, \ |
269 | 87 | storres | knownMonomials, \ |
270 | 87 | storres | protoMatrixRows, \ |
271 | 83 | storres | columnsWidth) |
272 | 77 | storres | # End for iPower |
273 | 77 | storres | # We want now to introduce a t * p^pPower polynomial. But before |
274 | 77 | storres | # that we must introduce some mixed monomials. |
275 | 77 | storres | # This loop is no triggered before pPower == 2. |
276 | 78 | storres | # It introduces a first set of high i degree mixed monomials. |
277 | 77 | storres | for iPower in xrange(1, pPower): |
278 | 77 | storres | tPower = pPower - iPower + 1 |
279 | 77 | storres | if columnsWidth != 0: |
280 | 92 | storres | polExpStr = spo_expression_as_string(iPower * pIdegree, |
281 | 77 | storres | tPower, |
282 | 77 | storres | 0, |
283 | 77 | storres | alpha) |
284 | 92 | storres | print "->", polExpStr |
285 | 91 | storres | currentExpression = i^(iPower * pIdegree) * t^tPower * nAtAlpha |
286 | 87 | storres | currentPolynomial = pRing(currentExpression) |
287 | 106 | storres | polynomialsList.append(currentPolynomial) |
288 | 77 | storres | pMonomials = currentPolynomial.monomials() |
289 | 77 | storres | pCoefficients = currentPolynomial.coefficients() |
290 | 83 | storres | spo_add_polynomial_coeffs_to_matrix_row(pMonomials, |
291 | 83 | storres | pCoefficients, |
292 | 83 | storres | knownMonomials, |
293 | 83 | storres | protoMatrixRows, |
294 | 83 | storres | columnsWidth) |
295 | 77 | storres | # End for iPower |
296 | 78 | storres | # |
297 | 78 | storres | # This is the mixed monomials main loop. It introduces: |
298 | 77 | storres | # - the missing mixed monomials needed before the |
299 | 78 | storres | # t^l * p^pPower * N^(alpha-pPower) polynomial; |
300 | 78 | storres | # - the t^l * p^pPower * N^(alpha-pPower) itself; |
301 | 78 | storres | # - for each of i^k * t^l * p^pPower * N^(alpha-pPower) polynomials: |
302 | 78 | storres | # - the the missing mixed monomials needed polynomials, |
303 | 78 | storres | # - the i^k * t^l * p^pPower * N^(alpha-pPower) itself. |
304 | 78 | storres | # The t^l * p^pPower * N^(alpha-pPower) is introduced when |
305 | 78 | storres | # |
306 | 77 | storres | for iShift in xrange(0, pIdegree): |
307 | 77 | storres | # When pTdegree == 1, the following loop only introduces |
308 | 77 | storres | # a single new monomial. |
309 | 77 | storres | #print "++++++++++" |
310 | 77 | storres | for outerTpower in xrange(1, pTdegree + 1): |
311 | 77 | storres | # First one high i degree mixed monomial. |
312 | 77 | storres | iPower = iShift + pPower * pIdegree |
313 | 77 | storres | if columnsWidth != 0: |
314 | 92 | storres | polExpStr = spo_expression_as_string(iPower, |
315 | 77 | storres | outerTpower, |
316 | 77 | storres | 0, |
317 | 77 | storres | alpha) |
318 | 92 | storres | print "->", polExpStr |
319 | 91 | storres | currentExpression = i^iPower * t^outerTpower * nAtAlpha |
320 | 87 | storres | currentPolynomial = pRing(currentExpression) |
321 | 106 | storres | polynomialsList.append(currentPolynomial) |
322 | 77 | storres | pMonomials = currentPolynomial.monomials() |
323 | 77 | storres | pCoefficients = currentPolynomial.coefficients() |
324 | 83 | storres | spo_add_polynomial_coeffs_to_matrix_row(pMonomials, |
325 | 83 | storres | pCoefficients, |
326 | 83 | storres | knownMonomials, |
327 | 83 | storres | protoMatrixRows, |
328 | 83 | storres | columnsWidth) |
329 | 77 | storres | #print "+++++" |
330 | 78 | storres | # At iShift == 0, the following innerTpower loop adds |
331 | 78 | storres | # duplicate monomials, since no extra i^l * t^k is needed |
332 | 78 | storres | # before introducing the |
333 | 77 | storres | # i^iShift * t^outerPpower * p^pPower * N^(alpha-pPower) |
334 | 77 | storres | # polynomial. |
335 | 77 | storres | # It introduces smaller i degree monomials than the |
336 | 77 | storres | # one(s) added previously (no pPower multiplication). |
337 | 77 | storres | # Here the exponent of t decreases as that of i increases. |
338 | 78 | storres | # This conditional is not entered before pPower == 1. |
339 | 78 | storres | # The innerTpower loop does not produce anything before |
340 | 78 | storres | # pPower == 2. We keep it anyway for other configuration of |
341 | 78 | storres | # p. |
342 | 77 | storres | if iShift > 0: |
343 | 77 | storres | iPower = pIdegree + iShift |
344 | 77 | storres | for innerTpower in xrange(pPower, 1, -1): |
345 | 77 | storres | if columnsWidth != 0: |
346 | 92 | storres | polExpStr = spo_expression_as_string(iPower, |
347 | 77 | storres | innerTpower, |
348 | 77 | storres | 0, |
349 | 77 | storres | alpha) |
350 | 77 | storres | currentExpression = \ |
351 | 91 | storres | i^(iPower) * t^(innerTpower) * nAtAlpha |
352 | 87 | storres | currentPolynomial = pRing(currentExpression) |
353 | 106 | storres | polynomialsList.append(currentPolynomial) |
354 | 77 | storres | pMonomials = currentPolynomial.monomials() |
355 | 77 | storres | pCoefficients = currentPolynomial.coefficients() |
356 | 83 | storres | spo_add_polynomial_coeffs_to_matrix_row(pMonomials, |
357 | 77 | storres | pCoefficients, |
358 | 77 | storres | knownMonomials, |
359 | 77 | storres | protoMatrixRows, |
360 | 77 | storres | columnsWidth) |
361 | 77 | storres | iPower += pIdegree |
362 | 77 | storres | # End for innerTpower |
363 | 77 | storres | # End of if iShift > 0 |
364 | 78 | storres | # When iShift == 0, just after each of the |
365 | 78 | storres | # p^pPower * N^(alpha-pPower) polynomials has |
366 | 78 | storres | # been introduced (followed by a string of |
367 | 78 | storres | # i^k * p^pPower * N^(alpha-pPower) polynomials) a |
368 | 78 | storres | # t^l * p^pPower * N^(alpha-pPower) is introduced here. |
369 | 78 | storres | # |
370 | 77 | storres | # Eventually, the following section introduces the |
371 | 105 | storres | # i^iShift * t^outerTpower * p^iPower * N^(alpha-pPower) |
372 | 77 | storres | # polynomials. |
373 | 77 | storres | if columnsWidth != 0: |
374 | 92 | storres | polExpStr = spo_expression_as_string(iShift, |
375 | 77 | storres | outerTpower, |
376 | 77 | storres | pPower, |
377 | 105 | storres | alpha-pPower) |
378 | 92 | storres | print "->", polExpStr |
379 | 77 | storres | currentExpression = i^iShift * t^outerTpower * nAtPower |
380 | 105 | storres | currentPolynomial = pRing(currentExpression) * \ |
381 | 105 | storres | polynomialAtPower |
382 | 106 | storres | polynomialsList.append(currentPolynomial) |
383 | 77 | storres | pMonomials = currentPolynomial.monomials() |
384 | 77 | storres | pCoefficients = currentPolynomial.coefficients() |
385 | 83 | storres | spo_add_polynomial_coeffs_to_matrix_row(pMonomials, |
386 | 83 | storres | pCoefficients, |
387 | 83 | storres | knownMonomials, |
388 | 83 | storres | protoMatrixRows, |
389 | 83 | storres | columnsWidth) |
390 | 77 | storres | # End for outerTpower |
391 | 77 | storres | #print "++++++++++" |
392 | 77 | storres | # End for iShift |
393 | 77 | storres | polynomialAtPower *= p |
394 | 77 | storres | nAtPower /= N |
395 | 77 | storres | # End for pPower loop |
396 | 92 | storres | return ((protoMatrixRows, knownMonomials, polynomialsList)) |
397 | 83 | storres | # End spo_polynomial_to_proto_matrix |
398 | 81 | storres | |
399 | 106 | storres | def spo_polynomial_to_polynomials_list_2(p, alpha, N, columnsWidth=0): |
400 | 105 | storres | """ |
401 | 106 | storres | From p, alpha, N build a list of polynomials... |
402 | 106 | storres | TODO: clean up the comments below! |
403 | 106 | storres | |
404 | 105 | storres | From a (bivariate) polynomial and some other parameters build a proto |
405 | 105 | storres | matrix (an array of "rows") to be converted into a "true" matrix and |
406 | 105 | storres | eventually by reduced by fpLLL. |
407 | 105 | storres | The matrix is based on a list of polynomials that are built in a way |
408 | 105 | storres | that one and only monomial is added at each new polynomial. Among the many |
409 | 105 | storres | possible ways to build this list we pick one strongly dependent on the |
410 | 105 | storres | structure of the polynomial and of the problem. |
411 | 105 | storres | We consider here the polynomials of the form: |
412 | 105 | storres | a_k*i^k + a_(k-1)*i^(k-1) + ... + a_1*i + a_0 - t |
413 | 105 | storres | The values of i and t are bounded and we eventually look for (i_0,t_0) |
414 | 105 | storres | pairs such that: |
415 | 105 | storres | a_k*i_0^k + a_(k-1)*i_0^(k-1) + ... + a_1*i_0 + a_0 = t_0 |
416 | 105 | storres | Hence, departing from the procedure in described in Boneh-Durfee, we will |
417 | 105 | storres | not use "t-shifts" but only "i-shifts". |
418 | 105 | storres | |
419 | 105 | storres | Parameters |
420 | 105 | storres | ---------- |
421 | 105 | storres | p: the (bivariate) polynomial; |
422 | 105 | storres | pRing: the ring over which p is defined; |
423 | 105 | storres | alpha: |
424 | 105 | storres | N: |
425 | 105 | storres | columsWidth: if == 0, no information is displayed, otherwise data is |
426 | 105 | storres | printed in colums of columnsWitdth width. |
427 | 105 | storres | """ |
428 | 105 | storres | pRing = p.parent() |
429 | 105 | storres | polynomialsList = [] |
430 | 105 | storres | pVariables = p.variables() |
431 | 105 | storres | iVariable = pVariables[0] |
432 | 105 | storres | tVariable = pVariables[1] |
433 | 105 | storres | polynomialAtPower = pRing(1) |
434 | 105 | storres | currentPolynomial = pRing(1) |
435 | 105 | storres | pIdegree = p.degree(iVariable) |
436 | 105 | storres | pTdegree = p.degree(tVariable) |
437 | 105 | storres | currentIdegree = currentPolynomial.degree(iVariable) |
438 | 105 | storres | nAtAlpha = N^alpha |
439 | 105 | storres | nAtPower = nAtAlpha |
440 | 105 | storres | polExpStr = "" |
441 | 105 | storres | # We work from p^0 * N^alpha to p^alpha * N^0 |
442 | 105 | storres | for pPower in xrange(0, alpha + 1): |
443 | 105 | storres | # pPower == 0 is a special case. We introduce all the monomials in i |
444 | 105 | storres | # up to i^pIdegree. |
445 | 105 | storres | if pPower == 0: |
446 | 105 | storres | # Notice who iPower runs up to i^pIdegree. |
447 | 105 | storres | for iPower in xrange(0, pIdegree + 1): |
448 | 105 | storres | # No t power is taken into account as we limit our selves to |
449 | 105 | storres | # degree 1 in t and make no "t-shifts". |
450 | 105 | storres | if columnsWidth != 0: |
451 | 105 | storres | polExpStr = spo_expression_as_string(iPower, |
452 | 105 | storres | 0, |
453 | 105 | storres | 0, |
454 | 105 | storres | alpha) |
455 | 105 | storres | print "->", polExpStr |
456 | 105 | storres | currentExpression = iVariable^iPower * nAtAlpha |
457 | 105 | storres | # polynomialAtPower == 1 here. Next line should be commented |
458 | 105 | storres | # out but it does not work! Some conversion problem? |
459 | 105 | storres | currentPolynomial = pRing(currentExpression) |
460 | 105 | storres | polynomialsList.append(currentPolynomial) |
461 | 105 | storres | # End for iPower. |
462 | 105 | storres | else: # pPower > 0: (p^1..p^alpha) |
463 | 105 | storres | # This where we introduce the p^pPower * N^(alpha-pPower) |
464 | 105 | storres | # polynomial. This is also where the t^pPower monomials shows up for |
465 | 105 | storres | # the first time. |
466 | 105 | storres | if columnsWidth != 0: |
467 | 105 | storres | polExpStr = spo_expression_as_string(0, 0, pPower, alpha-pPower) |
468 | 105 | storres | print "->", polExpStr |
469 | 105 | storres | currentPolynomial = polynomialAtPower * nAtPower |
470 | 105 | storres | polynomialsList.append(currentPolynomial) |
471 | 106 | storres | # Exit when pPower == alpha |
472 | 106 | storres | if pPower == alpha: |
473 | 106 | storres | return((knownMonomials, polynomialsList)) |
474 | 105 | storres | # This is where the "i-shifts" take place. Mixed terms, i^k * t^l |
475 | 105 | storres | # (that were introduced at a previous |
476 | 105 | storres | # stage or are introduced now) are only shifted to already existing |
477 | 105 | storres | # ones with the notable exception of i^iPower * t^pPower, which |
478 | 105 | storres | # must be manually introduced. |
479 | 105 | storres | # p^pPower is "shifted" to higher degrees in i as far as |
480 | 105 | storres | # possible, up to of the degree in i of p^(pPower+1). |
481 | 105 | storres | # These "pure" i^k monomials can only show up with i multiplications. |
482 | 105 | storres | for iPower in xrange(1, pIdegree + 1): |
483 | 105 | storres | # The i^iPower * t^pPower monomial. Notice the alpha exponent |
484 | 105 | storres | # for N. |
485 | 105 | storres | internalIpower = iPower |
486 | 105 | storres | for tPower in xrange(pPower,0,-1): |
487 | 105 | storres | if columnsWidth != 0: |
488 | 105 | storres | polExpStr = spo_expression_as_string(internalIpower, \ |
489 | 105 | storres | tPower, \ |
490 | 105 | storres | 0, \ |
491 | 105 | storres | alpha) |
492 | 105 | storres | print "->", polExpStr |
493 | 105 | storres | currentExpression = i^internalIpower * t^tPower * nAtAlpha |
494 | 105 | storres | currentPolynomial = pRing(currentExpression) |
495 | 105 | storres | polynomialsList.append(currentPolynomial) |
496 | 105 | storres | internalIpower += pIdegree |
497 | 105 | storres | # End for tPower |
498 | 105 | storres | # The i^iPower * p^pPower * N^(alpha-pPower) i-shift. |
499 | 105 | storres | if columnsWidth != 0: |
500 | 105 | storres | polExpStr = spo_expression_as_string(iPower, \ |
501 | 105 | storres | 0, \ |
502 | 105 | storres | pPower, \ |
503 | 105 | storres | alpha-pPower) |
504 | 105 | storres | print "->", polExpStr |
505 | 105 | storres | currentExpression = i^iPower * nAtPower |
506 | 105 | storres | currentPolynomial = pRing(currentExpression) * polynomialAtPower |
507 | 105 | storres | polynomialsList.append(currentPolynomial) |
508 | 105 | storres | # End for iPower |
509 | 105 | storres | polynomialAtPower *= p |
510 | 105 | storres | nAtPower /= N |
511 | 105 | storres | # End for pPower loop |
512 | 109 | storres | return polynomialsList |
513 | 105 | storres | # End spo_polynomial_to_proto_matrix_2 |
514 | 105 | storres | |
515 | 109 | storres | def spo_polynomial_to_polynomials_list_3(p, alpha, N, iBound, tBound, \ |
516 | 109 | storres | columnsWidth=0): |
517 | 108 | storres | """ |
518 | 108 | storres | From p, alpha, N build a list of polynomials... |
519 | 108 | storres | TODO: more in depth rationale... |
520 | 108 | storres | |
521 | 108 | storres | Our goal is to introduce each monomial with the smallest coefficient. |
522 | 108 | storres | |
523 | 108 | storres | |
524 | 108 | storres | |
525 | 108 | storres | Parameters |
526 | 108 | storres | ---------- |
527 | 108 | storres | p: the (bivariate) polynomial; |
528 | 108 | storres | pRing: the ring over which p is defined; |
529 | 108 | storres | alpha: |
530 | 108 | storres | N: |
531 | 108 | storres | columsWidth: if == 0, no information is displayed, otherwise data is |
532 | 108 | storres | printed in colums of columnsWitdth width. |
533 | 108 | storres | """ |
534 | 108 | storres | pRing = p.parent() |
535 | 108 | storres | knownMonomials = [] |
536 | 108 | storres | polynomialsList = [] |
537 | 108 | storres | pVariables = p.variables() |
538 | 108 | storres | iVariable = pVariables[0] |
539 | 108 | storres | tVariable = pVariables[1] |
540 | 108 | storres | polynomialAtPower = pRing(1) |
541 | 108 | storres | currentPolynomial = pRing(1) |
542 | 108 | storres | pIdegree = p.degree(iVariable) |
543 | 108 | storres | pTdegree = p.degree(tVariable) |
544 | 108 | storres | currentIdegree = currentPolynomial.degree(iVariable) |
545 | 108 | storres | nAtAlpha = N^alpha |
546 | 108 | storres | nAtPower = nAtAlpha |
547 | 108 | storres | polExpStr = "" |
548 | 108 | storres | # We work from p^0 * N^alpha to p^alpha * N^0 |
549 | 108 | storres | for pPower in xrange(0, alpha + 1): |
550 | 108 | storres | # pPower == 0 is a special case. We introduce all the monomials in i |
551 | 108 | storres | # up to i^pIdegree. |
552 | 108 | storres | if pPower == 0: |
553 | 108 | storres | # Notice who iPower runs up to i^pIdegree. |
554 | 108 | storres | for iPower in xrange(0, pIdegree + 1): |
555 | 108 | storres | # No t power is taken into account as we limit our selves to |
556 | 108 | storres | # degree 1 in t and make no "t-shifts". |
557 | 108 | storres | if columnsWidth != 0: |
558 | 108 | storres | polExpStr = spo_expression_as_string(iPower, |
559 | 108 | storres | 0, |
560 | 108 | storres | 0, |
561 | 108 | storres | alpha) |
562 | 108 | storres | print "->", polExpStr |
563 | 108 | storres | currentExpression = iVariable^iPower * nAtAlpha |
564 | 108 | storres | # polynomialAtPower == 1 here. Next line should be commented |
565 | 108 | storres | # out but it does not work! Some conversion problem? |
566 | 108 | storres | currentPolynomial = pRing(currentExpression) |
567 | 108 | storres | polynomialsList.append(currentPolynomial) |
568 | 108 | storres | # End for iPower. |
569 | 108 | storres | else: # pPower > 0: (p^1..p^alpha) |
570 | 108 | storres | # This where we introduce the p^pPower * N^(alpha-pPower) |
571 | 108 | storres | # polynomial. This is also where the t^pPower monomials shows up for |
572 | 108 | storres | # the first time. It app |
573 | 108 | storres | if columnsWidth != 0: |
574 | 108 | storres | polExpStr = spo_expression_as_string(0, 0, pPower, alpha-pPower) |
575 | 108 | storres | print "->", polExpStr |
576 | 108 | storres | currentPolynomial = polynomialAtPower * nAtPower |
577 | 108 | storres | polynomialsList.append(currentPolynomial) |
578 | 108 | storres | # Exit when pPower == alpha |
579 | 108 | storres | if pPower == alpha: |
580 | 108 | storres | return((knownMonomials, polynomialsList)) |
581 | 108 | storres | # This is where the "i-shifts" take place. Mixed terms, i^k * t^l |
582 | 108 | storres | # (that were introduced at a previous |
583 | 108 | storres | # stage or are introduced now) are only shifted to already existing |
584 | 108 | storres | # ones with the notable exception of i^iPower * t^pPower, which |
585 | 108 | storres | # must be manually introduced. |
586 | 108 | storres | # p^pPower is "shifted" to higher degrees in i as far as |
587 | 108 | storres | # possible, up to of the degree in i of p^(pPower+1). |
588 | 108 | storres | # These "pure" i^k monomials can only show up with i multiplications. |
589 | 108 | storres | for iPower in xrange(1, pIdegree + 1): |
590 | 108 | storres | # The i^iPower * t^pPower monomial. Notice the alpha exponent |
591 | 108 | storres | # for N. |
592 | 108 | storres | internalIpower = iPower |
593 | 108 | storres | for tPower in xrange(pPower,0,-1): |
594 | 108 | storres | if columnsWidth != 0: |
595 | 108 | storres | polExpStr = spo_expression_as_string(internalIpower, \ |
596 | 108 | storres | tPower, \ |
597 | 108 | storres | 0, \ |
598 | 108 | storres | alpha) |
599 | 108 | storres | print "->", polExpStr |
600 | 108 | storres | currentExpression = i^internalIpower * t^tPower * nAtAlpha |
601 | 108 | storres | currentPolynomial = pRing(currentExpression) |
602 | 108 | storres | polynomialsList.append(currentPolynomial) |
603 | 108 | storres | internalIpower += pIdegree |
604 | 108 | storres | # End for tPower |
605 | 109 | storres | # Here we have to choose between a |
606 | 109 | storres | # i^iPower * p^pPower * N^(alpha-pPower) i-shift and |
607 | 109 | storres | # i^iPower * i^(d_i(p) * pPower) * N^alpha, depend on which |
608 | 109 | storres | # coefficient is smallest. |
609 | 109 | storres | IcurrentExponent = iPower + \ |
610 | 109 | storres | (pPower * polynomialAtPower.degree(i)) |
611 | 109 | storres | currentMonomial = pRing(i^(IcurrentExponent)) |
612 | 109 | storres | currentPolynomial = pRing(i^iPower * nAtPower) * \ |
613 | 109 | storres | polynomialAtPower |
614 | 109 | storres | currMonomials = currentPolynomial.monomials() |
615 | 109 | storres | currCoefficients = currentPolynomial.coefficients() |
616 | 109 | storres | currentCoefficient = spo_get_coefficient_for_monomial( \ |
617 | 109 | storres | currMonomials, |
618 | 109 | storres | currCoefficients, |
619 | 109 | storres | currentMonomial) |
620 | 109 | storres | if currentCoefficient > nAtAlpha: |
621 | 109 | storres | if columnsWidth != 0: |
622 | 109 | storres | polExpStr = spo_expression_as_string(IcurrentCoefficient, \ |
623 | 109 | storres | 0, \ |
624 | 109 | storres | 0, \ |
625 | 109 | storres | alpha) |
626 | 108 | storres | print "->", polExpStr |
627 | 109 | storres | polynomialsList.append(currentMonomial * nAtAlpha) |
628 | 109 | storres | else: |
629 | 109 | storres | if columnsWidth != 0: |
630 | 109 | storres | polExpStr = spo_expression_as_string(iPower, \ |
631 | 109 | storres | 0, \ |
632 | 109 | storres | pPower, \ |
633 | 109 | storres | alpha-pPower) |
634 | 109 | storres | print "->", polExpStr |
635 | 109 | storres | polynomialsList.append(currentPolynomial) |
636 | 108 | storres | # End for iPower |
637 | 108 | storres | polynomialAtPower *= p |
638 | 108 | storres | nAtPower /= N |
639 | 108 | storres | # End for pPower loop |
640 | 109 | storres | return polynomialsList |
641 | 108 | storres | # End spo_polynomial_to_proto_matrix_3 |
642 | 108 | storres | |
643 | 90 | storres | def spo_proto_to_column_matrix(protoMatrixColumns, \ |
644 | 90 | storres | knownMonomialsList, \ |
645 | 90 | storres | boundVar1, \ |
646 | 90 | storres | boundVar2): |
647 | 83 | storres | """ |
648 | 87 | storres | Create a column (each row holds the coefficients of one monomial) matrix. |
649 | 83 | storres | |
650 | 83 | storres | Parameters |
651 | 83 | storres | ---------- |
652 | 87 | storres | protoMatrixColumns: a list of coefficient lists. |
653 | 83 | storres | """ |
654 | 87 | storres | numColumns = len(protoMatrixColumns) |
655 | 87 | storres | if numColumns == 0: |
656 | 83 | storres | return None |
657 | 87 | storres | # The last column holds has the maximum length. |
658 | 87 | storres | numRows = len(protoMatrixColumns[numColumns-1]) |
659 | 83 | storres | if numColumns == 0: |
660 | 83 | storres | return None |
661 | 83 | storres | baseMatrix = matrix(ZZ, numRows, numColumns) |
662 | 87 | storres | for colIndex in xrange(0, numColumns): |
663 | 87 | storres | for rowIndex in xrange(0, len(protoMatrixColumns[colIndex])): |
664 | 90 | storres | if protoMatrixColumns[colIndex][rowIndex] != 0: |
665 | 90 | storres | baseMatrix[rowIndex, colIndex] = \ |
666 | 90 | storres | protoMatrixColumns[colIndex][rowIndex] * \ |
667 | 90 | storres | knownMonomialsList[rowIndex](boundVar1, boundVar2) |
668 | 83 | storres | return baseMatrix |
669 | 83 | storres | # End spo_proto_to_column_matrix. |
670 | 83 | storres | # |
671 | 88 | storres | def spo_proto_to_row_matrix(protoMatrixRows, \ |
672 | 88 | storres | knownMonomialsList, \ |
673 | 88 | storres | boundVar1, \ |
674 | 88 | storres | boundVar2): |
675 | 83 | storres | """ |
676 | 90 | storres | Create a row (each column holds the evaluation one monomial at boundVar1 and |
677 | 90 | storres | boundVar2 values) matrix. |
678 | 83 | storres | |
679 | 83 | storres | Parameters |
680 | 83 | storres | ---------- |
681 | 83 | storres | protoMatrixRows: a list of coefficient lists. |
682 | 83 | storres | """ |
683 | 83 | storres | numRows = len(protoMatrixRows) |
684 | 83 | storres | if numRows == 0: |
685 | 83 | storres | return None |
686 | 91 | storres | # The last row is the longest one. |
687 | 83 | storres | numColumns = len(protoMatrixRows[numRows-1]) |
688 | 83 | storres | if numColumns == 0: |
689 | 83 | storres | return None |
690 | 83 | storres | baseMatrix = matrix(ZZ, numRows, numColumns) |
691 | 83 | storres | for rowIndex in xrange(0, numRows): |
692 | 83 | storres | for colIndex in xrange(0, len(protoMatrixRows[rowIndex])): |
693 | 89 | storres | if protoMatrixRows[rowIndex][colIndex] != 0: |
694 | 89 | storres | baseMatrix[rowIndex, colIndex] = \ |
695 | 89 | storres | protoMatrixRows[rowIndex][colIndex] * \ |
696 | 89 | storres | knownMonomialsList[colIndex](boundVar1,boundVar2) |
697 | 89 | storres | #print rowIndex, colIndex, |
698 | 89 | storres | #print protoMatrixRows[rowIndex][colIndex], |
699 | 89 | storres | #print knownMonomialsList[colIndex](boundVar1,boundVar2) |
700 | 83 | storres | return baseMatrix |
701 | 83 | storres | # End spo_proto_to_row_matrix. |
702 | 83 | storres | # |
703 | 87 | storres | print "\t...sagePolynomialOperations loaded" |