Révision 9cf1fb38
b/src/functions_for_cvp.sage | ||
---|---|---|
1 |
"""@package functions_for_cvp |
|
1 |
""" |
|
2 |
@file functions_for_cvp.sage |
|
3 |
@package functions_for_cvp |
|
2 | 4 |
Auxiliary functions used for CVP. |
5 |
|
|
6 |
@author S.T. |
|
3 | 7 |
""" |
4 | 8 |
print "Functions for CVP loading..." |
5 | 9 |
# |
... | ... | |
7 | 11 |
""" |
8 | 12 |
Compute the affine parameters to map [-1, 1] to the interval given |
9 | 13 |
as argument. |
10 |
@param lowerBound (of the target interval) |
|
11 |
@param upperBound (of the target interval) |
|
14 |
@param: lowerBound (of the target interval)
|
|
15 |
@param: upperBound (of the target interval)
|
|
12 | 16 |
@return the (scalingCoefficient, offset) tuple. |
13 | 17 |
""" |
14 | 18 |
## Check bounds consistency. Bounds must differ. |
... | ... | |
71 | 75 |
return fplllIntBasis._sage_() |
72 | 76 |
# End cvp_hkz_reduce. |
73 | 77 |
# |
78 |
def cvp_candidate_vectors(intVect, diffsList): |
|
79 |
""" |
|
80 |
Computes a list of best approximation vectors based on the CVP |
|
81 |
computed vector using the differences between this vector and the |
|
82 |
target function vector. |
|
83 |
@param intVect the vector from which candidates are built |
|
84 |
@param diffsList the list of the values that will be appended to the |
|
85 |
initial vector to form the candidates |
|
86 |
@return A matrix made of candidates rows or None if there is some invalid |
|
87 |
argument. |
|
88 |
@par How it works |
|
89 |
The idea is to create all the possible vectors based on the computed CVP |
|
90 |
vector and its differences to the target. Those are collected in |
|
91 |
diffsList.@n |
|
92 |
From the vector we create all the possible combinations between the original |
|
93 |
value and the differences in diffsList. Some of those can be equal to 0. |
|
94 |
They are not taken into account. If nonZeroDiffsCount is the number of |
|
95 |
diffsList element different from 0, there are 2^nonZeroDiffsCount |
|
96 |
possible variants.@n |
|
97 |
To compute those, we build a 2^nonZeroDiffsCount rows matrix. For the |
|
98 |
first element in the vector corresponding to a non-zero in diffsList, we |
|
99 |
switch values in the matrix at every row.@n |
|
100 |
For the second such element (non-zero corresponding diffsList element), we |
|
101 |
switch values in the matrix at every second row for a string of two similar |
|
102 |
values.@n |
|
103 |
For the third such element, change happens at every fourth row, for a |
|
104 |
string of four similar values. And so on... |
|
105 |
@par Example |
|
106 |
@verbatim |
|
107 |
vect = [10, 20, 30, 40, 50] |
|
108 |
diffsList = [ 1, 0, -1, 0, 1] |
|
109 |
vectCandMat = [[10, 20, 30, 40, 50], |
|
110 |
[11, 20, 30, 40, 50], |
|
111 |
[10, 20, 29, 40, 50], |
|
112 |
[11, 20, 29, 40, 50], |
|
113 |
[10, 20, 30, 40, 51], |
|
114 |
[11, 20, 30, 40, 51], |
|
115 |
[10, 20, 29, 40, 51], |
|
116 |
[11, 20, 29, 40, 51]] |
|
117 |
@endverbatim |
|
118 |
""" |
|
119 |
## Arguments check. |
|
120 |
vectLen = len(intVect) |
|
121 |
if vectLen != len(diffsList): |
|
122 |
return None |
|
123 |
# |
|
124 |
## Compute the number of diffsList elements different from 0. |
|
125 |
nonZeroDiffsCount = 0 |
|
126 |
for elem in diffsList: |
|
127 |
if elem != 0: |
|
128 |
nonZeroDiffsCount += 1 |
|
129 |
if nonZeroDiffsCount == 0: |
|
130 |
return matrix(ZZ, 0, vectLen) |
|
131 |
numRows = 2^nonZeroDiffsCount |
|
132 |
vectMat = matrix(ZZ, numRows, vectLen) |
|
133 |
for rowIndex in xrange(0,numRows): |
|
134 |
effColIndex = 0 |
|
135 |
for colIndex in xrange(0,vectLen): |
|
136 |
vectMat[rowIndex, colIndex] = intVect[colIndex] |
|
137 |
if diffsList[colIndex] != 0: |
|
138 |
if (rowIndex % 2^(effColIndex + 1)) >= 2^effColIndex: |
|
139 |
vectMat[rowIndex, colIndex] += diffsList[colIndex] |
|
140 |
effColIndex += 1 |
|
141 |
return vectMat |
|
142 |
# End cvp_candidate_vectors |
|
143 |
# |
|
74 | 144 |
def cvp_coefficients_bounds_projection(executablePath, arguments): |
75 | 145 |
""" |
76 | 146 |
Compute the min and max of the coefficients with linear |
... | ... | |
258 | 328 |
# End cvp_evaluation_points_list. |
259 | 329 |
# |
260 | 330 |
def cvp_extra_basis_scaling_exps(precsList, minExponentsList): |
331 |
""" |
|
332 |
Computes the exponents for the extra scaling down of the elements of the |
|
333 |
basis. |
|
334 |
This extra scaling down is necessary when there are elements of the |
|
335 |
basis that have negative exponents. |
|
336 |
""" |
|
261 | 337 |
extraScalingExpsList = [] |
262 | 338 |
for minExp, prec in zip(minExponentsList, precsList): |
263 | 339 |
if minExp - prec < 0: |
... | ... | |
396 | 472 |
# End cvp_monomials_list. |
397 | 473 |
# |
398 | 474 |
def cvp_polynomial_coeffs_from_vect(cvpVectInBasis, |
399 |
coeffsPrecList, |
|
400 |
minCoeffsExpList, |
|
401 |
extraFuncScalingExp): |
|
475 |
coeffsPrecList, |
|
476 |
minCoeffsExpList, |
|
477 |
extraFuncScalingExp): |
|
478 |
""" |
|
479 |
Computes polynomial coefficients out of the elements of the CVP vector. |
|
480 |
@todo |
|
481 |
Rewrite the code with a single exponentiation, at the very end. |
|
482 |
""" |
|
402 | 483 |
numElements = len(cvpVectInBasis) |
403 | 484 |
## Arguments check. |
404 | 485 |
if numElements != len(minCoeffsExpList) or \ |
... | ... | |
452 | 533 |
return poly |
453 | 534 |
# End cvp_polynomial_from_coeffs_and_exps. |
454 | 535 |
# |
455 |
def cvp_remez_all_poly_error_func_maxi(funct, |
|
536 |
def cvp_remez_all_poly_error_func_maxis(funct,
|
|
456 | 537 |
maxDegree, |
457 | 538 |
lowerBound, |
458 | 539 |
upperBound, |
459 | 540 |
precsList, |
460 | 541 |
realField = None, |
461 | 542 |
contFracMaxErr = None): |
462 |
pass |
|
463 | 543 |
""" |
464 | 544 |
For a given function f, a degree and an interval, compute the |
465 | 545 |
maxima of the (f-remez_d(f)) function and those of the (f-truncRemez_d(f)) |
466 | 546 |
function over the interval. |
467 | 547 |
""" |
468 |
# End cvp_remez_all_poly_error_func_maxi. |
|
548 |
## If no realField argument is given try to retrieve it from the |
|
549 |
# bounds. If impossible (e.g. rational bound), fall back on RR. |
|
550 |
if realField is None: |
|
551 |
try: |
|
552 |
### Force failure if parent does not have prec() member. |
|
553 |
lowerBound.parent().prec() |
|
554 |
### If no exception is thrown, set realField. |
|
555 |
realField = lowerBound.parent() |
|
556 |
except: |
|
557 |
realField = RR |
|
558 |
#print "Real field:", realField |
|
559 |
funcSa = func |
|
560 |
funcAsStringSa = func._assume_str().replace("_SAGE_VAR_","",100) |
|
561 |
print "Function as a string:", funcAsStringSa |
|
562 |
## Create the Sollya version of the function and compute the |
|
563 |
# Remez approximant |
|
564 |
funcSo = pobyso_parse_string(funcAsStringSa) |
|
565 |
pStarSo = pobyso_remez_canonical_sa_so(funcAsStringSa, |
|
566 |
maxDegree, |
|
567 |
lowerBound, |
|
568 |
upperBound) |
|
569 |
## Compute the error function and its derivative |
|
570 |
### First create the error function with copies since they are needed later. |
|
571 |
errorFuncSo = sollya_lib_build_function_sub(sollya_lib_copy_obj(pStarSo), |
|
572 |
sollya_lib_copy_obj(funcSo)) |
|
573 |
intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound) |
|
574 |
diffErrorFuncSo = pobyso_diff_so_so(errorFuncSo) |
|
575 |
pobyso_clear_obj(errorFuncSo) |
|
576 |
## Compute the zeros of the derivative. |
|
577 |
errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(diffErrorFuncSo, intervalSo) |
|
578 |
pobyso_clear_obj(diffErrorFuncSo) |
|
579 |
errorFuncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo) |
|
580 |
pobyso_clear_obj(errorFuncZerosSo) |
|
581 |
## Compute the truncated Remez polynomial and the error function. |
|
582 |
truncFormatListSo = pobyso_build_list_of_ints_sa_so(*precsList) |
|
583 |
pTruncSo = pobyso_round_coefficients_so_so(pStarSo, truncFormatListSo) |
|
584 |
pobyso_clear_obj(pStarSo) |
|
585 |
### Compute the error function. This time we consume both the function |
|
586 |
# and the polynomial. |
|
587 |
errorFuncSo = sollya_lib_build_function_sub(pTruncSo, funcSo) |
|
588 |
## Compute the derivative. |
|
589 |
diffErrorFuncSo = pobyso_diff_so_so(errorFuncSo) |
|
590 |
pobyso_clear_obj(errorFuncSo) |
|
591 |
## Compute the zeros of the derivative. |
|
592 |
errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(diffErrorFuncSo, intervalSo) |
|
593 |
pobyso_clear_obj(diffErrorFuncSo) |
|
594 |
pobyso_clear_obj(intervalSo) |
|
595 |
errorFuncTruncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo) |
|
596 |
pobyso_clear_obj(errorFuncZerosSo) |
|
597 |
errorFuncZerosSa += errorFuncTruncZerosSa |
|
598 |
errorFuncZerosSa.sort() |
|
599 |
## If required, convert the numbers to rational numbers. |
|
600 |
if not contFracMaxErr is None: |
|
601 |
for index in xrange(0, len(errorFuncZerosSa)): |
|
602 |
errorFuncZerosSa[index] = \ |
|
603 |
errorFuncZerosSa[index].nearby_rational(contFracMaxErr) |
|
604 |
return errorFuncZerosSa |
|
605 |
# End cvp_remez_all_poly_error_func_maxis. |
|
469 | 606 |
# |
470 | 607 |
def cvp_remez_all_poly_error_func_zeros(funct, |
471 | 608 |
maxDegree, |
... | ... | |
477 | 614 |
""" |
478 | 615 |
For a given function f, a degree and an interval, compute the |
479 | 616 |
zeros of the (f-remez_d(f)) function and those of the (f-truncRemez_d(f)) |
480 |
function over the interval. If the (f-truncRemez_d(f)) function has very |
|
481 |
few zeros, compute the zeros of the derivative instead. |
|
482 |
TODO: change the final behaviour! Now! |
|
617 |
function over the interval. |
|
483 | 618 |
""" |
484 | 619 |
## If no realField argument is given try to retrieve it from the |
485 | 620 |
# bounds. If impossible (e.g. rational bound), fall back on RR. |
... | ... | |
520 | 655 |
### Create the formats list. Notice the "*" before the list variable name. |
521 | 656 |
truncFormatListSo = pobyso_build_list_of_ints_sa_so(*precsList) |
522 | 657 |
#print "Precisions list as Sollya object:", |
523 |
pobyso_autoprint(truncFormatListSo) |
|
658 |
#pobyso_autoprint(truncFormatListSo)
|
|
524 | 659 |
pTruncSo = pobyso_round_coefficients_so_so(pStarSo, truncFormatListSo) |
525 | 660 |
#print "Truncated polynomial:", ; pobyso_autoprint(pTruncSo) |
526 | 661 |
### Compute the error function. This time we consume both the function |
... | ... | |
530 | 665 |
errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(errorFuncSo, intervalSo) |
531 | 666 |
pobyso_clear_obj(pStarSo) |
532 | 667 |
#print "Zeroes of the error function for the truncated polynomial from Sollya:" |
533 |
pobyso_autoprint(errorFuncZerosSo) |
|
668 |
#pobyso_autoprint(errorFuncZerosSo)
|
|
534 | 669 |
errorFuncTruncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo) |
535 | 670 |
pobyso_clear_obj(errorFuncZerosSo) |
536 |
## It may happen that the error function has only one or two zeros. |
|
537 |
# In this case, we are interested in the variations and we consider the |
|
538 |
# derivative |
|
539 |
if maxDegree > 3: |
|
540 |
if len(errorFuncTruncZerosSa) <= (maxDegree / 2): |
|
541 |
errorFuncDiffSo = pobyso_diff_so_so(errorFuncSo) |
|
542 |
errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(errorFuncDiffSo, |
|
543 |
intervalSo) |
|
544 |
errorFuncTruncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo) |
|
545 |
pobyso_clear_obj(errorFuncZerosSo) |
|
546 |
pobyso_clear_obj(errorFuncDiffSo) # Clears funcSo and pTruncSo as well. |
|
547 |
pobyso_clear_obj(errorFuncSo) # Clears funcSo and pTruncSo as well. |
|
548 | 671 |
## Sollya objects clean up. |
549 | 672 |
pobyso_clear_obj(intervalSo) |
550 | 673 |
errorFuncZerosSa += errorFuncTruncZerosSa |
... | ... | |
641 | 764 |
""" |
642 | 765 |
Compute the coordinates of "vect" in "basis" by |
643 | 766 |
solving a linear system. |
644 |
@param vect : the vector we want to compute the coordinates of
|
|
767 |
@param vect the vector we want to compute the coordinates of |
|
645 | 768 |
in coordinates of the ambient space; |
646 |
@param basis: the basis we want to compute the coordinates in
|
|
769 |
@param basis the basis we want to compute the coordinates in |
|
647 | 770 |
as a matrix relative to the ambient space. |
648 | 771 |
""" |
649 | 772 |
## Create the variables for the linear equations. |
... | ... | |
670 | 793 |
equationString += str(varsList[bIndex]) + "*" + str(basis[bIndex,vIndex]) |
671 | 794 |
equationString += " == " + str(vect[vIndex]) |
672 | 795 |
equationsList.append(sage_eval(equationString)) |
673 |
## Solve the equations system. The solution dictionnary is needed
|
|
796 |
## Solve the equations system. The solution dictionary is needed |
|
674 | 797 |
# to recover the values of the solutions. |
675 | 798 |
solutions = solve(equationsList,varsList, solution_dict=True) |
799 |
## This code is deactivated: did not solve the problem. |
|
800 |
""" |
|
801 |
if len(solutions) == 0: |
|
802 |
print "Trying Maxima to_poly_sove." |
|
803 |
solutions = solve(equationsList,varsList, solution_dict=True, to_poly_solve = 'force') |
|
804 |
""" |
|
676 | 805 |
#print "Solutions:", s |
677 | 806 |
## Recover solutions in rational components vector. |
678 | 807 |
vectInBasis = vector(QQ, basis.nrows()) |
679 | 808 |
### There can be several solution, in the general case. |
680 |
# Here, there is only one. For each solution, each |
|
809 |
# Here, there is only one (or none). For each solution, each
|
|
681 | 810 |
# variable has to be searched for. |
682 | 811 |
for sol in solutions: |
683 | 812 |
for bIndex in basisIterationsRange: |
Formats disponibles : Unified diff