cvp / src / functions_for_cvp.sage @ 4a0c5e95
Historique | Voir | Annoter | Télécharger (47,57 ko)
1 | 9cf1fb38 | Serge Torres | """ |
---|---|---|---|
2 | 9cf1fb38 | Serge Torres | @file functions_for_cvp.sage |
3 | 9cf1fb38 | Serge Torres | @package functions_for_cvp |
4 | 9645ea29 | Serge Torres | Auxiliary functions used for CVP. |
5 | 9cf1fb38 | Serge Torres | |
6 | 9cf1fb38 | Serge Torres | @author S.T. |
7 | 9645ea29 | Serge Torres | """ |
8 | 94c8237b | Serge Torres | sys.stderr.write("Functions for CVP loading...\n") |
9 | 9645ea29 | Serge Torres | # |
10 | 04d64614 | Serge Torres | def cvp_affine_from_chebyshev(lowerBound, upperBound): |
11 | 04d64614 | Serge Torres | """ |
12 | 04d64614 | Serge Torres | Compute the affine parameters to map [-1, 1] to the interval given |
13 | 04d64614 | Serge Torres | as argument. |
14 | 9cf1fb38 | Serge Torres | @param: lowerBound (of the target interval) |
15 | 9cf1fb38 | Serge Torres | @param: upperBound (of the target interval) |
16 | 04d64614 | Serge Torres | @return the (scalingCoefficient, offset) tuple. |
17 | 04d64614 | Serge Torres | """ |
18 | 04d64614 | Serge Torres | ## Check bounds consistency. Bounds must differ. |
19 | 04d64614 | Serge Torres | if lowerBound >= upperBound: |
20 | 04d64614 | Serge Torres | return None |
21 | 04d64614 | Serge Torres | scalingCoefficient = (upperBound - lowerBound) / 2 |
22 | 04d64614 | Serge Torres | offset = (lowerBound + upperBound) / 2 |
23 | 04d64614 | Serge Torres | return (scalingCoefficient, offset) |
24 | 04d64614 | Serge Torres | # End cvp_affine_from_chebyshev |
25 | 04d64614 | Serge Torres | # |
26 | 04d64614 | Serge Torres | def cvp_affine_to_chebyshev(lowerBound, upperBound): |
27 | 04d64614 | Serge Torres | """ |
28 | 04d64614 | Serge Torres | Compute the affine parameters to map the interval given |
29 | 04d64614 | Serge Torres | as argument to [-1, 1]. |
30 | 04d64614 | Serge Torres | @param lowerBound (of the target interval) |
31 | 04d64614 | Serge Torres | @param upperBound (of the target interval) |
32 | 04d64614 | Serge Torres | @return the (scalingCoefficient, offset) tuple. |
33 | 04d64614 | Serge Torres | """ |
34 | 04d64614 | Serge Torres | ## Check bounds consistency. Bounds must differ. |
35 | 04d64614 | Serge Torres | if lowerBound >= upperBound: |
36 | 04d64614 | Serge Torres | return None |
37 | 04d64614 | Serge Torres | scalingCoefficient = 2 / (upperBound - lowerBound) |
38 | 04d64614 | Serge Torres | ## If bounds are symmetrical with relation to 0, return 0 straight before |
39 | 04d64614 | Serge Torres | # attempting a division by 0. |
40 | 04d64614 | Serge Torres | if lowerBound == -upperBound: |
41 | 04d64614 | Serge Torres | offset = 0 |
42 | 04d64614 | Serge Torres | else: |
43 | 04d64614 | Serge Torres | offset = (lowerBound + upperBound) / (lowerBound - upperBound) |
44 | 04d64614 | Serge Torres | return (scalingCoefficient, offset) |
45 | 04d64614 | Serge Torres | # End cvp_affine_to_chebyshev |
46 | 04d64614 | Serge Torres | # |
47 | dd576474 | Serge Torres | def cvp_babai(readBasis, readBasisGso, vect): |
48 | 9645ea29 | Serge Torres | """ |
49 | 9645ea29 | Serge Torres | Closest plane vector implementation as per Babaï. |
50 | dd576474 | Serge Torres | @param readBasis : a lattice basis, preferably a reduced one; |
51 | dd576474 | Serge Torres | @param readBasisGSO: the GSO of the previous basis; |
52 | dd576474 | Serge Torres | @param vect : a vector, in coordinated in the ambient |
53 | 9645ea29 | Serge Torres | space of the lattice |
54 | 9645ea29 | Serge Torres | @return the closest vector to the input, in coordinates in the |
55 | 9645ea29 | Serge Torres | ambient space of the lattice. |
56 | 9645ea29 | Serge Torres | """ |
57 | 9645ea29 | Serge Torres | ## A deep copy is not necessary here. |
58 | 9645ea29 | Serge Torres | curVect = copy(vect) |
59 | 94c8237b | Serge Torres | #print "cvp_babai - Vector:", vect |
60 | 9645ea29 | Serge Torres | ## From index of last row down to 0. |
61 | dd576474 | Serge Torres | for vIndex in xrange(len(readBasis.rows())-1, -1, -1): |
62 | dd576474 | Serge Torres | curRBGSO = readBasisGso.row(vIndex) |
63 | 724064f1 | Serge Torres | curVect = curVect - \ |
64 | 724064f1 | Serge Torres | (round((curVect * curRBGSO) / (curRBGSO * curRBGSO)) * \ |
65 | dd576474 | Serge Torres | readBasis.row(vIndex)) |
66 | 9645ea29 | Serge Torres | return vect - curVect |
67 | 62861417 | Serge Torres | # End cvp_babai |
68 | 9645ea29 | Serge Torres | # |
69 | 9645ea29 | Serge Torres | def cvp_bkz_reduce(intBasis, blockSize): |
70 | 9645ea29 | Serge Torres | """ |
71 | 9645ea29 | Serge Torres | Thin and simplistic wrapper the HKZ function of the FP_LLL module. |
72 | 9645ea29 | Serge Torres | """ |
73 | 9645ea29 | Serge Torres | fplllIntBasis = FP_LLL(intBasis) |
74 | 9645ea29 | Serge Torres | fplllIntBasis.BKZ(blockSize) |
75 | 9645ea29 | Serge Torres | return fplllIntBasis._sage_() |
76 | 9645ea29 | Serge Torres | # End cvp_hkz_reduce. |
77 | 9645ea29 | Serge Torres | # |
78 | 9cf1fb38 | Serge Torres | def cvp_candidate_vectors(intVect, diffsList): |
79 | 9cf1fb38 | Serge Torres | """ |
80 | 9cf1fb38 | Serge Torres | Computes a list of best approximation vectors based on the CVP |
81 | 9cf1fb38 | Serge Torres | computed vector using the differences between this vector and the |
82 | 9cf1fb38 | Serge Torres | target function vector. |
83 | 9cf1fb38 | Serge Torres | @param intVect the vector from which candidates are built |
84 | 9cf1fb38 | Serge Torres | @param diffsList the list of the values that will be appended to the |
85 | 9cf1fb38 | Serge Torres | initial vector to form the candidates |
86 | 9cf1fb38 | Serge Torres | @return A matrix made of candidates rows or None if there is some invalid |
87 | 9cf1fb38 | Serge Torres | argument. |
88 | 9cf1fb38 | Serge Torres | @par How it works |
89 | 9cf1fb38 | Serge Torres | The idea is to create all the possible vectors based on the computed CVP |
90 | 9cf1fb38 | Serge Torres | vector and its differences to the target. Those are collected in |
91 | 9cf1fb38 | Serge Torres | diffsList.@n |
92 | 9cf1fb38 | Serge Torres | From the vector we create all the possible combinations between the original |
93 | 9cf1fb38 | Serge Torres | value and the differences in diffsList. Some of those can be equal to 0. |
94 | 9cf1fb38 | Serge Torres | They are not taken into account. If nonZeroDiffsCount is the number of |
95 | 9cf1fb38 | Serge Torres | diffsList element different from 0, there are 2^nonZeroDiffsCount |
96 | 9cf1fb38 | Serge Torres | possible variants.@n |
97 | 9cf1fb38 | Serge Torres | To compute those, we build a 2^nonZeroDiffsCount rows matrix. For the |
98 | 9cf1fb38 | Serge Torres | first element in the vector corresponding to a non-zero in diffsList, we |
99 | 9cf1fb38 | Serge Torres | switch values in the matrix at every row.@n |
100 | 9cf1fb38 | Serge Torres | For the second such element (non-zero corresponding diffsList element), we |
101 | 9cf1fb38 | Serge Torres | switch values in the matrix at every second row for a string of two similar |
102 | 9cf1fb38 | Serge Torres | values.@n |
103 | 9cf1fb38 | Serge Torres | For the third such element, change happens at every fourth row, for a |
104 | 9cf1fb38 | Serge Torres | string of four similar values. And so on... |
105 | 9cf1fb38 | Serge Torres | @par Example |
106 | 9cf1fb38 | Serge Torres | @verbatim |
107 | 9cf1fb38 | Serge Torres | vect = [10, 20, 30, 40, 50] |
108 | 9cf1fb38 | Serge Torres | diffsList = [ 1, 0, -1, 0, 1] |
109 | 9cf1fb38 | Serge Torres | vectCandMat = [[10, 20, 30, 40, 50], |
110 | 9cf1fb38 | Serge Torres | [11, 20, 30, 40, 50], |
111 | 9cf1fb38 | Serge Torres | [10, 20, 29, 40, 50], |
112 | 9cf1fb38 | Serge Torres | [11, 20, 29, 40, 50], |
113 | 9cf1fb38 | Serge Torres | [10, 20, 30, 40, 51], |
114 | 9cf1fb38 | Serge Torres | [11, 20, 30, 40, 51], |
115 | 9cf1fb38 | Serge Torres | [10, 20, 29, 40, 51], |
116 | 9cf1fb38 | Serge Torres | [11, 20, 29, 40, 51]] |
117 | 9cf1fb38 | Serge Torres | @endverbatim |
118 | 9cf1fb38 | Serge Torres | """ |
119 | 9cf1fb38 | Serge Torres | ## Arguments check. |
120 | 9cf1fb38 | Serge Torres | vectLen = len(intVect) |
121 | 9cf1fb38 | Serge Torres | if vectLen != len(diffsList): |
122 | 9cf1fb38 | Serge Torres | return None |
123 | 9cf1fb38 | Serge Torres | # |
124 | 9cf1fb38 | Serge Torres | ## Compute the number of diffsList elements different from 0. |
125 | 9cf1fb38 | Serge Torres | nonZeroDiffsCount = 0 |
126 | 9cf1fb38 | Serge Torres | for elem in diffsList: |
127 | 9cf1fb38 | Serge Torres | if elem != 0: |
128 | 9cf1fb38 | Serge Torres | nonZeroDiffsCount += 1 |
129 | 9cf1fb38 | Serge Torres | if nonZeroDiffsCount == 0: |
130 | 9cf1fb38 | Serge Torres | return matrix(ZZ, 0, vectLen) |
131 | 9cf1fb38 | Serge Torres | numRows = 2^nonZeroDiffsCount |
132 | 9cf1fb38 | Serge Torres | vectMat = matrix(ZZ, numRows, vectLen) |
133 | 9cf1fb38 | Serge Torres | for rowIndex in xrange(0,numRows): |
134 | 9cf1fb38 | Serge Torres | effColIndex = 0 |
135 | 9cf1fb38 | Serge Torres | for colIndex in xrange(0,vectLen): |
136 | 9cf1fb38 | Serge Torres | vectMat[rowIndex, colIndex] = intVect[colIndex] |
137 | 9cf1fb38 | Serge Torres | if diffsList[colIndex] != 0: |
138 | 9cf1fb38 | Serge Torres | if (rowIndex % 2^(effColIndex + 1)) >= 2^effColIndex: |
139 | 9cf1fb38 | Serge Torres | vectMat[rowIndex, colIndex] += diffsList[colIndex] |
140 | 9cf1fb38 | Serge Torres | effColIndex += 1 |
141 | 9cf1fb38 | Serge Torres | return vectMat |
142 | 9cf1fb38 | Serge Torres | # End cvp_candidate_vectors |
143 | 9cf1fb38 | Serge Torres | # |
144 | 04d64614 | Serge Torres | def cvp_coefficients_bounds_projection(executablePath, arguments): |
145 | 04d64614 | Serge Torres | """ |
146 | 04d64614 | Serge Torres | Compute the min and max of the coefficients with linear |
147 | 04d64614 | Serge Torres | programming projection. |
148 | 04d64614 | Serge Torres | @param executablePath: the path to the binary program; |
149 | 04d64614 | Serge Torres | @param arguments: a list of arguments to be givent to the binary |
150 | 04d64614 | Serge Torres | @return: the min and max coefficients value arrays (in this order). |
151 | 04d64614 | Serge Torres | """ |
152 | 04d64614 | Serge Torres | from subprocess import check_output |
153 | 04d64614 | Serge Torres | commandLine = [executablePath] + arguments |
154 | 04d64614 | Serge Torres | ## Get rid of output on stderr. |
155 | 04d64614 | Serge Torres | devNull = open("/dev/null", "rw") |
156 | 04d64614 | Serge Torres | ## Run ther program. |
157 | 04d64614 | Serge Torres | otp = check_output(commandLine, stderr=devNull) |
158 | 04d64614 | Serge Torres | devNull.close() |
159 | 04d64614 | Serge Torres | ## Recover the results |
160 | 04d64614 | Serge Torres | bounds = sage_eval(otp) |
161 | 04d64614 | Serge Torres | minCoeffsExpList = [] |
162 | 04d64614 | Serge Torres | maxCoeffsExpList = [] |
163 | 9b0c03e7 | Serge Torres | #print "bounds:", bounds |
164 | 04d64614 | Serge Torres | for boundsPair in bounds: |
165 | 04d64614 | Serge Torres | minCoeffsExpList.append(boundsPair[0]) |
166 | 04d64614 | Serge Torres | maxCoeffsExpList.append(boundsPair[1]) |
167 | 04d64614 | Serge Torres | print "minCoeffsExpList:", minCoeffsExpList |
168 | 04d64614 | Serge Torres | print "maxCoeffsExpList:", maxCoeffsExpList |
169 | 04d64614 | Serge Torres | return (minCoeffsExpList, maxCoeffsExpList) |
170 | 04d64614 | Serge Torres | # End cvp_coefficients_bounds_projection |
171 | 04d64614 | Serge Torres | |
172 | 04d64614 | Serge Torres | def cvp_coefficients_bounds_projection_exps(executablePath, |
173 | 04d64614 | Serge Torres | arguments, |
174 | 04d64614 | Serge Torres | realField = None): |
175 | 04d64614 | Serge Torres | """ |
176 | 04d64614 | Serge Torres | Compute the min and max exponents of the coefficients with linear |
177 | 04d64614 | Serge Torres | programming projection. |
178 | 04d64614 | Serge Torres | @param executablePath: the path to the binary program; |
179 | 04d64614 | Serge Torres | @param arguments: a list of arguments to be givent to the binary |
180 | 04d64614 | Serge Torres | @param realField: the realField to use for floating-point conversion. |
181 | 04d64614 | Serge Torres | @return: the min and max exponents arrays (in this order). |
182 | 04d64614 | Serge Torres | """ |
183 | 04d64614 | Serge Torres | ## If no realField is givne, fall back on RR. |
184 | 04d64614 | Serge Torres | if realField is None: |
185 | 04d64614 | Serge Torres | realField = RR |
186 | 04d64614 | Serge Torres | (minCoeffsExpList, maxCoeffsExpList) = \ |
187 | 04d64614 | Serge Torres | cvp_coefficients_bounds_projection(executablePath,arguments) |
188 | 04d64614 | Serge Torres | for index in xrange(0, len(minCoeffsExpList)): |
189 | 04d64614 | Serge Torres | minCoeffsExpList[index] = \ |
190 | 9b0c03e7 | Serge Torres | realField(minCoeffsExpList[index]).abs().log2().floor() |
191 | 04d64614 | Serge Torres | maxCoeffsExpList[index] = \ |
192 | 9b0c03e7 | Serge Torres | realField(maxCoeffsExpList[index]).abs().log2().floor() |
193 | 04d64614 | Serge Torres | return (minCoeffsExpList, maxCoeffsExpList) |
194 | 04d64614 | Serge Torres | # End cvp_coefficients_bounds_projection_exps |
195 | 04d64614 | Serge Torres | |
196 | c7bf1784 | Serge Torres | def cvp_chebyshev_maxis_1k(numPoints, realField, contFracMaxErr = None): |
197 | c7bf1784 | Serge Torres | """ |
198 | c7bf1784 | Serge Torres | Compute the Chebyshev maxis for some polynomial degree (numPoints, for the |
199 | dd576474 | Serge Torres | zeros, numPoints + 1 for the maxis) scaled to the [lowerBound, upperBound] |
200 | dd576474 | Serge Torres | interval. |
201 | dd576474 | Serge Torres | The list is returned as a row floating-point numbers is contFracMaxErr |
202 | dd576474 | Serge Torres | is None. |
203 | c7bf1784 | Serge Torres | Otherwise elements are transformed into rational numbers. |
204 | c7bf1784 | Serge Torres | """ |
205 | c7bf1784 | Serge Torres | if numPoints < 1: |
206 | c7bf1784 | Serge Torres | return None |
207 | c7bf1784 | Serge Torres | if numPoints == 0: |
208 | c7bf1784 | Serge Torres | return [0] |
209 | c7bf1784 | Serge Torres | ## Check that realField has a "prec()" member. |
210 | c7bf1784 | Serge Torres | try: |
211 | c7bf1784 | Serge Torres | realField.prec() |
212 | c7bf1784 | Serge Torres | except: |
213 | c7bf1784 | Serge Torres | return None |
214 | c7bf1784 | Serge Torres | # |
215 | c7bf1784 | Serge Torres | maxisList = [] |
216 | c7bf1784 | Serge Torres | ## n extrema are given by a degree (n-1) Chebyshev polynomial. |
217 | c7bf1784 | Serge Torres | # formulas: cos ((i * pi) / (numPoints - 1)) for i = 0,...,numPoints-1. |
218 | c7bf1784 | Serge Torres | # Source: https://en.wikipedia.org/wiki/Chebyshev_polynomials |
219 | c7bf1784 | Serge Torres | for index in xrange(0, numPoints): |
220 | c7bf1784 | Serge Torres | ## When number of points is odd (then, the Chebyshev degree is odd two), |
221 | c7bf1784 | Serge Torres | # the central point is 0. */ |
222 | c7bf1784 | Serge Torres | if (numPoints % 2 == 1) and ((2 * index + 1) == numPoints): |
223 | c7bf1784 | Serge Torres | if contFracMaxErr is None: |
224 | c7bf1784 | Serge Torres | maxisList.append(realField(0)) |
225 | c7bf1784 | Serge Torres | else: |
226 | c7bf1784 | Serge Torres | maxisList.append(0) |
227 | c7bf1784 | Serge Torres | else: |
228 | c7bf1784 | Serge Torres | currentCheby = \ |
229 | c7bf1784 | Serge Torres | ((realField(index) * realField(pi)) / |
230 | c7bf1784 | Serge Torres | realField(numPoints-1)).cos() |
231 | c7bf1784 | Serge Torres | #print "Current Cheby:", currentCheby |
232 | c7bf1784 | Serge Torres | ## Result is negated to have an increasing order list. |
233 | c7bf1784 | Serge Torres | if contFracMaxErr is None: |
234 | c7bf1784 | Serge Torres | maxisList.append(-currentCheby) |
235 | c7bf1784 | Serge Torres | else: |
236 | c7bf1784 | Serge Torres | maxisList.append(-currentCheby.nearby_rational(contFracMaxErr)) |
237 | c7bf1784 | Serge Torres | #print "Relative error:", (currentCheby/maxisList[index]) |
238 | c7bf1784 | Serge Torres | return maxisList |
239 | c7bf1784 | Serge Torres | # End cvp_chebyshev_maxis_1k. |
240 | c7bf1784 | Serge Torres | # |
241 | c7bf1784 | Serge Torres | def cvp_chebyshev_maxis_for_interval(lowerBound, |
242 | c7bf1784 | Serge Torres | upperBound, |
243 | c7bf1784 | Serge Torres | numPoints, |
244 | c7bf1784 | Serge Torres | realField = None, |
245 | c7bf1784 | Serge Torres | contFracMaxErr = None): |
246 | c7bf1784 | Serge Torres | """ |
247 | c7bf1784 | Serge Torres | Compute the Chebyshev maxis for some polynomial degree (numPoints, for the |
248 | c7bf1784 | Serge Torres | maxis) scaled to the [lowerBound, upperBound] interval. |
249 | c7bf1784 | Serge Torres | If no contFracMaxErr argument is given, we return the list as "raw" |
250 | c7bf1784 | Serge Torres | floating-points. Otherwise, rational numbers are returned. |
251 | c7bf1784 | Serge Torres | """ |
252 | c7bf1784 | Serge Torres | ## Arguments check. |
253 | c7bf1784 | Serge Torres | if lowerBound >= upperBound: |
254 | c7bf1784 | Serge Torres | return None |
255 | c7bf1784 | Serge Torres | if numPoints < 1: |
256 | c7bf1784 | Serge Torres | return None |
257 | c7bf1784 | Serge Torres | ## If no realField argument is given try to retrieve it from the |
258 | c7bf1784 | Serge Torres | # bounds. If impossible (e.g. rational bound), fall back on RR. |
259 | c7bf1784 | Serge Torres | if realField is None: |
260 | c7bf1784 | Serge Torres | try: |
261 | c7bf1784 | Serge Torres | ### Force failure if parent does not have prec() member. |
262 | c7bf1784 | Serge Torres | lowerBound.parent().prec() |
263 | c7bf1784 | Serge Torres | ### If no exception is thrown, set realField. |
264 | c7bf1784 | Serge Torres | realField = lowerBound.parent() |
265 | c7bf1784 | Serge Torres | except: |
266 | c7bf1784 | Serge Torres | realField = RR |
267 | c7bf1784 | Serge Torres | #print "Real field:", realField |
268 | c7bf1784 | Serge Torres | ## We want "raw"floating-point nodes to only have one final rounding. |
269 | c7bf1784 | Serge Torres | chebyshevMaxisList = \ |
270 | c7bf1784 | Serge Torres | cvp_chebyshev_maxis_1k(numPoints, realField) |
271 | c7bf1784 | Serge Torres | scalingFactor, offset = cvp_affine_from_chebyshev(lowerBound, upperBound) |
272 | c7bf1784 | Serge Torres | for index in xrange(0, len(chebyshevMaxisList)): |
273 | c7bf1784 | Serge Torres | chebyshevMaxisList[index] = \ |
274 | c7bf1784 | Serge Torres | chebyshevMaxisList[index] * scalingFactor + offset |
275 | c7bf1784 | Serge Torres | if not contFracMaxErr is None: |
276 | c7bf1784 | Serge Torres | chebyshevMaxisList[index] = \ |
277 | c7bf1784 | Serge Torres | chebyshevMaxisList[index].nearby_rational(contFracMaxErr) |
278 | c7bf1784 | Serge Torres | return chebyshevMaxisList |
279 | c7bf1784 | Serge Torres | # End cvp_chebyshev_maxis_for_interval. |
280 | c7bf1784 | Serge Torres | # |
281 | 04d64614 | Serge Torres | def cvp_chebyshev_zeros_1k(numPoints, realField, contFracMaxErr = None): |
282 | 04d64614 | Serge Torres | """ |
283 | 04d64614 | Serge Torres | Compute the Chebyshev zeros for some polynomial degree (numPoints, for the |
284 | 04d64614 | Serge Torres | zeros) scaled to the [lowerBound, upperBound] interval. |
285 | 04d64614 | Serge Torres | The list is returned as row floating-point numbers is contFracMaxErr is None. |
286 | 04d64614 | Serge Torres | Otherwise elements are transformed into rational numbers. |
287 | 04d64614 | Serge Torres | """ |
288 | 04d64614 | Serge Torres | if numPoints < 1: |
289 | 04d64614 | Serge Torres | return None |
290 | 04d64614 | Serge Torres | if numPoints == 0: |
291 | 04d64614 | Serge Torres | return [0] |
292 | 04d64614 | Serge Torres | ## Check that realField has a "prec()" member. |
293 | 04d64614 | Serge Torres | try: |
294 | 04d64614 | Serge Torres | realField.prec() |
295 | 04d64614 | Serge Torres | except: |
296 | 04d64614 | Serge Torres | return None |
297 | 04d64614 | Serge Torres | # |
298 | 04d64614 | Serge Torres | zerosList = [] |
299 | 04d64614 | Serge Torres | ## formulas: cos (((2*i - 1) * pi) / (2*numPoints)) for i = 1,...,numPoints. |
300 | 04d64614 | Serge Torres | # If i is -1-shifted, as in the following loop, formula is |
301 | 04d64614 | Serge Torres | # cos (((2*i + 1) * pi) / (2*numPoints)) for i = 0,...,numPoints-1. |
302 | 04d64614 | Serge Torres | for index in xrange(0, numPoints): |
303 | 04d64614 | Serge Torres | ## When number of points is odd (then, the Chebyshev degree is odd two), |
304 | 04d64614 | Serge Torres | # the central point is 0. */ |
305 | 04d64614 | Serge Torres | if (numPoints % 2 == 1) and ((2 * index + 1) == numPoints): |
306 | 04d64614 | Serge Torres | if contFracMaxErr is None: |
307 | 04d64614 | Serge Torres | zerosList.append(realField(0)) |
308 | 04d64614 | Serge Torres | else: |
309 | 04d64614 | Serge Torres | zerosList.append(0) |
310 | 04d64614 | Serge Torres | else: |
311 | 04d64614 | Serge Torres | currentCheby = \ |
312 | 04d64614 | Serge Torres | ((realField(2*index+1) * realField(pi)) / |
313 | 04d64614 | Serge Torres | realField(2*numPoints)).cos() |
314 | 04d64614 | Serge Torres | #print "Current Cheby:", currentCheby |
315 | 04d64614 | Serge Torres | ## Result is negated to have an increasing order list. |
316 | 04d64614 | Serge Torres | if contFracMaxErr is None: |
317 | 04d64614 | Serge Torres | zerosList.append(-currentCheby) |
318 | 04d64614 | Serge Torres | else: |
319 | 04d64614 | Serge Torres | zerosList.append(-currentCheby.nearby_rational(contFracMaxErr)) |
320 | 04d64614 | Serge Torres | #print "Relative error:", (currentCheby/zerosList[index]) |
321 | 04d64614 | Serge Torres | return zerosList |
322 | 04d64614 | Serge Torres | # End cvp_chebyshev_zeros_1k. |
323 | 04d64614 | Serge Torres | # |
324 | 04d64614 | Serge Torres | def cvp_chebyshev_zeros_for_interval(lowerBound, |
325 | 04d64614 | Serge Torres | upperBound, |
326 | 04d64614 | Serge Torres | numPoints, |
327 | 04d64614 | Serge Torres | realField = None, |
328 | 04d64614 | Serge Torres | contFracMaxErr = None): |
329 | 04d64614 | Serge Torres | """ |
330 | 04d64614 | Serge Torres | Compute the Chebyshev zeros for some polynomial degree (numPoints, for the |
331 | 04d64614 | Serge Torres | zeros) scaled to the [lowerBound, upperBound] interval. |
332 | 04d64614 | Serge Torres | If no contFracMaxErr argument is given, we return the list as "raw" |
333 | 04d64614 | Serge Torres | floating-points. Otherwise, rational numbers are returned. |
334 | 04d64614 | Serge Torres | """ |
335 | 04d64614 | Serge Torres | ## Arguments check. |
336 | 04d64614 | Serge Torres | if lowerBound >= upperBound: |
337 | 04d64614 | Serge Torres | return None |
338 | 04d64614 | Serge Torres | if numPoints < 1: |
339 | 04d64614 | Serge Torres | return None |
340 | 04d64614 | Serge Torres | ## If no realField argument is given try to retrieve it from the |
341 | 04d64614 | Serge Torres | # bounds. If impossible (e.g. rational bound), fall back on RR. |
342 | 04d64614 | Serge Torres | if realField is None: |
343 | 04d64614 | Serge Torres | try: |
344 | 04d64614 | Serge Torres | ### Force failure if parent does not have prec() member. |
345 | 04d64614 | Serge Torres | lowerBound.parent().prec() |
346 | 04d64614 | Serge Torres | ### If no exception is thrown, set realField. |
347 | 04d64614 | Serge Torres | realField = lowerBound.parent() |
348 | 04d64614 | Serge Torres | except: |
349 | 04d64614 | Serge Torres | realField = RR |
350 | 04d64614 | Serge Torres | #print "Real field:", realField |
351 | 04d64614 | Serge Torres | ## We want "raw"floating-point nodes to only have one final rounding. |
352 | 04d64614 | Serge Torres | chebyshevZerosList = \ |
353 | 04d64614 | Serge Torres | cvp_chebyshev_zeros_1k(numPoints, realField) |
354 | 04d64614 | Serge Torres | scalingFactor, offset = cvp_affine_from_chebyshev(lowerBound, upperBound) |
355 | 04d64614 | Serge Torres | for index in xrange(0, len(chebyshevZerosList)): |
356 | 04d64614 | Serge Torres | chebyshevZerosList[index] = \ |
357 | 04d64614 | Serge Torres | chebyshevZerosList[index] * scalingFactor + offset |
358 | 04d64614 | Serge Torres | if not contFracMaxErr is None: |
359 | 04d64614 | Serge Torres | chebyshevZerosList[index] = \ |
360 | 04d64614 | Serge Torres | chebyshevZerosList[index].nearby_rational(contFracMaxErr) |
361 | 04d64614 | Serge Torres | return chebyshevZerosList |
362 | 04d64614 | Serge Torres | # End cvp_chebyshev_zeros_for_interval. |
363 | 04d64614 | Serge Torres | # |
364 | 62861417 | Serge Torres | def cvp_common_scaling_exp(precision, |
365 | 62861417 | Serge Torres | precisionFraction = None): |
366 | 9645ea29 | Serge Torres | """ |
367 | 9645ea29 | Serge Torres | Compute the common scaling factor (a power of 2). |
368 | 62861417 | Serge Torres | The exponent is a fraction of the precision; |
369 | 62861417 | Serge Torres | A extra factor is computed for the vector, |
370 | 62861417 | Serge Torres | exra factors are computed for the basis vectors, all in the corresponding |
371 | 62861417 | Serge Torres | functions. |
372 | 9645ea29 | Serge Torres | """ |
373 | 9645ea29 | Serge Torres | ## Set a default value for the precisionFraction to 1/2. |
374 | 9645ea29 | Serge Torres | if precisionFraction is None: |
375 | 62861417 | Serge Torres | precisionFraction = 3/4 |
376 | 62861417 | Serge Torres | """ |
377 | 9645ea29 | Serge Torres | minBasisVectsNorm = oo |
378 | 9645ea29 | Serge Torres | currentNorm = 0 |
379 | 9645ea29 | Serge Torres | for vect in floatBasis.rows(): |
380 | 9645ea29 | Serge Torres | currentNorm = vect.norm() |
381 | 9645ea29 | Serge Torres | print "Current norm:", currentNorm |
382 | 9645ea29 | Serge Torres | if currentNorm < minBasisVectsNorm: |
383 | 9645ea29 | Serge Torres | minBasisVectsNorm = currentNorm |
384 | 9645ea29 | Serge Torres | currentNorm = funcVect.norm() |
385 | 9645ea29 | Serge Torres | print "Current norm:", currentNorm |
386 | 9645ea29 | Serge Torres | if currentNorm < minBasisVectsNorm: |
387 | 9645ea29 | Serge Torres | minBasisVectsNorm = currentNorm |
388 | 9645ea29 | Serge Torres | ## Check if a push is need because the smallest norm is below 0. |
389 | 9645ea29 | Serge Torres | powerForMinNorm = floor(log(minBasisVectsNorm)/log2) |
390 | 9645ea29 | Serge Torres | print "Power for min norm :", powerForMinNorm |
391 | 9645ea29 | Serge Torres | print "Power for precision:", ceil(precision*precisionFraction) |
392 | 9645ea29 | Serge Torres | if powerForMinNorm < 0: |
393 | 9645ea29 | Serge Torres | return 2^(ceil(precision*precisionFraction) - powerFromMinNorm) |
394 | 9645ea29 | Serge Torres | else: |
395 | 62861417 | Serge Torres | """ |
396 | 62861417 | Serge Torres | return ceil(precision * precisionFraction) |
397 | 9645ea29 | Serge Torres | # End cvp_common_scaling_factor. |
398 | 9645ea29 | Serge Torres | # |
399 | e2eb9ccc | Serge Torres | def cvp_cvp_polynomial(func, |
400 | e2eb9ccc | Serge Torres | lowerBound, |
401 | e2eb9ccc | Serge Torres | upperBound, |
402 | e2eb9ccc | Serge Torres | coeffsExpList, |
403 | e2eb9ccc | Serge Torres | coeffsPrecList, |
404 | e2eb9ccc | Serge Torres | minCoeffsBoundExpList, |
405 | e2eb9ccc | Serge Torres | maxCoeffsBoundExpList, |
406 | e2eb9ccc | Serge Torres | pointsList, |
407 | e2eb9ccc | Serge Torres | realField): |
408 | e2eb9ccc | Serge Torres | """ |
409 | e2eb9ccc | Serge Torres | Compute a polynomial based on a CVP vector for a function approximation. |
410 | e2eb9ccc | Serge Torres | """ |
411 | e2eb9ccc | Serge Torres | ## Build the basis for CVP. |
412 | e2eb9ccc | Serge Torres | ### Common scaling exponent. |
413 | e2eb9ccc | Serge Torres | commonScalingExp = cvp_common_scaling_exp(realField.prec()) |
414 | e2eb9ccc | Serge Torres | ### Monomials list derived from exponenets list. |
415 | e2eb9ccc | Serge Torres | monomialsList = cvp_monomials_list(coeffsExpList) |
416 | e2eb9ccc | Serge Torres | ### Float basis first |
417 | e2eb9ccc | Serge Torres | floatBasis = cvp_float_basis(monomialsList, pointsList, realField) |
418 | e2eb9ccc | Serge Torres | ### Integral basis. |
419 | e2eb9ccc | Serge Torres | extraScalingExpsList = \ |
420 | e2eb9ccc | Serge Torres | cvp_extra_basis_scaling_exps(coeffsPrecList, minCoeffsBoundExpList) |
421 | e2eb9ccc | Serge Torres | intBasis = \ |
422 | e2eb9ccc | Serge Torres | cvp_int_basis(floatBasis, commonScalingExp, extraScalingExpsList) |
423 | e2eb9ccc | Serge Torres | ### The reduced basis. |
424 | e2eb9ccc | Serge Torres | redIntBasis = cvp_lll_reduce(intBasis) |
425 | e2eb9ccc | Serge Torres | ### The reduced basis GSO. |
426 | e2eb9ccc | Serge Torres | (redIntBasisGso, mu) = redIntBasis.gram_schmidt() |
427 | e2eb9ccc | Serge Torres | ## Function vector. |
428 | e2eb9ccc | Serge Torres | #### Floating-point vector. |
429 | e2eb9ccc | Serge Torres | floatFuncVect = \ |
430 | e2eb9ccc | Serge Torres | cvp_float_vector_for_approx(func, pointsList, realField) |
431 | e2eb9ccc | Serge Torres | extraFuncScalingExp = \ |
432 | e2eb9ccc | Serge Torres | cvp_extra_function_scaling_exp(floatBasis, |
433 | e2eb9ccc | Serge Torres | floatFuncVect, |
434 | e2eb9ccc | Serge Torres | maxCoeffsBoundExpList) |
435 | e2eb9ccc | Serge Torres | #### Integral vector. |
436 | e2eb9ccc | Serge Torres | intFuncVect = \ |
437 | e2eb9ccc | Serge Torres | cvp_int_vector_for_approx(floatFuncVect, |
438 | e2eb9ccc | Serge Torres | commonScalingExp, |
439 | e2eb9ccc | Serge Torres | extraFuncScalingExp) |
440 | e2eb9ccc | Serge Torres | ## CPV vector |
441 | e2eb9ccc | Serge Torres | ### In ambient basis. |
442 | e2eb9ccc | Serge Torres | cvpVectInAmbient = cvp_babai(redIntBasis, redIntBasisGso, intFuncVect) |
443 | e2eb9ccc | Serge Torres | ### In intBasis. |
444 | e2eb9ccc | Serge Torres | cvpVectInIntBasis = cvp_vector_in_basis(cvpVectInAmbient, intBasis) |
445 | e2eb9ccc | Serge Torres | ## Polynomial coefficients |
446 | e2eb9ccc | Serge Torres | cvpPolynomialCoeffs = \ |
447 | e2eb9ccc | Serge Torres | cvp_polynomial_coeffs_from_vect(cvpVectInIntBasis, |
448 | e2eb9ccc | Serge Torres | coeffsPrecList, |
449 | e2eb9ccc | Serge Torres | minCoeffsBoundExpList, |
450 | e2eb9ccc | Serge Torres | extraFuncScalingExp) |
451 | e2eb9ccc | Serge Torres | #print "CVP polynomial coefficients:" |
452 | e2eb9ccc | Serge Torres | #print cvpPolynomialCoeffs |
453 | e2eb9ccc | Serge Torres | ## Polynomial in Sage. |
454 | e2eb9ccc | Serge Torres | cvpPolySa = \ |
455 | e2eb9ccc | Serge Torres | cvp_polynomial_from_coeffs_and_exps(cvpPolynomialCoeffs, |
456 | e2eb9ccc | Serge Torres | coeffsExpList, |
457 | e2eb9ccc | Serge Torres | realField[x]) |
458 | e2eb9ccc | Serge Torres | #print cvpPolySa |
459 | e2eb9ccc | Serge Torres | return cvpPolySa |
460 | e2eb9ccc | Serge Torres | # End cvp_cvp_polynomial. |
461 | e2eb9ccc | Serge Torres | # |
462 | 724064f1 | Serge Torres | def cvp_evaluation_points_list(funct, |
463 | 724064f1 | Serge Torres | maxDegree, |
464 | 724064f1 | Serge Torres | lowerBound, |
465 | 724064f1 | Serge Torres | upperBound, |
466 | 724064f1 | Serge Torres | realField = None): |
467 | 724064f1 | Serge Torres | """ |
468 | 724064f1 | Serge Torres | Compute a list of points for the vector creation. |
469 | 724064f1 | Serge Torres | Strategy: |
470 | 724064f1 | Serge Torres | - compute the zeros of the function-remez; |
471 | 724064f1 | Serge Torres | - compute the zeros of the function-rounded_remez; |
472 | 724064f1 | Serge Torres | - compute the Chebyshev points. |
473 | 724064f1 | Serge Torres | Merge the whole thing. |
474 | 724064f1 | Serge Torres | """ |
475 | 724064f1 | Serge Torres | |
476 | 724064f1 | Serge Torres | # End cvp_evaluation_points_list. |
477 | 724064f1 | Serge Torres | # |
478 | 62861417 | Serge Torres | def cvp_extra_basis_scaling_exps(precsList, minExponentsList): |
479 | 9cf1fb38 | Serge Torres | """ |
480 | 9cf1fb38 | Serge Torres | Computes the exponents for the extra scaling down of the elements of the |
481 | 9cf1fb38 | Serge Torres | basis. |
482 | 9cf1fb38 | Serge Torres | This extra scaling down is necessary when there are elements of the |
483 | 9cf1fb38 | Serge Torres | basis that have negative exponents. |
484 | 9cf1fb38 | Serge Torres | """ |
485 | 62861417 | Serge Torres | extraScalingExpsList = [] |
486 | 62861417 | Serge Torres | for minExp, prec in zip(minExponentsList, precsList): |
487 | 62861417 | Serge Torres | if minExp - prec < 0: |
488 | 62861417 | Serge Torres | extraScalingExpsList.append(minExp - prec) |
489 | 62861417 | Serge Torres | else: |
490 | 62861417 | Serge Torres | extraScalingExpsList.append(0) |
491 | 62861417 | Serge Torres | return extraScalingExpsList |
492 | 62861417 | Serge Torres | # End cvp_extra_basis_scaling_exps. |
493 | 62861417 | Serge Torres | # |
494 | 62861417 | Serge Torres | def cvp_extra_function_scaling_exp(floatBasis, |
495 | 62861417 | Serge Torres | floatFuncVect, |
496 | 62861417 | Serge Torres | maxExponentsList): |
497 | 9645ea29 | Serge Torres | """ |
498 | 62861417 | Serge Torres | Compute the extra scaling exponent for the function vector in ordre to |
499 | 62861417 | Serge Torres | guarantee that the maximum exponent can be reached for each element of the |
500 | 62861417 | Serge Torres | basis. |
501 | 9645ea29 | Serge Torres | """ |
502 | 62861417 | Serge Torres | ## Check arguments |
503 | 9645ea29 | Serge Torres | if floatBasis.nrows() == 0 or \ |
504 | 9645ea29 | Serge Torres | floatBasis.ncols() == 0 or \ |
505 | 62861417 | Serge Torres | len(floatFuncVect) == 0: |
506 | 62861417 | Serge Torres | return 1 |
507 | 62861417 | Serge Torres | if len(maxExponentsList) != floatBasis.nrows(): |
508 | 62861417 | Serge Torres | return None |
509 | 62861417 | Serge Torres | ## Compute the log of the norm of the function vector. |
510 | 62861417 | Serge Torres | funcVectNormLog = log(floatFuncVect.norm()) |
511 | 9645ea29 | Serge Torres | ## Compute the extra scaling factor for each vector of the basis. |
512 | 62861417 | Serge Torres | # for norms ratios an maxExponentsList. |
513 | 62861417 | Serge Torres | extraScalingExp = 0 |
514 | 62861417 | Serge Torres | for (row, maxExp) in zip(floatBasis.rows(),maxExponentsList): |
515 | 62861417 | Serge Torres | rowNormLog = log(row.norm()) |
516 | 62861417 | Serge Torres | normsRatioLog2 = floor((funcVectNormLog - rowNormLog) / log2) |
517 | 62861417 | Serge Torres | #print "Current norms ratio log2:", normsRatioLog2 |
518 | 62861417 | Serge Torres | scalingExpCandidate = normsRatioLog2 - maxExp |
519 | 62861417 | Serge Torres | #print "Current scaling exponent candidate:", scalingExpCandidate |
520 | 62861417 | Serge Torres | if scalingExpCandidate < 0: |
521 | 62861417 | Serge Torres | if -scalingExpCandidate > extraScalingExp: |
522 | 62861417 | Serge Torres | extraScalingExp = -scalingExpCandidate |
523 | 62861417 | Serge Torres | return extraScalingExp |
524 | 62861417 | Serge Torres | # End cvp_extra_function_scaling_exp. |
525 | 9645ea29 | Serge Torres | # |
526 | 2669308a | Serge Torres | def cvp_filter_out_undefined_image(initialPointList, func): |
527 | 2669308a | Serge Torres | """ |
528 | 2669308a | Serge Torres | Fom the initial list and function, built a list of points which have a |
529 | 2669308a | Serge Torres | defined image. |
530 | 2669308a | Serge Torres | """ |
531 | 2669308a | Serge Torres | finalPointsList = [] |
532 | 2669308a | Serge Torres | for iterPoint in initialPointList: |
533 | 2669308a | Serge Torres | try: |
534 | 2669308a | Serge Torres | finalPointsList.append(func(iterPoint)) |
535 | 2669308a | Serge Torres | #print "cfoui - Point", iterPoint, "done." |
536 | 2669308a | Serge Torres | except ValueError: |
537 | 2669308a | Serge Torres | pass |
538 | 2669308a | Serge Torres | #print "cfoui - Point", iterPoint, "failed." |
539 | 2669308a | Serge Torres | return finalPointsList |
540 | 2669308a | Serge Torres | # End cvp_filter_out_undefined_image |
541 | 2669308a | Serge Torres | |
542 | 9645ea29 | Serge Torres | def cvp_float_basis(monomialsList, pointsList, realField): |
543 | 9645ea29 | Serge Torres | """ |
544 | 9645ea29 | Serge Torres | For a given monomials list and points list, compute the floating-point |
545 | 9645ea29 | Serge Torres | basis matrix. |
546 | 9645ea29 | Serge Torres | """ |
547 | 9645ea29 | Serge Torres | numRows = len(monomialsList) |
548 | 9645ea29 | Serge Torres | numCols = len(pointsList) |
549 | 9645ea29 | Serge Torres | if numRows == 0 or numCols == 0: |
550 | 9645ea29 | Serge Torres | return matrix(realField, 0, 0) |
551 | 9645ea29 | Serge Torres | # |
552 | 9645ea29 | Serge Torres | floatBasis = matrix(realField, numRows, numCols) |
553 | 9645ea29 | Serge Torres | for rIndex in xrange(0, numRows): |
554 | 9645ea29 | Serge Torres | for cIndex in xrange(0, numCols): |
555 | 9645ea29 | Serge Torres | floatBasis[rIndex,cIndex] = \ |
556 | 9645ea29 | Serge Torres | monomialsList[rIndex](realField(pointsList[cIndex])) |
557 | 9645ea29 | Serge Torres | return floatBasis |
558 | 9645ea29 | Serge Torres | # End cvp_float_basis |
559 | 9645ea29 | Serge Torres | # |
560 | 9645ea29 | Serge Torres | def cvp_float_vector_for_approx(func, |
561 | 9645ea29 | Serge Torres | basisPointsList, |
562 | 9645ea29 | Serge Torres | realField): |
563 | 9645ea29 | Serge Torres | """ |
564 | 9645ea29 | Serge Torres | Compute a floating-point vector for the function and the points list. |
565 | 9645ea29 | Serge Torres | """ |
566 | 9645ea29 | Serge Torres | # |
567 | 9645ea29 | Serge Torres | ## Some local variables. |
568 | 9645ea29 | Serge Torres | basisPointsNum = len(basisPointsList) |
569 | 9645ea29 | Serge Torres | # |
570 | 2669308a | Serge Torres | floatVector = vector(realField, basisPointsNum) |
571 | 9645ea29 | Serge Torres | ## |
572 | 9645ea29 | Serge Torres | for vIndex in xrange(0,basisPointsNum): |
573 | 2669308a | Serge Torres | ### We assume the all for all points their image is defined. |
574 | 2669308a | Serge Torres | floatVector[vIndex] = \ |
575 | 2669308a | Serge Torres | func(basisPointsList[vIndex]) |
576 | 2669308a | Serge Torres | return floatVector |
577 | 9645ea29 | Serge Torres | # End cvp_float_vector_for_approx. |
578 | 9645ea29 | Serge Torres | # |
579 | 2669308a | Serge Torres | def cvp_func_abs_max_for_points(func, pointsList, realField): |
580 | e2eb9ccc | Serge Torres | """ |
581 | e2eb9ccc | Serge Torres | Compute the maximum absolute value of a function for a list of |
582 | e2eb9ccc | Serge Torres | points. |
583 | e2eb9ccc | Serge Torres | If several points yield the same value and this value is the maximum, |
584 | 1c8b6220 | Serge Torres | the last visited one is returned. |
585 | e2eb9ccc | Serge Torres | @return (theMaxPoint, theMaxValue) |
586 | e2eb9ccc | Serge Torres | """ |
587 | e2eb9ccc | Serge Torres | evalDict = dict() |
588 | 1c8b6220 | Serge Torres | # |
589 | 1c8b6220 | Serge Torres | ## An empty points list is really an error. We cannot return an empty tuple. |
590 | e2eb9ccc | Serge Torres | if len(pointsList) == 0: |
591 | e2eb9ccc | Serge Torres | return None |
592 | e2eb9ccc | Serge Torres | # |
593 | e2eb9ccc | Serge Torres | for pt in pointsList: |
594 | 2669308a | Serge Torres | try: |
595 | 2669308a | Serge Torres | evalDict[abs(realField(func(pt)))] = realField(pt) |
596 | 2669308a | Serge Torres | #print "cfamfp - point:", realField(pt) , "- image:", abs(realField(func(pt))) |
597 | 2669308a | Serge Torres | except ValueError: |
598 | 2669308a | Serge Torres | pass |
599 | e2eb9ccc | Serge Torres | maxAbs = max(evalDict.keys()) |
600 | 2669308a | Serge Torres | #print "cfamfp - maxAbs:", maxAbs, evalDict[maxAbs] |
601 | e2eb9ccc | Serge Torres | return (evalDict[maxAbs], maxAbs) |
602 | e2eb9ccc | Serge Torres | # End cvp_func_abs_max_for_points |
603 | e2eb9ccc | Serge Torres | # |
604 | 9645ea29 | Serge Torres | def cvp_hkz_reduce(intBasis): |
605 | 9645ea29 | Serge Torres | """ |
606 | 2669308a | Serge Torres | Thin and simplistic wrapper on the HKZ function of the FP_LLL module. |
607 | 9645ea29 | Serge Torres | """ |
608 | 9645ea29 | Serge Torres | fplllIntBasis = FP_LLL(intBasis) |
609 | 9645ea29 | Serge Torres | fplllIntBasis.HKZ() |
610 | 9645ea29 | Serge Torres | return fplllIntBasis._sage_() |
611 | 9645ea29 | Serge Torres | # End cvp_hkz_reduce. |
612 | 9645ea29 | Serge Torres | # |
613 | 62861417 | Serge Torres | def cvp_int_basis(floatBasis, |
614 | 62861417 | Serge Torres | commonScalingExp, |
615 | 62861417 | Serge Torres | extraScalingExpsList): |
616 | 9645ea29 | Serge Torres | """ |
617 | 62861417 | Serge Torres | From the float basis, the common scaling factor and the extra exponents |
618 | 62861417 | Serge Torres | compute the integral basis. |
619 | 9645ea29 | Serge Torres | """ |
620 | 62861417 | Serge Torres | ## Checking arguments. |
621 | 62861417 | Serge Torres | if floatBasis.nrows() != len(extraScalingExpsList): |
622 | 62861417 | Serge Torres | return None |
623 | 9645ea29 | Serge Torres | intBasis = matrix(ZZ, floatBasis.nrows(), floatBasis.ncols()) |
624 | 9645ea29 | Serge Torres | for rIndex in xrange(0, floatBasis.nrows()): |
625 | 9645ea29 | Serge Torres | for cIndex in xrange(0, floatBasis.ncols()): |
626 | 9645ea29 | Serge Torres | intBasis[rIndex, cIndex] = \ |
627 | 9b0c03e7 | Serge Torres | (floatBasis[rIndex, cIndex] * \ |
628 | 9b0c03e7 | Serge Torres | 2^(commonScalingExp + extraScalingExpsList[rIndex])).round() |
629 | 9645ea29 | Serge Torres | return intBasis |
630 | 9645ea29 | Serge Torres | # End cvp_int_basis. |
631 | 9645ea29 | Serge Torres | # |
632 | 62861417 | Serge Torres | def cvp_int_vector_for_approx(floatVect, commonScalingExp, extraScalingExp): |
633 | 9b0c03e7 | Serge Torres | """ |
634 | 9b0c03e7 | Serge Torres | Compute the integral version of the function vector. |
635 | 9b0c03e7 | Serge Torres | """ |
636 | 62861417 | Serge Torres | totalScalingFactor = 2^(commonScalingExp + extraScalingExp) |
637 | 9645ea29 | Serge Torres | intVect = vector(ZZ, len(floatVect)) |
638 | 9645ea29 | Serge Torres | for index in xrange(0, len(floatVect)): |
639 | 9645ea29 | Serge Torres | intVect[index] = (floatVect[index] * totalScalingFactor).round() |
640 | 9645ea29 | Serge Torres | return intVect |
641 | 9645ea29 | Serge Torres | # End cvp_int_vector_for_approx. |
642 | 9645ea29 | Serge Torres | # |
643 | 9645ea29 | Serge Torres | def cvp_lll_reduce(intBasis): |
644 | 9645ea29 | Serge Torres | """ |
645 | 9645ea29 | Serge Torres | Thin and simplistic wrapper around the LLL function |
646 | 9645ea29 | Serge Torres | """ |
647 | 9645ea29 | Serge Torres | return intBasis.LLL() |
648 | 9645ea29 | Serge Torres | # End cvp_lll_reduce. |
649 | 9645ea29 | Serge Torres | # |
650 | 9645ea29 | Serge Torres | def cvp_monomials_list(exponentsList, varName = None): |
651 | 9645ea29 | Serge Torres | """ |
652 | 9645ea29 | Serge Torres | Create a list of monomials corresponding to the given exponentsList. |
653 | 9645ea29 | Serge Torres | Monomials are defined as functions. |
654 | 9645ea29 | Serge Torres | """ |
655 | 9645ea29 | Serge Torres | monomialsList = [] |
656 | 9645ea29 | Serge Torres | for exponent in exponentsList: |
657 | 9645ea29 | Serge Torres | if varName is None: |
658 | 9645ea29 | Serge Torres | monomialsList.append((x^exponent).function(x)) |
659 | 9645ea29 | Serge Torres | else: |
660 | 9645ea29 | Serge Torres | monomialsList.append((varName^exponent).function(varName)) |
661 | 9645ea29 | Serge Torres | return monomialsList |
662 | 9645ea29 | Serge Torres | # End cvp_monomials_list. |
663 | 9645ea29 | Serge Torres | # |
664 | 62861417 | Serge Torres | def cvp_polynomial_coeffs_from_vect(cvpVectInBasis, |
665 | 9cf1fb38 | Serge Torres | coeffsPrecList, |
666 | 9cf1fb38 | Serge Torres | minCoeffsExpList, |
667 | 9cf1fb38 | Serge Torres | extraFuncScalingExp): |
668 | 9cf1fb38 | Serge Torres | """ |
669 | 9cf1fb38 | Serge Torres | Computes polynomial coefficients out of the elements of the CVP vector. |
670 | 9cf1fb38 | Serge Torres | @todo |
671 | 9cf1fb38 | Serge Torres | Rewrite the code with a single exponentiation, at the very end. |
672 | 9cf1fb38 | Serge Torres | """ |
673 | 62861417 | Serge Torres | numElements = len(cvpVectInBasis) |
674 | 62861417 | Serge Torres | ## Arguments check. |
675 | 62861417 | Serge Torres | if numElements != len(minCoeffsExpList) or \ |
676 | 62861417 | Serge Torres | numElements != len(coeffsPrecList): |
677 | 62861417 | Serge Torres | return None |
678 | 62861417 | Serge Torres | polynomialCoeffsList = [] |
679 | 62861417 | Serge Torres | for index in xrange(0, numElements): |
680 | 62861417 | Serge Torres | currentCoeff = cvp_round_to_bits(cvpVectInBasis[index], |
681 | 62861417 | Serge Torres | coeffsPrecList[index]) |
682 | e2eb9ccc | Serge Torres | #print "cvp_polynomial_coeffs - current coefficient rounded:", currentCoeff |
683 | 62861417 | Serge Torres | currentCoeff *= 2^(minCoeffsExpList[index]) |
684 | e2eb9ccc | Serge Torres | #print "cvp_polynomial_coeffs - current coefficient scaled :", currentCoeff |
685 | 62861417 | Serge Torres | currentCoeff *= 2^(-coeffsPrecList[index]) |
686 | e2eb9ccc | Serge Torres | #print "cvp_polynomial_coeffs - current coefficient prec corrected :", currentCoeff |
687 | 62861417 | Serge Torres | currentCoeff *= 2^(-extraFuncScalingExp) |
688 | e2eb9ccc | Serge Torres | #print "cvp_polynomial_coeffs - current coefficient extra func scaled :", currentCoeff |
689 | 62861417 | Serge Torres | polynomialCoeffsList.append(currentCoeff) |
690 | 62861417 | Serge Torres | return polynomialCoeffsList |
691 | 62861417 | Serge Torres | # En polynomial_coeffs_from_vect. |
692 | 62861417 | Serge Torres | # |
693 | 9c97e92f | Serge Torres | def cvp_polynomial_error_func_maxis(funcSa, |
694 | 9c97e92f | Serge Torres | polySa, |
695 | 9c97e92f | Serge Torres | lowerBoundSa, |
696 | 9c97e92f | Serge Torres | upperBoundSa, |
697 | 9c97e92f | Serge Torres | realField = None, |
698 | 9c97e92f | Serge Torres | contFracMaxErr = None): |
699 | 9c97e92f | Serge Torres | """ |
700 | 9c97e92f | Serge Torres | For a given function, approximation polynomial and interval (given |
701 | 9c97e92f | Serge Torres | as bounds) compute the maxima of the functSa - polySo on the interval. |
702 | 9c97e92f | Serge Torres | Also computes the infnorm of the error function. |
703 | 9c97e92f | Serge Torres | """ |
704 | 9c97e92f | Serge Torres | ## Arguments check. |
705 | 9c97e92f | Serge Torres | # @todo. |
706 | 9c97e92f | Serge Torres | ## If no realField argument is given try to retrieve it from the |
707 | 9c97e92f | Serge Torres | # bounds. If impossible (e.g. rational bound), fall back on RR. |
708 | 9c97e92f | Serge Torres | if realField is None: |
709 | 9c97e92f | Serge Torres | try: |
710 | 9c97e92f | Serge Torres | ### Force failure if parent does not have prec() member. |
711 | 9c97e92f | Serge Torres | lowerBound.parent().prec() |
712 | 9c97e92f | Serge Torres | ### If no exception is thrown, set realField. |
713 | 9c97e92f | Serge Torres | realField = lowerBound.parent() |
714 | 9c97e92f | Serge Torres | except: |
715 | 9c97e92f | Serge Torres | realField = RR |
716 | 9c97e92f | Serge Torres | #print "Real field:", realField |
717 | 9c97e92f | Serge Torres | ## Compute the Sollya version of the function. |
718 | 9c97e92f | Serge Torres | funcAsStringSa = funcSa._assume_str().replace("_SAGE_VAR_","",100) |
719 | 3296902f | Serge Torres | #print "cpefa:", funcAsStringSa |
720 | 9c97e92f | Serge Torres | funcSo = pobyso_parse_string(funcAsStringSa) |
721 | 9c97e92f | Serge Torres | if pobyso_is_error_so_sa(funcSo): |
722 | 9c97e92f | Serge Torres | pobyso_clear_obj(funcSo) |
723 | 9c97e92f | Serge Torres | return None |
724 | 3296902f | Serge Torres | #print "cpefa: function conversion OK." |
725 | 9c97e92f | Serge Torres | ## Compute the Sollya version of the polynomial. |
726 | 9c97e92f | Serge Torres | ## The conversion is made from a floating-point coefficients polynomial. |
727 | 9c97e92f | Serge Torres | try: |
728 | 9c97e92f | Serge Torres | polySa.base_ring().prec() |
729 | 9c97e92f | Serge Torres | convFloatPolySa = polySa |
730 | 9c97e92f | Serge Torres | except: |
731 | 9c97e92f | Serge Torres | convFloatPolySa = realField[polySa.variables()[0]](polySa) |
732 | 9c97e92f | Serge Torres | polySo = pobyso_float_poly_sa_so(convFloatPolySa) |
733 | 9c97e92f | Serge Torres | if pobyso_is_error_so_sa(funcSo): |
734 | 9c97e92f | Serge Torres | pobyso_clear_obj(funcSo) |
735 | 9c97e92f | Serge Torres | pobyso_clear_obj(polySo) |
736 | 9c97e92f | Serge Torres | return None |
737 | 3296902f | Serge Torres | #print "cpefa: polynomial conversion to Sollya OK." |
738 | 9c97e92f | Serge Torres | ## Copy both funcSo and polySo as they are needed later for the infnorm.. |
739 | 3296902f | Serge Torres | errorFuncSo = \ |
740 | 3296902f | Serge Torres | sollya_lib_build_function_sub(sollya_lib_copy_obj(funcSo), |
741 | 3296902f | Serge Torres | sollya_lib_copy_obj(polySo)) |
742 | 9c97e92f | Serge Torres | if pobyso_is_error_so_sa(errorFuncSo): |
743 | 9c97e92f | Serge Torres | pobyso_clear_obj(errorFuncSo) |
744 | 9c97e92f | Serge Torres | return None |
745 | 3296902f | Serge Torres | #print "cpefa: error function in Sollya OK." |
746 | 2669308a | Serge Torres | ## Evaluate the error function at both bounds, it may be usefull, if |
747 | 2669308a | Serge Torres | # the error function is monotonous |
748 | 2669308a | Serge Torres | ## Lower bound stuff. |
749 | 2669308a | Serge Torres | lowerBoundSo = pobyso_constant_sa_so(lowerBoundSa) |
750 | 2669308a | Serge Torres | if pobyso_is_error_so_sa(lowerBoundSo): |
751 | 2669308a | Serge Torres | pobyso_clear_obj(errorFuncSo) |
752 | 2669308a | Serge Torres | pobyso_clear_obj(lowerBoundSo) |
753 | 2669308a | Serge Torres | return None |
754 | 2669308a | Serge Torres | errFuncAtLbSa = pobyso_evaluate_so_sa(errorFuncSo, lowerBoundSo) |
755 | 2669308a | Serge Torres | pobyso_clear_obj(lowerBoundSo) |
756 | 2669308a | Serge Torres | if errFuncAtLbSa is None: |
757 | 2669308a | Serge Torres | pobyso_clear_obj(errorFuncSo) |
758 | 2669308a | Serge Torres | return None |
759 | 2669308a | Serge Torres | ## The result of the evaluation can be an interval. |
760 | 2669308a | Serge Torres | try: |
761 | 2669308a | Serge Torres | errFuncAtLbSa = errFuncAtLbSa.center() |
762 | 2669308a | Serge Torres | except: |
763 | 2669308a | Serge Torres | errFuncAtLbSa = errFuncAtLbSa |
764 | 2669308a | Serge Torres | #print "cpefa: errFuncAtLbSa:", errFuncAtLbSa |
765 | 2669308a | Serge Torres | ## Upper bound stuff. |
766 | 2669308a | Serge Torres | upperBoundSo = pobyso_constant_sa_so(upperBoundSa) |
767 | 2669308a | Serge Torres | if pobyso_is_error_so_sa(upperBoundSo): |
768 | 2669308a | Serge Torres | pobyso_clear_obj(errorFuncSo) |
769 | 2669308a | Serge Torres | pobyso_clear_obj(upperBoundSo) |
770 | 2669308a | Serge Torres | return None |
771 | 2669308a | Serge Torres | errFuncAtUbSa = pobyso_evaluate_so_sa(errorFuncSo, upperBoundSo) |
772 | 2669308a | Serge Torres | pobyso_clear_obj(upperBoundSo) |
773 | 2669308a | Serge Torres | if errFuncAtUbSa is None: |
774 | 2669308a | Serge Torres | return None |
775 | 2669308a | Serge Torres | ## The result of the evaluation can be an interval. |
776 | 2669308a | Serge Torres | try: |
777 | 2669308a | Serge Torres | errFuncAtUbSa = errFuncAtUbSa.center() |
778 | 2669308a | Serge Torres | except: |
779 | 2669308a | Serge Torres | errFuncAtUbSa = errFuncAtUbSa |
780 | 2669308a | Serge Torres | #print "cpefa: errFuncAtUbSa:", errFuncAtUbSa |
781 | 9c97e92f | Serge Torres | ## Compute the derivative. |
782 | 9c97e92f | Serge Torres | diffErrorFuncSo = pobyso_diff_so_so(errorFuncSo) |
783 | 9c97e92f | Serge Torres | pobyso_clear_obj(errorFuncSo) |
784 | 9c97e92f | Serge Torres | if pobyso_is_error_so_sa(diffErrorFuncSo): |
785 | 9c97e92f | Serge Torres | pobyso_clear_obj(diffErrorFuncSo) |
786 | 9c97e92f | Serge Torres | return None |
787 | 3296902f | Serge Torres | #print "cpefa: polynomial conversion to Sollya OK." |
788 | 3296902f | Serge Torres | #print "cpefa: error function derivative in Sollya OK." |
789 | 9c97e92f | Serge Torres | ## Compute the interval. |
790 | 9c97e92f | Serge Torres | intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound) |
791 | 9c97e92f | Serge Torres | if pobyso_is_error_so_sa(intervalSo): |
792 | 9c97e92f | Serge Torres | pobyso_clear_obj(diffErrorFuncSo) |
793 | 9c97e92f | Serge Torres | pobyso_clear_obj(intervalSo) |
794 | 9c97e92f | Serge Torres | return None |
795 | 9c97e92f | Serge Torres | ## Compute the infnorm of the error function. |
796 | 9c97e92f | Serge Torres | errFuncSupNormSa = pobyso_supnorm_so_sa(polySo, |
797 | 9c97e92f | Serge Torres | funcSo, |
798 | 9c97e92f | Serge Torres | intervalSo, |
799 | 9c97e92f | Serge Torres | realFieldSa = realField) |
800 | 9c97e92f | Serge Torres | pobyso_clear_obj(polySo) |
801 | 9c97e92f | Serge Torres | pobyso_clear_obj(funcSo) |
802 | 9c97e92f | Serge Torres | ## Compute the zeros of the derivative. |
803 | 3296902f | Serge Torres | ### Give it a first try with dirtyfindzeros but it may |
804 | 3296902f | Serge Torres | # fail. |
805 | 3296902f | Serge Torres | errorFuncMaxisSo = pobyso_dirty_find_zeros_so_so(diffErrorFuncSo, |
806 | 3296902f | Serge Torres | intervalSo) |
807 | 9c97e92f | Serge Torres | if pobyso_is_error_so_sa(errorFuncMaxisSo): |
808 | 3296902f | Serge Torres | pobyso_clear_obj(diffErrorFuncSo) |
809 | 3296902f | Serge Torres | pobyso_clear_obj(intervalSo) |
810 | 9c97e92f | Serge Torres | pobyso_clear_obj(errorFuncMaxisSo) |
811 | 9c97e92f | Serge Torres | return None |
812 | 3296902f | Serge Torres | #print "cpefa: error function maxis in Sollya OK." |
813 | 9c97e92f | Serge Torres | errorFuncMaxisSa = pobyso_float_list_so_sa(errorFuncMaxisSo) |
814 | 9c97e92f | Serge Torres | pobyso_clear_obj(errorFuncMaxisSo) |
815 | 3296902f | Serge Torres | #### If the list is empty try the more sophisticated |
816 | 3296902f | Serge Torres | # findzeros. |
817 | 3296902f | Serge Torres | if len(errorFuncMaxisSa) == 0: |
818 | 3296902f | Serge Torres | errorFuncMaxisSo = \ |
819 | 3296902f | Serge Torres | pobyso_find_zeros_so_so(diffErrorFuncSo, |
820 | 3296902f | Serge Torres | intervalSo) |
821 | 3296902f | Serge Torres | if pobyso_is_error_so_sa(errorFuncMaxisSo): |
822 | 3296902f | Serge Torres | pobyso_clear_obj(diffErrorFuncSo) |
823 | 3296902f | Serge Torres | pobyso_clear_obj(intervalSo) |
824 | 3296902f | Serge Torres | pobyso_clear_obj(errorFuncMaxisSo) |
825 | 3296902f | Serge Torres | return None |
826 | 3296902f | Serge Torres | #print "cpefa: error function maxis in Sollya OK." |
827 | 3296902f | Serge Torres | #print "cpefa:", ; pobyso_autoprint(errorFuncMaxisSo) |
828 | 3296902f | Serge Torres | ##### The findzeros functions returns intervals (ranges). |
829 | 3296902f | Serge Torres | errorFuncRangeMaxisSa = pobyso_range_list_so_sa(errorFuncMaxisSo) |
830 | 2669308a | Serge Torres | #print "cpefa:", errorFuncRangeMaxisSa |
831 | 3296902f | Serge Torres | pobyso_clear_obj(errorFuncMaxisSo) |
832 | 3296902f | Serge Torres | errorFuncMaxisSa = [] |
833 | 2669308a | Serge Torres | if len(errorFuncRangeMaxisSa) != 0: |
834 | 2669308a | Serge Torres | for interval in errorFuncRangeMaxisSa: |
835 | 2669308a | Serge Torres | errorFuncMaxisSa.append(interval.center()) |
836 | 2669308a | Serge Torres | #print "cpefa:", errorFuncMaxisSa |
837 | 2669308a | Serge Torres | else: # The error function is monotonous. It reaches its maximum |
838 | 2669308a | Serge Torres | # at either of the bounds. |
839 | 2669308a | Serge Torres | errFuncMaxAtBounds = max(abs(errFuncAtLbSa), abs(errFuncAtUbSa)) |
840 | 2669308a | Serge Torres | if errFuncMaxAtBounds == abs(errFuncAtLbSa): |
841 | 2669308a | Serge Torres | errorFuncMaxisSa.append(lowerBoundSa) |
842 | 2669308a | Serge Torres | else: |
843 | 2669308a | Serge Torres | errorFuncMaxisSa.append(upperBoundSa) |
844 | 3296902f | Serge Torres | pobyso_clear_obj(diffErrorFuncSo) |
845 | 3296902f | Serge Torres | pobyso_clear_obj(intervalSo) |
846 | 9c97e92f | Serge Torres | ## If required, convert the numbers to rational numbers. |
847 | 3296902f | Serge Torres | #print "cpefa - errorFuncMaxisSa:", errorFuncMaxisSa |
848 | 9c97e92f | Serge Torres | if not contFracMaxErr is None: |
849 | 9c97e92f | Serge Torres | for index in xrange(0, len(errorFuncMaxisSa)): |
850 | 9c97e92f | Serge Torres | errorFuncMaxisSa[index] = \ |
851 | 9c97e92f | Serge Torres | errorFuncMaxisSa[index].nearby_rational(contFracMaxErr) |
852 | 9c97e92f | Serge Torres | return (errorFuncMaxisSa, errFuncSupNormSa) |
853 | 9c97e92f | Serge Torres | # End cvp_polynomial_error_func_maxis |
854 | 9c97e92f | Serge Torres | # |
855 | 9b0c03e7 | Serge Torres | def cvp_polynomial_from_coeffs_and_exps(coeffsList, |
856 | 9b0c03e7 | Serge Torres | expsList, |
857 | 9b0c03e7 | Serge Torres | polyField = None, |
858 | 9b0c03e7 | Serge Torres | theVar = None): |
859 | 9b0c03e7 | Serge Torres | """ |
860 | 9b0c03e7 | Serge Torres | Build a polynomial in the classical monomials (possibly lacunary) basis |
861 | 9b0c03e7 | Serge Torres | from a list of coefficients and a list of exponents. The polynomial is in |
862 | 9b0c03e7 | Serge Torres | the polynomial field given as argument. |
863 | 9b0c03e7 | Serge Torres | """ |
864 | 9b0c03e7 | Serge Torres | if len(coeffsList) != len(expsList): |
865 | 9b0c03e7 | Serge Torres | return None |
866 | 9b0c03e7 | Serge Torres | ## If no variable is given, "x" is used. |
867 | 9b0c03e7 | Serge Torres | ## If no polyField is given, we fall back on a polynomial field on RR. |
868 | 9b0c03e7 | Serge Torres | if theVar is None: |
869 | 9b0c03e7 | Serge Torres | if polyField is None: |
870 | 9b0c03e7 | Serge Torres | theVar = x |
871 | 9b0c03e7 | Serge Torres | polyField = RR[theVar] |
872 | 9b0c03e7 | Serge Torres | else: |
873 | 9b0c03e7 | Serge Torres | theVar = var(polyField.variable_name()) |
874 | e2eb9ccc | Serge Torres | else: ### theVar is set. |
875 | e2eb9ccc | Serge Torres | ### No polyField, fallback on RR[theVar]. |
876 | 9b0c03e7 | Serge Torres | if polyField is None: |
877 | 9b0c03e7 | Serge Torres | polyField = RR[theVar] |
878 | e2eb9ccc | Serge Torres | else: ### Both the polyFiled and theVar are set: create a new polyField |
879 | e2eb9ccc | Serge Torres | # with theVar. The original polyField is not affected by the |
880 | e2eb9ccc | Serge Torres | # change. |
881 | 9b0c03e7 | Serge Torres | polyField = polyField.change_var(theVar) |
882 | 9b0c03e7 | Serge Torres | ## Seed the polynomial. |
883 | 9b0c03e7 | Serge Torres | poly = polyField(0) |
884 | 9b0c03e7 | Serge Torres | ## Append the terms. |
885 | 9b0c03e7 | Serge Torres | for coeff, exp in zip(coeffsList, expsList): |
886 | 9b0c03e7 | Serge Torres | poly += polyField(coeff * theVar^exp) |
887 | 9b0c03e7 | Serge Torres | return poly |
888 | 9b0c03e7 | Serge Torres | # End cvp_polynomial_from_coeffs_and_exps. |
889 | 9b0c03e7 | Serge Torres | # |
890 | 9cf1fb38 | Serge Torres | def cvp_remez_all_poly_error_func_maxis(funct, |
891 | 9b0c03e7 | Serge Torres | maxDegree, |
892 | 9b0c03e7 | Serge Torres | lowerBound, |
893 | 9b0c03e7 | Serge Torres | upperBound, |
894 | 9b0c03e7 | Serge Torres | precsList, |
895 | 9b0c03e7 | Serge Torres | realField = None, |
896 | 9b0c03e7 | Serge Torres | contFracMaxErr = None): |
897 | 9b0c03e7 | Serge Torres | """ |
898 | 9b0c03e7 | Serge Torres | For a given function f, a degree and an interval, compute the |
899 | 9b0c03e7 | Serge Torres | maxima of the (f-remez_d(f)) function and those of the (f-truncRemez_d(f)) |
900 | 9b0c03e7 | Serge Torres | function over the interval. |
901 | 9b0c03e7 | Serge Torres | """ |
902 | 9cf1fb38 | Serge Torres | ## If no realField argument is given try to retrieve it from the |
903 | 9cf1fb38 | Serge Torres | # bounds. If impossible (e.g. rational bound), fall back on RR. |
904 | 9cf1fb38 | Serge Torres | if realField is None: |
905 | 9cf1fb38 | Serge Torres | try: |
906 | 9cf1fb38 | Serge Torres | ### Force failure if parent does not have prec() member. |
907 | 9cf1fb38 | Serge Torres | lowerBound.parent().prec() |
908 | 9cf1fb38 | Serge Torres | ### If no exception is thrown, set realField. |
909 | 9cf1fb38 | Serge Torres | realField = lowerBound.parent() |
910 | 9cf1fb38 | Serge Torres | except: |
911 | 9cf1fb38 | Serge Torres | realField = RR |
912 | 9cf1fb38 | Serge Torres | #print "Real field:", realField |
913 | 9cf1fb38 | Serge Torres | funcSa = func |
914 | 9cf1fb38 | Serge Torres | funcAsStringSa = func._assume_str().replace("_SAGE_VAR_","",100) |
915 | 9cf1fb38 | Serge Torres | print "Function as a string:", funcAsStringSa |
916 | 9cf1fb38 | Serge Torres | ## Create the Sollya version of the function and compute the |
917 | 9cf1fb38 | Serge Torres | # Remez approximant |
918 | 9cf1fb38 | Serge Torres | funcSo = pobyso_parse_string(funcAsStringSa) |
919 | 9cf1fb38 | Serge Torres | pStarSo = pobyso_remez_canonical_sa_so(funcAsStringSa, |
920 | 9cf1fb38 | Serge Torres | maxDegree, |
921 | 9cf1fb38 | Serge Torres | lowerBound, |
922 | 9cf1fb38 | Serge Torres | upperBound) |
923 | 9cf1fb38 | Serge Torres | ## Compute the error function and its derivative |
924 | 9cf1fb38 | Serge Torres | ### First create the error function with copies since they are needed later. |
925 | 9cf1fb38 | Serge Torres | errorFuncSo = sollya_lib_build_function_sub(sollya_lib_copy_obj(pStarSo), |
926 | 9cf1fb38 | Serge Torres | sollya_lib_copy_obj(funcSo)) |
927 | 9cf1fb38 | Serge Torres | intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound) |
928 | 9cf1fb38 | Serge Torres | diffErrorFuncSo = pobyso_diff_so_so(errorFuncSo) |
929 | 9cf1fb38 | Serge Torres | pobyso_clear_obj(errorFuncSo) |
930 | 9cf1fb38 | Serge Torres | ## Compute the zeros of the derivative. |
931 | 9c97e92f | Serge Torres | errorFuncMaxisSo = pobyso_dirty_find_zeros_so_so(diffErrorFuncSo, intervalSo) |
932 | 9cf1fb38 | Serge Torres | pobyso_clear_obj(diffErrorFuncSo) |
933 | 9c97e92f | Serge Torres | errorFuncMaxisSa = pobyso_float_list_so_sa(errorFuncMaxisSo) |
934 | 9c97e92f | Serge Torres | pobyso_clear_obj(errorFuncMaxisSo) |
935 | 9cf1fb38 | Serge Torres | ## Compute the truncated Remez polynomial and the error function. |
936 | 9cf1fb38 | Serge Torres | truncFormatListSo = pobyso_build_list_of_ints_sa_so(*precsList) |
937 | 9cf1fb38 | Serge Torres | pTruncSo = pobyso_round_coefficients_so_so(pStarSo, truncFormatListSo) |
938 | 9cf1fb38 | Serge Torres | pobyso_clear_obj(pStarSo) |
939 | 9cf1fb38 | Serge Torres | ### Compute the error function. This time we consume both the function |
940 | 9cf1fb38 | Serge Torres | # and the polynomial. |
941 | 9cf1fb38 | Serge Torres | errorFuncSo = sollya_lib_build_function_sub(pTruncSo, funcSo) |
942 | 9cf1fb38 | Serge Torres | ## Compute the derivative. |
943 | 9cf1fb38 | Serge Torres | diffErrorFuncSo = pobyso_diff_so_so(errorFuncSo) |
944 | 9cf1fb38 | Serge Torres | pobyso_clear_obj(errorFuncSo) |
945 | 9cf1fb38 | Serge Torres | ## Compute the zeros of the derivative. |
946 | 9c97e92f | Serge Torres | errorFuncMaxisSo = pobyso_dirty_find_zeros_so_so(diffErrorFuncSo, intervalSo) |
947 | 9cf1fb38 | Serge Torres | pobyso_clear_obj(diffErrorFuncSo) |
948 | 9cf1fb38 | Serge Torres | pobyso_clear_obj(intervalSo) |
949 | 9c97e92f | Serge Torres | errorFuncTruncMaxisSa = pobyso_float_list_so_sa(errorFuncMaxisSo) |
950 | 9c97e92f | Serge Torres | pobyso_clear_obj(errorFuncMaxisSo) |
951 | 9c97e92f | Serge Torres | ## Merge with the first list, removing duplicates if any. |
952 | 9c97e92f | Serge Torres | errorFuncMaxisSa.extend(elem for elem in errorFuncTruncMaxisSa \ |
953 | 9c97e92f | Serge Torres | if elem not in errorFuncMaxisSa) |
954 | 9c97e92f | Serge Torres | errorFuncMaxisSa.sort() |
955 | 9cf1fb38 | Serge Torres | ## If required, convert the numbers to rational numbers. |
956 | 9cf1fb38 | Serge Torres | if not contFracMaxErr is None: |
957 | 9c97e92f | Serge Torres | for index in xrange(0, len(errorFuncMaxisSa)): |
958 | 9c97e92f | Serge Torres | errorFuncMaxisSa[index] = \ |
959 | 9c97e92f | Serge Torres | errorFuncMaxisSa[index].nearby_rational(contFracMaxErr) |
960 | 9c97e92f | Serge Torres | return errorFuncMaxisSa |
961 | 9cf1fb38 | Serge Torres | # End cvp_remez_all_poly_error_func_maxis. |
962 | 9b0c03e7 | Serge Torres | # |
963 | 724064f1 | Serge Torres | def cvp_remez_all_poly_error_func_zeros(funct, |
964 | 724064f1 | Serge Torres | maxDegree, |
965 | 724064f1 | Serge Torres | lowerBound, |
966 | 724064f1 | Serge Torres | upperBound, |
967 | 724064f1 | Serge Torres | precsList, |
968 | 04d64614 | Serge Torres | realField = None, |
969 | 04d64614 | Serge Torres | contFracMaxErr = None): |
970 | 724064f1 | Serge Torres | """ |
971 | 724064f1 | Serge Torres | For a given function f, a degree and an interval, compute the |
972 | 04d64614 | Serge Torres | zeros of the (f-remez_d(f)) function and those of the (f-truncRemez_d(f)) |
973 | 9cf1fb38 | Serge Torres | function over the interval. |
974 | 724064f1 | Serge Torres | """ |
975 | 04d64614 | Serge Torres | ## If no realField argument is given try to retrieve it from the |
976 | 04d64614 | Serge Torres | # bounds. If impossible (e.g. rational bound), fall back on RR. |
977 | 04d64614 | Serge Torres | if realField is None: |
978 | 04d64614 | Serge Torres | try: |
979 | 04d64614 | Serge Torres | ### Force failure if parent does not have prec() member. |
980 | 04d64614 | Serge Torres | lowerBound.parent().prec() |
981 | 04d64614 | Serge Torres | ### If no exception is thrown, set realField. |
982 | 04d64614 | Serge Torres | realField = lowerBound.parent() |
983 | 04d64614 | Serge Torres | except: |
984 | 04d64614 | Serge Torres | realField = RR |
985 | 04d64614 | Serge Torres | #print "Real field:", realField |
986 | 724064f1 | Serge Torres | funcSa = func |
987 | 724064f1 | Serge Torres | funcAsStringSa = func._assume_str().replace("_SAGE_VAR_","",100) |
988 | 724064f1 | Serge Torres | print "Function as a string:", funcAsStringSa |
989 | 724064f1 | Serge Torres | ## Create the Sollya version of the function and compute the |
990 | 724064f1 | Serge Torres | # Remez approximant |
991 | 724064f1 | Serge Torres | funcSo = pobyso_parse_string(funcAsStringSa) |
992 | 724064f1 | Serge Torres | pStarSo = pobyso_remez_canonical_sa_so(funcAsStringSa, |
993 | 724064f1 | Serge Torres | maxDegree, |
994 | 724064f1 | Serge Torres | lowerBound, |
995 | 724064f1 | Serge Torres | upperBound) |
996 | 724064f1 | Serge Torres | ## Compute the zeroes of the error function. |
997 | 724064f1 | Serge Torres | ### First create the error function with copies since they are needed later. |
998 | 724064f1 | Serge Torres | errorFuncSo = sollya_lib_build_function_sub(sollya_lib_copy_obj(pStarSo), |
999 | 724064f1 | Serge Torres | sollya_lib_copy_obj(funcSo)) |
1000 | 04d64614 | Serge Torres | intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound) |
1001 | 724064f1 | Serge Torres | errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(errorFuncSo, intervalSo) |
1002 | 724064f1 | Serge Torres | pobyso_clear_obj(errorFuncSo) # Clears funcSo and pStarSo as well. |
1003 | 724064f1 | Serge Torres | #print "Zeroes of the error function from Sollya:" |
1004 | 724064f1 | Serge Torres | #pobyso_autoprint(errorFuncZerosSo) |
1005 | 724064f1 | Serge Torres | errorFuncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo) |
1006 | 724064f1 | Serge Torres | pobyso_clear_obj(errorFuncZerosSo) |
1007 | 724064f1 | Serge Torres | #print "\nZeroes of the error function from Sage:" |
1008 | 724064f1 | Serge Torres | #print errorFuncZerosSa |
1009 | 724064f1 | Serge Torres | # |
1010 | 724064f1 | Serge Torres | ## Deal with the truncated polynomial now. |
1011 | 724064f1 | Serge Torres | ### Create the formats list. Notice the "*" before the list variable name. |
1012 | 724064f1 | Serge Torres | truncFormatListSo = pobyso_build_list_of_ints_sa_so(*precsList) |
1013 | 9b0c03e7 | Serge Torres | #print "Precisions list as Sollya object:", |
1014 | 9cf1fb38 | Serge Torres | #pobyso_autoprint(truncFormatListSo) |
1015 | 724064f1 | Serge Torres | pTruncSo = pobyso_round_coefficients_so_so(pStarSo, truncFormatListSo) |
1016 | 9b0c03e7 | Serge Torres | #print "Truncated polynomial:", ; pobyso_autoprint(pTruncSo) |
1017 | 724064f1 | Serge Torres | ### Compute the error function. This time we consume both the function |
1018 | 724064f1 | Serge Torres | # and the polynomial. |
1019 | 724064f1 | Serge Torres | errorFuncSo = sollya_lib_build_function_sub(pTruncSo, |
1020 | 724064f1 | Serge Torres | funcSo) |
1021 | 724064f1 | Serge Torres | errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(errorFuncSo, intervalSo) |
1022 | 724064f1 | Serge Torres | pobyso_clear_obj(pStarSo) |
1023 | 9b0c03e7 | Serge Torres | #print "Zeroes of the error function for the truncated polynomial from Sollya:" |
1024 | 9cf1fb38 | Serge Torres | #pobyso_autoprint(errorFuncZerosSo) |
1025 | 724064f1 | Serge Torres | errorFuncTruncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo) |
1026 | 724064f1 | Serge Torres | pobyso_clear_obj(errorFuncZerosSo) |
1027 | 724064f1 | Serge Torres | ## Sollya objects clean up. |
1028 | 724064f1 | Serge Torres | pobyso_clear_obj(intervalSo) |
1029 | 724064f1 | Serge Torres | errorFuncZerosSa += errorFuncTruncZerosSa |
1030 | 724064f1 | Serge Torres | errorFuncZerosSa.sort() |
1031 | 04d64614 | Serge Torres | ## If required, convert the numbers to rational numbers. |
1032 | 04d64614 | Serge Torres | if not contFracMaxErr is None: |
1033 | 04d64614 | Serge Torres | for index in xrange(0, len(errorFuncZerosSa)): |
1034 | 04d64614 | Serge Torres | errorFuncZerosSa[index] = \ |
1035 | 04d64614 | Serge Torres | errorFuncZerosSa[index].nearby_rational(contFracMaxErr) |
1036 | 04d64614 | Serge Torres | return errorFuncZerosSa |
1037 | 04d64614 | Serge Torres | # |
1038 | 04d64614 | Serge Torres | # End remez_all_poly_error_func_zeros |
1039 | 04d64614 | Serge Torres | # |
1040 | 04d64614 | Serge Torres | def cvp_remez_poly_error_func_zeros(funct, |
1041 | 04d64614 | Serge Torres | maxDegree, |
1042 | 04d64614 | Serge Torres | lowerBound, |
1043 | 04d64614 | Serge Torres | upperBound, |
1044 | 04d64614 | Serge Torres | realField = None, |
1045 | 04d64614 | Serge Torres | contFracMaxErr = None): |
1046 | 04d64614 | Serge Torres | """ |
1047 | 04d64614 | Serge Torres | For a given function f, a degree and an interval, compute the |
1048 | 04d64614 | Serge Torres | zeros of the (f-remez_d(f)) function. |
1049 | 04d64614 | Serge Torres | """ |
1050 | 04d64614 | Serge Torres | ## If no realField argument is given try to retrieve it from the |
1051 | 04d64614 | Serge Torres | # bounds. If impossible (e.g. rational bound), fall back on RR. |
1052 | 04d64614 | Serge Torres | if realField is None: |
1053 | 04d64614 | Serge Torres | try: |
1054 | 04d64614 | Serge Torres | ### Force failure if parent does not have prec() member. |
1055 | 04d64614 | Serge Torres | lowerBound.parent().prec() |
1056 | 04d64614 | Serge Torres | ### If no exception is thrown, set realField. |
1057 | 04d64614 | Serge Torres | realField = lowerBound.parent() |
1058 | 04d64614 | Serge Torres | except: |
1059 | 04d64614 | Serge Torres | realField = RR |
1060 | 04d64614 | Serge Torres | #print "Real field:", realField |
1061 | 04d64614 | Serge Torres | funcSa = func |
1062 | 04d64614 | Serge Torres | funcAsStringSa = func._assume_str().replace("_SAGE_VAR_","",100) |
1063 | 04d64614 | Serge Torres | #print "Function as a string:", funcAsStringSa |
1064 | 04d64614 | Serge Torres | ## Create the Sollya version of the function and compute the |
1065 | 04d64614 | Serge Torres | # Remez approximant |
1066 | 04d64614 | Serge Torres | funcSo = pobyso_parse_string(funcAsStringSa) |
1067 | 04d64614 | Serge Torres | pStarSo = pobyso_remez_canonical_sa_so(funcAsStringSa, |
1068 | 04d64614 | Serge Torres | maxDegree, |
1069 | 04d64614 | Serge Torres | lowerBound, |
1070 | 04d64614 | Serge Torres | upperBound) |
1071 | 04d64614 | Serge Torres | ## Compute the zeroes of the error function. |
1072 | 04d64614 | Serge Torres | ### Error function creation consumes both pStarSo and funcSo. |
1073 | 04d64614 | Serge Torres | errorFuncSo = sollya_lib_build_function_sub(pStarSo, funcSo) |
1074 | 04d64614 | Serge Torres | intervalSo = pobyso_range_from_bounds_sa_so(lowerBound, upperBound) |
1075 | 04d64614 | Serge Torres | errorFuncZerosSo = pobyso_dirty_find_zeros_so_so(errorFuncSo, intervalSo) |
1076 | 04d64614 | Serge Torres | pobyso_clear_obj(errorFuncSo) # Clears funcSo and pStarSo as well. |
1077 | 04d64614 | Serge Torres | #print "Zeroes of the error function from Sollya:" |
1078 | 04d64614 | Serge Torres | #pobyso_autoprint(errorFuncZerosSo) |
1079 | 04d64614 | Serge Torres | errorFuncZerosSa = pobyso_float_list_so_sa(errorFuncZerosSo) |
1080 | 04d64614 | Serge Torres | pobyso_clear_obj(errorFuncZerosSo) |
1081 | 04d64614 | Serge Torres | ## Sollya objects clean up. |
1082 | 04d64614 | Serge Torres | pobyso_clear_obj(intervalSo) |
1083 | 04d64614 | Serge Torres | ## Converting to rational numbers, if required. |
1084 | 04d64614 | Serge Torres | if not contFracMaxErr is None: |
1085 | 04d64614 | Serge Torres | for index in xrange(0, len(errorFuncZerosSa)): |
1086 | 04d64614 | Serge Torres | errorFuncZerosSa[index] = \ |
1087 | 04d64614 | Serge Torres | errorFuncZerosSa[index].nearby_rational(contFracMaxErr) |
1088 | 724064f1 | Serge Torres | return errorFuncZerosSa |
1089 | 724064f1 | Serge Torres | # |
1090 | 724064f1 | Serge Torres | # End remez_poly_error_func_zeros |
1091 | 724064f1 | Serge Torres | # |
1092 | 62861417 | Serge Torres | def cvp_round_to_bits(num, numBits): |
1093 | 62861417 | Serge Torres | """ |
1094 | 62861417 | Serge Torres | Round "num" to "numBits" bits. |
1095 | 62861417 | Serge Torres | @param num : the number to round; |
1096 | 62861417 | Serge Torres | @param numBits: the number of bits to round to. |
1097 | 62861417 | Serge Torres | """ |
1098 | 62861417 | Serge Torres | if num == 0: |
1099 | 62861417 | Serge Torres | return num |
1100 | 62861417 | Serge Torres | log2ofNum = 0 |
1101 | 62861417 | Serge Torres | numRounded = 0 |
1102 | 62861417 | Serge Torres | ## Avoid conversion to floating-point if not necessary. |
1103 | 62861417 | Serge Torres | try: |
1104 | 62861417 | Serge Torres | log2OfNum = num.abs().log2() |
1105 | 62861417 | Serge Torres | except: |
1106 | 62861417 | Serge Torres | log2OfNum = RR(num).abs().log2() |
1107 | 62861417 | Serge Torres | ## Works equally well for num >= 1 and num < 1. |
1108 | 62861417 | Serge Torres | log2OfNum = ceil(log2OfNum) |
1109 | 62861417 | Serge Torres | # print "cvp_round_to_bits - Log2OfNum:", log2OfNum |
1110 | 62861417 | Serge Torres | divMult = log2OfNum - numBits |
1111 | 62861417 | Serge Torres | #print "cvp_round_to_bits - DivMult:", divMult |
1112 | 62861417 | Serge Torres | if divMult != 0: |
1113 | 62861417 | Serge Torres | numRounded = round(num/2^divMult) * 2^divMult |
1114 | 62861417 | Serge Torres | else: |
1115 | 62861417 | Serge Torres | numRounded = num |
1116 | 62861417 | Serge Torres | return numRounded |
1117 | 62861417 | Serge Torres | # End cvp_round_to_bits |
1118 | 62861417 | Serge Torres | # |
1119 | 9645ea29 | Serge Torres | def cvp_vector_in_basis(vect, basis): |
1120 | 9645ea29 | Serge Torres | """ |
1121 | 9645ea29 | Serge Torres | Compute the coordinates of "vect" in "basis" by |
1122 | 9645ea29 | Serge Torres | solving a linear system. |
1123 | dd576474 | Serge Torres | @param vect: the vector we want to compute the coordinates of |
1124 | dd576474 | Serge Torres | in coordinates of the ambient space; |
1125 | dd576474 | Serge Torres | @param basis: the basis we want to compute the coordinates in |
1126 | dd576474 | Serge Torres | as a matrix relative to the ambient space. |
1127 | 9645ea29 | Serge Torres | """ |
1128 | 9645ea29 | Serge Torres | ## Create the variables for the linear equations. |
1129 | 9645ea29 | Serge Torres | varDeclString = "" |
1130 | 9645ea29 | Serge Torres | basisIterationsRange = xrange(0, basis.nrows()) |
1131 | 9645ea29 | Serge Torres | ### Building variables declaration string. |
1132 | 9645ea29 | Serge Torres | for index in basisIterationsRange: |
1133 | 9645ea29 | Serge Torres | varName = "a" + str(index) |
1134 | 9645ea29 | Serge Torres | if varDeclString == "": |
1135 | 9645ea29 | Serge Torres | varDeclString += varName |
1136 | 9645ea29 | Serge Torres | else: |
1137 | 9645ea29 | Serge Torres | varDeclString += "," + varName |
1138 | 9645ea29 | Serge Torres | ### Variables declaration |
1139 | 9645ea29 | Serge Torres | varsList = var(varDeclString) |
1140 | 9645ea29 | Serge Torres | sage_eval("var('" + varDeclString + "')") |
1141 | 9645ea29 | Serge Torres | ## Create the equations |
1142 | 9645ea29 | Serge Torres | equationString = "" |
1143 | 9645ea29 | Serge Torres | equationsList = [] |
1144 | 9645ea29 | Serge Torres | for vIndex in xrange(0, len(vect)): |
1145 | 9645ea29 | Serge Torres | equationString = "" |
1146 | 9645ea29 | Serge Torres | for bIndex in basisIterationsRange: |
1147 | 9645ea29 | Serge Torres | if equationString != "": |
1148 | 9645ea29 | Serge Torres | equationString += "+" |
1149 | 9645ea29 | Serge Torres | equationString += str(varsList[bIndex]) + "*" + str(basis[bIndex,vIndex]) |
1150 | 9645ea29 | Serge Torres | equationString += " == " + str(vect[vIndex]) |
1151 | 9645ea29 | Serge Torres | equationsList.append(sage_eval(equationString)) |
1152 | 9cf1fb38 | Serge Torres | ## Solve the equations system. The solution dictionary is needed |
1153 | 9645ea29 | Serge Torres | # to recover the values of the solutions. |
1154 | 9645ea29 | Serge Torres | solutions = solve(equationsList,varsList, solution_dict=True) |
1155 | 9cf1fb38 | Serge Torres | ## This code is deactivated: did not solve the problem. |
1156 | 9cf1fb38 | Serge Torres | """ |
1157 | 9cf1fb38 | Serge Torres | if len(solutions) == 0: |
1158 | 9cf1fb38 | Serge Torres | print "Trying Maxima to_poly_sove." |
1159 | 9cf1fb38 | Serge Torres | solutions = solve(equationsList,varsList, solution_dict=True, to_poly_solve = 'force') |
1160 | 9cf1fb38 | Serge Torres | """ |
1161 | 9645ea29 | Serge Torres | #print "Solutions:", s |
1162 | 9645ea29 | Serge Torres | ## Recover solutions in rational components vector. |
1163 | 9645ea29 | Serge Torres | vectInBasis = vector(QQ, basis.nrows()) |
1164 | 9645ea29 | Serge Torres | ### There can be several solution, in the general case. |
1165 | 9cf1fb38 | Serge Torres | # Here, there is only one (or none). For each solution, each |
1166 | 9645ea29 | Serge Torres | # variable has to be searched for. |
1167 | 9645ea29 | Serge Torres | for sol in solutions: |
1168 | 9645ea29 | Serge Torres | for bIndex in basisIterationsRange: |
1169 | 9645ea29 | Serge Torres | vectInBasis[bIndex] = sol[varsList[bIndex]] |
1170 | 9645ea29 | Serge Torres | return vectInBasis |
1171 | 9645ea29 | Serge Torres | # End cpv_vector_in_basis. |
1172 | 9645ea29 | Serge Torres | # |
1173 | 94c8237b | Serge Torres | sys.stderr.write("... functions for CVP loaded.\n") |