Statistiques
| Révision :

root / pobysoPythonSage / src / sageSLZ / sagePolynomialOperations.sage @ 87

Historique | Voir | Annoter | Télécharger (20,31 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
        print    
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
    # For 1 norm.
131
    if p == 1:
132
        for coefficient in poly.coefficients():
133
            norm +=  coefficient.abs()
134
        return norm
135
    # For other norms
136
    for coefficient in poly.coefficients():
137
        norm +=  (coefficient^p).abs()
138
    return pow(norm, 1/p)
139
# end spo_norm
140

    
141
def spo_polynomial_to_proto_matrix(p, pRing, alpha, N, columnsWidth=0):
142
    """
143
    From a (bivariate) polynomial and some other parameters build a proto 
144
    matrix (an array of "rows") to be converted into a "true" matrix and 
145
    eventually by reduced by fpLLL.
146
    The matrix is such as those found in Boneh-Durphee and Stehl?.
147
    
148
    Parameters
149
    ----------
150
    p: the (bivariate) polynomial;
151
    pRing: the ring over which p is defined;
152
    alpha:
153
    N:
154
    columsWidth: if == 0, no information is displayed, otherwise data is 
155
                 printed in colums of columnsWitdth width.
156
    """
157
    knownMonomials = []
158
    protoMatrixRows = []
159
    pVariables = p.variables()
160
    iVariable = pVariables[0]
161
    tVariable = pVariables[1]
162
    polynomialAtPower = pRing(1)
163
    currentPolynomial = pRing(1)
164
    pIdegree = p.degree(pVariables[0])
165
    pTdegree = p.degree(pVariables[1])
166
    currentIdegree = currentPolynomial.degree(iVariable)
167
    nAtPower = N^alpha
168
    # We work from p^0 * N^alpha to p^alpha * N^0
169
    for pPower in xrange(0, alpha + 1):
170
        # pPower == 0 is a special case. We introduce all the monomials but one
171
        # in i and those in t necessary to be able to introduce
172
        # p. We arbitrary choose to introduce the highest degree monomial in i
173
        # with p. We also introduce all the mixed i^k * t^l monomials with
174
        # k < p.degree(i) and l <= p.degree(t).
175
        # Mixed terms introduction is necessary here before we start "i shifts"
176
        # in the next iteration.
177
        if pPower == 0:
178
            # Notice that i^pIdegree is excluded as the bound of the xrange is
179
            # pIdegree
180
            for iPower in xrange(0, pIdegree): 
181
                for tPower in xrange(0, pTdegree + 1):
182
                    if columnsWidth != 0:
183
                        print "->", spo_expression_as_string(iPower, 
184
                                                             tPower, 
185
                                                             pPower, 
186
                                                             alpha)
187
                    currentExpression = iVariable^iPower * \
188
                                        tVariable^tPower * nAtPower
189
                    # polynomialAtPower == 1 here. Next line should be commented
190
                    # out but it does not work! Some conversion problem?
191
                    currentPolynomial = pRing(currentExpression) * \
192
                                        polynomialAtPower 
193
                    pMonomials = currentPolynomial.monomials()
194
                    pCoefficients = currentPolynomial.coefficients()
195
                    spo_add_polynomial_coeffs_to_matrix_row(pMonomials, 
196
                                                            pCoefficients, 
197
                                                            knownMonomials, 
198
                                                            protoMatrixRows, 
199
                                                            columnsWidth)
200
                # End tPower.
201
            # End for iPower.
202
        else: # pPower > 0: (p^1..p^alpha)
203
            # This where we introduce the p^pPower * N^(alpha-pPower)
204
            # polynomial.
205
            # This step could technically be fused as the first iteration
206
            # of the next loop (with iPower starting at 0).
207
            # We set it apart for clarity.
208
            if columnsWidth != 0:
209
                print "->", spo_expression_as_string(0, 0, pPower, alpha)
210
            currentPolynomial = polynomialAtPower * nAtPower
211
            pMonomials = currentPolynomial.monomials()
212
            pCoefficients = currentPolynomial.coefficients()
213
            spo_add_polynomial_coeffs_to_matrix_row(pMonomials, 
214
                                                    pCoefficients, 
215
                                                    knownMonomials, 
216
                                                    protoMatrixRows, 
217
                                                    columnsWidth)
218
            
219
            # The i^iPower * p^pPower polynomials: they add i^k monomials to  
220
            # p^pPower up to k < pIdegree * pPower. This only introduces i^k 
221
            # monomials since mixed terms (that were introduced at a previous
222
            # stage) are only shifted to already existing 
223
            # ones. p^pPower is "shifted" to higher degrees in i as far as 
224
            # possible, one step short of the degree in i of p^(pPower+1) .
225
            # These "pure" i^k monomials can only show up with i multiplications.
226
            for iPower in xrange(1, pIdegree):
227
                if columnsWidth != 0:
228
                    print "->", spo_expression_as_string(iPower, \
229
                                                         0,      \
230
                                                         pPower, \
231
                                                         alpha)
232
                currentExpression = i^iPower * nAtPower
233
                currentPolynomial = pRing(currentExpression) * polynomialAtPower
234
                pMonomials = currentPolynomial.monomials()
235
                pCoefficients = currentPolynomial.coefficients()
236
                spo_add_polynomial_coeffs_to_matrix_row(pMonomials,      \
237
                                                        pCoefficients,   \
238
                                                        knownMonomials,  \
239
                                                        protoMatrixRows, \
240
                                                        columnsWidth)
241
            # End for iPower
242
            # We want now to introduce a t * p^pPower polynomial. But before
243
            # that we must introduce some mixed monomials.
244
            # This loop is no triggered before pPower == 2.
245
            # It introduces a first set of high i degree mixed monomials.
246
            for iPower in xrange(1, pPower):
247
                tPower = pPower - iPower + 1
248
                if columnsWidth != 0:
249
                    print "->", spo_expression_as_string(iPower * pIdegree, 
250
                                                         tPower, 
251
                                                         0,  
252
                                                         alpha)
253
                currentExpression = i^(iPower * pIdegree) * t^tPower * nAtPower
254
                currentPolynomial = pRing(currentExpression)
255
                pMonomials = currentPolynomial.monomials()
256
                pCoefficients = currentPolynomial.coefficients()
257
                spo_add_polynomial_coeffs_to_matrix_row(pMonomials, 
258
                                                        pCoefficients, 
259
                                                        knownMonomials, 
260
                                                        protoMatrixRows, 
261
                                                        columnsWidth)
262
            # End for iPower
263
            #
264
            # This is the mixed monomials main loop. It introduces:
265
            # - the missing mixed monomials needed before the 
266
            #   t^l * p^pPower * N^(alpha-pPower) polynomial;
267
            # - the t^l * p^pPower * N^(alpha-pPower) itself;
268
            # - for each of i^k * t^l * p^pPower * N^(alpha-pPower) polynomials:
269
            #   - the the missing mixed monomials needed  polynomials,
270
            #   - the i^k * t^l * p^pPower * N^(alpha-pPower) itself.
271
            # The t^l * p^pPower * N^(alpha-pPower) is introduced when
272
            # 
273
            for iShift in xrange(0, pIdegree):
274
                # When pTdegree == 1, the following loop only introduces 
275
                # a single new monomial.
276
                #print "++++++++++"
277
                for outerTpower in xrange(1, pTdegree + 1):
278
                    # First one high i degree mixed monomial.
279
                    iPower = iShift + pPower * pIdegree
280
                    if columnsWidth != 0:
281
                        print "->", spo_expression_as_string(iPower, 
282
                                                             outerTpower,
283
                                                             0,
284
                                                             alpha)
285
                    currentExpression = i^iPower * t^outerTpower * nAtPower
286
                    currentPolynomial = pRing(currentExpression)
287
                    pMonomials = currentPolynomial.monomials()
288
                    pCoefficients = currentPolynomial.coefficients()
289
                    spo_add_polynomial_coeffs_to_matrix_row(pMonomials, 
290
                                                            pCoefficients, 
291
                                                            knownMonomials, 
292
                                                            protoMatrixRows, 
293
                                                            columnsWidth)
294
                    #print "+++++"
295
                    # At iShift == 0, the following innerTpower loop adds  
296
                    # duplicate monomials, since no extra i^l * t^k is needed 
297
                    # before introducing the  
298
                    # i^iShift * t^outerPpower * p^pPower * N^(alpha-pPower) 
299
                    # polynomial.
300
                    # It introduces smaller i degree monomials than the
301
                    # one(s) added previously (no pPower multiplication).
302
                    # Here the exponent of t decreases as that of i increases.
303
                    # This conditional is not entered before pPower == 1.
304
                    # The innerTpower loop does not produce anything before
305
                    # pPower == 2. We keep it anyway for other configuration of
306
                    # p.
307
                    if iShift > 0:
308
                        iPower = pIdegree + iShift
309
                        for innerTpower in xrange(pPower, 1, -1):
310
                            if columnsWidth != 0:
311
                                print "->", spo_expression_as_string(iPower, 
312
                                                                     innerTpower,
313
                                                                     0,
314
                                                                     alpha) 
315
                            currentExpression = \
316
                                    i^(iPower) * t^(innerTpower) * nAtPower
317
                            currentPolynomial = pRing(currentExpression)
318
                            pMonomials = currentPolynomial.monomials()
319
                            pCoefficients = currentPolynomial.coefficients()
320
                            spo_add_polynomial_coeffs_to_matrix_row(pMonomials, 
321
                                                                pCoefficients, 
322
                                                                knownMonomials, 
323
                                                                protoMatrixRows, 
324
                                                                columnsWidth)
325
                            iPower += pIdegree
326
                        # End for innerTpower
327
                    # End of if iShift > 0
328
                    # When iShift == 0, just after each of the  
329
                    # p^pPower * N^(alpha-pPower) polynomials has 
330
                    # been introduced (followed by a string of 
331
                    # i^k * p^pPower * N^(alpha-pPower) polynomials) a
332
                    # t^l *  p^pPower * N^(alpha-pPower) is introduced here.
333
                    # 
334
                    # Eventually, the following section introduces the 
335
                    # i^iShift * t^outerTpower * p^iPower * N^(alpha-iPower) 
336
                    # polynomials.
337
                    if columnsWidth != 0:
338
                        print "->", spo_expression_as_string(iShift, 
339
                                                             outerTpower,
340
                                                             pPower,
341
                                                             alpha)
342
                    currentExpression = i^iShift * t^outerTpower * nAtPower
343
                    currentPolynomial = pRing(currentExpression) * polynomialAtPower
344
                    pMonomials = currentPolynomial.monomials()
345
                    pCoefficients = currentPolynomial.coefficients()
346
                    spo_add_polynomial_coeffs_to_matrix_row(pMonomials, 
347
                                                            pCoefficients, 
348
                                                            knownMonomials, 
349
                                                            protoMatrixRows, 
350
                                                            columnsWidth)
351
                # End for outerTpower 
352
                #print "++++++++++"
353
            # End for iShift
354
        polynomialAtPower *= p  
355
        nAtPower /= N
356
    # End for pPower loop
357
    return ((protoMatrixRows, knownMonomials))
358
# End spo_polynomial_to_proto_matrix
359

    
360
def spo_proto_to_column_matrix(protoMatrixColumns):
361
    """
362
    Create a column (each row holds the coefficients of one monomial) matrix.
363
    protoMatrixRows.
364
    
365
    Parameters
366
    ----------
367
    protoMatrixColumns: a list of coefficient lists.
368
    """
369
    numColumns = len(protoMatrixColumns)
370
    if numColumns == 0:
371
        return None
372
    # The last column holds has the maximum length. 
373
    numRows = len(protoMatrixColumns[numColumns-1])
374
    if numColumns == 0:
375
        return None
376
    baseMatrix = matrix(ZZ, numRows, numColumns)
377
    for colIndex in xrange(0, numColumns):
378
        for rowIndex in xrange(0, len(protoMatrixColumns[colIndex])):
379
            baseMatrix[rowIndex, colIndex] = \
380
            protoMatrixColumns[colIndex][rowIndex]
381
    return baseMatrix
382
# End spo_proto_to_column_matrix.
383
#
384
def spo_proto_to_row_matrix(protoMatrixRows):
385
    """
386
    Create a row (each column holds the coefficients of one monomial) matrix.
387
    protoMatrixRows.
388
    
389
    Parameters
390
    ----------
391
    protoMatrixRows: a list of coefficient lists.
392
    """
393
    numRows = len(protoMatrixRows)
394
    if numRows == 0:
395
        return None
396
    numColumns = len(protoMatrixRows[numRows-1])
397
    if numColumns == 0:
398
        return None
399
    baseMatrix = matrix(ZZ, numRows, numColumns)
400
    for rowIndex in xrange(0, numRows):
401
        for colIndex in xrange(0, len(protoMatrixRows[rowIndex])):
402
            baseMatrix[rowIndex, colIndex] = protoMatrixRows[rowIndex][colIndex]
403
    return baseMatrix
404
# End spo_proto_to_row_matrix.
405
#
406
print "\t...sagePolynomialOperations loaded"