Statistiques
| Révision :

root / pobysoPythonSage / src / sageSLZ / runSLZ-01.sage @ 191

Historique | Voir | Annoter | Télécharger (21,07 ko)

1
#! /opt/sage/sage
2
from scipy.constants.codata import precision
3
def initialize_env():
4
    #Load all necessary modules.
5
    if not 'mpfi' in sage.misc.cython.standard_libs:
6
        sage.misc.cython.standard_libs.append('mpfi')
7
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sollya_lib.sage")
8
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageMpfr.spyx")
9
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/pobyso.py")
10
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageSLZ.sage")
11
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageNumericalOperations.sage")
12
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageRationalOperations.sage")
13
    # Matrix operations are loaded by polynomial operations.
14
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sagePolynomialOperations.sage")
15

    
16

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

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

    
459
print "Running SLZ..."
460
initialize_env()
461
x = var('x')
462
func(x) = exp(x)
463
precision = 53
464
RRR = RealField(precision)
465
run_SLZ_v01(inputFunction=func, 
466
            inputLowerBound = 1/4, 
467
            inputUpperBound = RRR(1/2) - RRR(1/4).ulp(), 
468
            alpha = 2, 
469
            degree = 10, 
470
            precision = 53, 
471
            emin = -1022, 
472
            emax = 1023, 
473
            targetHardnessToRound =  precision+50, 
474
            debug = True)