Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (49,8 ko)

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

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

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

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

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

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

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

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

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

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

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

    
843
def spo_polynomial_to_polynomials_list_6(p, alpha, N, iBound, tBound,
844
                                         columnsWidth=0):
845
    """
846
    From p, alpha, N build a list of polynomials use to create a base
847
    that will eventually be reduced with LLL.
848
    
849
    The bounds are computed for the coefficients that will be used to
850
    form the base.
851
    
852
    We try to introduce only one new monomial at a time, whithout trying to
853
    obtain a triangular matrix.
854

    
855
    There are many possibilities to introduce the monomials: our goal is also 
856
    to introduce each of them on the diagonal with the smallest coefficient.
857

    
858
    The method depends on the structure of the polynomial. Here it is adapted
859
    to the a_n*i^n + ... + a_1 * i - t + b form.     
860
        
861
    Parameters
862
    ----------
863
    p: the (bivariate) polynomial;
864
    alpha:
865
    N:
866
    iBound:
867
    tBound:
868
    columsWidth: if == 0, no information is displayed, otherwise data is 
869
                 printed in colums of columnsWitdth width.
870
    """
871
    pRing = p.parent()
872
    polynomialsList = []
873
    pVariables = p.variables()
874
    iVariable = pVariables[0]
875
    tVariable = pVariables[1]
876
    polynomialAtPower = copy(p)
877
    currentPolynomial = pRing(1)     # Constant term.
878
    pIdegree = p.degree(iVariable)
879
    pTdegree = p.degree(tVariable)
880
    maxIdegree = pIdegree * alpha
881
    currentIdegree = currentPolynomial.degree(iVariable)
882
    nAtAlpha = N^alpha
883
    nAtPower = nAtAlpha
884
    polExpStr = ""
885
    #
886
    """
887
    ## Bound for iPower + pIdegree*tPower <= alpha*pIdegree
888
    print "degree in i:", pIdegree
889
    powersRangeUpperBound = alpha * pIdegree + 1 # +1 for the range.
890
    for iPower in xrange(0, powersRangeUpperBound):
891
        tPower = 0
892
        while (iPower + tPower * pIdegree) < powersRangeUpperBound:
893
                print "iPower:", iPower, " tPower:", tPower
894
                q = pRing(iVariable * iBound)^iPower * ((p * N)^tPower)
895
                print "q monomials:", q.monomials()
896
                polynomialsList.append(q)
897
                tPower += 1
898
    """
899
    """
900
    Start from iExp = 0 since starting from 1 does not allow for 
901
    resultants != 0.
902
    """
903
    for iExp in xrange(0, alpha+1):
904
        tExp = 0
905
        while iExp + tExp <= alpha:
906
            q = pRing(iVariable * iBound)^iExp * ((p * N)^tExp)
907
            sys.stdout.write("q " + str(iExp) + "," + str(tExp) + ": ")
908
            print q
909
            polynomialsList.append(q)
910
            tExp += 1
911
    return polynomialsList
912
                
913
    """
914
    # We first introduce all the monomials in i alone multiplied by N^alpha.
915
    for iPower in xrange(0, maxIdegree + 1):
916
        if columnsWidth !=0:
917
            polExpStr = spo_expression_as_string(iPower, iBound,
918
                                                 0, tBound, 
919
                                                 0, alpha)
920
            print "->", polExpStr
921
        currentExpression = iVariable^iPower * nAtAlpha * iBound^iPower
922
        currentPolynomial = pRing(currentExpression)
923
        polynomialsList.append(currentPolynomial)
924
    # End for iPower
925
    # We work from p^1 * N^alpha-1 to p^alpha * N^0
926
    for pPower in xrange(1, alpha + 1):
927
        # First of all the p^pPower * N^(alpha-pPower) polynomial.
928
        nAtPower /= N
929
        if columnsWidth !=0:
930
            polExpStr = spo_expression_as_string(0, iBound,
931
                                                 0, tBound,
932
                                                 pPower, alpha-pPower)
933
            print "->", polExpStr
934
        currentPolynomial = polynomialAtPower * nAtPower
935
        polynomialsList.append(currentPolynomial)
936
        # Exit when pPower == alpha
937
        if pPower == alpha:
938
            return polynomialsList
939
        for iPower in xrange(1, pIdegree + 1):
940
            iCurrentPower = pIdegree + iPower
941
            for tPower in xrange(pPower-1, 0, -1):
942
                #print "tPower:", tPower
943
                if columnsWidth != 0:
944
                    polExpStr = spo_expression_as_string(iCurrentPower, iBound,
945
                                                         tPower, tBound, 
946
                                                         0, alpha)
947
                    print "->", polExpStr
948
                currentExpression = i^iCurrentPower * iBound^iCurrentPower * t^tPower * tBound^tPower *nAtAlpha 
949
                currentPolynomial = pRing(currentExpression)
950
                polynomialsList.append(currentPolynomial)
951
                iCurrentPower += pIdegree 
952
            # End for tPower 
953
        # We now introduce the mixed i^k * t^l monomials by i^m * p^n * N^(alpha-n)
954
            if columnsWidth != 0:
955
                polExpStr = spo_expression_as_string(iPower, iBound,
956
                                                     0, tBound, 
957
                                                     pPower, alpha-pPower)
958
                print "->", polExpStr
959
            currentExpression = i^iPower * iBound^iPower * nAtPower
960
            currentPolynomial = pRing(currentExpression) * polynomialAtPower
961
            polynomialsList.append(currentPolynomial) 
962
        # End for iPower
963
        polynomialAtPower *= p  
964
    # End for pPower loop
965
    """
966
    return polynomialsList 
967
# End spo_polynomial_to_proto_matrix_6
968

    
969
def spo_polynomial_to_polynomials_list_7(p, alpha, N, iBound, tBound,
970
                                         columnsWidth=0):
971
    """
972
    As per Random Bits... direct loops nesting.
973
    """
974
    pRing = p.parent()
975
    polynomialsList = []
976
    pVariables = p.variables()
977
    iVariable = pVariables[0]
978
    tVariable = pVariables[1]
979
    polynomialAtPower = copy(p)
980
    currentPolynomial = pRing(1)     # Constant term.
981

    
982
    for iExp in xrange(0, alpha+1):
983
        pExp = 0
984
        while (iExp + pExp) <= alpha:
985
            print "iExp:", iExp, \
986
                "- pExp:", pExp, \
987
                "- alpha-pExp:", alpha-pExp
988
            q = pRing(iVariable * iBound)^iExp * p^pExp * N^(alpha-pExp)
989
            print q.monomials()
990
            polynomialsList.append(q)
991
            pExp += 1
992
    return polynomialsList
993
# End spo_polynomial_to_polynomials_list_7
994

    
995
def spo_polynomial_to_polynomials_list_8(p, alpha, N, iBound, tBound,
996
                                         columnsWidth=0):
997
    """
998
    As per Random Bits... (reversed loop nesting)
999
    """
1000
    pRing = p.parent()
1001
    polynomialsList = []
1002
    pVariables = p.variables()
1003
    iVariable = pVariables[0]
1004
    tVariable = pVariables[1]
1005
    polynomialAtPower = copy(p)
1006
    currentPolynomial = pRing(1)     # Constant term.
1007
     
1008
    for pExp in xrange(0, alpha+1):
1009
        iExp = 0
1010
        while (iExp + pExp) <= alpha:
1011
            print "iExp:", iExp, \
1012
                "- pExp:", pExp, \
1013
                "- alpha-pExp:", alpha-pExp
1014
            q = pRing(iVariable * iBound)^iExp * p^pExp * N^(alpha-pExp)
1015
            print q.monomials()
1016
            polynomialsList.append(q)
1017
            iExp += 1
1018
    return polynomialsList
1019
# End spo_polynomial_to_polynomials_list_8
1020

    
1021
def spo_proto_to_column_matrix(protoMatrixColumns):
1022
    """
1023
    Create a column (each row holds the coefficients for one monomial) matrix.
1024
    
1025
    Parameters
1026
    ----------
1027
    protoMatrixColumns: a list of coefficient lists.
1028
    """
1029
    numColumns = len(protoMatrixColumns)
1030
    if numColumns == 0:
1031
        return None
1032
    # The last column holds has the maximum length. 
1033
    numRows = len(protoMatrixColumns[numColumns-1])
1034
    if numColumns == 0:
1035
        return None
1036
    baseMatrix = matrix(ZZ, numRows, numColumns)
1037
    for colIndex in xrange(0, numColumns):
1038
        for rowIndex in xrange(0, len(protoMatrixColumns[colIndex])):
1039
            if protoMatrixColumns[colIndex][rowIndex] != 0:
1040
                baseMatrix[rowIndex, colIndex] = \
1041
                    protoMatrixColumns[colIndex][rowIndex]
1042
    return baseMatrix
1043
# End spo_proto_to_column_matrix.
1044
#
1045
def spo_proto_to_row_matrix(protoMatrixRows):
1046
    """
1047
    Create a row (each column holds the coefficients corresponding to one 
1048
    monomial) matrix from the protoMatrixRows list.
1049
    
1050
    Parameters
1051
    ----------
1052
    protoMatrixRows: a list of coefficient lists.
1053
    """
1054
    numRows = len(protoMatrixRows)
1055
    if numRows == 0:
1056
        return None
1057
    # Search for the longest row to get the number of columns.
1058
    numColumns = 0
1059
    for row in protoMatrixRows:
1060
        rowLength = len(row)
1061
        if numColumns < rowLength:
1062
            numColumns = rowLength
1063
    if numColumns == 0:
1064
        return None
1065
    baseMatrix = matrix(ZZ, numRows, numColumns)
1066
    for rowIndex in xrange(0, numRows):
1067
        for colIndex in xrange(0, len(protoMatrixRows[rowIndex])):
1068
            if protoMatrixRows[rowIndex][colIndex] !=  0:
1069
                baseMatrix[rowIndex, colIndex] = \
1070
                    protoMatrixRows[rowIndex][colIndex]
1071
            #print rowIndex, colIndex,
1072
            #print protoMatrixRows[rowIndex][colIndex],
1073
            #print knownMonomialsList[colIndex](boundVar1,boundVar2)
1074
    return baseMatrix
1075
# End spo_proto_to_row_matrix.
1076
#
1077
print "\t...sagePolynomialOperations loaded"