Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (42,75 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(poly, 
4
                                            knownMonomials, 
5
                                            protoMatrixRows, 
6
                                            columnsWidth=0):
7
    """
8
    For a given polynomial ,
9
    add the coefficients of the protoMatrix (a list of proto matrix rows).
10
    Coefficients are added to the protoMatrix row in the order imposed by the 
11
    monomials discovery list (the knownMonomials list) built as construction
12
    goes on. 
13
    As a bonus, data can be printed out for a visual check.
14
    poly           : the polynomial; in argument;
15
    knownMonomials : the list of the already known monomials; will determine
16
                     the order of the coefficients appending to a row; in-out
17
                     argument (new monomials may be discovered and then 
18
                     appended the the knowMonomials list);
19
    protoMatrixRows: a list of lists, each one holding the coefficients of the 
20
                     monomials of a polynomial; in-out argument: a new row is
21
                     added at each call;
22
    columnWith     : the width, in characters, of the displayed column ; if 0, 
23
                     do not display anything; in argument.
24
    """
25
    pMonomials   = poly.monomials()
26
    pCoefficients = poly.coefficients()
27
    # We have started with the smaller degrees in the first variable.
28
    pMonomials.reverse()
29
    pCoefficients.reverse()
30
    # New empty proto matrix row.
31
    protoMatrixRowCoefficients = []
32
    # We work according to the order of the already known monomials
33
    # No known monomials yet: add the pMonomials to knownMonomials 
34
    # and add the coefficients to the proto matrix row.
35
    if len(knownMonomials) == 0: 
36
        for pmIdx in xrange(0, len(pMonomials)):
37
            knownMonomials.append(pMonomials[pmIdx])
38
            protoMatrixRowCoefficients.append(pCoefficients[pmIdx])
39
            if columnsWidth != 0:
40
                monomialAsString = str(pCoefficients[pmIdx]) + " " + \
41
                                   str(pMonomials[pmIdx])
42
                print monomialAsString, " " * \
43
                      (columnsWidth - len(monomialAsString)),
44
    # There are some known monomials. We search for them in pMonomials and 
45
    # add their coefficients to the proto matrix row.
46
    else: 
47
        for knownMonomialIndex in xrange(0,len(knownMonomials)):
48
            # We lazily use an exception here since pMonomials.index() function
49
            # may fail throwing the ValueError exception.
50
            try:
51
                indexInPmonomials = \
52
                    pMonomials.index(knownMonomials[knownMonomialIndex])
53
                if columnsWidth != 0:
54
                    monomialAsString = str(pCoefficients[indexInPmonomials]) + \
55
                        " " + str(knownMonomials[knownMonomialIndex])
56
                    print monomialAsString, " " * \
57
                        (columnsWidth - len(monomialAsString)),
58
                # Add the coefficient to the proto matrix row and delete the \
59
                # known monomial from the current pMonomial list 
60
                #(and the corresponding coefficient as well).
61
                protoMatrixRowCoefficients.append(pCoefficients[indexInPmonomials])
62
                del pMonomials[indexInPmonomials]
63
                del pCoefficients[indexInPmonomials]
64
            # The knownMonomials element is not in pMonomials
65
            except ValueError:   
66
                protoMatrixRowCoefficients.append(0)
67
                if columnsWidth != 0:
68
                    monomialAsString = "0" + " "+ \
69
                        str(knownMonomials[knownMonomialIndex])
70
                    print monomialAsString, " " * \
71
                        (columnsWidth - len(monomialAsString)),
72
        # End for knownMonomialKey loop. 
73
        # We now append the remaining monomials of pMonomials to knownMonomials 
74
        # and the corresponding coefficients to proto matrix row.
75
        for pmIdx in xrange(0, len(pMonomials)):
76
            knownMonomials.append(pMonomials[pmIdx])
77
            protoMatrixRowCoefficients.append(pCoefficients[pmIdx])
78
            if columnsWidth != 0:
79
                monomialAsString = str(pCoefficients[pmIdx]) + " " \
80
                    + str(pMonomials[pmIdx])
81
                print monomialAsString, " " * \
82
                    (columnsWidth - len(monomialAsString)),
83
        # End for pmIdx loop.
84
    # Add the new list row elements to the proto matrix.
85
    protoMatrixRows.append(protoMatrixRowCoefficients)
86
    if columnsWidth != 0:
87
        print    
88
# End spo_add_polynomial_coeffs_to_matrix_row
89

    
90
def spo_get_coefficient_for_monomial(monomialsList, coefficientsList, monomial):
91
    """
92
    Get, for a polynomial, the coefficient for a given monomial.
93
    The polynomial is given as two lists (monomials and coefficients as
94
    return by the respective methods ; indexes of the two lists must match).
95
    If the monomial is not found, 0 is returned.
96
    """
97
    monomialIndex = 0
98
    for mono in monomialsList:
99
        if mono == monomial:
100
            return coefficientsList[monomialIndex]
101
        monomialIndex += 1
102
    return 0
103
# End spo_get_coefficient_for_monomial.
104
    
105

    
106
def spo_expression_as_string(powI, boundI, powT, boundT, powP, powN):
107
    """
108
    Computes a string version of the i^k + t^l + p^m + N^n expression for
109
    output.
110
    """
111
    expressionAsString =""
112
    if powI != 0:
113
        expressionAsString += str(iBound^powI) + " i^" + str(powI)
114
    if powT != 0:
115
        if len(expressionAsString) != 0:
116
            expressionAsString += " * "
117
        expressionAsString += str(tBound^powT) + " t^" + str(powT)
118
    if powP != 0:
119
        if len(expressionAsString) != 0:
120
            expressionAsString += " * "
121
        expressionAsString += "p^" + str(powP)
122
    if (powN) != 0 :
123
        if len(expressionAsString) != 0:
124
            expressionAsString += " * "
125
        expressionAsString += "N^" + str(powN)
126
    return(expressionAsString)
127
# End spo_expression_as_string.
128

    
129
def spo_norm(poly, p=2):
130
    """
131
    Behaves more or less (no infinity defined) as the norm for the
132
    univariate polynomials.
133
    Quoting Sage documentation:
134
    "Definition: For integer p, the p-norm of a polynomial is the pth root of 
135
    the sum of the pth powers of the absolute values of the coefficients of 
136
    the polynomial."
137
    
138
    """
139
    # TODO: check the arguments (for p see below)..
140
    norm = 0
141
    # For infinity norm.
142
    if p == Infinity:
143
        for coefficient in poly.coefficients():
144
            coefficientAbs = coefficient.abs()
145
            if coefficientAbs > norm:
146
                norm = coefficientAbs
147
        return norm
148
    # TODO: check here the value of p
149
    # p must be a positive integer >= 1.
150
    if p < 1 or (not p in ZZ):
151
        return None
152
    # For 1 norm.
153
    if p == 1:
154
        for coefficient in poly.coefficients():
155
            norm +=  coefficient.abs()
156
        return norm
157
    # For other norms
158
    for coefficient in poly.coefficients():
159
        norm +=  coefficient.abs()^p
160
    return pow(norm, 1/p)
161
# end spo_norm
162

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

    
399
def spo_polynomial_to_polynomials_list_2(p, alpha, N, iBound, tBound,
400
                                         columnsWidth=0):
401
    """
402
    Badly out of sync code: check with versions 3 or 4.
403
    
404
    From p, alpha, N build a list of polynomials...
405
    TODO: clean up the comments below!
406
    
407
    From a (bivariate) polynomial and some other parameters build a proto 
408
    matrix (an array of "rows") to be converted into a "true" matrix and 
409
    eventually by reduced by fpLLL.
410
    The matrix is based on a list of polynomials that are built in a way
411
    that one and only monomial is added at each new polynomial. Among the many
412
    possible ways to build this list we pick one strongly dependent on the 
413
    structure of the polynomial and of the problem.
414
    We consider here the polynomials of the form: 
415
    a_k*i^k + a_(k-1)*i^(k-1) + ... + a_1*i + a_0 - t 
416
    The values of i and t are bounded and we eventually look for (i_0,t_0) 
417
    pairs such that:
418
    a_k*i_0^k + a_(k-1)*i_0^(k-1) + ... + a_1*i_0 + a_0 = t_0
419
    Hence, departing from the procedure in described in Boneh-Durfee, we will 
420
    not use "t-shifts" but only "i-shifts".
421
        
422
    Parameters
423
    ----------
424
    p: the (bivariate) polynomial;
425
    pRing: the ring over which p is defined;
426
    alpha:
427
    N:
428
    columsWidth: if == 0, no information is displayed, otherwise data is 
429
                 printed in colums of columnsWitdth width.
430
    """
431
    pRing = p.parent()
432
    polynomialsList = []
433
    pVariables = p.variables()
434
    iVariable = pVariables[0]
435
    tVariable = pVariables[1]
436
    polynomialAtPower = pRing(1)
437
    currentPolynomial = pRing(1)
438
    pIdegree = p.degree(iVariable)
439
    pTdegree = p.degree(tVariable)
440
    currentIdegree = currentPolynomial.degree(iVariable)
441
    nAtAlpha = N^alpha
442
    nAtPower = nAtAlpha
443
    polExpStr = ""
444
    # We work from p^0 * N^alpha to p^alpha * N^0
445
    for pPower in xrange(0, alpha + 1):
446
        # pPower == 0 is a special case. We introduce all the monomials in i 
447
        # up to i^pIdegree.
448
        if pPower == 0:
449
            # Notice who iPower runs up to i^pIdegree.
450
            for iPower in xrange(0, pIdegree + 1): 
451
                # No t power is taken into account as we limit our selves to
452
                # degree 1 in t and make no "t-shifts".
453
                if columnsWidth != 0:
454
                    polExpStr = spo_expression_as_string(iPower,
455
                                                         iBound, 
456
                                                         0, 
457
                                                         tBound,
458
                                                         0, 
459
                                                         alpha)
460
                    print "->", polExpStr
461
                currentExpression = iVariable^iPower * nAtAlpha * iBound^iPower
462
                # polynomialAtPower == 1 here. Next line should be commented
463
                # out but it does not work! Some conversion problem?
464
                currentPolynomial = pRing(currentExpression)
465
                polynomialsList.append(currentPolynomial) 
466
            # End for iPower.
467
        else: # pPower > 0: (p^1..p^alpha)
468
            # This where we introduce the p^pPower * N^(alpha-pPower)
469
            # polynomial. This is also where the t^pPower monomials shows up for
470
            # the first time.
471
            if columnsWidth != 0:
472
                polExpStr = spo_expression_as_string(0, iBound, 0, tBound, \
473
                                                     pPower, alpha-pPower)
474
                print "->", polExpStr
475
            currentPolynomial = polynomialAtPower * nAtPower
476
            polynomialsList.append(currentPolynomial) 
477
            # Exit when pPower == alpha
478
            if pPower == alpha:
479
                return polynomialsList
480
            # This is where the "i-shifts" take place. Mixed terms, i^k * t^l
481
            # (that were introduced at a previous
482
            # stage or are introduced now) are only shifted to already existing 
483
            # ones with the notable exception of i^iPower * t^pPower, which
484
            # must be manually introduced.
485
            # p^pPower is "shifted" to higher degrees in i as far as 
486
            # possible, up to of the degree in i of p^(pPower+1).
487
            # These "pure" i^k monomials can only show up with i multiplications.
488
            for iPower in xrange(1, pIdegree + 1):
489
                # The i^iPower * t^pPower monomial. Notice the alpha exponent
490
                # for N.
491
                internalIpower = iPower
492
                for tPower in xrange(pPower,0,-1):
493
                    if columnsWidth != 0:
494
                        polExpStr = spo_expression_as_string(internalIpower, 
495
                                                             iBound,
496
                                                             tPower,
497
                                                             tBound,
498
                                                             0,
499
                                                             alpha)
500
                        print "->", polExpStr
501
                    currentExpression = i^internalIpower * t^tPower * \
502
                                        nAtAlpha * iBound^internalIpower * \
503
                                        tBound^tPower
504
                    
505
                    currentPolynomial = pRing(currentExpression)
506
                    polynomialsList.append(currentPolynomial) 
507
                    internalIpower += pIdegree
508
                # End for tPower
509
                # The i^iPower * p^pPower * N^(alpha-pPower) i-shift.
510
                if columnsWidth != 0:
511
                    polExpStr = spo_expression_as_string(iPower, 
512
                                                         iBound,
513
                                                         0,      
514
                                                         tBound,
515
                                                         pPower, 
516
                                                         alpha-pPower)
517
                    print "->", polExpStr
518
                currentExpression = i^iPower * nAtPower * iBound^iPower
519
                currentPolynomial = pRing(currentExpression) * polynomialAtPower
520
                polynomialsList.append(currentPolynomial) 
521
            # End for iPower
522
        polynomialAtPower *= p  
523
        nAtPower /= N
524
    # End for pPower loop
525
    return polynomialsList
526
# End spo_polynomial_to_proto_matrix_2
527

    
528
def spo_polynomial_to_polynomials_list_3(p, alpha, N, iBound, tBound,
529
                                         columnsWidth=0):
530
    """
531
    From p, alpha, N build a list of polynomials...
532
    TODO: more in depth rationale...
533
    
534
    Our goal is to introduce each monomial with the smallest coefficient.
535
     
536
    
537
        
538
    Parameters
539
    ----------
540
    p: the (bivariate) polynomial;
541
    pRing: the ring over which p is defined;
542
    alpha:
543
    N:
544
    columsWidth: if == 0, no information is displayed, otherwise data is 
545
                 printed in colums of columnsWitdth width.
546
    """
547
    pRing = p.parent()
548
    polynomialsList = []
549
    pVariables = p.variables()
550
    iVariable = pVariables[0]
551
    tVariable = pVariables[1]
552
    polynomialAtPower = pRing(1)
553
    currentPolynomial = pRing(1)
554
    pIdegree = p.degree(iVariable)
555
    pTdegree = p.degree(tVariable)
556
    currentIdegree = currentPolynomial.degree(iVariable)
557
    nAtAlpha = N^alpha
558
    nAtPower = nAtAlpha
559
    polExpStr = ""
560
    # We work from p^0 * N^alpha to p^alpha * N^0
561
    for pPower in xrange(0, alpha + 1):
562
        # pPower == 0 is a special case. We introduce all the monomials in i 
563
        # up to i^pIdegree.
564
        if pPower == 0:
565
            # Notice who iPower runs up to i^pIdegree.
566
            for iPower in xrange(0, pIdegree + 1): 
567
                # No t power is taken into account as we limit our selves to
568
                # degree 1 in t and make no "t-shifts".
569
                if columnsWidth != 0:
570
                    polExpStr = spo_expression_as_string(iPower, 
571
                                                         iBound,
572
                                                         0, 
573
                                                         tBound,
574
                                                         0, 
575
                                                         alpha)
576
                    print "->", polExpStr
577
                currentExpression = iVariable^iPower * nAtAlpha * iBound^iPower
578
                # polynomialAtPower == 1 here. Next line should be commented
579
                # out but it does not work! Some conversion problem?
580
                currentPolynomial = pRing(currentExpression)
581
                polynomialsList.append(currentPolynomial) 
582
            # End for iPower.
583
        else: # pPower > 0: (p^1..p^alpha)
584
            # This where we introduce the p^pPower * N^(alpha-pPower)
585
            # polynomial. This is also where the t^pPower monomials shows up for
586
            # the first time. It app
587
            if columnsWidth != 0:
588
                polExpStr = spo_expression_as_string(0, iBound, 
589
                                                     0, tBound,
590
                                                     pPower, alpha-pPower)
591
                print "->", polExpStr
592
            currentPolynomial = polynomialAtPower * nAtPower
593
            polynomialsList.append(currentPolynomial) 
594
            # Exit when pPower == alpha
595
            if pPower == alpha:
596
                return polynomialsList
597
            # This is where the "i-shifts" take place. Mixed terms, i^k * t^l
598
            # (that were introduced at a previous
599
            # stage or are introduced now) are only shifted to already existing 
600
            # ones with the notable exception of i^iPower * t^pPower, which
601
            # must be manually introduced.
602
            # p^pPower is "shifted" to higher degrees in i as far as 
603
            # possible, up to of the degree in i of p^(pPower+1).
604
            # These "pure" i^k monomials can only show up with i multiplications.
605
            for iPower in xrange(1, pIdegree + 1):
606
                # The i^iPower * t^pPower monomial. Notice the alpha exponent
607
                # for N.
608
                internalIpower = iPower
609
                for tPower in xrange(pPower,0,-1):
610
                    if columnsWidth != 0:
611
                        polExpStr = spo_expression_as_string(internalIpower,
612
                                                             iBound, 
613
                                                             tPower,  
614
                                                             tBound,
615
                                                             0,
616
                                                             alpha)
617
                        print "->", polExpStr
618
                    currentExpression = i^internalIpower * t^tPower * nAtAlpha * \
619
                                        iBound^internalIpower * tBound^tPower
620
                    currentPolynomial = pRing(currentExpression)
621
                    polynomialsList.append(currentPolynomial) 
622
                    internalIpower += pIdegree
623
                # End for tPower
624
                # Here we have to choose between a 
625
                # i^iPower * p^pPower * N^(alpha-pPower) i-shift and
626
                # i^iPower * i^(d_i(p) * pPower) * N^alpha, depending on which 
627
                # coefficient is smallest.
628
                IcurrentExponent = iPower + \
629
                                (pPower * polynomialAtPower.degree(iVariable))
630
                currentMonomial = pRing(iVariable^IcurrentExponent)
631
                currentPolynomial = pRing(iVariable^iPower * nAtPower * \
632
                                          iBound^iPower) * \
633
                                          polynomialAtPower
634
                currMonomials = currentPolynomial.monomials()
635
                currCoefficients = currentPolynomial.coefficients()
636
                currentCoefficient = spo_get_coefficient_for_monomial( \
637
                                                    currMonomials, 
638
                                                    currCoefficients, 
639
                                                    currentMonomial)
640
                print "Current coefficient:", currentCoefficient
641
                alterCoefficient = iBound^IcurrentExponent * nAtAlpha 
642
                print "N^alpha * ibound^", IcurrentExponent, ":", \
643
                         alterCoefficient
644
                if currentCoefficient > alterCoefficient :
645
                    if columnsWidth != 0:
646
                        polExpStr = spo_expression_as_string(IcurrentExponent,
647
                                                             iBound,
648
                                                             0,
649
                                                             tBound,
650
                                                             0,
651
                                                             alpha)
652
                        print "->", polExpStr
653
                    polynomialsList.append(currentMonomial * \
654
                                           alterCoefficient)
655
                else:
656
                    if columnsWidth != 0:
657
                        polExpStr = spo_expression_as_string(iPower, iBound,
658
                                                             0, tBound,
659
                                                             pPower, 
660
                                                             alpha-pPower)
661
                        print "->", polExpStr
662
                    polynomialsList.append(currentPolynomial) 
663
            # End for iPower
664
        polynomialAtPower *= p  
665
        nAtPower /= N
666
    # End for pPower loop
667
    return polynomialsList 
668
# End spo_polynomial_to_proto_matrix_3
669

    
670
def spo_polynomial_to_polynomials_list_4(p, alpha, N, iBound, tBound,
671
                                         columnsWidth=0):
672
    """
673
    From p, alpha, N build a list of polynomials...
674
    TODO: more in depth rationale...
675
    
676
    Our goal is to introduce each monomial with the smallest coefficient.
677
     
678
    
679
        
680
    Parameters
681
    ----------
682
    p: the (bivariate) polynomial;
683
    pRing: the ring over which p is defined;
684
    alpha:
685
    N:
686
    columsWidth: if == 0, no information is displayed, otherwise data is 
687
                 printed in colums of columnsWitdth width.
688
    """
689
    pRing = p.parent()
690
    polynomialsList = []
691
    pVariables = p.variables()
692
    iVariable = pVariables[0]
693
    tVariable = pVariables[1]
694
    polynomialAtPower = copy(p)
695
    currentPolynomial = pRing(1)
696
    pIdegree = p.degree(iVariable)
697
    pTdegree = p.degree(tVariable)
698
    maxIdegree = pIdegree * alpha
699
    currentIdegree = currentPolynomial.degree(iVariable)
700
    nAtAlpha = N^alpha
701
    nAtPower = nAtAlpha
702
    polExpStr = ""
703
    # We first introduce all the monomials in i alone multiplied by N^alpha.
704
    for iPower in xrange(0, maxIdegree + 1):
705
        if columnsWidth !=0:
706
            polExpStr = spo_expression_as_string(iPower, iBound,
707
                                                 0, tBound, 
708
                                                 0, alpha)
709
            print "->", polExpStr
710
        currentExpression = iVariable^iPower * nAtAlpha * iBound^iPower
711
        currentPolynomial = pRing(currentExpression)
712
        polynomialsList.append(currentPolynomial)
713
    # End for iPower
714
    # We work from p^1 * N^alpha-1 to p^alpha * N^0
715
    for pPower in xrange(1, alpha + 1):
716
        # First of all the p^pPower * N^(alpha-pPower) polynomial.
717
        nAtPower /= N
718
        if columnsWidth !=0:
719
            polExpStr = spo_expression_as_string(0, iBound,
720
                                                 0, tBound,
721
                                                 pPower, alpha-pPower)
722
            print "->", polExpStr
723
        currentPolynomial = polynomialAtPower * nAtPower
724
        polynomialsList.append(currentPolynomial)
725
        # Exit when pPower == alpha
726
        if pPower == alpha:
727
            return polynomialsList
728
        # We now introduce the mixed i^k * t^l monomials by i^m * p^n * N^(alpha-n)
729
        for iPower in xrange(1, pIdegree + 1): 
730
            if columnsWidth != 0:
731
                polExpStr = spo_expression_as_string(iPower, iBound,
732
                                                     0, tBound, 
733
                                                     pPower, alpha-pPower)
734
                print "->", polExpStr
735
            currentExpression = i^iPower * iBound^iPower * nAtPower
736
            currentPolynomial = pRing(currentExpression) * polynomialAtPower
737
            polynomialsList.append(currentPolynomial) 
738
        # End for iPower
739
        polynomialAtPower *= p  
740
    # End for pPower loop
741
    return polynomialsList 
742
# End spo_polynomial_to_proto_matrix_4
743

    
744
def spo_polynomial_to_polynomials_list_5(p, alpha, N, iBound, tBound,
745
                                         columnsWidth=0):
746
    """
747
    From p, alpha, N build a list of polynomials use to create a base
748
    that will eventually be reduced with LLL.
749
    
750
    The bounds are computed for the coefficients that will be used to
751
    form the base.
752
    
753
    We try to introduce only one new monomial at a time, to obtain a
754
    triangular matrix (it is easy to compute the volume of the underlining
755
    latice if the matrix is triangular).
756

    
757
    There are many possibilities to introduce the monomials: our goal is also 
758
    to introduce each of them on the diagonal with the smallest coefficient.
759

    
760
    The method depends on the structure of the polynomial. Here it is adapted
761
    to the a_n*i^n + ... + a_1 * i - t + b form.     
762
        
763
    Parameters
764
    ----------
765
    p: the (bivariate) polynomial;
766
    alpha:
767
    N:
768
    iBound:
769
    tBound:
770
    columsWidth: if == 0, no information is displayed, otherwise data is 
771
                 printed in colums of columnsWitdth width.
772
    """
773
    pRing = p.parent()
774
    polynomialsList = []
775
    pVariables = p.variables()
776
    iVariable = pVariables[0]
777
    tVariable = pVariables[1]
778
    polynomialAtPower = copy(p)
779
    currentPolynomial = pRing(1)
780
    pIdegree = p.degree(iVariable)
781
    pTdegree = p.degree(tVariable)
782
    maxIdegree = pIdegree * alpha
783
    currentIdegree = currentPolynomial.degree(iVariable)
784
    nAtAlpha = N^alpha
785
    nAtPower = nAtAlpha
786
    polExpStr = ""
787
    # We first introduce all the monomials in i alone multiplied by N^alpha.
788
    for iPower in xrange(0, maxIdegree + 1):
789
        if columnsWidth !=0:
790
            polExpStr = spo_expression_as_string(iPower, iBound,
791
                                                 0, tBound, 
792
                                                 0, alpha)
793
            print "->", polExpStr
794
        currentExpression = iVariable^iPower * nAtAlpha * iBound^iPower
795
        currentPolynomial = pRing(currentExpression)
796
        polynomialsList.append(currentPolynomial)
797
    # End for iPower
798
    # We work from p^1 * N^alpha-1 to p^alpha * N^0
799
    for pPower in xrange(1, alpha + 1):
800
        # First of all the p^pPower * N^(alpha-pPower) polynomial.
801
        nAtPower /= N
802
        if columnsWidth !=0:
803
            polExpStr = spo_expression_as_string(0, iBound,
804
                                                 0, tBound,
805
                                                 pPower, alpha-pPower)
806
            print "->", polExpStr
807
        currentPolynomial = polynomialAtPower * nAtPower
808
        polynomialsList.append(currentPolynomial)
809
        # Exit when pPower == alpha
810
        if pPower == alpha:
811
            return polynomialsList
812
        for iPower in xrange(1, pIdegree + 1):
813
            iCurrentPower = pIdegree + iPower
814
            for tPower in xrange(pPower-1, 0, -1):
815
                print "tPower:", tPower
816
                if columnsWidth != 0:
817
                    polExpStr = spo_expression_as_string(iCurrentPower, iBound,
818
                                                         tPower, tBound, 
819
                                                         0, alpha)
820
                    print "->", polExpStr
821
                currentExpression = i^iCurrentPower * iBound^iCurrentPower * t^tPower * tBound^tPower *nAtAlpha 
822
                currentPolynomial = pRing(currentExpression)
823
                polynomialsList.append(currentPolynomial)
824
                iCurrentPower += pIdegree 
825
            # End for tPower 
826
        # We now introduce the mixed i^k * t^l monomials by i^m * p^n * N^(alpha-n)
827
            if columnsWidth != 0:
828
                polExpStr = spo_expression_as_string(iPower, iBound,
829
                                                     0, tBound, 
830
                                                     pPower, alpha-pPower)
831
                print "->", polExpStr
832
            currentExpression = i^iPower * iBound^iPower * nAtPower
833
            currentPolynomial = pRing(currentExpression) * polynomialAtPower
834
            polynomialsList.append(currentPolynomial) 
835
        # End for iPower
836
        polynomialAtPower *= p  
837
    # End for pPower loop
838
    return polynomialsList 
839
# End spo_polynomial_to_proto_matrix_5
840

    
841
def spo_proto_to_column_matrix(protoMatrixColumns):
842
    """
843
    Create a column (each row holds the coefficients for one monomial) matrix.
844
    
845
    Parameters
846
    ----------
847
    protoMatrixColumns: a list of coefficient lists.
848
    """
849
    numColumns = len(protoMatrixColumns)
850
    if numColumns == 0:
851
        return None
852
    # The last column holds has the maximum length. 
853
    numRows = len(protoMatrixColumns[numColumns-1])
854
    if numColumns == 0:
855
        return None
856
    baseMatrix = matrix(ZZ, numRows, numColumns)
857
    for colIndex in xrange(0, numColumns):
858
        for rowIndex in xrange(0, len(protoMatrixColumns[colIndex])):
859
            if protoMatrixColumns[colIndex][rowIndex] != 0:
860
                baseMatrix[rowIndex, colIndex] = \
861
                    protoMatrixColumns[colIndex][rowIndex]
862
    return baseMatrix
863
# End spo_proto_to_column_matrix.
864
#
865
def spo_proto_to_row_matrix(protoMatrixRows):
866
    """
867
    Create a row (each column holds the coefficients corresponding to one 
868
    monomial) matrix from the protoMatrixRows list.
869
    
870
    Parameters
871
    ----------
872
    protoMatrixRows: a list of coefficient lists.
873
    """
874
    numRows = len(protoMatrixRows)
875
    if numRows == 0:
876
        return None
877
    # The last row is the longest one.
878
    numColumns = len(protoMatrixRows[numRows-1])
879
    if numColumns == 0:
880
        return None
881
    baseMatrix = matrix(ZZ, numRows, numColumns)
882
    for rowIndex in xrange(0, numRows):
883
        for colIndex in xrange(0, len(protoMatrixRows[rowIndex])):
884
            if protoMatrixRows[rowIndex][colIndex] !=  0:
885
                baseMatrix[rowIndex, colIndex] = \
886
                    protoMatrixRows[rowIndex][colIndex]
887
            #print rowIndex, colIndex,
888
            #print protoMatrixRows[rowIndex][colIndex],
889
            #print knownMonomialsList[colIndex](boundVar1,boundVar2)
890
    return baseMatrix
891
# End spo_proto_to_row_matrix.
892
#
893
print "\t...sagePolynomialOperations loaded"