Révision 04d64614 src/functions_for_cvp.sage
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