Révision 247

pobysoPythonSage/src/sageSLZ/runSLZ-113gram.sage (revision 247)
1 1
#! /opt/sage/sage
2
# @file runSLZ-113.sage
2
# @file runSLZ-113gram.sage
3 3
#
4
#@par Changes from runSLZ-113.sage
5
# LLL reduction is not performed on the matrix itself but on its Gram matrix as
6
# an attempt for a faster reduction.
7
#
4 8
# Run SLZ for p=113
5 9
#from scipy.constants.codata import precision
6 10
def initialize_env():
pobysoPythonSage/src/sageSLZ/sageSLZ.sage (revision 247)
371 371
    return ccReducedPolynomialsList
372 372
# End slz_compute_coppersmith_reduced_polynomials_gram
373 373
#
374
def slz_compute_coppersmith_reduced_polynomials_proj(inputPolynomial,
375
                                                     alpha,
376
                                                     N,
377
                                                     iBound,
378
                                                     tBound,
379
                                                     debug = False):
380
    """
381
    For a given set of arguments (see below), compute a list
382
    of "reduced polynomials" that could be used to compute roots
383
    of the inputPolynomial.
384
    INPUT:
385
    
386
    - "inputPolynomial" -- (no default) a bivariate integer polynomial;
387
    - "alpha" -- the alpha parameter of the Coppersmith algorithm;
388
    - "N" -- the modulus;
389
    - "iBound" -- the bound on the first variable;
390
    - "tBound" -- the bound on the second variable.
391
    
392
    OUTPUT:
393
    
394
    A list of bivariate integer polynomial obtained using the Coppersmith
395
    algorithm. The polynomials correspond to the rows of the LLL-reduce
396
    reduced base that comply with the Coppersmith condition.
397
    """
398
    #@par Changes from runSLZ-113.sage
399
    # LLL reduction is not performed on the matrix itself but rather on the
400
    # product of the matrix with a uniform random matrix.
401
    # The reduced matrix obtained is discarded but the transformation matrix 
402
    # obtained is used to multiply the original matrix in order to reduced it.
403
    # If a sufficient level of reduction is obtained, we stop here. If not
404
    # the product matrix obtained above is LLL reduced. But as it has been
405
    # pre-reduced at the above step, reduction is supposed to be much faster.
406
    #
407
    # Arguments check.
408
    if iBound == 0 or tBound == 0:
409
        return None
410
    # End arguments check.
411
    nAtAlpha = N^alpha
412
    ## Building polynomials for matrix.
413
    polyRing   = inputPolynomial.parent()
414
    # Whatever the 2 variables are actually called, we call them
415
    # 'i' and 't' in all the variable names.
416
    (iVariable, tVariable) = inputPolynomial.variables()[:2]
417
    #print polyVars[0], type(polyVars[0])
418
    initialPolynomial = inputPolynomial.subs({iVariable:iVariable * iBound,
419
                                              tVariable:tVariable * tBound})
420
    if debug:
421
        polynomialsList = \
422
            spo_polynomial_to_polynomials_list_8(initialPolynomial,
423
                                                 alpha,
424
                                                 N,
425
                                                 iBound,
426
                                                 tBound,
427
                                                 20)
428
    else:
429
        polynomialsList = \
430
            spo_polynomial_to_polynomials_list_8(initialPolynomial,
431
                                                 alpha,
432
                                                 N,
433
                                                 iBound,
434
                                                 tBound,
435
                                                 0)
436
    #print "Polynomials list:", polynomialsList
437
    ## Building the proto matrix.
438
    knownMonomials = []
439
    protoMatrix    = []
440
    if debug:
441
        for poly in polynomialsList:
442
            spo_add_polynomial_coeffs_to_matrix_row(poly,
443
                                                    knownMonomials,
444
                                                    protoMatrix,
445
                                                    20)
446
    else:
447
        for poly in polynomialsList:
448
            spo_add_polynomial_coeffs_to_matrix_row(poly,
449
                                                    knownMonomials,
450
                                                    protoMatrix,
451
                                                    0)
452
    matrixToReduce = spo_proto_to_row_matrix(protoMatrix)
453
    #print matrixToReduce
454
    ## Reduction and checking.
455
    ### Reduction with projection
456
    (reducedMatrix1, reductionMatrix1) = \
457
         slz_reduce_lll_proj(matrixToReduce, 2^16)
458
    #print "Reduced matrix:"
459
    matrixIsReducedEnough = reducedMatrix1.is_LLL_reduced()
460
    #
461
    if not matrixIsReducedEnough:
462
        reducedMatrix = reducedMatrix1.LLL(algorithm='fpLLL:wrapper')
463
        isLLLReduced  = reducedMatrix.is_LLL_reduced()
464
    else:
465
        reducedMatrix = reducedMatrix1
466
        isLLLReduced  = matrixIsReducedEnough
467
    #for row in reducedMatrix.rows():
468
    #    print row
469
    if not isLLLReduced:
470
        return None
471
    monomialsCount     = len(knownMonomials)
472
    monomialsCountSqrt = sqrt(monomialsCount)
473
    #print "Monomials count:", monomialsCount, monomialsCountSqrt.n()
474
    #print reducedMatrix
475
    ## Check the Coppersmith condition for each row and build the reduced 
476
    #  polynomials.
477
    ccReducedPolynomialsList = []
478
    for row in reducedMatrix.rows():
479
        l2Norm = row.norm(2)
480
        if (l2Norm * monomialsCountSqrt) < nAtAlpha:
481
            #print (l2Norm * monomialsCountSqrt).n()
482
            #print l2Norm.n()
483
            ccReducedPolynomial = \
484
                slz_compute_reduced_polynomial(row,
485
                                               knownMonomials,
486
                                               iVariable,
487
                                               iBound,
488
                                               tVariable,
489
                                               tBound)
490
            if not ccReducedPolynomial is None:
491
                ccReducedPolynomialsList.append(ccReducedPolynomial)
492
        else:
493
            #print l2Norm.n() , ">", nAtAlpha
494
            pass
495
    if len(ccReducedPolynomialsList) < 2:
496
        print "Less than 2 Coppersmith condition compliant vectors."
497
        return ()
498
    #print ccReducedPolynomialsList
499
    return ccReducedPolynomialsList
500
# End slz_compute_coppersmith_reduced_polynomials_proj
501
#
374 502
def slz_compute_coppersmith_reduced_polynomials_with_lattice_volume(inputPolynomial,
375 503
                                                                    alpha,
376 504
                                                                    N,
......
1941 2069
    #  abs(quasiExactRF(roundedValuePrecPlusOnePrev) - quasiExactValue).n(prec=100).str(base=2)
1942 2070
    return False
1943 2071
# End slz_is_htrn
1944

  
2072
#
2073
def slz_pm1():
2074
    """
2075
    Compute a uniform RV in {-1, 1}.
2076
    """
2077
    ## function getrandbits(N) generates a long int with N random bits.
2078
    return getrandbits(1) * 2-1
2079
# End slz_pm1.
2080
#
2081
def slz_random_proj_pm1(r, c):
2082
    """
2083
    r x c matrix with \pm 1 ({-1, 1}) coefficients
2084
    """
2085
    M = matrix(r, c)
2086
    for i in range(0, r):
2087
        for j in range (0, c):
2088
            M[i,j] = slz_pm1()
2089
    return M
2090
# End random_proj_pm1.
2091
#
2092
def slz_random_proj_uniform(n, r, c):
2093
    """
2094
    r x c integer matrix with uniform n-bit integer coefficients
2095
    """
2096
    M = matrix(r, c)
2097
    for i in range(0, r):
2098
        for j in range (0, c):
2099
            M[i,j] = slz_uniform(n)
2100
    return M       
2101
# End slz_random_proj_uniform.
2102
#
1945 2103
def slz_rat_poly_of_int_to_poly_for_coppersmith(ratPolyOfInt, 
1946 2104
                                                precision,
1947 2105
                                                targetHardnessToRound,
......
2054 2212
    return ccComplientRowsList
2055 2213
# End slz_reduce_and_test_base
2056 2214

  
2215
def slz_reduce_lll_proj(matToReduce, n):
2216
    """
2217
    Compute the transformation matrix that realizes an LLL reduction on
2218
    the random uniform projected matrix.
2219
    Return both the initial matrix "reduced" by the transformation matrix and
2220
    the transformation matrix itself.
2221
    """
2222
    ## Compute the projected matrix.
2223
    matProjector = slz_random_proj_uniform(n,
2224
                                           matToReduce.ncols(),
2225
                                           matToReduce.nrows())
2226
    matProjected = matToReduce * matProjector
2227
    ## Build the argument matrix for LLL in such a way that the transformation
2228
    #  matrix is also returned. This matrix is obtained at almost no extra
2229
    # cost. An identity matrix must be appended to 
2230
    #  the left of the initial matrix. The transformation matrix will
2231
    # will be recovered at the same location from the returned matrix .
2232
    idMat = identity_matrix(matProjected.nrows())
2233
    augmentedMatToReduce = idMat.augment(matProjected)
2234
    reducedProjMat = \
2235
        augmentedMatToReduce.LLL(algorithm='fpLLL:wrapper')
2236
    ## Recover the transformation matrix (the left part of the reduced matrix). 
2237
    #  We discard the reduced matrix itself.
2238
    transMat = reducedProjMat.submatrix(0,
2239
                                        0,
2240
                                        reducedProjMat.nrows(),
2241
                                        reducedProjMat.nrows())
2242
    ## Return the initial matrix "reduced" and the transformation matrix tuple.
2243
    return (transMat * matToReduce, transMat)
2244
# End  slz_reduce_lll_proj.
2245
#
2057 2246
def slz_resultant(poly1, poly2, elimVar, debug = False):
2058 2247
    """
2059 2248
    Compute the resultant for two polynomials for a given variable
......
2098 2287
        return (poly1, poly2, resultantInElimVar)
2099 2288
# End slz_resultant_tuple.
2100 2289
#
2290
def slz_uniform(n):
2291
    """
2292
    Compute a uniform RV in {-1, 1}.
2293
    """
2294
    ## function getrandbits(n) generates a long int with n random bits.
2295
    return getrandbits(n) - 2^(n-1)
2296
# End slz_uniform.
2297
#
2101 2298
sys.stderr.write("\t...sageSLZ loaded\n")
2102 2299

  
pobysoPythonSage/src/sageSLZ/runSLZ-113proj.sage (revision 247)
1
#! /opt/sage/sage
2
# @file runSLZ-113proj.sage
3
#
4
#@par Changes from runSLZ-113.sage
5
# LLL reduction is not performed on the matrix itself but rather on the
6
# product of the matrix with a uniform random matrix.
7
# The reduced matrix obtained is discarded but the transformation matrix 
8
# obtained is used to multiply the original matrix in order to reduced it.
9
# If a sufficient level of reduction is obtained, we stop here. If not
10
# the product matrix obtained above is LLL reduced. But as it has been
11
# pre-reduced at the above step, reduction is supposed to be much faster.
12
#
13
# Both reductions combined should hopefully be faster than a straight single
14
# reduction.
15
#
16
# Run SLZ for p=113
17
#from scipy.constants.codata import precision
18
def initialize_env():
19
    """
20
    Load all necessary modules.
21
    """
22
    compiledSpyxDir = "/home/storres/recherche/arithmetique/pobysoPythonSage/compiledSpyx"
23
    if compiledSpyxDir not in sys.path:
24
        sys.path.append(compiledSpyxDir)
25
    if not 'mpfi' in sage.misc.cython.standard_libs:
26
        sage.misc.cython.standard_libs.append('mpfi')
27
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sollya_lib.sage")
28
#    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageMpfr.spyx")
29
#    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageGMP.spyx")
30
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/pobyso.py")
31
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageSLZ.sage")
32
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageNumericalOperations.sage")
33
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageRationalOperations.sage")
34
    # Matrix operations are loaded by polynomial operations.
35
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sagePolynomialOperations.sage")
36
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageRunSLZ.sage")
37

  
38

  
39
print "Running SLZ..."
40
initialize_env()
41
from sageMpfr import *
42
from sageGMP  import *
43
import sys
44
from subprocess import call
45
#
46
## Main variables and parameters.
47
x         = var('x')
48
func(x)   = exp(x)
49
precision = 113
50
emin      = -16382
51
emax      = 16383 
52
RRR = RealField(precision)
53
degree              = 0
54
alpha               = 0
55
htrn                = 0
56
intervalCenter      = 0
57
intervalRadius      = 0
58
debugMode           = False          
59
## Local functions
60
#
61
def usage():
62
    write = sys.stderr.write
63
    write("\nUsage:\n")
64
    write("  " + scriptName + " <degree> <alpha> <htrn> <intervalCenter>\n")
65
    write("               <numberOfNumbers> [debug]\n")
66
    write("\nArguments:\n")
67
    write("  degree          the degree of the polynomial (integer)\n")
68
    write("  alpha           alpha (integer)\n")
69
    write("  htrn            hardness-to-round - a number of bits (integer)\n")
70
    write("  intervalCenter  the interval center (a floating-point number)\n")
71
    write("  numberOfNumbers the number of floating-point numbers in the interval\n")
72
    write("                  as a positive integral expression\n")
73
    write("  debug           debug mode (\"debug\", in any case)\n\n")
74
    sys.exit(2)
75
# End usage.
76
#
77
argsCount = len(sys.argv)
78
scriptName = os.path.basename(__file__)
79
if argsCount < 5:
80
    usage()
81
for index in xrange(1,argsCount):
82
    if index == 1:
83
        degree = int(sys.argv[index])
84
    elif index == 2:
85
        alpha = int(sys.argv[index])
86
    elif index == 3:
87
        htrn = int(eval(sys.argv[index]))
88
    elif index == 4:
89
        try:
90
            intervalCenter = QQ(sage_eval(sys.argv[index]))
91
        except:
92
            intervalCenter = RRR(sys.argv[index])
93
        intervalCenter = RRR(intervalCenter)
94
    elif index == 5:
95
        ## Can be read as rational number but must end up as an integer.
96
        numberOfNumbers = QQ(sage_eval(sys.argv[index]))
97
        if numberOfNumbers != numberOfNumbers.round():
98
            raise Exception("Invalid number of numbers: " + sys.argv[index] + ".")
99
        numberOfNumbers = numberOfNumbers.round()
100
        ## The number must be strictly positive.
101
        if numberOfNumbers <= 0:
102
            raise Exception("Invalid number of numbers: " + sys.argv[index] + ".")
103
    elif index == 6:
104
        debugMode = sys.argv[index].upper()
105
        debugMode = (debugMode == "DEBUG")
106
# Done with command line arguments collection.
107
#
108
## Debug printing
109
print "degree         :", degree
110
print "alpha          :", alpha
111
print "htrn           :", htrn
112
print "interval center:", intervalCenter.n(prec=10).str(truncate=False)
113
print "num of nums    :", RR(numberOfNumbers).log2().n(prec=10).str(truncate=False)
114
print "debug mode     :", debugMode
115
print
116
#
117
## Set the terminal window title.
118
terminalWindowTitle = ['stt', str(degree), str(alpha), str(htrn), 
119
                       intervalCenter.n(prec=10).str(truncate=False), 
120
                       RRR(numberOfNumbers).log2().n(prec=10).str(truncate=False)]
121
call(terminalWindowTitle)
122
#
123
intervalCenterBinade = slz_compute_binade(intervalCenter)
124
intervalRadius       = \
125
    2^intervalCenterBinade * 2^(-precision + 1) * numberOfNumbers / 2
126
srs_run_SLZ_v05_gram(inputFunction=func, 
127
                     inputLowerBound         = intervalCenter - intervalRadius, 
128
                     inputUpperBound         = intervalCenter + intervalRadius, 
129
                     alpha                   = alpha, 
130
                     degree                  = degree, 
131
                     precision               = precision, 
132
                     emin                    = emin, 
133
                     emax                    = emax, 
134
                     targetHardnessToRound   = htrn, 
135
                     debug                   = debugMode)
136
    
0 137

  
pobysoPythonSage/src/sageSLZ/runSLZ-113gram.sage.py (revision 247)
1
# This file was *autogenerated* from the file ./runSLZ-113gram.sage
2
from sage.all_cmdline import *   # import sage library
3
_sage_const_3 = Integer(3); _sage_const_2 = Integer(2); _sage_const_1 = Integer(1); _sage_const_0 = Integer(0); _sage_const_6 = Integer(6); _sage_const_5 = Integer(5); _sage_const_4 = Integer(4); _sage_const_113 = Integer(113); _sage_const_10 = Integer(10); _sage_const_16383 = Integer(16383); _sage_const_16382 = Integer(16382)#! /opt/sage/sage
4
# @file runSLZ-113.sage
5
#
6
# Run SLZ for p=113
7
#from scipy.constants.codata import precision
8
def initialize_env():
9
    """
10
    Load all necessary modules.
11
    """
12
    compiledSpyxDir = "/home/storres/recherche/arithmetique/pobysoPythonSage/compiledSpyx"
13
    if compiledSpyxDir not in sys.path:
14
        sys.path.append(compiledSpyxDir)
15
    if not 'mpfi' in sage.misc.cython.standard_libs:
16
        sage.misc.cython.standard_libs.append('mpfi')
17
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sollya_lib.sage")
18
#    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageMpfr.spyx")
19
#    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageGMP.spyx")
20
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/pobyso.py")
21
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageSLZ.sage")
22
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageNumericalOperations.sage")
23
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageRationalOperations.sage")
24
    # Matrix operations are loaded by polynomial operations.
25
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sagePolynomialOperations.sage")
26
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageRunSLZ.sage")
27

  
28

  
29
print "Running SLZ..."
30
initialize_env()
31
from sageMpfr import *
32
from sageGMP  import *
33
import sys
34
from subprocess import call
35
#
36
## Main variables and parameters.
37
x         = var('x')
38
__tmp__=var("x"); func = symbolic_expression(exp(x)).function(x)
39
precision = _sage_const_113 
40
emin      = -_sage_const_16382 
41
emax      = _sage_const_16383  
42
RRR = RealField(precision)
43
degree              = _sage_const_0 
44
alpha               = _sage_const_0 
45
htrn                = _sage_const_0 
46
intervalCenter      = _sage_const_0 
47
intervalRadius      = _sage_const_0 
48
debugMode           = False          
49
## Local functions
50
#
51
def usage():
52
    write = sys.stderr.write
53
    write("\nUsage:\n")
54
    write("  " + scriptName + " <degree> <alpha> <htrn> <intervalCenter>\n")
55
    write("               <numberOfNumbers> [debug]\n")
56
    write("\nArguments:\n")
57
    write("  degree          the degree of the polynomial (integer)\n")
58
    write("  alpha           alpha (integer)\n")
59
    write("  htrn            hardness-to-round - a number of bits (integer)\n")
60
    write("  intervalCenter  the interval center (a floating-point number)\n")
61
    write("  numberOfNumbers the number of floating-point numbers in the interval\n")
62
    write("                  as a positive integral expression\n")
63
    write("  debug           debug mode (\"debug\", in any case)\n\n")
64
    sys.exit(_sage_const_2 )
65
# End usage.
66
#
67
argsCount = len(sys.argv)
68
scriptName = os.path.basename(__file__)
69
if argsCount < _sage_const_5 :
70
    usage()
71
for index in xrange(_sage_const_1 ,argsCount):
72
    if index == _sage_const_1 :
73
        degree = int(sys.argv[index])
74
    elif index == _sage_const_2 :
75
        alpha = int(sys.argv[index])
76
    elif index == _sage_const_3 :
77
        htrn = int(eval(sys.argv[index]))
78
    elif index == _sage_const_4 :
79
        try:
80
            intervalCenter = QQ(sage_eval(sys.argv[index]))
81
        except:
82
            intervalCenter = RRR(sys.argv[index])
83
        intervalCenter = RRR(intervalCenter)
84
    elif index == _sage_const_5 :
85
        ## Can be read as rational number but must end up as an integer.
86
        numberOfNumbers = QQ(sage_eval(sys.argv[index]))
87
        if numberOfNumbers != numberOfNumbers.round():
88
            raise Exception("Invalid number of numbers: " + sys.argv[index] + ".")
89
        numberOfNumbers = numberOfNumbers.round()
90
        ## The number must be strictly positive.
91
        if numberOfNumbers <= _sage_const_0 :
92
            raise Exception("Invalid number of numbers: " + sys.argv[index] + ".")
93
    elif index == _sage_const_6 :
94
        debugMode = sys.argv[index].upper()
95
        debugMode = (debugMode == "DEBUG")
96
# Done with command line arguments collection.
97
#
98
## Debug printing
99
print "degree         :", degree
100
print "alpha          :", alpha
101
print "htrn           :", htrn
102
print "interval center:", intervalCenter.n(prec=_sage_const_10 ).str(truncate=False)
103
print "num of nums    :", RR(numberOfNumbers).log2().n(prec=_sage_const_10 ).str(truncate=False)
104
print "debug mode     :", debugMode
105
print
106
#
107
## Set the terminal window title.
108
terminalWindowTitle = ['stt', str(degree), str(alpha), str(htrn), 
109
                       intervalCenter.n(prec=_sage_const_10 ).str(truncate=False), 
110
                       RRR(numberOfNumbers).log2().n(prec=_sage_const_10 ).str(truncate=False)]
111
call(terminalWindowTitle)
112
#
113
intervalCenterBinade = slz_compute_binade(intervalCenter)
114
intervalRadius       = \
115
    _sage_const_2 **intervalCenterBinade * _sage_const_2 **(-precision + _sage_const_1 ) * numberOfNumbers / _sage_const_2 
116
srs_run_SLZ_v05_gram(inputFunction=func, 
117
                     inputLowerBound         = intervalCenter - intervalRadius, 
118
                     inputUpperBound         = intervalCenter + intervalRadius, 
119
                     alpha                   = alpha, 
120
                     degree                  = degree, 
121
                     precision               = precision, 
122
                     emin                    = emin, 
123
                     emax                    = emax, 
124
                     targetHardnessToRound   = htrn, 
125
                     debug                   = debugMode)
126
    
0 127

  
pobysoPythonSage/src/sageSLZ/sageRunSLZ.sage (revision 247)
3460 3460
    ## Output counters
3461 3461
# End srs_runSLZ-v05_gram
3462 3462
#
3463
def srs_run_SLZ_v05_proj(inputFunction,
3464
                         inputLowerBound,
3465
                         inputUpperBound,
3466
                         alpha,
3467
                         degree,
3468
                         precision,
3469
                         emin,
3470
                         emax,
3471
                         targetHardnessToRound,
3472
                         debug = False):
3473
    """
3474
    changes from plain V5:
3475
       LLL reduction is not performed on the matrix itself but rather on the
3476
       product of the matrix with a uniform random matrix.
3477
       The reduced matrix obtained is discarded but the transformation matrix 
3478
       obtained is used to multiply the original matrix in order to reduced it.
3479
       If a sufficient level of reduction is obtained, we stop here. If not
3480
       the product matrix obtained above is LLL reduced. But as it has been
3481
       pre-reduced at the above step, reduction is supposed to be much fastet.
3482
       Both reductions combined should hopefully be faster than a straight
3483
       single reduction.
3484
    Changes from V4:
3485
        Approximation polynomial has coefficients rounded.
3486
    Changes from V3:
3487
        Root search is changed again:
3488
            - only resultants in i are computed;
3489
            - roots in i are searched for;
3490
            - if any, they are tested for hardness-to-round.
3491
    Changes from V2:
3492
        Root search is changed:
3493
            - we compute the resultants in i and in t;
3494
            - we compute the roots set of each of these resultants;
3495
            - we combine all the possible pairs between the two sets;
3496
            - we check these pairs in polynomials for correctness.
3497
    Changes from V1: 
3498
        1- check for roots as soon as a resultant is computed;
3499
        2- once a non null resultant is found, check for roots;
3500
        3- constant resultant == no root.
3501
    """
3502

  
3503
    if debug:
3504
        print "Function                :", inputFunction
3505
        print "Lower bound             :", inputLowerBound
3506
        print "Upper bounds            :", inputUpperBound
3507
        print "Alpha                   :", alpha
3508
        print "Degree                  :", degree
3509
        print "Precision               :", precision
3510
        print "Emin                    :", emin
3511
        print "Emax                    :", emax
3512
        print "Target hardness-to-round:", targetHardnessToRound
3513
        print
3514
    ## Important constants.
3515
    ### Stretch the interval if no error happens.
3516
    noErrorIntervalStretch = 1 + 2^(-5)
3517
    ### If no vector validates the Coppersmith condition, shrink the interval
3518
    #   by the following factor.
3519
    noCoppersmithIntervalShrink = 1/2
3520
    ### If only (or at least) one vector validates the Coppersmith condition, 
3521
    #   shrink the interval by the following factor.
3522
    oneCoppersmithIntervalShrink = 3/4
3523
    #### If only null resultants are found, shrink the interval by the 
3524
    #    following factor.
3525
    onlyNullResultantsShrink     = 3/4
3526
    ## Structures.
3527
    RRR         = RealField(precision)
3528
    RRIF        = RealIntervalField(precision)
3529
    ## Converting input bound into the "right" field.
3530
    lowerBound = RRR(inputLowerBound)
3531
    upperBound = RRR(inputUpperBound)
3532
    ## Before going any further, check domain and image binade conditions.
3533
    print inputFunction(1).n()
3534
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
3535
    if output is None:
3536
        print "Invalid domain/image binades. Domain:",\
3537
        lowerBound, upperBound, "Images:", \
3538
        inputFunction(lowerBound), inputFunction(upperBound)
3539
        raise Exception("Invalid domain/image binades.")
3540
    lb = output[0] ; ub = output[1]
3541
    if lb != lowerBound or ub != upperBound:
3542
        print "lb:", lb, " - ub:", ub
3543
        print "Invalid domain/image binades. Domain:",\
3544
        lowerBound, upperBound, "Images:", \
3545
        inputFunction(lowerBound), inputFunction(upperBound)
3546
        raise Exception("Invalid domain/image binades.")
3547
    #
3548
    ## Progam initialization
3549
    ### Approximation polynomial accuracy and hardness to round.
3550
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
3551
    polyTargetHardnessToRound = targetHardnessToRound + 1
3552
    ### Significand to integer conversion ratio.
3553
    toIntegerFactor           = 2^(precision-1)
3554
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
3555
    ### Variables and rings for polynomials and root searching.
3556
    i=var('i')
3557
    t=var('t')
3558
    inputFunctionVariable = inputFunction.variables()[0]
3559
    function = inputFunction.subs({inputFunctionVariable:i})
3560
    #  Polynomial Rings over the integers, for root finding.
3561
    Zi = ZZ[i]
3562
    Zt = ZZ[t]
3563
    Zit = ZZ[i,t]
3564
    ## Number of iterations limit.
3565
    maxIter = 100000
3566
    #
3567
    ## Set the variable name in Sollya.
3568
    pobyso_name_free_variable_sa_so(str(function.variables()[0]))
3569
    ## Compute the scaled function and the degree, in their Sollya version 
3570
    #  once for all.
3571
    (scaledf, sdlb, sdub, silb, siub) = \
3572
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
3573
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
3574
    #print "Scaled bounds:", sdlb, sdub
3575
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
3576
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
3577
    #
3578
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
3579
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
3580
    (unscalingFunction, scalingFunction) = \
3581
        slz_interval_scaling_expression(domainBoundsInterval, i)
3582
    #print scalingFunction, unscalingFunction
3583
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
3584
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
3585
    if internalSollyaPrec < 192:
3586
        internalSollyaPrec = 192
3587
    pobyso_set_prec_sa_so(internalSollyaPrec)
3588
    print "Sollya internal precision:", internalSollyaPrec
3589
    ## Some variables.
3590
    ### General variables
3591
    lb                  = sdlb
3592
    ub                  = sdub
3593
    nbw                 = 0
3594
    intervalUlp         = ub.ulp()
3595
    #### Will be set by slz_interval_and_polynomila_to_sage.
3596
    ic                  = 0 
3597
    icAsInt             = 0    # Set from ic.
3598
    solutionsSet        = set()
3599
    tsErrorWidth        = []
3600
    csErrorVectors      = []
3601
    csVectorsResultants = []
3602
    floatP              = 0  # Taylor polynomial.
3603
    floatPcv            = 0  # Ditto with variable change.
3604
    intvl               = "" # Taylor interval
3605
    terr                = 0  # Taylor error.
3606
    iterCount = 0
3607
    htrnSet = set()
3608
    ### Timers and counters.
3609
    wallTimeStart                   = 0
3610
    cpuTimeStart                    = 0
3611
    taylCondFailedCount             = 0
3612
    coppCondFailedCount             = 0
3613
    resultCondFailedCount           = 0
3614
    coppCondFailed                  = False
3615
    resultCondFailed                = False
3616
    globalResultsList               = []
3617
    basisConstructionsCount         = 0
3618
    basisConstructionsFullTime      = 0
3619
    basisConstructionTime           = 0
3620
    reductionsCount                 = 0
3621
    reductionsFullTime              = 0
3622
    reductionTime                   = 0
3623
    resultantsComputationsCount     = 0
3624
    resultantsComputationsFullTime  = 0
3625
    resultantsComputationTime       = 0
3626
    rootsComputationsCount          = 0
3627
    rootsComputationsFullTime       = 0
3628
    rootsComputationTime            = 0
3629
    print
3630
    ## Global times are started here.
3631
    wallTimeStart                   = walltime()
3632
    cpuTimeStart                    = cputime()
3633
    ## Main loop.
3634
    while True:
3635
        if lb >= sdub:
3636
            print "Lower bound reached upper bound."
3637
            break
3638
        if iterCount == maxIter:
3639
            print "Reached maxIter. Aborting"
3640
            break
3641
        iterCount += 1
3642
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
3643
            "log2(numbers)." 
3644
        ### Compute a Sollya polynomial that will honor the Taylor condition.
3645
        prceSo = slz_compute_polynomial_and_interval_01(scaledfSo,
3646
                                                        degreeSo,
3647
                                                        lb,
3648
                                                        ub,
3649
                                                        polyApproxAccur)
3650
        if debug:
3651
            print "Approximation polynomial computed."
3652
        if prceSo is None:
3653
            raise Exception("Could not compute an approximation polynomial.")
3654
        ### Convert back the data into Sage space.                         
3655
        (floatP, floatPcv, intvl, ic, terr) = \
3656
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
3657
                                                 prceSo[1], prceSo[2], 
3658
                                                 prceSo[3]))
3659
        intvl = RRIF(intvl)
3660
        ## Clean-up Sollya stuff.
3661
        for elem in prceSo:
3662
            sollya_lib_clear_obj(elem)
3663
        #print  floatP, floatPcv, intvl, ic, terr
3664
        #print floatP
3665
        #print intvl.endpoints()[0].n(), \
3666
        #      ic.n(),
3667
        #intvl.endpoints()[1].n()
3668
        ### Check returned data.
3669
        #### Is approximation error OK?
3670
        if terr > polyApproxAccur:
3671
            exceptionErrorMess  = \
3672
                "Approximation failed - computed error:" + \
3673
                str(terr) + " - target error: "
3674
            exceptionErrorMess += \
3675
                str(polyApproxAccur) + ". Aborting!"
3676
            raise Exception(exceptionErrorMess)
3677
        #### Is lower bound OK?
3678
        if lb != intvl.endpoints()[0]:
3679
            exceptionErrorMess =  "Wrong lower bound:" + \
3680
                               str(lb) + ". Aborting!"
3681
            raise Exception(exceptionErrorMess)
3682
        #### Set upper bound.
3683
        if ub > intvl.endpoints()[1]:
3684
            ub = intvl.endpoints()[1]
3685
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
3686
            "log2(numbers)." 
3687
            taylCondFailedCount += 1
3688
        #### Is interval not degenerate?
3689
        if lb >= ub:
3690
            exceptionErrorMess = "Degenerate interval: " + \
3691
                                "lowerBound(" + str(lb) +\
3692
                                ")>= upperBound(" + str(ub) + \
3693
                                "). Aborting!"
3694
            raise Exception(exceptionErrorMess)
3695
        #### Is interval center ok?
3696
        if ic <= lb or ic >= ub:
3697
            exceptionErrorMess =  "Invalid interval center for " + \
3698
                                str(lb) + ',' + str(ic) + ',' +  \
3699
                                str(ub) + ". Aborting!"
3700
            raise Exception(exceptionErrorMess)
3701
        ##### Current interval width and reset future interval width.
3702
        bw = ub - lb
3703
        nbw = 0
3704
        icAsInt = int(ic * toIntegerFactor)
3705
        #### The following ratio is always >= 1. In case we may want to
3706
        #    enlarge the interval
3707
        curTaylErrRat = polyApproxAccur / terr
3708
        ### Make the  integral transformations.
3709
        #### Bounds and interval center.
3710
        intIc = int(ic * toIntegerFactor)
3711
        intLb = int(lb * toIntegerFactor) - intIc
3712
        intUb = int(ub * toIntegerFactor) - intIc
3713
        #
3714
        #### Polynomials
3715
        basisConstructionTime         = cputime()
3716
        ##### To a polynomial with rational coefficients with rational arguments
3717
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
3718
        ##### To a polynomial with rational coefficients with integer arguments
3719
        ratIntP = \
3720
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
3721
        #####  Ultimately a multivariate polynomial with integer coefficients  
3722
        #      with integer arguments.
3723
        coppersmithTuple = \
3724
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP, 
3725
                                                        precision, 
3726
                                                        targetHardnessToRound, 
3727
                                                        i, t)
3728
        #### Recover Coppersmith information.
3729
        intIntP = coppersmithTuple[0]
3730
        N = coppersmithTuple[1]
3731
        nAtAlpha = N^alpha
3732
        tBound = coppersmithTuple[2]
3733
        leastCommonMultiple = coppersmithTuple[3]
3734
        iBound = max(abs(intLb),abs(intUb))
3735
        basisConstructionsFullTime        += cputime(basisConstructionTime)
3736
        basisConstructionsCount           += 1
3737
        #### Compute the matrix to reduce for debug purpose. Otherwise
3738
        #    slz_compute_coppersmith_reduced_polynomials does the job
3739
        #    invisibly.
3740
        if debug:
3741
            matrixToReduce = slz_compute_initial_lattice_matrix(intIntP,
3742
                                                                alpha,
3743
                                                                N,
3744
                                                                iBound,
3745
                                                                tBound)
3746
            maxNorm     = 0
3747
            latticeSize = 0
3748
            matrixFile = file('/tmp/matrixToReduce.txt', 'w')
3749
            for row in matrixToReduce.rows():
3750
                currentNorm = row.norm()
3751
                if currentNorm > maxNorm:
3752
                    maxNorm = currentNorm
3753
                latticeSize += 1
3754
                for elem in row:
3755
                    matrixFile.write(elem.str(base=2) + ",")
3756
                matrixFile.write("\n")
3757
            #matrixFile.write(matrixToReduce.str(radix="2") + "\n")
3758
            matrixFile.close()
3759
            #### We use here binary length as defined in LLL princepts.
3760
            binaryLength = latticeSize * log(maxNorm)
3761
            print "Binary length:", binaryLength.n()
3762
            raise Exception("Deliberate stop here.")
3763
        # End if debug
3764
        reductionTime                     = cputime()
3765
        #### Compute the reduced polynomials.
3766
        print "Starting reduction..."
3767
        ccReducedPolynomialsList =  \
3768
                slz_compute_coppersmith_reduced_polynomials_proj(intIntP, 
3769
                                                                 alpha, 
3770
                                                                 N, 
3771
                                                                 iBound, 
3772
                                                                 tBound)
3773
        print "...reduction accomplished in", cputime(reductionTime), "s."
3774
        if ccReducedPolynomialsList is None:
3775
            raise Exception("Reduction failed.")
3776
        reductionsFullTime    += cputime(reductionTime)
3777
        reductionsCount       += 1
3778
        if len(ccReducedPolynomialsList) < 2:
3779
            print "Nothing to form resultants with."
3780
            print
3781
            coppCondFailedCount += 1
3782
            coppCondFailed = True
3783
            ##### Apply a different shrink factor according to 
3784
            #  the number of compliant polynomials.
3785
            if len(ccReducedPolynomialsList) == 0:
3786
                ub = lb + bw * noCoppersmithIntervalShrink
3787
            else: # At least one compliant polynomial.
3788
                ub = lb + bw * oneCoppersmithIntervalShrink
3789
            if ub > sdub:
3790
                ub = sdub
3791
            if lb == ub:
3792
                raise Exception("Cant shrink interval \
3793
                anymore to get Coppersmith condition.")
3794
            nbw = 0
3795
            continue
3796
        #### We have at least two polynomials.
3797
        #    Let us try to compute resultants.
3798
        #    For each resultant computed, go for the solutions.
3799
        ##### Build the pairs list.
3800
        polyPairsList           = []
3801
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
3802
            for polyInnerIndex in xrange(polyOuterIndex+1, 
3803
                                         len(ccReducedPolynomialsList)):
3804
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
3805
                                      ccReducedPolynomialsList[polyInnerIndex]))
3806
        #### Actual root search.
3807
        iRootsSet           = set()
3808
        hasNonNullResultant = False
3809
        for polyPair in polyPairsList:
3810
            resultantsComputationTime   = cputime()
3811
            currentResultantI = \
3812
                slz_resultant(polyPair[0],
3813
                              polyPair[1],
3814
                              t)
3815
            resultantsComputationsCount    += 1
3816
            resultantsComputationsFullTime +=  \
3817
                cputime(resultantsComputationTime)
3818
            #### Function slz_resultant returns None both for None and O
3819
            #    resultants.
3820
            if currentResultantI is None:
3821
                print "Nul resultant"
3822
                continue # Next polyPair.
3823
            ## We deleted the currentResultantI computation.
3824
            #### We have a non null resultant. From now on, whatever this
3825
            #    root search yields, no extra root search is necessary.
3826
            hasNonNullResultant = True
3827
            #### A constant resultant leads to no root. Root search is done.
3828
            if currentResultantI.degree() < 1:
3829
                print "Resultant is constant:", currentResultantI
3830
                break # There is no root.
3831
            #### Actual iroots computation.
3832
            rootsComputationTime        = cputime()
3833
            iRootsList = Zi(currentResultantI).roots()
3834
            rootsComputationsCount      +=  1
3835
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
3836
            if len(iRootsList) == 0:
3837
                print "No roots in \"i\"."
3838
                break # No roots in i.
3839
            else:
3840
                for iRoot in iRootsList:
3841
                    # A root is given as a (value, multiplicity) tuple.
3842
                    iRootsSet.add(iRoot[0])
3843
        # End loop for polyPair in polyParsList. We only loop again if a 
3844
        # None or zero resultant is found.
3845
        #### Prepare for results for the current interval..
3846
        intervalResultsList = []
3847
        intervalResultsList.append((lb, ub))
3848
        #### Check roots.
3849
        rootsResultsList = []
3850
        for iRoot in iRootsSet:
3851
            specificRootResultsList = []
3852
            failingBounds           = []
3853
            # Root qualifies for modular equation, test it for hardness to round.
3854
            hardToRoundCaseAsFloat = RRR((icAsInt + iRoot) / toIntegerFactor)
3855
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
3856
            #print scalingFunction
3857
            scaledHardToRoundCaseAsFloat = \
3858
                scalingFunction(hardToRoundCaseAsFloat) 
3859
            print "Candidate HTRNc at x =", \
3860
                scaledHardToRoundCaseAsFloat.n().str(base=2),
3861
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
3862
                           function,
3863
                           2^-(targetHardnessToRound),
3864
                           RRR):
3865
                print hardToRoundCaseAsFloat, "is HTRN case."
3866
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
3867
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
3868
                    print "Found in interval."
3869
                else:
3870
                    print "Found out of interval."
3871
                # Check the i root is within the i bound.
3872
                if abs(iRoot) > iBound:
3873
                    print "IRoot", iRoot, "is out of bounds for modular equation."
3874
                    print "i bound:", iBound
3875
                    failingBounds.append('i')
3876
                    failingBounds.append(iRoot)
3877
                    failingBounds.append(iBound)
3878
                if len(failingBounds) > 0:
3879
                    specificRootResultsList.append(failingBounds)
3880
            else: # From slz_is_htrn...
3881
                print "is not an HTRN case."
3882
            if len(specificRootResultsList) > 0:
3883
                rootsResultsList.append(specificRootResultsList)
3884
        if len(rootsResultsList) > 0:
3885
            intervalResultsList.append(rootsResultsList)
3886
        ### Check if a non null resultant was found. If not shrink the interval.
3887
        if not hasNonNullResultant:
3888
            print "Only null resultants for this reduction, shrinking interval."
3889
            resultCondFailed      =  True
3890
            resultCondFailedCount += 1
3891
            ### Shrink interval for next iteration.
3892
            ub = lb + bw * onlyNullResultantsShrink
3893
            if ub > sdub:
3894
                ub = sdub
3895
            nbw = 0
3896
            continue
3897
        #### An intervalResultsList has at least the bounds.
3898
        globalResultsList.append(intervalResultsList)   
3899
        #### Compute an incremented width for next upper bound, only
3900
        #    if not Coppersmith condition nor resultant condition
3901
        #    failed at the previous run. 
3902
        if not coppCondFailed and not resultCondFailed:
3903
            nbw = noErrorIntervalStretch * bw
3904
        else:
3905
            nbw = bw
3906
        ##### Reset the failure flags. They will be raised
3907
        #     again if needed.
3908
        coppCondFailed   = False
3909
        resultCondFailed = False
3910
        #### For next iteration (at end of loop)
3911
        #print "nbw:", nbw
3912
        lb  = ub
3913
        ub += nbw     
3914
        if ub > sdub:
3915
            ub = sdub
3916
        print
3917
    # End while True
3918
    ## Main loop just ended.
3919
    globalWallTime = walltime(wallTimeStart)
3920
    globalCpuTime  = cputime(cpuTimeStart)
3921
    ## Output results
3922
    print ; print "Intervals and HTRNs" ; print
3923
    for intervalResultsList in globalResultsList:
3924
        intervalResultString = "[" + str(intervalResultsList[0][0]) +\
3925
                               "," + str(intervalResultsList[0][1])  + "]"
3926
        print intervalResultString,
3927
        if len(intervalResultsList) > 1:
3928
            rootsResultsList = intervalResultsList[1]
3929
            specificRootResultIndex = 0
3930
            for specificRootResultsList in rootsResultsList:
3931
                if specificRootResultIndex == 0:
3932
                    print "\t", specificRootResultsList[0],
3933
                else:
3934
                    print " " * len(intervalResultString), "\t", \
3935
                          specificRootResultsList[0],
3936
                if len(specificRootResultsList) > 1:
3937
                    print specificRootResultsList[1]
3938
                specificRootResultIndex += 1
3939
        print ; print
3940
    #print globalResultsList
3941
    #
3942
    print "Timers and counters"
3943
    print
3944
    print "Number of iterations:", iterCount
3945
    print "Taylor condition failures:", taylCondFailedCount
3946
    print "Coppersmith condition failures:", coppCondFailedCount
3947
    print "Resultant condition failures:", resultCondFailedCount
3948
    print "Iterations count: ", iterCount
3949
    print "Number of intervals:", len(globalResultsList)
3950
    print "Number of basis constructions:", basisConstructionsCount 
3951
    print "Total CPU time spent in basis constructions:", \
3952
        basisConstructionsFullTime
3953
    if basisConstructionsCount != 0:
3954
        print "Average basis construction CPU time:", \
3955
            basisConstructionsFullTime/basisConstructionsCount
3956
    print "Number of reductions:", reductionsCount
3957
    print "Total CPU time spent in reductions:", reductionsFullTime
3958
    if reductionsCount != 0:
3959
        print "Average reduction CPU time:", \
3960
            reductionsFullTime/reductionsCount
3961
    print "Number of resultants computation rounds:", \
3962
        resultantsComputationsCount
3963
    print "Total CPU time spent in resultants computation rounds:", \
3964
        resultantsComputationsFullTime
3965
    if resultantsComputationsCount != 0:
3966
        print "Average resultants computation round CPU time:", \
3967
            resultantsComputationsFullTime/resultantsComputationsCount
3968
    print "Number of root finding rounds:", rootsComputationsCount
3969
    print "Total CPU time spent in roots finding rounds:", \
3970
        rootsComputationsFullTime
3971
    if rootsComputationsCount != 0:
3972
        print "Average roots finding round CPU time:", \
3973
            rootsComputationsFullTime/rootsComputationsCount
3974
    print "Global Wall time:", globalWallTime
3975
    print "Global CPU time:", globalCpuTime
3976
    ## Output counters
3977
# End srs_runSLZ-v05_proj
3978
#
3463 3979
def srs_run_SLZ_v06(inputFunction,
3464 3980
                    inputLowerBound,
3465 3981
                    inputUpperBound,

Formats disponibles : Unified diff