Statistiques
| Révision :

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

Historique | Voir | Annoter | Télécharger (51,59 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_float_poly_of_float_to_rat_poly_of_rat(polyOfFloat):
92
    """
93
    Create a polynomial over the rationals from a polynomial over
94
    a RealField.
95
    Important warning: default Sage behavior is to convert coefficients
96
    using continued fractions instead of making a simple conversion
97
    with a powers of two at denominators (and possible simplification).
98
    Hence conversion is not exact but with a relative error around 10^(-521).
99
    """
100
    ratPolynomialRing = QQ[str(polyOfFloat.variables()[0])]
101
    return(ratPolynomialRing(polyOfFloat))
102
# End spo_float_poly_of_float_to_rat_poly_of_rat.
103

    
104
def spo_float_poly_of_float_to_rat_poly_of_rat_pow_two(polyOfFloat):
105
    """
106
    Create a polynomial over the rationals from a polynomial over
107
    a RealField where all denominators are
108
    powers of two.
109
    Allows for exact conversions (and lcm computation of the coefficients
110
    denominator).
111
    """
112
    polyVariable = polyOfFloat.variables()[0] 
113
    RPR = QQ[str(polyVariable)]
114
    polyCoeffs      = polyOfFloat.coefficients()
115
    #print polyCoeffs
116
    polyExponents   = polyOfFloat.exponents()
117
    #print polyExponents
118
    polyDenomPtwoCoeffs = []
119
    for coeff in polyCoeffs:
120
        polyDenomPtwoCoeffs.append(sno_float_to_rat_pow_of_two_denom(coeff))
121
        #print "Converted coefficient:", sno_float_to_rat_pow_of_two_denom(coeff),
122
        #print type(sno_float_to_rat_pow_of_two_denom(coeff))
123
    ratPoly = RPR(0)
124
    #print type(ratPoly)
125
    ## !!! CAUTION !!! Do not use the RPR(coeff * polyVariagle^exponent)
126
    #  construction.
127
    #  The coefficient becomes plainly wrong when exponent == 0.
128
    #  No clue as to why.
129
    for coeff, exponent in zip(polyDenomPtwoCoeffs, polyExponents):
130
        ratPoly += coeff * RPR(polyVariable^exponent)
131
    return ratPoly
132
# End slz_float_poly_of_float_to_rat_poly_of_rat.
133

    
134

    
135
def spo_get_coefficient_for_monomial(monomialsList, coefficientsList, monomial):
136
    """
137
    Get, for a polynomial, the coefficient for a given monomial.
138
    The polynomial is given as two lists (monomials and coefficients as
139
    return by the respective methods ; indexes of the two lists must match).
140
    If the monomial is not found, 0 is returned.
141
    """
142
    monomialIndex = 0
143
    for mono in monomialsList:
144
        if mono == monomial:
145
            return coefficientsList[monomialIndex]
146
        monomialIndex += 1
147
    return 0
148
# End spo_get_coefficient_for_monomial.
149
    
150

    
151
def spo_expression_as_string(powI, boundI, powT, boundT, powP, powN):
152
    """
153
    Computes a string version of the i^k + t^l + p^m + N^n expression for
154
    output.
155
    """
156
    expressionAsString =""
157
    if powI != 0:
158
        expressionAsString += str(iBound^powI) + " i^" + str(powI)
159
    if powT != 0:
160
        if len(expressionAsString) != 0:
161
            expressionAsString += " * "
162
        expressionAsString += str(tBound^powT) + " t^" + str(powT)
163
    if powP != 0:
164
        if len(expressionAsString) != 0:
165
            expressionAsString += " * "
166
        expressionAsString += "p^" + str(powP)
167
    if (powN) != 0 :
168
        if len(expressionAsString) != 0:
169
            expressionAsString += " * "
170
        expressionAsString += "N^" + str(powN)
171
    return(expressionAsString)
172
# End spo_expression_as_string.
173

    
174
def spo_norm(poly, p=2):
175
    """
176
    Behaves more or less (no infinity defined) as the norm for the
177
    univariate polynomials.
178
    Quoting Sage documentation:
179
    "Definition: For integer p, the p-norm of a polynomial is the pth root of 
180
    the sum of the pth powers of the absolute values of the coefficients of 
181
    the polynomial."
182
    
183
    """
184
    # TODO: check the arguments (for p see below)..
185
    norm = 0
186
    # For infinity norm.
187
    if p == Infinity:
188
        for coefficient in poly.coefficients():
189
            coefficientAbs = coefficient.abs()
190
            if coefficientAbs > norm:
191
                norm = coefficientAbs
192
        return norm
193
    # TODO: check here the value of p
194
    # p must be a positive integer >= 1.
195
    if p < 1 or (not p in ZZ):
196
        return None
197
    # For 1 norm.
198
    if p == 1:
199
        for coefficient in poly.coefficients():
200
            norm +=  coefficient.abs()
201
        return norm
202
    # For other norms
203
    for coefficient in poly.coefficients():
204
        norm +=  coefficient.abs()^p
205
    return pow(norm, 1/p)
206
# end spo_norm
207

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

    
445
def spo_polynomial_to_polynomials_list_2(p, alpha, N, iBound, tBound,
446
                                         columnsWidth=0):
447
    """
448
    Badly out of sync code: check with versions 3 or 4.
449
    
450
    From p, alpha, N build a list of polynomials...
451
    TODO: clean up the comments below!
452
    
453
    From a (bivariate) polynomial and some other parameters build a proto 
454
    matrix (an array of "rows") to be converted into a "true" matrix and 
455
    eventually by reduced by fpLLL.
456
    The matrix is based on a list of polynomials that are built in a way
457
    that one and only monomial is added at each new polynomial. Among the many
458
    possible ways to build this list we pick one strongly dependent on the 
459
    structure of the polynomial and of the problem.
460
    We consider here the polynomials of the form: 
461
    a_k*i^k + a_(k-1)*i^(k-1) + ... + a_1*i + a_0 - t 
462
    The values of i and t are bounded and we eventually look for (i_0,t_0) 
463
    pairs such that:
464
    a_k*i_0^k + a_(k-1)*i_0^(k-1) + ... + a_1*i_0 + a_0 = t_0
465
    Hence, departing from the procedure in described in Boneh-Durfee, we will 
466
    not use "t-shifts" but only "i-shifts".
467
        
468
    Parameters
469
    ----------
470
    p: the (bivariate) polynomial;
471
    pRing: the ring over which p is defined;
472
    alpha:
473
    N:
474
    columsWidth: if == 0, no information is displayed, otherwise data is 
475
                 printed in colums of columnsWitdth width.
476
    """
477
    pRing = p.parent()
478
    polynomialsList = []
479
    pVariables = p.variables()
480
    iVariable = pVariables[0]
481
    tVariable = pVariables[1]
482
    polynomialAtPower = pRing(1)
483
    currentPolynomial = pRing(1)
484
    pIdegree = p.degree(iVariable)
485
    pTdegree = p.degree(tVariable)
486
    currentIdegree = currentPolynomial.degree(iVariable)
487
    nAtAlpha = N^alpha
488
    nAtPower = nAtAlpha
489
    polExpStr = ""
490
    # We work from p^0 * N^alpha to p^alpha * N^0
491
    for pPower in xrange(0, alpha + 1):
492
        # pPower == 0 is a special case. We introduce all the monomials in i 
493
        # up to i^pIdegree.
494
        if pPower == 0:
495
            # Notice who iPower runs up to i^pIdegree.
496
            for iPower in xrange(0, pIdegree + 1): 
497
                # No t power is taken into account as we limit our selves to
498
                # degree 1 in t and make no "t-shifts".
499
                if columnsWidth != 0:
500
                    polExpStr = spo_expression_as_string(iPower,
501
                                                         iBound, 
502
                                                         0, 
503
                                                         tBound,
504
                                                         0, 
505
                                                         alpha)
506
                    print "->", polExpStr
507
                currentExpression = iVariable^iPower * nAtAlpha * iBound^iPower
508
                # polynomialAtPower == 1 here. Next line should be commented
509
                # out but it does not work! Some conversion problem?
510
                currentPolynomial = pRing(currentExpression)
511
                polynomialsList.append(currentPolynomial) 
512
            # End for iPower.
513
        else: # pPower > 0: (p^1..p^alpha)
514
            # This where we introduce the p^pPower * N^(alpha-pPower)
515
            # polynomial. This is also where the t^pPower monomials shows up for
516
            # the first time.
517
            if columnsWidth != 0:
518
                polExpStr = spo_expression_as_string(0, iBound, 0, tBound, \
519
                                                     pPower, alpha-pPower)
520
                print "->", polExpStr
521
            currentPolynomial = polynomialAtPower * nAtPower
522
            polynomialsList.append(currentPolynomial) 
523
            # Exit when pPower == alpha
524
            if pPower == alpha:
525
                return polynomialsList
526
            # This is where the "i-shifts" take place. Mixed terms, i^k * t^l
527
            # (that were introduced at a previous
528
            # stage or are introduced now) are only shifted to already existing 
529
            # ones with the notable exception of i^iPower * t^pPower, which
530
            # must be manually introduced.
531
            # p^pPower is "shifted" to higher degrees in i as far as 
532
            # possible, up to of the degree in i of p^(pPower+1).
533
            # These "pure" i^k monomials can only show up with i multiplications.
534
            for iPower in xrange(1, pIdegree + 1):
535
                # The i^iPower * t^pPower monomial. Notice the alpha exponent
536
                # for N.
537
                internalIpower = iPower
538
                for tPower in xrange(pPower,0,-1):
539
                    if columnsWidth != 0:
540
                        polExpStr = spo_expression_as_string(internalIpower, 
541
                                                             iBound,
542
                                                             tPower,
543
                                                             tBound,
544
                                                             0,
545
                                                             alpha)
546
                        print "->", polExpStr
547
                    currentExpression = i^internalIpower * t^tPower * \
548
                                        nAtAlpha * iBound^internalIpower * \
549
                                        tBound^tPower
550
                    
551
                    currentPolynomial = pRing(currentExpression)
552
                    polynomialsList.append(currentPolynomial) 
553
                    internalIpower += pIdegree
554
                # End for tPower
555
                # The i^iPower * p^pPower * N^(alpha-pPower) i-shift.
556
                if columnsWidth != 0:
557
                    polExpStr = spo_expression_as_string(iPower, 
558
                                                         iBound,
559
                                                         0,      
560
                                                         tBound,
561
                                                         pPower, 
562
                                                         alpha-pPower)
563
                    print "->", polExpStr
564
                currentExpression = i^iPower * nAtPower * iBound^iPower
565
                currentPolynomial = pRing(currentExpression) * polynomialAtPower
566
                polynomialsList.append(currentPolynomial) 
567
            # End for iPower
568
        polynomialAtPower *= p  
569
        nAtPower /= N
570
    # End for pPower loop
571
    return polynomialsList
572
# End spo_polynomial_to_proto_matrix_2
573

    
574
def spo_polynomial_to_polynomials_list_3(p, alpha, N, iBound, tBound,
575
                                         columnsWidth=0):
576
    """
577
    From p, alpha, N build a list of polynomials...
578
    TODO: more in depth rationale...
579
    
580
    Our goal is to introduce each monomial with the smallest coefficient.
581
     
582
    
583
        
584
    Parameters
585
    ----------
586
    p: the (bivariate) polynomial;
587
    pRing: the ring over which p is defined;
588
    alpha:
589
    N:
590
    columsWidth: if == 0, no information is displayed, otherwise data is 
591
                 printed in colums of columnsWitdth width.
592
    """
593
    pRing = p.parent()
594
    polynomialsList = []
595
    pVariables = p.variables()
596
    iVariable = pVariables[0]
597
    tVariable = pVariables[1]
598
    polynomialAtPower = pRing(1)
599
    currentPolynomial = pRing(1)
600
    pIdegree = p.degree(iVariable)
601
    pTdegree = p.degree(tVariable)
602
    currentIdegree = currentPolynomial.degree(iVariable)
603
    nAtAlpha = N^alpha
604
    nAtPower = nAtAlpha
605
    polExpStr = ""
606
    # We work from p^0 * N^alpha to p^alpha * N^0
607
    for pPower in xrange(0, alpha + 1):
608
        # pPower == 0 is a special case. We introduce all the monomials in i 
609
        # up to i^pIdegree.
610
        if pPower == 0:
611
            # Notice who iPower runs up to i^pIdegree.
612
            for iPower in xrange(0, pIdegree + 1): 
613
                # No t power is taken into account as we limit our selves to
614
                # degree 1 in t and make no "t-shifts".
615
                if columnsWidth != 0:
616
                    polExpStr = spo_expression_as_string(iPower, 
617
                                                         iBound,
618
                                                         0, 
619
                                                         tBound,
620
                                                         0, 
621
                                                         alpha)
622
                    print "->", polExpStr
623
                currentExpression = iVariable^iPower * nAtAlpha * iBound^iPower
624
                # polynomialAtPower == 1 here. Next line should be commented
625
                # out but it does not work! Some conversion problem?
626
                currentPolynomial = pRing(currentExpression)
627
                polynomialsList.append(currentPolynomial) 
628
            # End for iPower.
629
        else: # pPower > 0: (p^1..p^alpha)
630
            # This where we introduce the p^pPower * N^(alpha-pPower)
631
            # polynomial. This is also where the t^pPower monomials shows up for
632
            # the first time. It app
633
            if columnsWidth != 0:
634
                polExpStr = spo_expression_as_string(0, iBound, 
635
                                                     0, tBound,
636
                                                     pPower, alpha-pPower)
637
                print "->", polExpStr
638
            currentPolynomial = polynomialAtPower * nAtPower
639
            polynomialsList.append(currentPolynomial) 
640
            # Exit when pPower == alpha
641
            if pPower == alpha:
642
                return polynomialsList
643
            # This is where the "i-shifts" take place. Mixed terms, i^k * t^l
644
            # (that were introduced at a previous
645
            # stage or are introduced now) are only shifted to already existing 
646
            # ones with the notable exception of i^iPower * t^pPower, which
647
            # must be manually introduced.
648
            # p^pPower is "shifted" to higher degrees in i as far as 
649
            # possible, up to of the degree in i of p^(pPower+1).
650
            # These "pure" i^k monomials can only show up with i multiplications.
651
            for iPower in xrange(1, pIdegree + 1):
652
                # The i^iPower * t^pPower monomial. Notice the alpha exponent
653
                # for N.
654
                internalIpower = iPower
655
                for tPower in xrange(pPower,0,-1):
656
                    if columnsWidth != 0:
657
                        polExpStr = spo_expression_as_string(internalIpower,
658
                                                             iBound, 
659
                                                             tPower,  
660
                                                             tBound,
661
                                                             0,
662
                                                             alpha)
663
                        print "->", polExpStr
664
                    currentExpression = i^internalIpower * t^tPower * nAtAlpha * \
665
                                        iBound^internalIpower * tBound^tPower
666
                    currentPolynomial = pRing(currentExpression)
667
                    polynomialsList.append(currentPolynomial) 
668
                    internalIpower += pIdegree
669
                # End for tPower
670
                # Here we have to choose between a 
671
                # i^iPower * p^pPower * N^(alpha-pPower) i-shift and
672
                # i^iPower * i^(d_i(p) * pPower) * N^alpha, depending on which 
673
                # coefficient is smallest.
674
                IcurrentExponent = iPower + \
675
                                (pPower * polynomialAtPower.degree(iVariable))
676
                currentMonomial = pRing(iVariable^IcurrentExponent)
677
                currentPolynomial = pRing(iVariable^iPower * nAtPower * \
678
                                          iBound^iPower) * \
679
                                          polynomialAtPower
680
                currMonomials = currentPolynomial.monomials()
681
                currCoefficients = currentPolynomial.coefficients()
682
                currentCoefficient = spo_get_coefficient_for_monomial( \
683
                                                    currMonomials, 
684
                                                    currCoefficients, 
685
                                                    currentMonomial)
686
                print "Current coefficient:", currentCoefficient
687
                alterCoefficient = iBound^IcurrentExponent * nAtAlpha 
688
                print "N^alpha * ibound^", IcurrentExponent, ":", \
689
                         alterCoefficient
690
                if currentCoefficient > alterCoefficient :
691
                    if columnsWidth != 0:
692
                        polExpStr = spo_expression_as_string(IcurrentExponent,
693
                                                             iBound,
694
                                                             0,
695
                                                             tBound,
696
                                                             0,
697
                                                             alpha)
698
                        print "->", polExpStr
699
                    polynomialsList.append(currentMonomial * \
700
                                           alterCoefficient)
701
                else:
702
                    if columnsWidth != 0:
703
                        polExpStr = spo_expression_as_string(iPower, iBound,
704
                                                             0, tBound,
705
                                                             pPower, 
706
                                                             alpha-pPower)
707
                        print "->", polExpStr
708
                    polynomialsList.append(currentPolynomial) 
709
            # End for iPower
710
        polynomialAtPower *= p  
711
        nAtPower /= N
712
    # End for pPower loop
713
    return polynomialsList 
714
# End spo_polynomial_to_proto_matrix_3
715

    
716
def spo_polynomial_to_polynomials_list_4(p, alpha, N, iBound, tBound,
717
                                         columnsWidth=0):
718
    """
719
    From p, alpha, N build a list of polynomials...
720
    TODO: more in depth rationale...
721
    
722
    Our goal is to introduce each monomial with the smallest coefficient.
723
     
724
    
725
        
726
    Parameters
727
    ----------
728
    p: the (bivariate) polynomial;
729
    pRing: the ring over which p is defined;
730
    alpha:
731
    N:
732
    columsWidth: if == 0, no information is displayed, otherwise data is 
733
                 printed in colums of columnsWitdth width.
734
    """
735
    pRing = p.parent()
736
    polynomialsList = []
737
    pVariables = p.variables()
738
    iVariable = pVariables[0]
739
    tVariable = pVariables[1]
740
    polynomialAtPower = copy(p)
741
    currentPolynomial = pRing(1)
742
    pIdegree = p.degree(iVariable)
743
    pTdegree = p.degree(tVariable)
744
    maxIdegree = pIdegree * alpha
745
    currentIdegree = currentPolynomial.degree(iVariable)
746
    nAtAlpha = N^alpha
747
    nAtPower = nAtAlpha
748
    polExpStr = ""
749
    # We first introduce all the monomials in i alone multiplied by N^alpha.
750
    for iPower in xrange(0, maxIdegree + 1):
751
        if columnsWidth !=0:
752
            polExpStr = spo_expression_as_string(iPower, iBound,
753
                                                 0, tBound, 
754
                                                 0, alpha)
755
            print "->", polExpStr
756
        currentExpression = iVariable^iPower * nAtAlpha * iBound^iPower
757
        currentPolynomial = pRing(currentExpression)
758
        polynomialsList.append(currentPolynomial)
759
    # End for iPower
760
    # We work from p^1 * N^alpha-1 to p^alpha * N^0
761
    for pPower in xrange(1, alpha + 1):
762
        # First of all the p^pPower * N^(alpha-pPower) polynomial.
763
        nAtPower /= N
764
        if columnsWidth !=0:
765
            polExpStr = spo_expression_as_string(0, iBound,
766
                                                 0, tBound,
767
                                                 pPower, alpha-pPower)
768
            print "->", polExpStr
769
        currentPolynomial = polynomialAtPower * nAtPower
770
        polynomialsList.append(currentPolynomial)
771
        # Exit when pPower == alpha
772
        if pPower == alpha:
773
            return polynomialsList
774
        # We now introduce the mixed i^k * t^l monomials by i^m * p^n * N^(alpha-n)
775
        for iPower in xrange(1, pIdegree + 1): 
776
            if columnsWidth != 0:
777
                polExpStr = spo_expression_as_string(iPower, iBound,
778
                                                     0, tBound, 
779
                                                     pPower, alpha-pPower)
780
                print "->", polExpStr
781
            currentExpression = i^iPower * iBound^iPower * nAtPower
782
            currentPolynomial = pRing(currentExpression) * polynomialAtPower
783
            polynomialsList.append(currentPolynomial) 
784
        # End for iPower
785
        polynomialAtPower *= p  
786
    # End for pPower loop
787
    return polynomialsList 
788
# End spo_polynomial_to_proto_matrix_4
789

    
790
def spo_polynomial_to_polynomials_list_5(p, alpha, N, iBound, tBound,
791
                                         columnsWidth=0):
792
    """
793
    From p, alpha, N build a list of polynomials use to create a base
794
    that will eventually be reduced with LLL.
795
    
796
    The bounds are computed for the coefficients that will be used to
797
    form the base.
798
    
799
    We try to introduce only one new monomial at a time, to obtain a
800
    triangular matrix (it is easy to compute the volume of the underlining
801
    latice if the matrix is triangular).
802

    
803
    There are many possibilities to introduce the monomials: our goal is also 
804
    to introduce each of them on the diagonal with the smallest coefficient.
805

    
806
    The method depends on the structure of the polynomial. Here it is adapted
807
    to the a_n*i^n + ... + a_1 * i - t + b form.     
808
        
809
    Parameters
810
    ----------
811
    p: the (bivariate) polynomial;
812
    alpha:
813
    N:
814
    iBound:
815
    tBound:
816
    columsWidth: if == 0, no information is displayed, otherwise data is 
817
                 printed in colums of columnsWitdth width.
818
    """
819
    pRing = p.parent()
820
    polynomialsList = []
821
    pVariables = p.variables()
822
    iVariable = pVariables[0]
823
    tVariable = pVariables[1]
824
    polynomialAtPower = copy(p)
825
    currentPolynomial = pRing(1)
826
    pIdegree = p.degree(iVariable)
827
    pTdegree = p.degree(tVariable)
828
    maxIdegree = pIdegree * alpha
829
    currentIdegree = currentPolynomial.degree(iVariable)
830
    nAtAlpha = N^alpha
831
    nAtPower = nAtAlpha
832
    polExpStr = ""
833
    # We first introduce all the monomials in i alone multiplied by N^alpha.
834
    for iPower in xrange(0, maxIdegree + 1):
835
        if columnsWidth !=0:
836
            polExpStr = spo_expression_as_string(iPower, iBound,
837
                                                 0, tBound, 
838
                                                 0, alpha)
839
            print "->", polExpStr
840
        currentExpression = iVariable^iPower * nAtAlpha * iBound^iPower
841
        currentPolynomial = pRing(currentExpression)
842
        polynomialsList.append(currentPolynomial)
843
    # End for iPower
844
    # We work from p^1 * N^alpha-1 to p^alpha * N^0
845
    for pPower in xrange(1, alpha + 1):
846
        # First of all the p^pPower * N^(alpha-pPower) polynomial.
847
        nAtPower /= N
848
        if columnsWidth !=0:
849
            polExpStr = spo_expression_as_string(0, iBound,
850
                                                 0, tBound,
851
                                                 pPower, alpha-pPower)
852
            print "->", polExpStr
853
        currentPolynomial = polynomialAtPower * nAtPower
854
        polynomialsList.append(currentPolynomial)
855
        # Exit when pPower == alpha
856
        if pPower == alpha:
857
            return polynomialsList
858
        for iPower in xrange(1, pIdegree + 1):
859
            iCurrentPower = pIdegree + iPower
860
            for tPower in xrange(pPower-1, 0, -1):
861
                #print "tPower:", tPower
862
                if columnsWidth != 0:
863
                    polExpStr = spo_expression_as_string(iCurrentPower, iBound,
864
                                                         tPower, tBound, 
865
                                                         0, alpha)
866
                    print "->", polExpStr
867
                currentExpression = i^iCurrentPower * iBound^iCurrentPower * t^tPower * tBound^tPower *nAtAlpha 
868
                currentPolynomial = pRing(currentExpression)
869
                polynomialsList.append(currentPolynomial)
870
                iCurrentPower += pIdegree 
871
            # End for tPower 
872
        # We now introduce the mixed i^k * t^l monomials by i^m * p^n * N^(alpha-n)
873
            if columnsWidth != 0:
874
                polExpStr = spo_expression_as_string(iPower, iBound,
875
                                                     0, tBound, 
876
                                                     pPower, alpha-pPower)
877
                print "->", polExpStr
878
            currentExpression = i^iPower * iBound^iPower * nAtPower
879
            currentPolynomial = pRing(currentExpression) * polynomialAtPower
880
            polynomialsList.append(currentPolynomial) 
881
        # End for iPower
882
        polynomialAtPower *= p  
883
    # End for pPower loop
884
    return polynomialsList 
885
# End spo_polynomial_to_proto_matrix_5
886

    
887
def spo_polynomial_to_polynomials_list_6(p, alpha, N, iBound, tBound,
888
                                         columnsWidth=0):
889
    """
890
    From p, alpha, N build a list of polynomials use to create a base
891
    that will eventually be reduced with LLL.
892
    
893
    The bounds are computed for the coefficients that will be used to
894
    form the base.
895
    
896
    We try to introduce only one new monomial at a time, whithout trying to
897
    obtain a triangular matrix.
898

    
899
    There are many possibilities to introduce the monomials: our goal is also 
900
    to introduce each of them on the diagonal with the smallest coefficient.
901

    
902
    The method depends on the structure of the polynomial. Here it is adapted
903
    to the a_n*i^n + ... + a_1 * i - t + b form.     
904
        
905
    Parameters
906
    ----------
907
    p: the (bivariate) polynomial;
908
    alpha:
909
    N:
910
    iBound:
911
    tBound:
912
    columsWidth: if == 0, no information is displayed, otherwise data is 
913
                 printed in colums of columnsWitdth width.
914
    """
915
    pRing = p.parent()
916
    polynomialsList = []
917
    pVariables = p.variables()
918
    iVariable = pVariables[0]
919
    tVariable = pVariables[1]
920
    polynomialAtPower = copy(p)
921
    currentPolynomial = pRing(1)     # Constant term.
922
    pIdegree = p.degree(iVariable)
923
    pTdegree = p.degree(tVariable)
924
    maxIdegree = pIdegree * alpha
925
    currentIdegree = currentPolynomial.degree(iVariable)
926
    nAtAlpha = N^alpha
927
    nAtPower = nAtAlpha
928
    polExpStr = ""
929
    #
930
    """
931
    ## Bound for iPower + pIdegree*tPower <= alpha*pIdegree
932
    print "degree in i:", pIdegree
933
    powersRangeUpperBound = alpha * pIdegree + 1 # +1 for the range.
934
    for iPower in xrange(0, powersRangeUpperBound):
935
        tPower = 0
936
        while (iPower + tPower * pIdegree) < powersRangeUpperBound:
937
                print "iPower:", iPower, " tPower:", tPower
938
                q = pRing(iVariable * iBound)^iPower * ((p * N)^tPower)
939
                print "q monomials:", q.monomials()
940
                polynomialsList.append(q)
941
                tPower += 1
942
    """
943
    """
944
    Start from iExp = 0 since starting from 1 does not allow for 
945
    resultants != 0.
946
    """
947
    for iExp in xrange(0, alpha+1):
948
        tExp = 0
949
        while iExp + tExp <= alpha:
950
            q = pRing(iVariable * iBound)^iExp * ((p * N)^tExp)
951
            sys.stdout.write("q " + str(iExp) + "," + str(tExp) + ": ")
952
            print q
953
            polynomialsList.append(q)
954
            tExp += 1
955
    return polynomialsList
956
                
957
    """
958
    # We first introduce all the monomials in i alone multiplied by N^alpha.
959
    for iPower in xrange(0, maxIdegree + 1):
960
        if columnsWidth !=0:
961
            polExpStr = spo_expression_as_string(iPower, iBound,
962
                                                 0, tBound, 
963
                                                 0, alpha)
964
            print "->", polExpStr
965
        currentExpression = iVariable^iPower * nAtAlpha * iBound^iPower
966
        currentPolynomial = pRing(currentExpression)
967
        polynomialsList.append(currentPolynomial)
968
    # End for iPower
969
    # We work from p^1 * N^alpha-1 to p^alpha * N^0
970
    for pPower in xrange(1, alpha + 1):
971
        # First of all the p^pPower * N^(alpha-pPower) polynomial.
972
        nAtPower /= N
973
        if columnsWidth !=0:
974
            polExpStr = spo_expression_as_string(0, iBound,
975
                                                 0, tBound,
976
                                                 pPower, alpha-pPower)
977
            print "->", polExpStr
978
        currentPolynomial = polynomialAtPower * nAtPower
979
        polynomialsList.append(currentPolynomial)
980
        # Exit when pPower == alpha
981
        if pPower == alpha:
982
            return polynomialsList
983
        for iPower in xrange(1, pIdegree + 1):
984
            iCurrentPower = pIdegree + iPower
985
            for tPower in xrange(pPower-1, 0, -1):
986
                #print "tPower:", tPower
987
                if columnsWidth != 0:
988
                    polExpStr = spo_expression_as_string(iCurrentPower, iBound,
989
                                                         tPower, tBound, 
990
                                                         0, alpha)
991
                    print "->", polExpStr
992
                currentExpression = i^iCurrentPower * iBound^iCurrentPower * t^tPower * tBound^tPower *nAtAlpha 
993
                currentPolynomial = pRing(currentExpression)
994
                polynomialsList.append(currentPolynomial)
995
                iCurrentPower += pIdegree 
996
            # End for tPower 
997
        # We now introduce the mixed i^k * t^l monomials by i^m * p^n * N^(alpha-n)
998
            if columnsWidth != 0:
999
                polExpStr = spo_expression_as_string(iPower, iBound,
1000
                                                     0, tBound, 
1001
                                                     pPower, alpha-pPower)
1002
                print "->", polExpStr
1003
            currentExpression = i^iPower * iBound^iPower * nAtPower
1004
            currentPolynomial = pRing(currentExpression) * polynomialAtPower
1005
            polynomialsList.append(currentPolynomial) 
1006
        # End for iPower
1007
        polynomialAtPower *= p  
1008
    # End for pPower loop
1009
    """
1010
    return polynomialsList 
1011
# End spo_polynomial_to_proto_matrix_6
1012

    
1013
def spo_polynomial_to_polynomials_list_7(p, alpha, N, iBound, tBound,
1014
                                         columnsWidth=0):
1015
    """
1016
    As per Random Bits... direct loops nesting.
1017
    """
1018
    pRing = p.parent()
1019
    polynomialsList = []
1020
    pVariables = p.variables()
1021
    iVariable = pVariables[0]
1022
    tVariable = pVariables[1]
1023
    polynomialAtPower = copy(p)
1024
    currentPolynomial = pRing(1)     # Constant term.
1025

    
1026
    for iExp in xrange(0, alpha+1):
1027
        pExp = 0
1028
        while (iExp + pExp) <= alpha:
1029
            print "iExp:", iExp, \
1030
                "- pExp:", pExp, \
1031
                "- alpha-pExp:", alpha-pExp
1032
            q = pRing(iVariable * iBound)^iExp * p^pExp * N^(alpha-pExp)
1033
            print q.monomials()
1034
            polynomialsList.append(q)
1035
            pExp += 1
1036
    return polynomialsList
1037
# End spo_polynomial_to_polynomials_list_7
1038

    
1039
def spo_polynomial_to_polynomials_list_8(p, alpha, N, iBound, tBound,
1040
                                         columnsWidth=0):
1041
    """
1042
    As per Random Bits... (reversed loop nesting)
1043
    """
1044
    pRing = p.parent()
1045
    polynomialsList = []
1046
    pVariables = p.variables()
1047
    iVariable = pVariables[0]
1048
    tVariable = pVariables[1]
1049
    polynomialAtPower = copy(p)
1050
    currentPolynomial = pRing(1)     # Constant term.
1051
     
1052
    for pExp in xrange(0, alpha+1):
1053
        iExp = 0
1054
        while (iExp + pExp) <= alpha:
1055
            #print "iExp:", iExp, \
1056
            #    "- pExp:", pExp, \
1057
            #    "- alpha-pExp:", alpha-pExp
1058
            q = pRing(iVariable * iBound)^iExp * p^pExp * N^(alpha-pExp)
1059
            #print q.monomials()
1060
            polynomialsList.append(q)
1061
            iExp += 1
1062
    return polynomialsList
1063
# End spo_polynomial_to_polynomials_list_8
1064

    
1065
def spo_proto_to_column_matrix(protoMatrixColumns):
1066
    """
1067
    Create a column (each row holds the coefficients for one monomial) matrix.
1068
    
1069
    Parameters
1070
    ----------
1071
    protoMatrixColumns: a list of coefficient lists.
1072
    """
1073
    numColumns = len(protoMatrixColumns)
1074
    if numColumns == 0:
1075
        return None
1076
    # The last column holds has the maximum length. 
1077
    numRows = len(protoMatrixColumns[numColumns-1])
1078
    if numColumns == 0:
1079
        return None
1080
    baseMatrix = matrix(ZZ, numRows, numColumns)
1081
    for colIndex in xrange(0, numColumns):
1082
        for rowIndex in xrange(0, len(protoMatrixColumns[colIndex])):
1083
            if protoMatrixColumns[colIndex][rowIndex] != 0:
1084
                baseMatrix[rowIndex, colIndex] = \
1085
                    protoMatrixColumns[colIndex][rowIndex]
1086
    return baseMatrix
1087
# End spo_proto_to_column_matrix.
1088
#
1089
def spo_proto_to_row_matrix(protoMatrixRows):
1090
    """
1091
    Create a row (each column holds the coefficients corresponding to one 
1092
    monomial) matrix from the protoMatrixRows list.
1093
    
1094
    Parameters
1095
    ----------
1096
    protoMatrixRows: a list of coefficient lists.
1097
    """
1098
    numRows = len(protoMatrixRows)
1099
    if numRows == 0:
1100
        return None
1101
    # Search for the longest row to get the number of columns.
1102
    numColumns = 0
1103
    for row in protoMatrixRows:
1104
        rowLength = len(row)
1105
        if numColumns < rowLength:
1106
            numColumns = rowLength
1107
    if numColumns == 0:
1108
        return None
1109
    baseMatrix = matrix(ZZ, numRows, numColumns)
1110
    for rowIndex in xrange(0, numRows):
1111
        for colIndex in xrange(0, len(protoMatrixRows[rowIndex])):
1112
            if protoMatrixRows[rowIndex][colIndex] !=  0:
1113
                baseMatrix[rowIndex, colIndex] = \
1114
                    protoMatrixRows[rowIndex][colIndex]
1115
            #print rowIndex, colIndex,
1116
            #print protoMatrixRows[rowIndex][colIndex],
1117
            #print knownMonomialsList[colIndex](boundVar1,boundVar2)
1118
    return baseMatrix
1119
# End spo_proto_to_row_matrix.
1120
#
1121
print "\t...sagePolynomialOperations loaded"