Révision 04d64614

b/src/functions_for_cvp.sage
3 3
"""
4 4
print "Functions for CVP loading..."
5 5
#
6
def cvp_affine_from_chebyshev(lowerBound, upperBound):
7
    """
8
    Compute the affine parameters to map [-1, 1] to the interval given
9
    as argument.
10
    @param lowerBound (of the target interval)
11
    @param upperBound (of the target interval)
12
    @return the (scalingCoefficient, offset) tuple.
13
    """
14
    ## Check bounds consistency. Bounds must differ.
15
    if lowerBound >= upperBound:
16
        return None
17
    scalingCoefficient = (upperBound - lowerBound) / 2
18
    offset             = (lowerBound + upperBound) / 2
19
    return (scalingCoefficient, offset)
20
# End cvp_affine_from_chebyshev
21
#
22
def cvp_affine_to_chebyshev(lowerBound, upperBound):
23
    """
24
    Compute the affine parameters to map the interval given
25
    as argument to  [-1, 1].
26
    @param lowerBound (of the target interval)
27
    @param upperBound (of the target interval)
28
    @return the (scalingCoefficient, offset) tuple.
29
    """
30
    ## Check bounds consistency. Bounds must differ.
31
    if lowerBound >= upperBound:
32
        return None
33
    scalingCoefficient = 2 / (upperBound - lowerBound)
34
    ## If bounds are symmetrical with relation to 0, return 0 straight before
35
    #  attempting a division by 0.
36
    if lowerBound == -upperBound:
37
        offset         = 0
38
    else:
39
        offset         =  (lowerBound + upperBound) / (lowerBound - upperBound)
40
    return (scalingCoefficient, offset)
41
# End cvp_affine_to_chebyshev
42
#
6 43
def cvp_babai(redBasis, redBasisGso, vect):
7 44
    """
8 45
    Closest plane vector implementation as per Babaï.
......
34 71
    return fplllIntBasis._sage_()
35 72
# End cvp_hkz_reduce.
36 73
#
74
def cvp_coefficients_bounds_projection(executablePath, arguments):
75
    """
76
    Compute the min and max of the coefficients with linear
77
    programming projection.
78
    @param executablePath: the path to the binary program;
79
    @param arguments: a list of arguments to be givent to the binary
80
    @return: the min and max coefficients value arrays (in this order).
81
    """
82
    from subprocess import check_output
83
    commandLine = [executablePath] + arguments
84
    ## Get rid of output on stderr.
85
    devNull = open("/dev/null", "rw")
86
    ## Run ther program.
87
    otp = check_output(commandLine, stderr=devNull)
88
    devNull.close()
89
    ## Recover the results
90
    bounds = sage_eval(otp)
91
    minCoeffsExpList = []
92
    maxCoeffsExpList = [] 
93
    print "bounds:", bounds
94
    for boundsPair in bounds:
95
        minCoeffsExpList.append(boundsPair[0])
96
        maxCoeffsExpList.append(boundsPair[1])
97
    print "minCoeffsExpList:", minCoeffsExpList
98
    print "maxCoeffsExpList:", maxCoeffsExpList
99
    return (minCoeffsExpList, maxCoeffsExpList)
100
# End cvp_coefficients_bounds_projection
101

  
102
def cvp_coefficients_bounds_projection_exps(executablePath, 
103
                                            arguments, 
104
                                            realField = None):
105
    """
106
    Compute the min and max exponents of the coefficients with linear
107
    programming projection.
108
    @param executablePath: the path to the binary program;
109
    @param arguments: a list of arguments to be givent to the binary
110
    @param realField: the realField to use for floating-point conversion.
111
    @return: the min and max exponents arrays (in this order).
112
    """
113
    ## If no realField is givne, fall back on RR.
114
    if realField is None:
115
        realField = RR
116
    (minCoeffsExpList, maxCoeffsExpList) = \
117
        cvp_coefficients_bounds_projection(executablePath,arguments)
118
    for index in xrange(0, len(minCoeffsExpList)):
119
        minCoeffsExpList[index] = \
120
            realField(minCoeffsExpList[index]).log2().floor()
121
        maxCoeffsExpList[index] = \
122
            realField(maxCoeffsExpList[index]).log2().floor()
123
    return (minCoeffsExpList, maxCoeffsExpList)
124
# End cvp_coefficients_bounds_projection_exps
125

  
126
def cvp_chebyshev_zeros_1k(numPoints, realField, contFracMaxErr = None):
127
    """
128
    Compute the Chebyshev zeros for some polynomial degree (numPoints, for the
129
    zeros) scaled to the [lowerBound, upperBound] interval.
130
    The list is returned as row floating-point numbers is contFracMaxErr is None.
131
    Otherwise elements are transformed into rational numbers. 
132
    """
133
    if numPoints < 1:
134
        return None
135
    if numPoints == 0:
136
        return [0]
137
    ## Check that realField has a "prec()" member.
138
    try:
139
        realField.prec()
140
    except:
141
        return None
142
    #
143
    zerosList = []
144
    ## formulas: cos (((2*i - 1) * pi) / (2*numPoints)) for i = 1,...,numPoints.
145
    #  If i is -1-shifted, as in the following loop, formula is 
146
    #  cos (((2*i + 1) * pi) / (2*numPoints)) for i = 0,...,numPoints-1.
147
    for index in xrange(0, numPoints):
148
        ## When number of points is odd (then, the Chebyshev degree is odd two), 
149
        #  the central point is 0. */
150
        if (numPoints % 2 == 1) and ((2 * index + 1) == numPoints):
151
            if contFracMaxErr is None:
152
                zerosList.append(realField(0))
153
            else:
154
                zerosList.append(0)
155
        else:
156
            currentCheby = \
157
                ((realField(2*index+1) * realField(pi)) / 
158
                 realField(2*numPoints)).cos()
159
            #print  "Current Cheby:", currentCheby
160
            ## Result is negated to have an increasing order list.
161
            if contFracMaxErr is None:
162
                zerosList.append(-currentCheby)
163
            else:
164
                zerosList.append(-currentCheby.nearby_rational(contFracMaxErr))
165
            #print "Relative error:", (currentCheby/zerosList[index])
166
    return zerosList
167
# End cvp_chebyshev_zeros_1k.
168
#
169
def cvp_chebyshev_zeros_for_interval(lowerBound, 
170
                                     upperBound, 
171
                                     numPoints,
172
                                     realField = None, 
173
                                     contFracMaxErr = None):
174
    """
175
    Compute the Chebyshev zeros for some polynomial degree (numPoints, for the
176
    zeros) scaled to the [lowerBound, upperBound] interval.
177
    If no contFracMaxErr argument is given, we return the list as "raw"
178
    floating-points. Otherwise, rational numbers are returned.
179
    """
180
    ## Arguments check.
181
    if lowerBound >= upperBound:
182
        return None
183
    if numPoints < 1:
184
        return None
185
    ## If no realField argument is given try to retrieve it from the 
186
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
187
    if realField is None:
188
        try:
189
            ### Force failure if parent does not have prec() member.
190
            lowerBound.parent().prec()
191
            ### If no exception is thrown, set realField.
192
            realField = lowerBound.parent()
193
        except:
194
            realField = RR
195
    #print "Real field:", realField
196
    ## We want "raw"floating-point nodes to only have one final rounding.
197
    chebyshevZerosList = \
198
        cvp_chebyshev_zeros_1k(numPoints, realField)
199
    scalingFactor, offset = cvp_affine_from_chebyshev(lowerBound, upperBound)
200
    for index in xrange(0, len(chebyshevZerosList)):
201
        chebyshevZerosList[index] = \
202
            chebyshevZerosList[index] * scalingFactor + offset
203
        if not contFracMaxErr is None:
204
            chebyshevZerosList[index] = \
205
                chebyshevZerosList[index].nearby_rational(contFracMaxErr)
206
    return chebyshevZerosList                                                             
207
# End cvp_chebyshev_zeros_for_interval.
208
#
37 209
def cvp_common_scaling_exp(precision, 
38 210
                           precisionFraction = None):
39 211
    """
......
244 416
    return polynomialCoeffsList
245 417
# En polynomial_coeffs_from_vect.
246 418
#
247

  
248 419
def cvp_remez_all_poly_error_func_zeros(funct, 
249 420
                                        maxDegree, 
250 421
                                        lowerBound, 
251 422
                                        upperBound,
252 423
                                        precsList, 
253
                                        realField = None):
424
                                        realField = None,
425
                                        contFracMaxErr = None):
254 426
    """
255 427
    For a given function f, a degree and an interval, compute the 
256
    zeros of the ||f-remez_d(f)|| function and those of the truncated Remez 
257
    ovet the interval of the interval
428
    zeros of the (f-remez_d(f)) function and those of the (f-truncRemez_d(f)) 
429
    function over the interval. If the (f-truncRemez_d(f)) function has very 
430
    few zeros, compute the zeros of the derivative instead.
258 431
    """
259
    
432
    ## If no realField argument is given try to retrieve it from the 
433
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
434
    if realField is None:
435
        try:
436
            ### Force failure if parent does not have prec() member.
437
            lowerBound.parent().prec()
438
            ### If no exception is thrown, set realField.
439
            realField = lowerBound.parent()
440
        except:
441
            realField = RR
442
    #print "Real field:", realField
260 443
    funcSa         = func
261 444
    funcAsStringSa = func._assume_str().replace("_SAGE_VAR_","",100)
262 445
    print "Function as a string:", funcAsStringSa
......
267 450
                                           maxDegree, 
268 451
                                           lowerBound,
269 452
                                           upperBound)
270
    ## Compute the infnorm of the error functions.
271
    absoluteSo = pobyso_absolute_so_so()
272
    intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound)
273
    infNormSo  = pobyso_range_max_abs_so_so(pobyso_supnorm_so_so(pStarSo, 
274
                                                                 funcSo, 
275
                                                                 intervalSo, 
276
                                                                 absoluteSo))
277
    print "\nError function infnorm: ", ;pobyso_autoprint(infNormSo)
278
    pobyso_clear_obj(infNormSo)
279
    #
280 453
    ## Compute the zeroes of the error function.
281 454
    ### First create the error function with copies since they are needed later.
282 455
    errorFuncSo = sollya_lib_build_function_sub(sollya_lib_copy_obj(pStarSo), 
283 456
                                                sollya_lib_copy_obj(funcSo))
457
    intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound)
284 458
    errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(errorFuncSo, intervalSo)
285 459
    pobyso_clear_obj(errorFuncSo) # Clears funcSo and pStarSo as well.
286 460
    #print "Zeroes of the error function from Sollya:"
......
320 494
            pobyso_clear_obj(errorFuncDiffSo) # Clears funcSo and pTruncSo as well.
321 495
    pobyso_clear_obj(errorFuncSo) # Clears funcSo and pTruncSo as well.
322 496
    ## Sollya objects clean up.
323
    pobyso_clear_obj(absoluteSo)
324 497
    pobyso_clear_obj(intervalSo)
325 498
    errorFuncZerosSa += errorFuncTruncZerosSa
326 499
    errorFuncZerosSa.sort()
327
    ## Convert the numbers to rationals.
328
    for index in xrange(0, len(errorFuncZerosSa)):
329
        errorFuncZerosSa[index] = errorFuncZerosSa[index].nearby_rational(1/100000)
500
    ## If required, convert the numbers to rational numbers.
501
    if not contFracMaxErr is None:
502
        for index in xrange(0, len(errorFuncZerosSa)):
503
            errorFuncZerosSa[index] = \
504
                errorFuncZerosSa[index].nearby_rational(contFracMaxErr)
505
    return errorFuncZerosSa
506
    #
507
# End remez_all_poly_error_func_zeros
508
#
509
def cvp_remez_poly_error_func_zeros(funct, 
510
                                    maxDegree, 
511
                                    lowerBound, 
512
                                    upperBound,
513
                                    realField = None,
514
                                    contFracMaxErr = None):
515
    """
516
    For a given function f, a degree and an interval, compute the 
517
    zeros of the (f-remez_d(f)) function.
518
    """
519
    ## If no realField argument is given try to retrieve it from the 
520
    #  bounds. If impossible (e.g. rational bound), fall back on RR. 
521
    if realField is None:
522
        try:
523
            ### Force failure if parent does not have prec() member.
524
            lowerBound.parent().prec()
525
            ### If no exception is thrown, set realField.
526
            realField = lowerBound.parent()
527
        except:
528
            realField = RR
529
    #print "Real field:", realField
530
    funcSa         = func
531
    funcAsStringSa = func._assume_str().replace("_SAGE_VAR_","",100)
532
    #print "Function as a string:", funcAsStringSa
533
    ## Create the Sollya version of the function and compute the
534
    #  Remez approximant
535
    funcSo  = pobyso_parse_string(funcAsStringSa)
536
    pStarSo = pobyso_remez_canonical_sa_so(funcAsStringSa, 
537
                                           maxDegree, 
538
                                           lowerBound,
539
                                           upperBound)
540
    ## Compute the zeroes of the error function.
541
    ### Error function creation consumes both pStarSo and funcSo.
542
    errorFuncSo = sollya_lib_build_function_sub(pStarSo, funcSo)
543
    intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound)
544
    errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(errorFuncSo, intervalSo)
545
    pobyso_clear_obj(errorFuncSo) # Clears funcSo and pStarSo as well.
546
    #print "Zeroes of the error function from Sollya:"
547
    #pobyso_autoprint(errorFuncZerosSo)
548
    errorFuncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo)
549
    pobyso_clear_obj(errorFuncZerosSo)
550
    ## Sollya objects clean up.
551
    pobyso_clear_obj(intervalSo)
552
    ## Converting to rational numbers, if required.
553
    if not contFracMaxErr is None:
554
        for index in xrange(0, len(errorFuncZerosSa)):
555
            errorFuncZerosSa[index] = \
556
                errorFuncZerosSa[index].nearby_rational(contFracMaxErr)
330 557
    return errorFuncZerosSa
331 558
    #
332 559
# End remez_poly_error_func_zeros

Formats disponibles : Unified diff