Révision 277

pobysoPythonSage/src/sageSLZ/sageRunSLZ.sage (revision 277)
3992 3992
    ## Output counters
3993 3993
# End srs_runSLZ-v05_proj
3994 3994
#
3995
def srs_run_SLZ_v05_proj_02(inputFunction,
3996
                            inputLowerBound,
3997
                            inputUpperBound,
3998
                            alpha,
3999
                            degree,
4000
                            precision,
4001
                            emin,
4002
                            emax,
4003
                            targetHardnessToRound,
4004
                            debug = False):
4005
    """
4006
    changes from plain V5:
4007
       LLL reduction is not performed on the matrix itself but rather on the
4008
       product of the matrix with a uniform random matrix.
4009
       The reduced matrix obtained is discarded but the transformation matrix 
4010
       obtained is used to multiply the original matrix in order to reduced it.
4011
       If a sufficient level of reduction is obtained, we stop here. If not
4012
       the product matrix obtained above is LLL reduced. But as it has been
4013
       pre-reduced at the above step, reduction is supposed to be much fastet.
4014
       In the worst case, both reductions combined should hopefully be faster 
4015
       than a straight single reduction.
4016
    Changes from V4:
4017
        Approximation polynomial has coefficients rounded.
4018
    Changes from V3:
4019
        Root search is changed again:
4020
            - only resultants in i are computed;
4021
            - roots in i are searched for;
4022
            - if any, they are tested for hardness-to-round.
4023
    Changes from V2:
4024
        Root search is changed:
4025
            - we compute the resultants in i and in t;
4026
            - we compute the roots set of each of these resultants;
4027
            - we combine all the possible pairs between the two sets;
4028
            - we check these pairs in polynomials for correctness.
4029
    Changes from V1: 
4030
        1- check for roots as soon as a resultant is computed;
4031
        2- once a non null resultant is found, check for roots;
4032
        3- constant resultant == no root.
4033
    """
4034

  
4035
    if debug:
4036
        print "Function                :", inputFunction
4037
        print "Lower bound             :", inputLowerBound.str(truncate=False)
4038
        print "Upper bounds            :", inputUpperBound.str(truncate=False)
4039
        print "Alpha                   :", alpha
4040
        print "Degree                  :", degree
4041
        print "Precision               :", precision
4042
        print "Emin                    :", emin
4043
        print "Emax                    :", emax
4044
        print "Target hardness-to-round:", targetHardnessToRound
4045
        print
4046
    ## Important constants.
4047
    ### Stretch the interval if no error happens.
4048
    noErrorIntervalStretch = 1 + 2^(-5)
4049
    ### If no vector validates the Coppersmith condition, shrink the interval
4050
    #   by the following factor.
4051
    noCoppersmithIntervalShrink = 1/2
4052
    ### If only (or at least) one vector validates the Coppersmith condition, 
4053
    #   shrink the interval by the following factor.
4054
    oneCoppersmithIntervalShrink = 3/4
4055
    #### If only null resultants are found, shrink the interval by the 
4056
    #    following factor.
4057
    onlyNullResultantsShrink     = 3/4
4058
    ## Structures.
4059
    RRR         = RealField(precision)
4060
    RRIF        = RealIntervalField(precision)
4061
    ## Converting input bound into the "right" field.
4062
    lowerBound = RRR(inputLowerBound)
4063
    upperBound = RRR(inputUpperBound)
4064
    ## Before going any further, check domain and image binade conditions.
4065
    print inputFunction._assume_str(), "at 1:", inputFunction(1).n()
4066
    output = slz_fix_bounds_for_binades(lowerBound, upperBound, inputFunction)
4067
    #print "srsv04p:", output, (output is None)
4068
    #
4069
    ## Check if input to thr fix_bounds function is valid.
4070
    if output is None:
4071
        print "Invalid domain/image binades. Domain:",\
4072
        lowerBound.str(truncate=False), upperBound(truncate=False), \
4073
        "Images:", \
4074
        inputFunction(lowerBound), inputFunction(upperBound)
4075
        raise Exception("Invalid domain/image binades.")
4076
    lb = output[0] ; ub = output[1]
4077
    #
4078
    ## Check if bounds have changed.
4079
    if lb != lowerBound or ub != upperBound:
4080
        print "lb:", lb.str(truncate=False), " - ub:", ub.str(truncate=False)
4081
        print "Invalid domain/image binades."
4082
        print "Domain:", lowerBound, upperBound
4083
        print "Images:", \
4084
        inputFunction(lowerBound), inputFunction(upperBound)
4085
        raise Exception("Invalid domain/image binades.")
4086
    #
4087
    ## Progam initialization
4088
    ### Approximation polynomial accuracy and hardness to round.
4089
    polyApproxAccur           = 2^(-(targetHardnessToRound + 1))
4090
    #polyApproxAccur           = 2^(-(targetHardnessToRound + 12))
4091
    polyTargetHardnessToRound = targetHardnessToRound + 1
4092
    ### Significand to integer conversion ratio.
4093
    toIntegerFactor           = 2^(precision-1)
4094
    print "Polynomial approximation required accuracy:", polyApproxAccur.n()
4095
    ### Variables and rings for polynomials and root searching.
4096
    i=var('i')
4097
    t=var('t')
4098
    inputFunctionVariable = inputFunction.variables()[0]
4099
    function = inputFunction.subs({inputFunctionVariable:i})
4100
    #  Polynomial Rings over the integers, for root finding.
4101
    Zi = ZZ[i]
4102
    Zt = ZZ[t]
4103
    Zit = ZZ[i,t]
4104
    ## Number of iterations limit.
4105
    maxIter = 100000
4106
    #
4107
    ## Set the variable name in Sollya.
4108
    pobyso_name_free_variable_sa_so(str(function.variables()[0]))
4109
    ## Compute the scaled function and the degree, in their Sollya version 
4110
    #  once for all.
4111
    #print "srsvp initial bounds:",lowerBound, upperBound
4112
    (scaledf, sdlb, sdub, silb, siub) = \
4113
        slz_compute_scaled_function(function, lowerBound, upperBound, precision)
4114
    print "Scaled function:", scaledf._assume_str().replace('_SAGE_VAR_', '')
4115
    #print "srsvp Scaled bounds:", sdlb, sdub
4116
    scaledfSo = sollya_lib_parse_string(scaledf._assume_str().replace('_SAGE_VAR_', ''))
4117
    degreeSo  = pobyso_constant_from_int_sa_so(degree)
4118
    #
4119
    ## Compute the scaling. boundsIntervalRifSa defined out of the loops.
4120
    domainBoundsInterval   = RRIF(lowerBound, upperBound)
4121
    (unscalingFunction, scalingFunction) = \
4122
        slz_interval_scaling_expression(domainBoundsInterval, i)
4123
    #print scalingFunction, unscalingFunction
4124
    ## Set the Sollya internal precision (with an arbitrary minimum of 192).
4125
    internalSollyaPrec = ceil((RR('1.5') * targetHardnessToRound) / 64) * 64
4126
    if internalSollyaPrec < 192:
4127
        internalSollyaPrec = 192
4128
    pobyso_set_prec_sa_so(internalSollyaPrec)
4129
    print "Sollya internal precision:", internalSollyaPrec
4130
    ## Some variables.
4131
    ### General variables
4132
    lb                  = sdlb
4133
    ub                  = sdub
4134
    nbw                 = 0
4135
    intervalUlp         = ub.ulp()
4136
    #### Will be set by slz_interval_and_polynomila_to_sage.
4137
    ic                  = 0 
4138
    icAsInt             = 0    # Set from ic.
4139
    solutionsSet        = set()
4140
    tsErrorWidth        = []
4141
    csErrorVectors      = []
4142
    csVectorsResultants = []
4143
    floatP              = 0  # Taylor polynomial.
4144
    floatPcv            = 0  # Ditto with variable change.
4145
    intvl               = "" # Taylor interval
4146
    terr                = 0  # Taylor error.
4147
    iterCount = 0
4148
    htrnSet = set()
4149
    ### Timers and counters.
4150
    wallTimeStart                   = 0
4151
    cpuTimeStart                    = 0
4152
    taylCondFailedCount             = 0
4153
    coppCondFailedCount             = 0
4154
    resultCondFailedCount           = 0
4155
    coppCondFailed                  = False
4156
    resultCondFailed                = False
4157
    globalResultsList               = []
4158
    basisConstructionsCount         = 0
4159
    basisConstructionsFullTime      = 0
4160
    basisConstructionTime           = 0
4161
    reductionsCount                 = 0
4162
    reductionsFullTime              = 0
4163
    reductionTime                   = 0
4164
    resultantsComputationsCount     = 0
4165
    resultantsComputationsFullTime  = 0
4166
    resultantsComputationTime       = 0
4167
    rootsComputationsCount          = 0
4168
    rootsComputationsFullTime       = 0
4169
    rootsComputationTime            = 0
4170
    print
4171
    ## Global times are started here.
4172
    wallTimeStart                   = walltime()
4173
    cpuTimeStart                    = cputime()
4174
    ## Main loop.
4175
    while True:
4176
        if lb >= sdub:
4177
            print "Lower bound reached upper bound."
4178
            break
4179
        if iterCount == maxIter:
4180
            print "Reached maxIter. Aborting"
4181
            break
4182
        iterCount += 1
4183
        print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
4184
            "log2(numbers)." 
4185
        ### Compute a Sollya polynomial that will honor the Taylor condition.
4186
        prceSo = slz_compute_polynomial_and_interval_01(scaledfSo,
4187
                                                        degreeSo,
4188
                                                        lb,
4189
                                                        ub,
4190
                                                        polyApproxAccur,
4191
                                                        debug=debug)
4192
        if debug:
4193
            print "Approximation polynomial computed."
4194
        if prceSo is None:
4195
            raise Exception("Could not compute an approximation polynomial.")
4196
        ### Convert back the data into Sage space.                         
4197
        (floatP, floatPcv, intvl, ic, terr) = \
4198
            slz_interval_and_polynomial_to_sage((prceSo[0], prceSo[0],
4199
                                                 prceSo[1], prceSo[2], 
4200
                                                 prceSo[3]))
4201
        intvl = RRIF(intvl)
4202
        ## Clean-up Sollya stuff.
4203
        for elem in prceSo:
4204
            sollya_lib_clear_obj(elem)
4205
        #print  floatP, floatPcv, intvl, ic, terr
4206
        #print floatP
4207
        #print intvl.endpoints()[0].n(), \
4208
        #      ic.n(),
4209
        #intvl.endpoints()[1].n()
4210
        ### Check returned data.
4211
        #### Is approximation error OK?
4212
        if terr > polyApproxAccur:
4213
            exceptionErrorMess  = \
4214
                "Approximation failed - computed error:" + \
4215
                str(terr) + " - target error: "
4216
            exceptionErrorMess += \
4217
                str(polyApproxAccur) + ". Aborting!"
4218
            raise Exception(exceptionErrorMess)
4219
        #### Is lower bound OK?
4220
        if lb != intvl.endpoints()[0]:
4221
            exceptionErrorMess =  "Wrong lower bound:" + \
4222
                               str(lb) + ". Aborting!"
4223
            raise Exception(exceptionErrorMess)
4224
        #### Set upper bound.
4225
        if ub > intvl.endpoints()[1]:
4226
            ub = intvl.endpoints()[1]
4227
            print "[", lb, ",", ub, "]", ((ub - lb) / intervalUlp).log2().n(), \
4228
            "log2(numbers)." 
4229
            taylCondFailedCount += 1
4230
        #### Is interval not degenerate?
4231
        if lb >= ub:
4232
            exceptionErrorMess = "Degenerate interval: " + \
4233
                                "lowerBound(" + str(lb) +\
4234
                                ")>= upperBound(" + str(ub) + \
4235
                                "). Aborting!"
4236
            raise Exception(exceptionErrorMess)
4237
        #### Is interval center ok?
4238
        if ic <= lb or ic >= ub:
4239
            exceptionErrorMess =  "Invalid interval center for " + \
4240
                                str(lb) + ',' + str(ic) + ',' +  \
4241
                                str(ub) + ". Aborting!"
4242
            raise Exception(exceptionErrorMess)
4243
        ##### Current interval width and reset future interval width.
4244
        bw = ub - lb
4245
        nbw = 0
4246
        icAsInt = int(ic * toIntegerFactor)
4247
        #### The following ratio is always >= 1. In case we may want to
4248
        #    enlarge the interval
4249
        curTaylErrRat = polyApproxAccur / terr
4250
        ### Make the  integral transformations.
4251
        #### Bounds and interval center.
4252
        intIc = int(ic * toIntegerFactor)
4253
        intLb = int(lb * toIntegerFactor) - intIc
4254
        intUb = int(ub * toIntegerFactor) - intIc
4255
        #
4256
        #### Polynomials
4257
        basisConstructionTime         = cputime()
4258
        ##### To a polynomial with rational coefficients with rational arguments
4259
        ratRatP = slz_float_poly_of_float_to_rat_poly_of_rat_pow_two(floatP)
4260
        ##### To a polynomial with rational coefficients with integer arguments
4261
        ratIntP = \
4262
            slz_rat_poly_of_rat_to_rat_poly_of_int(ratRatP, precision)
4263
        #####  Ultimately a multivariate polynomial with integer coefficients  
4264
        #      with integer arguments.
4265
        coppersmithTuple = \
4266
            slz_rat_poly_of_int_to_poly_for_coppersmith(ratIntP, 
4267
                                                        precision, 
4268
                                                        targetHardnessToRound, 
4269
                                                        i, t)
4270
        #### Recover Coppersmith information.
4271
        intIntP = coppersmithTuple[0]
4272
        N = coppersmithTuple[1]
4273
        nAtAlpha = N^alpha
4274
        tBound = coppersmithTuple[2]
4275
        leastCommonMultiple = coppersmithTuple[3]
4276
        iBound = max(abs(intLb),abs(intUb))
4277
        basisConstructionsFullTime        += cputime(basisConstructionTime)
4278
        basisConstructionsCount           += 1
4279
        #### Compute the matrix to reduce for debug purpose. Otherwise
4280
        #    slz_compute_coppersmith_reduced_polynomials does the job
4281
        #    invisibly.
4282
        if debug:
4283
            matrixToReduce = slz_compute_initial_lattice_matrix(intIntP,
4284
                                                                alpha,
4285
                                                                N,
4286
                                                                iBound,
4287
                                                                tBound)
4288
            maxNorm     = 0
4289
            latticeSize = 0
4290
            matrixFile = file('/tmp/matrixToReduce.txt', 'w')
4291
            for row in matrixToReduce.rows():
4292
                currentNorm = row.norm()
4293
                if currentNorm > maxNorm:
4294
                    maxNorm = currentNorm
4295
                latticeSize += 1
4296
                for elem in row:
4297
                    matrixFile.write(elem.str(base=2) + ",")
4298
                matrixFile.write("\n")
4299
            #matrixFile.write(matrixToReduce.str(radix="2") + "\n")
4300
            matrixFile.close()
4301
            #### We use here binary length as defined in LLL princepts.
4302
            binaryLength = latticeSize * log(maxNorm)
4303
            print "Binary length:", binaryLength.n()
4304
            #raise Exception("Deliberate stop here.")
4305
        # End if debug
4306
        reductionTime                     = cputime()
4307
        #### Compute the reduced polynomials.
4308
        print "Starting reduction..."
4309
        ccReducedPolynomialsList =  \
4310
                slz_compute_coppersmith_reduced_polynomials_proj(intIntP, 
4311
                                                                 alpha, 
4312
                                                                 N, 
4313
                                                                 iBound, 
4314
                                                                 tBound)
4315
        print "...reduction accomplished in", cputime(reductionTime), "s."
4316
        if ccReducedPolynomialsList is None:
4317
            raise Exception("Reduction failed.")
4318
        reductionsFullTime    += cputime(reductionTime)
4319
        reductionsCount       += 1
4320
        if len(ccReducedPolynomialsList) < 2:
4321
            print "Nothing to form resultants with."
4322
            print
4323
            coppCondFailedCount += 1
4324
            coppCondFailed = True
4325
            ##### Apply a different shrink factor according to 
4326
            #  the number of compliant polynomials.
4327
            if len(ccReducedPolynomialsList) == 0:
4328
                ub = lb + bw * noCoppersmithIntervalShrink
4329
            else: # At least one compliant polynomial.
4330
                ub = lb + bw * oneCoppersmithIntervalShrink
4331
            if ub > sdub:
4332
                ub = sdub
4333
            if lb == ub:
4334
                raise Exception("Cant shrink interval \
4335
                anymore to get Coppersmith condition.")
4336
            nbw = 0
4337
            continue
4338
        #### We have at least two polynomials.
4339
        #    Let us try to compute resultants.
4340
        #    For each resultant computed, go for the solutions.
4341
        ##### Build the pairs list.
4342
        polyPairsList           = []
4343
        for polyOuterIndex in xrange(0, len(ccReducedPolynomialsList) - 1):
4344
            for polyInnerIndex in xrange(polyOuterIndex+1, 
4345
                                         len(ccReducedPolynomialsList)):
4346
                polyPairsList.append((ccReducedPolynomialsList[polyOuterIndex],
4347
                                      ccReducedPolynomialsList[polyInnerIndex]))
4348
        #### Actual root search.
4349
        iRootsSet           = set()
4350
        hasNonNullResultant = False
4351
        for polyPair in polyPairsList:
4352
            resultantsComputationTime = cputime()
4353
            currentResultantI = \
4354
                slz_resultant(polyPair[0],
4355
                              polyPair[1],
4356
                              t)
4357
            resultantsComputationsCount    += 1
4358
            resultantsComputationsFullTime +=  \
4359
                cputime(resultantsComputationTime)
4360
            #### Function slz_resultant returns None both for None and O
4361
            #    resultants.
4362
            if currentResultantI is None:
4363
                print "Nul resultant"
4364
                continue # Next polyPair.
4365
            ## We deleted the currentResultantI computation.
4366
            #### We have a non null resultant. From now on, whatever this
4367
            #    root search yields, no extra root search is necessary.
4368
            hasNonNullResultant = True
4369
            #### A constant resultant leads to no root. Root search is done.
4370
            if currentResultantI.degree() < 1:
4371
                print "Resultant is constant:", currentResultantI
4372
                break # There is no root.
4373
            #### Actual iroots computation.
4374
            rootsComputationTime        = cputime()
4375
            iRootsList = Zi(currentResultantI).roots()
4376
            rootsComputationsCount      +=  1
4377
            rootsComputationsFullTime   =   cputime(rootsComputationTime)
4378
            if len(iRootsList) == 0:
4379
                print "No roots in \"i\"."
4380
                #break # No roots in i.
4381
            else:
4382
                for iRoot in iRootsList:
4383
                    # A root is given as a (value, multiplicity) tuple.
4384
                    iRootsSet.add(iRoot[0])
4385
                    print "Root added."
4386
            #### A non null, non constant resultant has been tested
4387
            #    for. There is no need to check for another one. Break
4388
            #    whether roots are found or not.
4389
            break
4390
        # End loop for polyPair in polyParsList. We only loop again if a 
4391
        # None or zero resultant is found.
4392
        #### Prepare for results for the current interval..
4393
        intervalResultsList = []
4394
        intervalResultsList.append((lb, ub))
4395
        #### Check roots.
4396
        rootsResultsList = []
4397
        for iRoot in iRootsSet:
4398
            specificRootResultsList = []
4399
            failingBounds           = []
4400
            # Root qualifies for modular equation, test it for hardness to round.
4401
            hardToRoundCaseAsFloat = RRR((icAsInt + iRoot) / toIntegerFactor)
4402
            #print "Before unscaling:", hardToRoundCaseAsFloat.n(prec=precision)
4403
            #print scalingFunction
4404
            scaledHardToRoundCaseAsFloat = \
4405
                scalingFunction(hardToRoundCaseAsFloat) 
4406
            print "Candidate HTRNc at x =", \
4407
                scaledHardToRoundCaseAsFloat.n().str(base=2),
4408
            if slz_is_htrn(scaledHardToRoundCaseAsFloat,
4409
                           function,
4410
                           2^-(targetHardnessToRound),
4411
                           RRR):
4412
                print hardToRoundCaseAsFloat, "is HTRN case."
4413
                specificRootResultsList.append(hardToRoundCaseAsFloat.n().str(base=2))
4414
                if lb <= hardToRoundCaseAsFloat and hardToRoundCaseAsFloat <= ub:
4415
                    print "Found in interval."
4416
                else:
4417
                    print "Found out of interval."
4418
                # Check the i root is within the i bound.
4419
                if abs(iRoot) > iBound:
4420
                    print "IRoot", iRoot, "is out of bounds for modular equation."
4421
                    print "i bound:", iBound
4422
                    failingBounds.append('i')
4423
                    failingBounds.append(iRoot)
4424
                    failingBounds.append(iBound)
4425
                if len(failingBounds) > 0:
4426
                    specificRootResultsList.append(failingBounds)
4427
            else: # From slz_is_htrn...
4428
                print "is not an HTRN case."
4429
            if len(specificRootResultsList) > 0:
4430
                rootsResultsList.append(specificRootResultsList)
4431
        if len(rootsResultsList) > 0:
4432
            intervalResultsList.append(rootsResultsList)
4433
        ### Check if a non null resultant was found. If not shrink the interval.
4434
        if not hasNonNullResultant:
4435
            print "Only null resultants for this reduction, shrinking interval."
4436
            resultCondFailed      =  True
4437
            resultCondFailedCount += 1
4438
            ### Shrink interval for next iteration.
4439
            ub = lb + bw * onlyNullResultantsShrink
4440
            if ub > sdub:
4441
                ub = sdub
4442
            nbw = 0
4443
            continue
4444
        #### An intervalResultsList has at least the bounds.
4445
        globalResultsList.append(intervalResultsList)   
4446
        #### Compute an incremented width for next upper bound, only
4447
        #    if not Coppersmith condition nor resultant condition
4448
        #    failed at the previous run. 
4449
        if not coppCondFailed and not resultCondFailed:
4450
            nbw = noErrorIntervalStretch * bw
4451
        else:
4452
            nbw = bw
4453
        ##### Reset the failure flags. They will be raised
4454
        #     again if needed.
4455
        coppCondFailed   = False
4456
        resultCondFailed = False
4457
        #### For next iteration (at end of loop)
4458
        #print "nbw:", nbw
4459
        lb  = ub
4460
        ub += nbw     
4461
        if ub > sdub:
4462
            ub = sdub
4463
        print
4464
    # End while True
4465
    ## Main loop just ended.
4466
    globalWallTime = walltime(wallTimeStart)
4467
    globalCpuTime  = cputime(cpuTimeStart)
4468
    ## Output results
4469
    print ; print "Intervals and HTRNs" ; print
4470
    for intervalResultsList in globalResultsList:
4471
        intervalResultString = "[" + str(intervalResultsList[0][0]) +\
4472
                               "," + str(intervalResultsList[0][1])  + "]"
4473
        print intervalResultString,
4474
        if len(intervalResultsList) > 1:
4475
            rootsResultsList = intervalResultsList[1]
4476
            specificRootResultIndex = 0
4477
            for specificRootResultsList in rootsResultsList:
4478
                if specificRootResultIndex == 0:
4479
                    print "\t", specificRootResultsList[0],
4480
                else:
4481
                    print " " * len(intervalResultString), "\t", \
4482
                          specificRootResultsList[0],
4483
                if len(specificRootResultsList) > 1:
4484
                    print specificRootResultsList[1]
4485
                specificRootResultIndex += 1
4486
        print ; print
4487
    #print globalResultsList
4488
    #
4489
    print "Timers and counters"
4490
    print
4491
    print "Number of iterations:", iterCount
4492
    print "Taylor condition failures:", taylCondFailedCount
4493
    print "Coppersmith condition failures:", coppCondFailedCount
4494
    print "Resultant condition failures:", resultCondFailedCount
4495
    print "Iterations count: ", iterCount
4496
    print "Number of intervals:", len(globalResultsList)
4497
    print "Number of basis constructions:", basisConstructionsCount 
4498
    print "Total CPU time spent in basis constructions:", \
4499
        basisConstructionsFullTime
4500
    if basisConstructionsCount != 0:
4501
        print "Average basis construction CPU time:", \
4502
            basisConstructionsFullTime/basisConstructionsCount
4503
    print "Number of reductions:", reductionsCount
4504
    print "Total CPU time spent in reductions:", reductionsFullTime
4505
    if reductionsCount != 0:
4506
        print "Average reduction CPU time:", \
4507
            reductionsFullTime/reductionsCount
4508
    print "Number of resultants computation rounds:", \
4509
        resultantsComputationsCount
4510
    print "Total CPU time spent in resultants computation rounds:", \
4511
        resultantsComputationsFullTime
4512
    if resultantsComputationsCount != 0:
4513
        print "Average resultants computation round CPU time:", \
4514
            resultantsComputationsFullTime/resultantsComputationsCount
4515
    print "Number of root finding rounds:", rootsComputationsCount
4516
    print "Total CPU time spent in roots finding rounds:", \
4517
        rootsComputationsFullTime
4518
    if rootsComputationsCount != 0:
4519
        print "Average roots finding round CPU time:", \
4520
            rootsComputationsFullTime/rootsComputationsCount
4521
    print "Global Wall time:", globalWallTime
4522
    print "Global CPU time:", globalCpuTime
4523
    ## Output counters
4524
# End srs_runSLZ-v05_proj_02
4525
#
3995 4526
def srs_run_SLZ_v05_proj_weak(inputFunction,
3996 4527
                              inputLowerBound,
3997 4528
                              inputUpperBound,
pobysoPythonSage/src/sageSLZ/sageSLZ.sage (revision 277)
521 521
    else:
522 522
        return ccReducedPolynomialsList
523 523
# End slz_compute_coppersmith_reduced_polynomials_proj
524
#
525
def slz_compute_weak_coppersmith_reduced_polynomials_proj_02(inputPolynomial,
526
                                                             alpha,
527
                                                             N,
528
                                                             iBound,
529
                                                             tBound,
530
                                                             debug = False):
531
    """
532
    For a given set of arguments (see below), compute a list
533
    of "reduced polynomials" that could be used to compute roots
534
    of the inputPolynomial.
535
    INPUT:
536
    
537
    - "inputPolynomial" -- (no default) a bivariate integer polynomial;
538
    - "alpha" -- the alpha parameter of the Coppersmith algorithm;
539
    - "N" -- the modulus;
540
    - "iBound" -- the bound on the first variable;
541
    - "tBound" -- the bound on the second variable.
542
    
543
    OUTPUT:
544
    
545
    A list of bivariate integer polynomial obtained using the Coppersmith
546
    algorithm. The polynomials correspond to the rows of the LLL-reduce
547
    reduced base that comply with the weak version of Coppersmith condition.
548
    """
549
    #@par Changes from runSLZ-113.sage
550
    # LLL reduction is not performed on the matrix itself but rather on the
551
    # product of the matrix with a uniform random matrix.
552
    # The reduced matrix obtained is discarded but the transformation matrix 
553
    # obtained is used to multiply the original matrix in order to reduced it.
554
    # If a sufficient level of reduction is obtained, we stop here. If not
555
    # the product matrix obtained above is LLL reduced. But as it has been
556
    # pre-reduced at the above step, reduction is supposed to be much faster.
557
    #
558
    # Arguments check.
559
    if iBound == 0 or tBound == 0:
560
        return None
561
    # End arguments check.
562
    nAtAlpha = N^alpha
563
    ## Building polynomials for matrix.
564
    polyRing   = inputPolynomial.parent()
565
    # Whatever the 2 variables are actually called, we call them
566
    # 'i' and 't' in all the variable names.
567
    (iVariable, tVariable) = inputPolynomial.variables()[:2]
568
    #print polyVars[0], type(polyVars[0])
569
    initialPolynomial = inputPolynomial.subs({iVariable:iVariable * iBound,
570
                                              tVariable:tVariable * tBound})
571
    if debug:
572
        polynomialsList = \
573
            spo_polynomial_to_polynomials_list_8(initialPolynomial,
574
                                                 alpha,
575
                                                 N,
576
                                                 iBound,
577
                                                 tBound,
578
                                                 20)
579
    else:
580
        polynomialsList = \
581
            spo_polynomial_to_polynomials_list_8(initialPolynomial,
582
                                                 alpha,
583
                                                 N,
584
                                                 iBound,
585
                                                 tBound,
586
                                                 0)
587
    #print "Polynomials list:", polynomialsList
588
    ## Building the proto matrix.
589
    knownMonomials = []
590
    protoMatrix    = []
591
    if debug:
592
        for poly in polynomialsList:
593
            spo_add_polynomial_coeffs_to_matrix_row(poly,
594
                                                    knownMonomials,
595
                                                    protoMatrix,
596
                                                    20)
597
    else:
598
        for poly in polynomialsList:
599
            spo_add_polynomial_coeffs_to_matrix_row(poly,
600
                                                    knownMonomials,
601
                                                    protoMatrix,
602
                                                    0)
603
    matrixToReduce = spo_proto_to_row_matrix(protoMatrix)
604
    #print matrixToReduce
605
    ## Reduction and checking.
606
    ### Reduction with projection
607
    (reducedMatrixStep1, reductionMatrixStep1) = \
608
         slz_reduce_lll_proj_02(matrixToReduce,16)
609
    #print "Reduced matrix:"
610
    #print reducedMatrixStep1
611
    #for row in reducedMatrix.rows():
612
    #    print row
613
    monomialsCount     = len(knownMonomials)
614
    monomialsCountSqrt = sqrt(monomialsCount)
615
    #print "Monomials count:", monomialsCount, monomialsCountSqrt.n()
616
    #print reducedMatrix
617
    ## Check the Coppersmith condition for each row and build the reduced 
618
    #  polynomials.
619
    ccReducedPolynomialsList = []
620
    for row in reducedMatrixStep1.rows():
621
        l1Norm = row.norm(1)
622
        l2Norm = row.norm(2)
623
        if l2Norm * monomialsCountSqrt < l1Norm:
624
            print "l1norm is smaller than l2norm*sqrt(w)."
625
        else:
626
            print "l1norm is NOT smaller than l2norm*sqrt(w)."
627
            print (l2Norm * monomialsCountSqrt).n(), 'vs ', l1Norm.n()
628
        if l1Norm < nAtAlpha:
629
            #print l2Norm.n()
630
            ccReducedPolynomial = \
631
                slz_compute_reduced_polynomial(row,
632
                                               knownMonomials,
633
                                               iVariable,
634
                                               iBound,
635
                                               tVariable,
636
                                               tBound)
637
            if not ccReducedPolynomial is None:
638
                ccReducedPolynomialsList.append(ccReducedPolynomial)
639
        else:
640
            #print l2Norm.n() , ">", nAtAlpha
641
            pass
642
    if len(ccReducedPolynomialsList) < 2: # Insufficient reduction.
643
        print "Less than 2 Coppersmith condition compliant vectors."
644
        print "Extra reduction starting..."
645
        reducedMatrix = reducedMatrixStep1.LLL(algorithm='fpLLL:wrapper')
646
        ### If uncommented, the following statement avoids performing
647
        #   an actual LLL reduction. This allows for demonstrating
648
        #   the behavior of our pseudo-reduction alone.
649
        #return ()
650
    else:
651
        print "First step of reduction afforded enough vectors"
652
        return ccReducedPolynomialsList
653
    #print ccReducedPolynomialsList
654
    ## Check again the Coppersmith condition for each row and build the reduced 
655
    #  polynomials.
656
    ccReducedPolynomialsList = []
657
    for row in reducedMatrix.rows():
658
        l2Norm = row.norm(2)
659
        if (l2Norm * monomialsCountSqrt) < nAtAlpha:
660
            #print (l2Norm * monomialsCountSqrt).n()
661
            #print l2Norm.n()
662
            ccReducedPolynomial = \
663
                slz_compute_reduced_polynomial(row,
664
                                               knownMonomials,
665
                                               iVariable,
666
                                               iBound,
667
                                               tVariable,
668
                                               tBound)
669
            if not ccReducedPolynomial is None:
670
                ccReducedPolynomialsList.append(ccReducedPolynomial)
671
        else:
672
            #print l2Norm.n() , ">", nAtAlpha
673
            pass
674
    if len(ccReducedPolynomialsList) < 2: # Insufficient reduction.
675
        print "Less than 2 Coppersmith condition compliant vectors after extra reduction."
676
        return ()
677
    else:
678
        return ccReducedPolynomialsList
679
# End slz_compute_coppersmith_reduced_polynomials_proj_02
680
#
681
def slz_compute_coppersmith_reduced_polynomials_proj(inputPolynomial,
682
                                                     alpha,
683
                                                     N,
684
                                                     iBound,
685
                                                     tBound,
686
                                                     debug = False):
687
    """
688
    For a given set of arguments (see below), compute a list
689
    of "reduced polynomials" that could be used to compute roots
690
    of the inputPolynomial.
691
    INPUT:
692
    
693
    - "inputPolynomial" -- (no default) a bivariate integer polynomial;
694
    - "alpha" -- the alpha parameter of the Coppersmith algorithm;
695
    - "N" -- the modulus;
696
    - "iBound" -- the bound on the first variable;
697
    - "tBound" -- the bound on the second variable.
698
    
699
    OUTPUT:
700
    
701
    A list of bivariate integer polynomial obtained using the Coppersmith
702
    algorithm. The polynomials correspond to the rows of the LLL-reduce
703
    reduced base that comply with the Coppersmith condition.
704
    """
705
    #@par Changes from runSLZ-113.sage
706
    # LLL reduction is not performed on the matrix itself but rather on the
707
    # product of the matrix with a uniform random matrix.
708
    # The reduced matrix obtained is discarded but the transformation matrix 
709
    # obtained is used to multiply the original matrix in order to reduced it.
710
    # If a sufficient level of reduction is obtained, we stop here. If not
711
    # the product matrix obtained above is LLL reduced. But as it has been
712
    # pre-reduced at the above step, reduction is supposed to be much faster.
713
    #
714
    # Arguments check.
715
    if iBound == 0 or tBound == 0:
716
        return None
717
    # End arguments check.
718
    nAtAlpha = N^alpha
719
    ## Building polynomials for matrix.
720
    polyRing   = inputPolynomial.parent()
721
    # Whatever the 2 variables are actually called, we call them
722
    # 'i' and 't' in all the variable names.
723
    (iVariable, tVariable) = inputPolynomial.variables()[:2]
724
    #print polyVars[0], type(polyVars[0])
725
    initialPolynomial = inputPolynomial.subs({iVariable:iVariable * iBound,
726
                                              tVariable:tVariable * tBound})
727
    if debug:
728
        polynomialsList = \
729
            spo_polynomial_to_polynomials_list_8(initialPolynomial,
730
                                                 alpha,
731
                                                 N,
732
                                                 iBound,
733
                                                 tBound,
734
                                                 20)
735
    else:
736
        polynomialsList = \
737
            spo_polynomial_to_polynomials_list_8(initialPolynomial,
738
                                                 alpha,
739
                                                 N,
740
                                                 iBound,
741
                                                 tBound,
742
                                                 0)
743
    #print "Polynomials list:", polynomialsList
744
    ## Building the proto matrix.
745
    knownMonomials = []
746
    protoMatrix    = []
747
    if debug:
748
        for poly in polynomialsList:
749
            spo_add_polynomial_coeffs_to_matrix_row(poly,
750
                                                    knownMonomials,
751
                                                    protoMatrix,
752
                                                    20)
753
    else:
754
        for poly in polynomialsList:
755
            spo_add_polynomial_coeffs_to_matrix_row(poly,
756
                                                    knownMonomials,
757
                                                    protoMatrix,
758
                                                    0)
759
    matrixToReduce = spo_proto_to_row_matrix(protoMatrix)
760
    #print matrixToReduce
761
    ## Reduction and checking.
762
    ### Reduction with projection
763
    (reducedMatrixStep1, reductionMatrixStep1) = \
764
         slz_reduce_lll_proj(matrixToReduce,16)
765
    #print "Reduced matrix:"
766
    #print reducedMatrixStep1
767
    #for row in reducedMatrix.rows():
768
    #    print row
769
    monomialsCount     = len(knownMonomials)
770
    monomialsCountSqrt = sqrt(monomialsCount)
771
    #print "Monomials count:", monomialsCount, monomialsCountSqrt.n()
772
    #print reducedMatrix
773
    ## Check the Coppersmith condition for each row and build the reduced 
774
    #  polynomials.
775
    ccReducedPolynomialsList = []
776
    for row in reducedMatrixStep1.rows():
777
        l2Norm = row.norm(2)
778
        if (l2Norm * monomialsCountSqrt) < nAtAlpha:
779
            #print (l2Norm * monomialsCountSqrt).n()
780
            #print l2Norm.n()
781
            ccReducedPolynomial = \
782
                slz_compute_reduced_polynomial(row,
783
                                               knownMonomials,
784
                                               iVariable,
785
                                               iBound,
786
                                               tVariable,
787
                                               tBound)
788
            if not ccReducedPolynomial is None:
789
                ccReducedPolynomialsList.append(ccReducedPolynomial)
790
        else:
791
            #print l2Norm.n() , ">", nAtAlpha
792
            pass
793
    if len(ccReducedPolynomialsList) < 2: # Insufficient reduction.
794
        print "Less than 2 Coppersmith condition compliant vectors."
795
        print "Extra reduction starting..."
796
        reducedMatrix = reducedMatrixStep1.LLL(algorithm='fpLLL:wrapper')
797
        ### If uncommented, the following statement avoids performing
798
        #   an actual LLL reduction. This allows for demonstrating
799
        #   the behavior of our pseudo-reduction alone.
800
        #return ()
801
    else:
802
        print "First step of reduction afforded enough vectors"
803
        return ccReducedPolynomialsList
804
    #print ccReducedPolynomialsList
805
    ## Check again the Coppersmith condition for each row and build the reduced 
806
    #  polynomials.
807
    ccReducedPolynomialsList = []
808
    for row in reducedMatrix.rows():
809
        l2Norm = row.norm(2)
810
        if (l2Norm * monomialsCountSqrt) < nAtAlpha:
811
            #print (l2Norm * monomialsCountSqrt).n()
812
            #print l2Norm.n()
813
            ccReducedPolynomial = \
814
                slz_compute_reduced_polynomial(row,
815
                                               knownMonomials,
816
                                               iVariable,
817
                                               iBound,
818
                                               tVariable,
819
                                               tBound)
820
            if not ccReducedPolynomial is None:
821
                ccReducedPolynomialsList.append(ccReducedPolynomial)
822
        else:
823
            #print l2Norm.n() , ">", nAtAlpha
824
            pass
825
    if len(ccReducedPolynomialsList) < 2: # Insufficient reduction.
826
        print "Less than 2 Coppersmith condition compliant vectors after extra reduction."
827
        return ()
828
    else:
829
        return ccReducedPolynomialsList
830
# End slz_compute_coppersmith_reduced_polynomials_proj
524 831
def slz_compute_weak_coppersmith_reduced_polynomials_proj(inputPolynomial,
525 832
                                                          alpha,
526 833
                                                          N,
......
675 982
        return ()
676 983
    else:
677 984
        return ccReducedPolynomialsList
678
# End slz_compute_coppersmith_reduced_polynomials_proj
985
# End slz_compute_coppersmith_reduced_polynomials_proj2
679 986
#
680 987
def slz_compute_coppersmith_reduced_polynomials_with_lattice_volume(inputPolynomial,
681 988
                                                                    alpha,
......
2291 2598
#
2292 2599
def slz_random_proj_uniform(n, r, c):
2293 2600
    """
2294
    r x c integer matrix with uniform n-bit integer coefficients
2601
    r x c integer matrix with uniform n-bit integer elements.
2295 2602
    """
2296 2603
    M = matrix(r, c)
2297 2604
    for i in range(0, r):
......
2449 2756
    return (transMat * matToReduce, transMat)
2450 2757
# End  slz_reduce_lll_proj.
2451 2758
#
2759
def slz_reduce_lll_proj_02(matToReduce, n):
2760
    """
2761
    Compute the transformation matrix that realizes an LLL reduction on
2762
    the random uniform projected matrix.
2763
    Return both the initial matrix "reduced" by the transformation matrix and
2764
    the transformation matrix itself.
2765
    """
2766
    ## Compute the projected matrix.
2767
    """
2768
    # Random matrix elements {-2^(n-1),...,0,...,2^(n-1)-1}.
2769
    matProjector = slz_random_proj_uniform(n,
2770
                                           matToReduce.ncols(),
2771
                                           matToReduce.nrows())
2772
    """
2773
    # Random matrix elements in {-8,0,7} -> 4. 
2774
    matProjector = slz_random_proj_uniform(matToReduce.ncols(),
2775
                                           matToReduce.nrows(),
2776
                                           4)
2777
    matProjected = matToReduce * matProjector
2778
    ## Build the argument matrix for LLL in such a way that the transformation
2779
    #  matrix is also returned. This matrix is obtained at almost no extra
2780
    # cost. An identity matrix must be appended to 
2781
    #  the left of the initial matrix. The transformation matrix will
2782
    # will be recovered at the same location from the returned matrix .
2783
    idMat = identity_matrix(matProjected.nrows())
2784
    augmentedMatToReduce = idMat.augment(matProjected)
2785
    reducedProjMat = \
2786
        augmentedMatToReduce.LLL(algorithm='fpLLL:wrapper')
2787
    ## Recover the transformation matrix (the left part of the reduced matrix). 
2788
    #  We discard the reduced matrix itself.
2789
    transMat = reducedProjMat.submatrix(0,
2790
                                        0,
2791
                                        reducedProjMat.nrows(),
2792
                                        reducedProjMat.nrows())
2793
    ## Return the initial matrix "reduced" and the transformation matrix tuple.
2794
    return (transMat * matToReduce, transMat)
2795
# End  slz_reduce_lll_proj_02.
2796
#
2452 2797
def slz_resultant(poly1, poly2, elimVar, debug = False):
2453 2798
    """
2454 2799
    Compute the resultant for two polynomials for a given variable
pobysoPythonSage/src/sageSLZ/runSLZ-113proj-02.sage (revision 277)
1
#! /opt/sage/sage
2
# @file runSLZ-113proj-92.sage
3
#
4
#@par Changes from runSLZ-113proj.sage
5
# The uniform random matrix element can be integers in the
6
# [-2^(n-1),2^(n-1)-1] range. The value of "n" is set in function 
7
# slz_reduce_lll_proj_02.  
8
#
9
#@par Changes from runSLZ-113.sage
10
# LLL reduction is not performed on the matrix itself but rather on the
11
# product of the matrix with a uniform random matrix.
12
# The reduced matrix obtained is discarded but the transformation matrix 
13
# obtained is used to multiply the original matrix in order to reduced it.
14
# If a sufficient level of reduction is obtained, we stop here. If not
15
# the product matrix obtained above is LLL reduced. But as it has been
16
# pre-reduced at the above step, reduction is supposed to be much faster.
17
#
18
# Both reductions combined should hopefully be faster than a straight single
19
# reduction.
20
#
21
# Run SLZ for p=113
22
#from scipy.constants.codata import precision
23
def initialize_env():
24
    """
25
    Load all necessary modules.
26
    """
27
    if version().split()[2].replace(',','') > '6.6':
28
        compiledSpyxDir = \
29
            "/home/storres/recherche/arithmetique/pobysoPythonSage/compiledSpyx"
30
        if compiledSpyxDir not in sys.path:
31
            sys.path.append(compiledSpyxDir)
32
    else:
33
        if not 'mpfi' in sage.misc.cython.standard_libs:
34
            sage.misc.cython.standard_libs.append('mpfi')
35
        load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageMpfr.spyx")
36
        load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageGMP.spyx")
37
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sollya_lib.sage")
38
#    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageMpfr.spyx")
39
#    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageGMP.spyx")
40
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/pobyso.py")
41
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageSLZ.sage")
42
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageNumericalOperations.sage")
43
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageRationalOperations.sage")
44
    # Matrix operations are loaded by polynomial operations.
45
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sagePolynomialOperations.sage")
46
    load("/home/storres/recherche/arithmetique/pobysoPythonSage/src/sageSLZ/sageRunSLZ.sage")
47

  
48

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

  

Formats disponibles : Unified diff