Révision 196 pobysoPythonSage/src/sageSLZ/runSLZ-01.sage

runSLZ-01.sage (revision 196)
14 14
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageRationalOperations.sage")
15 15
    # Matrix operations are loaded by polynomial operations.
16 16
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sagePolynomialOperations.sage")
17
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageRunSLZ.sage")
17 18

  
18 19

  
19
def run_SLZ_v01(inputFunction,
20
                inputLowerBound,
21
                inputUpperBound,
22
                alpha,
23
                degree,
24
                precision,
25
                emin,
26
                emax,
27
                targetHardnessToRound,
28
                debug = False):
29

  
30
    if debug:
31
        print "Function                :", inputFunction
32
        print "Lower bound             :", inputLowerBound
33
        print "Upper bounds            :", inputUpperBound
34
        print "Alpha                   :", alpha
35
        print "Degree                  :", degree
36
        print "Precision               :", precision
37
        print "Emin                    :", emin
38
        print "Emax                    :", emax
39
        print "Target hardness-to-round:", targetHardnessToRound
40
        print
41
    ## Important constants.
42
    ### Stretch the interval if no error happens.
43
    noErrorIntervalStretch = 1 + 2^(-5)
44
    ### If no vector validates the Coppersmith condition, shrink the interval
45
    #   by the following factor.
46
    noCoppersmithIntervalShrink = 1/2
47
    ### If only (or at least) one vector validates the Coppersmith condition, 
48
    #   shrink the interval by the following factor.
49
    oneCoppersmithIntervalShrink = 3/4
50
    #### If only null resultants are found, shrink the interval by the 
51
    #    following factor.
52
    onlyNullResultantsShrink     = 3/4
53
    ## Structures.
54
    RRR         = RealField(precision)
55
    RRIF        = RealIntervalField(precision)
56
    ## Converting input bound into the "right" field.
57
    lowerBound = RRR(inputLowerBound)
58
    upperBound = RRR(inputUpperBound)
59
    ## Before going any further, check domain and image binade conditions.
60
    print inputFunction(1).n()
61
    (lb,ub) = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
62
    if lb != lowerBound or ub != upperBound:
63
        print "lb:", lb, " - ub:", ub
64
        print "Invalid domain/image binades. Domain:",\
65
        lowerBound, upperBound, "Images:", \
66
        inputFunction(lowerBound), inputFunction(upperBound)
67
        raise Exception("Invalid domain/image binades.")
68
    #
69
    ## Progam initialization
70
    ### Approximation polynomial accuracy and hardness to round.
71
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
72
    polyTargetHardnessToRound = targetHardnessToRound + 1
73
    ### Significand to integer conversion ratio.
74
    toIntegerFactor           = 2^(precision-1)
75
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
76
    ### Variables and rings for polynomials and root searching.
77
    i=var('i')
78
    t=var('t')
79
    inputFunctionVariable = inputFunction.variables()[0]
80
    function = inputFunction.subs({inputFunctionVariable:i})
81
    #  Polynomial Rings over the integers, for root finding.
82
    Zi = ZZ[i]
83
    Zt = ZZ[t]
84
    Zit = ZZ[i,t]
85
    ## Number of iterations limit.
86
    maxIter = 100000
87
    #
88
    ## Compute the scaled function and the degree, in their Sollya version 
89
    #  once for all.
90
    (scaledf, sdlb, sdub, silb, siub) = \
91
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
92
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
93
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
94
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
95
    #
96
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
97
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
98
    (unscalingFunction, scalingFunction) = \
99
        slz_interval_scaling_expression(domainBoundsInterval, i)
100
    #print scalingFunction, unscalingFunction
101
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
102
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
103
    if internalSollyaPrec < 192:
104
        internalSollyaPrec = 192
105
    pobyso_set_prec_sa_so(internalSollyaPrec)
106
    print "Sollya internal precision:", internalSollyaPrec
107
    ## Some variables.
108
    ### General variables
109
    lb                  = sdlb
110
    ub                  = sdub
111
    nbw                 = 0
112
    intervalUlp         = ub.ulp()
113
    #### Will be set by slz_interval_and_polynomila_to_sage.
114
    ic                  = 0 
115
    icAsInt             = 0    # Set from ic.
116
    solutionsSet        = set()
117
    tsErrorWidth        = []
118
    csErrorVectors      = []
119
    csVectorsResultants = []
120
    floatP              = 0  # Taylor polynomial.
121
    floatPcv            = 0  # Ditto with variable change.
122
    intvl               = "" # Taylor interval
123
    terr                = 0  # Taylor error.
124
    iterCount = 0
125
    htrnSet = set()
126
    ### Timers and counters.
127
    wallTimeStart                   = 0
128
    cpuTimeStart                    = 0
129
    taylCondFailedCount             = 0
130
    coppCondFailedCount             = 0
131
    resultCondFailedCount           = 0
132
    coppCondFailed                  = False
133
    resultCondFailed                = False
134
    globalResultsList               = []
135
    basisConstructionsCount         = 0
136
    basisConstructionsFullTime      = 0
137
    basisConstructionTime           = 0
138
    reductionsCount                 = 0
139
    reductionsFullTime              = 0
140
    reductionTime                   = 0
141
    resultantsComputationsCount     = 0
142
    resultantsComputationsFullTime  = 0
143
    resultantsComputationTime       = 0
144
    rootsComputationsCount          = 0
145
    rootsComputationsFullTime       = 0
146
    rootsComputationTime            = 0
147
    print
148
    ## Global times are started here.
149
    wallTimeStart                   = walltime()
150
    cpuTimeStart                    = cputime()
151
    ## Main loop.
152
    while True:
153
        if lb >= sdub:
154
            print "Lower bound reached upper bound."
155
            break
156
        if iterCount == maxIter:
157
            print "Reached maxIter. Aborting"
158
            break
159
        iterCount += 1
160
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
161
            "log2(numbers)." 
162
        ### Compute a Sollya polynomial that will honor the Taylor condition.
163
        prceSo = slz_compute_polynomial_and_interval(scaledfSo,
164
                                                     degreeSo,
165
                                                     lb,
166
                                                     ub,
167
                                                     polyApproxAccur)
168
        ### Convert back the data into Sage space.                         
169
        (floatP, floatPcv, intvl, ic, terr) = \
170
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
171
                                                 prceSo[1], prceSo[2], 
172
                                                 prceSo[3]))
173
        intvl = RRIF(intvl)
174
        ## Clean-up Sollya stuff.
175
        for elem in prceSo:
176
            sollya_lib_clear_obj(elem)
177
        #print  floatP, floatPcv, intvl, ic, terr
178
        #print floatP
179
        #print intvl.endpoints()[0].n(), \
180
        #      ic.n(),
181
        #intvl.endpoints()[1].n()
182
        ### Check returned data.
183
        #### Is approximation error OK?
184
        if terr > polyApproxAccur:
185
            exceptionErrorMess  = \
186
                "Approximation failed - computed error:" + \
187
                str(terr) + " - target error: "
188
            exceptionErrorMess += \
189
                str(polyApproxAccur) + ". Aborting!"
190
            raise Exception(exceptionErrorMess)
191
        #### Is lower bound OK?
192
        if lb != intvl.endpoints()[0]:
193
            exceptionErrorMess =  "Wrong lower bound:" + \
194
                               str(lb) + ". Aborting!"
195
            raise Exception(exceptionErrorMess)
196
        #### Set upper bound.
197
        if ub > intvl.endpoints()[1]:
198
            ub = intvl.endpoints()[1]
199
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
200
            "log2(numbers)." 
201
            taylCondFailedCount += 1
202
        #### Is interval not degenerate?
203
        if lb >= ub:
204
            exceptionErrorMess = "Degenerate interval: " + \
205
                                "lowerBound(" + str(lb) +\
206
                                ")>= upperBound(" + str(ub) + \
207
                                "). Aborting!"
208
            raise Exception(exceptionErrorMess)
209
        #### Is interval center ok?
210
        if ic <= lb or ic >= ub:
211
            exceptionErrorMess =  "Invalid interval center for " + \
212
                                str(lb) + ',' + str(ic) + ',' +  \
213
                                str(ub) + ". Aborting!"
214
            raise Exception(exceptionErrorMess)
215
        ##### Current interval width and reset future interval width.
216
        bw = ub - lb
217
        nbw = 0
218
        icAsInt = int(ic * toIntegerFactor)
219
        #### The following ratio is always >= 1. In case we may want to
220
        #  enlarge the interval
221
        curTaylErrRat = polyApproxAccur / terr
222
        ## Make the  integral transformations.
223
        ### First for interval center and bounds.
224
        intIc = int(ic * toIntegerFactor)
225
        intLb = int(lb * toIntegerFactor) - intIc
226
        intUb = int(ub * toIntegerFactor) - intIc
227
        #
228
        #### For polynomials
229
        basisConstructionTime         = cputime()
230
        ##### To a polynomial with rational coefficients with rational arguments
231
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
232
        ##### To a polynomial with rational coefficients with integer arguments
233
        ratIntP = \
234
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
235
        #####  Ultimately a polynomial with integer coefficients with integer 
236
        #      arguments.
237
        coppersmithTuple = \
238
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP, 
239
                                                        precision, 
240
                                                        targetHardnessToRound, 
241
                                                        i, t)
242
        #### Recover Coppersmith information.
243
        intIntP = coppersmithTuple[0]
244
        N = coppersmithTuple[1]
245
        nAtAlpha = N^alpha
246
        tBound = coppersmithTuple[2]
247
        leastCommonMultiple = coppersmithTuple[3]
248
        iBound = max(abs(intLb),abs(intUb))
249
        basisConstructionsFullTime        += cputime(basisConstructionTime)
250
        basisConstructionsCount           += 1
251
        reductionTime                     = cputime()
252
        # Compute the reduced polynomials.
253
        ccReducedPolynomialsList =  \
254
            slz_compute_coppersmith_reduced_polynomials(intIntP, 
255
                                                        alpha, 
256
                                                        N, 
257
                                                        iBound, 
258
                                                        tBound)
259
        if ccReducedPolynomialsList is None:
260
            raise Exception("Reduction failed.")
261
        reductionsFullTime    += cputime(reductionTime)
262
        reductionsCount       += 1
263
        if len(ccReducedPolynomialsList) < 2:
264
            print "Nothing to form resultants with."
265
            print
266
            coppCondFailedCount += 1
267
            coppCondFailed = True
268
            ##### Apply a different shrink factor according to 
269
            #  the number of compliant polynomials.
270
            if len(ccReducedPolynomialsList) == 0:
271
                ub = lb + bw * noCoppersmithIntervalShrink
272
            else: # At least one compliant polynomial.
273
                ub = lb + bw * oneCoppersmithIntervalShrink
274
            if ub > sdub:
275
                ub = sdub
276
            if lb == ub:
277
                raise Exception("Cant shrink interval \
278
                anymore to get Coppersmith condition.")
279
            nbw = 0
280
            continue
281
        #### We have at least two polynomials.
282
        #    Let us try to compute resultants.
283
        resultantsComputationTime      = cputime()
284
        resultantsInTTuplesList = []
285
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
286
            for polyInnerIndex in xrange(polyOuterIndex+1, 
287
                                         len(ccReducedPolynomialsList)):
288
                resultantTuple = \
289
                slz_resultant_tuple(ccReducedPolynomialsList[polyOuterIndex],
290
                                ccReducedPolynomialsList[polyInnerIndex],
291
                                t)
292
                if len(resultantTuple) > 2:                    
293
                    #print resultantTuple[2]
294
                    resultantsInTTuplesList.append(resultantTuple)
295
                else:
296
                    print "No non nul resultant"
297
        print len(resultantsInTTuplesList), "resultant(s) in t tuple(s) created."
298
        resultantsComputationsFullTime += cputime(resultantsComputationTime)
299
        resultantsComputationsCount    += 1
300
        if len(resultantsInTTuplesList) == 0:
301
            print "Only null resultants, shrinking interval."
302
            resultCondFailed      =  True
303
            resultCondFailedCount += 1
304
            ### Shrink interval for next iteration.
305
            ub = lb + bw * onlyNullResultantsShrink
306
            if ub > sdub:
307
                ub = sdub
308
            nbw = 0
309
            continue
310
        #### Compute roots.
311
        rootsComputationTime       = cputime()
312
        reducedPolynomialsRootsSet = set()
313
        ##### Solve in the second variable since resultants are in the first
314
        #     variable.
315
        for resultantInTTuple in resultantsInTTuplesList:
316
            currentResultant = resultantInTTuple[2]
317
            ##### If the resultant degree is not at least 1, there are no roots.
318
            if currentResultant.degree() < 1:
319
                print "Resultant is constant:", currentResultant
320
                continue # Next resultantInTTuple
321
            ##### Compute i roots
322
            iRootsList = Zi(currentResultant).roots()
323
            ##### For each iRoot, compute the corresponding tRoots and check 
324
            #     them in the input polynomial.
325
            for iRoot in iRootsList:
326
                ####### Roots returned by roots() are (value, multiplicity) 
327
                #       tuples.
328
                #print "iRoot:", iRoot
329
                ###### Use the tRoot against each polynomial, alternatively.
330
                for indexInTuple in range(0,2):
331
                    currentPolynomial = resultantInTTuple[indexInTuple]
332
                    ####### If the polynomial is univariate, just drop it.
333
                    if len(currentPolynomial.variables()) < 2:
334
                        print "    Current polynomial is not in two variables."
335
                        continue # Next indexInTuple
336
                    tRootsList = \
337
                        Zt(currentPolynomial.subs({currentPolynomial.variables()[0]:iRoot[0]})).roots()
338
                    ####### The tRootsList can be empty, hence the test.
339
                    if len(tRootsList) == 0:
340
                        print "    No t root."
341
                        continue # Next indexInTuple
342
                    for tRoot in tRootsList:
343
                        reducedPolynomialsRootsSet.add((iRoot[0], tRoot[0]))
344
        # End of roots computation
345
        rootsComputationsFullTime   =   cputime(rootsComputationTime)
346
        rootsComputationsCount      +=  1
347
        ##### Prepare for results.
348
        intervalResultsList = []
349
        intervalResultsList.append((lb, ub))
350
        #### Check roots.
351
        rootsResultsList = []
352
        for root in reducedPolynomialsRootsSet:
353
            specificRootResultsList = []
354
            failingBounds = []
355
            intIntPdivN = intIntP(root[0], root[1]) / N
356
            if int(intIntPdivN) != intIntPdivN:
357
                continue # Next root
358
            # Root qualifies for modular equation, test it for hardness to round.
359
            hardToRoundCaseAsFloat = RRR((icAsInt + root[0]) / toIntegerFactor)
360
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
361
            #print scalingFunction
362
            scaledHardToRoundCaseAsFloat = \
363
                scalingFunction(hardToRoundCaseAsFloat) 
364
            print "Candidate HTRNc at x =", \
365
                scaledHardToRoundCaseAsFloat.n().str(base=2),
366
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
367
                           function,
368
                           2^-(targetHardnessToRound),
369
                           RRR):
370
                print hardToRoundCaseAsFloat, "is HTRN case."
371
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
372
                    print "Found in interval."
373
                else:
374
                    print "Found out of interval."
375
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
376
                # Check the root is in the bounds
377
                if abs(root[0]) > iBound or abs(root[1]) > tBound:
378
                    print "Root", root, "is out of bounds."
379
                    if abs(root[0]) > iBound:
380
                        print "root[0]:", root[0]
381
                        print "i bound:", iBound
382
                        failingBounds.append('i')
383
                        failingBounds.append(root[0])
384
                        failingBounds.append(iBound)
385
                    if abs(root[1]) > tBound:
386
                        print "root[1]:", root[1]
387
                        print "t bound:", tBound
388
                        failingBounds.append('t')
389
                        failingBounds.append(root[1])
390
                        failingBounds.append(tBound)
391
                if len(failingBounds) > 0:
392
                    specificRootResultsList.append(failingBounds)
393
            else: # From slz_is_htrn...
394
                print "is not an HTRN case."
395
            if len(specificRootResultsList) > 0:
396
                rootsResultsList.append(specificRootResultsList)
397
        if len(rootsResultsList) > 0:
398
            intervalResultsList.append(rootsResultsList)
399
        #### An intervalResultsList has at least the bounds.
400
        globalResultsList.append(intervalResultsList)   
401
        #### Compute an incremented width for next upper bound, only
402
        #    if not Coppersmith condition nor resultant condition
403
        #    failed at the previous run. 
404
        if not coppCondFailed and not resultCondFailed:
405
            nbw = noErrorIntervalStretch * bw
406
        else:
407
            nbw = bw
408
        ##### Reset the failure flags. They will be raised
409
        #     again if needed.
410
        coppCondFailed   = False
411
        resultCondFailed = False
412
        #### For next iteration (at end of loop)
413
        #print "nbw:", nbw
414
        lb  = ub
415
        ub += nbw     
416
        if ub > sdub:
417
            ub = sdub
418
        print
419
    # End while True
420
    ## Main loop just ended.
421
    globalWallTime = walltime(wallTimeStart)
422
    globalCpuTime  = cputime(cpuTimeStart)
423
    ## Output results
424
    print ; print "Intervals and HTRNs" ; print
425
    for intervalResultsList in globalResultsList:
426
        print "[", intervalResultsList[0][0], ",",intervalResultsList[0][1], "]",
427
        if len(intervalResultsList) > 1:
428
            rootsResultsList = intervalResultsList[1]
429
            for specificRootResultsList in rootsResultsList:
430
                print "\t", specificRootResultsList[0],
431
                if len(specificRootResultsList) > 1:
432
                    print specificRootResultsList[1],
433
        print ; print
434
    #print globalResultsList
435
    #
436
    print "Timers and counters"
437
    print
438
    print "Number of iterations:", iterCount
439
    print "Taylor condition failures:", taylCondFailedCount
440
    print "Coppersmith condition failures:", coppCondFailedCount
441
    print "Resultant condition failures:", resultCondFailedCount
442
    print "Iterations count: ", iterCount
443
    print "Number of intervals:", len(globalResultsList)
444
    print "Number of basis constructions:", basisConstructionsCount 
445
    print "Total CPU time spent in basis constructions:", \
446
        basisConstructionsFullTime
447
    if basisConstructionsCount != 0:
448
        print "Average basis construction CPU time:", \
449
            basisConstructionsFullTime/basisConstructionsCount
450
    print "Number of reductions:", reductionsCount
451
    print "Total CPU time spent in reductions:", reductionsFullTime
452
    if reductionsCount != 0:
453
        print "Average reduction CPU time:", \
454
            reductionsFullTime/reductionsCount
455
    print "Number of resultants computation rounds:", \
456
        resultantsComputationsCount
457
    print "Total CPU time spent in resultants computation rounds:", \
458
        resultantsComputationsFullTime
459
    if resultantsComputationsCount != 0:
460
        print "Average resultants computation round CPU time:", \
461
            resultantsComputationsFullTime/resultantsComputationsCount
462
    print "Number of root finding rounds:", rootsComputationsCount
463
    print "Total CPU time spent in roots finding rounds:", \
464
        rootsComputationsFullTime
465
    if rootsComputationsCount != 0:
466
        print "Average roots finding round CPU time:", \
467
            rootsComputationsFullTime/rootsComputationsCount
468
    print "Global Wall time:", globalWallTime
469
    print "Global CPU time:", globalCpuTime
470
    ## Output counters
471
# End runSLZ-v01
472

  
473 20
print "Running SLZ..."
474 21
initialize_env()
475 22
x = var('x')
476 23
func(x) = exp(x)
477 24
precision = 53
478 25
RRR = RealField(precision)
479
run_SLZ_v01(inputFunction=func, 
480
            inputLowerBound = 402653184/1073741824, 
481
            inputUpperBound = 402653185/1073741824, 
482
            alpha = 2, 
483
            degree = 10, 
484
            precision = 53, 
485
            emin = -1022, 
486
            emax = 1023, 
487
            targetHardnessToRound =  precision+50, 
488
            debug = True)
26
intervalCenter      = RRR("1.9E9CBBFD6080B",16)  * 2^-31
27
icUlp               = intervalCenter.ulp()
28
intervalRadiusInUlp = 2^49 + 2^45          
29
srs_run_SLZ_v01(inputFunction=func, 
30
                inputLowerBound = intervalCenter - icUlp * intervalRadiusInUlp, 
31
                inputUpperBound = intervalCenter + icUlp * intervalRadiusInUlp, 
32
                alpha           = 2, 
33
                degree          = 2, 
34
                precision       = 53, 
35
                emin            = -1022, 
36
                emax            = 1023, 
37
                targetHardnessToRound =  precision+50, 
38
                debug           = True)
39
#
40
"""
41
srs_run_SLZ_v01(inputFunction=func, 
42
                inputLowerBound = 402653184/1073741824, 
43
                inputUpperBound = 402653185/1073741824, 
44
                alpha = 2, 
45
                degree = 10, 
46
                precision = 53, 
47
                emin = -1022, 
48
                emax = 1023, 
49
                targetHardnessToRound =  precision+50, 
50
                debug = True)
489 51

  
490 52
#inputUpperBound = RRR(1/2) - RRR(1/4).ulp(), 
53
RR("1.9E9CBBFD6080B",16)  * 2^-31]
54
"""

Formats disponibles : Unified diff