cvp / src / functions_for_cvp.sage @ 62861417
Historique | Voir | Annoter | Télécharger (11,1 ko)
1 | 9645ea29 | Serge Torres | """@package functions_for_cvp |
---|---|---|---|
2 | 9645ea29 | Serge Torres | Auxiliary functions used for CVP. |
3 | 9645ea29 | Serge Torres | """ |
4 | 9645ea29 | Serge Torres | print "Functions for CVP loading..." |
5 | 9645ea29 | Serge Torres | # |
6 | 9645ea29 | Serge Torres | def cvp_babai(redBasis, redBasisGso, vect): |
7 | 9645ea29 | Serge Torres | """ |
8 | 9645ea29 | Serge Torres | Closest plane vector implementation as per Babaï. |
9 | 9645ea29 | Serge Torres | @param redBasis : a lattice basis, preferably a reduced one; |
10 | 9645ea29 | Serge Torres | @param redBasisGSO: the GSO of the previous basis; |
11 | 9645ea29 | Serge Torres | @param vector : a vector, in coordinated in the ambient |
12 | 9645ea29 | Serge Torres | space of the lattice |
13 | 9645ea29 | Serge Torres | @return the closest vector to the input, in coordinates in the |
14 | 9645ea29 | Serge Torres | ambient space of the lattice. |
15 | 9645ea29 | Serge Torres | """ |
16 | 9645ea29 | Serge Torres | ## A deep copy is not necessary here. |
17 | 9645ea29 | Serge Torres | curVect = copy(vect) |
18 | 62861417 | Serge Torres | print "cvp_babai - Vector:", vect |
19 | 9645ea29 | Serge Torres | ## From index of last row down to 0. |
20 | 9645ea29 | Serge Torres | for vIndex in xrange(len(redBasis.rows())-1, -1, -1): |
21 | 9645ea29 | Serge Torres | curRBGSO = redBasisGso.row(vIndex) |
22 | 9645ea29 | Serge Torres | curVect = curVect - (round((curVect * curRBGSO) / (curRBGSO * curRBGSO)) * redBasis.row(vIndex)) |
23 | 9645ea29 | Serge Torres | return vect - curVect |
24 | 62861417 | Serge Torres | # End cvp_babai |
25 | 9645ea29 | Serge Torres | # |
26 | 9645ea29 | Serge Torres | def cvp_bkz_reduce(intBasis, blockSize): |
27 | 9645ea29 | Serge Torres | """ |
28 | 9645ea29 | Serge Torres | Thin and simplistic wrapper the HKZ function of the FP_LLL module. |
29 | 9645ea29 | Serge Torres | """ |
30 | 9645ea29 | Serge Torres | fplllIntBasis = FP_LLL(intBasis) |
31 | 9645ea29 | Serge Torres | fplllIntBasis.BKZ(blockSize) |
32 | 9645ea29 | Serge Torres | return fplllIntBasis._sage_() |
33 | 9645ea29 | Serge Torres | # End cvp_hkz_reduce. |
34 | 9645ea29 | Serge Torres | # |
35 | 62861417 | Serge Torres | def cvp_common_scaling_exp(precision, |
36 | 62861417 | Serge Torres | precisionFraction = None): |
37 | 9645ea29 | Serge Torres | """ |
38 | 9645ea29 | Serge Torres | Compute the common scaling factor (a power of 2). |
39 | 62861417 | Serge Torres | The exponent is a fraction of the precision; |
40 | 62861417 | Serge Torres | A extra factor is computed for the vector, |
41 | 62861417 | Serge Torres | exra factors are computed for the basis vectors, all in the corresponding |
42 | 62861417 | Serge Torres | functions. |
43 | 9645ea29 | Serge Torres | """ |
44 | 9645ea29 | Serge Torres | ## Set a default value for the precisionFraction to 1/2. |
45 | 9645ea29 | Serge Torres | if precisionFraction is None: |
46 | 62861417 | Serge Torres | precisionFraction = 3/4 |
47 | 62861417 | Serge Torres | """ |
48 | 9645ea29 | Serge Torres | minBasisVectsNorm = oo |
49 | 9645ea29 | Serge Torres | currentNorm = 0 |
50 | 9645ea29 | Serge Torres | for vect in floatBasis.rows(): |
51 | 9645ea29 | Serge Torres | currentNorm = vect.norm() |
52 | 9645ea29 | Serge Torres | print "Current norm:", currentNorm |
53 | 9645ea29 | Serge Torres | if currentNorm < minBasisVectsNorm: |
54 | 9645ea29 | Serge Torres | minBasisVectsNorm = currentNorm |
55 | 9645ea29 | Serge Torres | currentNorm = funcVect.norm() |
56 | 9645ea29 | Serge Torres | print "Current norm:", currentNorm |
57 | 9645ea29 | Serge Torres | if currentNorm < minBasisVectsNorm: |
58 | 9645ea29 | Serge Torres | minBasisVectsNorm = currentNorm |
59 | 9645ea29 | Serge Torres | ## Check if a push is need because the smallest norm is below 0. |
60 | 9645ea29 | Serge Torres | powerForMinNorm = floor(log(minBasisVectsNorm)/log2) |
61 | 9645ea29 | Serge Torres | print "Power for min norm :", powerForMinNorm |
62 | 9645ea29 | Serge Torres | print "Power for precision:", ceil(precision*precisionFraction) |
63 | 9645ea29 | Serge Torres | if powerForMinNorm < 0: |
64 | 9645ea29 | Serge Torres | return 2^(ceil(precision*precisionFraction) - powerFromMinNorm) |
65 | 9645ea29 | Serge Torres | else: |
66 | 62861417 | Serge Torres | """ |
67 | 62861417 | Serge Torres | return ceil(precision * precisionFraction) |
68 | 9645ea29 | Serge Torres | # End cvp_common_scaling_factor. |
69 | 9645ea29 | Serge Torres | # |
70 | 62861417 | Serge Torres | def cvp_extra_basis_scaling_exps(precsList, minExponentsList): |
71 | 62861417 | Serge Torres | extraScalingExpsList = [] |
72 | 62861417 | Serge Torres | for minExp, prec in zip(minExponentsList, precsList): |
73 | 62861417 | Serge Torres | if minExp - prec < 0: |
74 | 62861417 | Serge Torres | extraScalingExpsList.append(minExp - prec) |
75 | 62861417 | Serge Torres | else: |
76 | 62861417 | Serge Torres | extraScalingExpsList.append(0) |
77 | 62861417 | Serge Torres | return extraScalingExpsList |
78 | 62861417 | Serge Torres | # End cvp_extra_basis_scaling_exps. |
79 | 62861417 | Serge Torres | # |
80 | 62861417 | Serge Torres | def cvp_extra_function_scaling_exp(floatBasis, |
81 | 62861417 | Serge Torres | floatFuncVect, |
82 | 62861417 | Serge Torres | maxExponentsList): |
83 | 9645ea29 | Serge Torres | """ |
84 | 62861417 | Serge Torres | Compute the extra scaling exponent for the function vector in ordre to |
85 | 62861417 | Serge Torres | guarantee that the maximum exponent can be reached for each element of the |
86 | 62861417 | Serge Torres | basis. |
87 | 9645ea29 | Serge Torres | """ |
88 | 62861417 | Serge Torres | ## Check arguments |
89 | 9645ea29 | Serge Torres | if floatBasis.nrows() == 0 or \ |
90 | 9645ea29 | Serge Torres | floatBasis.ncols() == 0 or \ |
91 | 62861417 | Serge Torres | len(floatFuncVect) == 0: |
92 | 62861417 | Serge Torres | return 1 |
93 | 62861417 | Serge Torres | if len(maxExponentsList) != floatBasis.nrows(): |
94 | 62861417 | Serge Torres | return None |
95 | 62861417 | Serge Torres | ## Compute the log of the norm of the function vector. |
96 | 62861417 | Serge Torres | funcVectNormLog = log(floatFuncVect.norm()) |
97 | 9645ea29 | Serge Torres | ## Compute the extra scaling factor for each vector of the basis. |
98 | 62861417 | Serge Torres | # for norms ratios an maxExponentsList. |
99 | 62861417 | Serge Torres | extraScalingExp = 0 |
100 | 62861417 | Serge Torres | for (row, maxExp) in zip(floatBasis.rows(),maxExponentsList): |
101 | 62861417 | Serge Torres | rowNormLog = log(row.norm()) |
102 | 62861417 | Serge Torres | normsRatioLog2 = floor((funcVectNormLog - rowNormLog) / log2) |
103 | 62861417 | Serge Torres | #print "Current norms ratio log2:", normsRatioLog2 |
104 | 62861417 | Serge Torres | scalingExpCandidate = normsRatioLog2 - maxExp |
105 | 62861417 | Serge Torres | #print "Current scaling exponent candidate:", scalingExpCandidate |
106 | 62861417 | Serge Torres | if scalingExpCandidate < 0: |
107 | 62861417 | Serge Torres | if -scalingExpCandidate > extraScalingExp: |
108 | 62861417 | Serge Torres | extraScalingExp = -scalingExpCandidate |
109 | 62861417 | Serge Torres | return extraScalingExp |
110 | 62861417 | Serge Torres | # End cvp_extra_function_scaling_exp. |
111 | 9645ea29 | Serge Torres | # |
112 | 9645ea29 | Serge Torres | def cvp_float_basis(monomialsList, pointsList, realField): |
113 | 9645ea29 | Serge Torres | """ |
114 | 9645ea29 | Serge Torres | For a given monomials list and points list, compute the floating-point |
115 | 9645ea29 | Serge Torres | basis matrix. |
116 | 9645ea29 | Serge Torres | """ |
117 | 9645ea29 | Serge Torres | numRows = len(monomialsList) |
118 | 9645ea29 | Serge Torres | numCols = len(pointsList) |
119 | 9645ea29 | Serge Torres | if numRows == 0 or numCols == 0: |
120 | 9645ea29 | Serge Torres | return matrix(realField, 0, 0) |
121 | 9645ea29 | Serge Torres | # |
122 | 9645ea29 | Serge Torres | floatBasis = matrix(realField, numRows, numCols) |
123 | 9645ea29 | Serge Torres | for rIndex in xrange(0, numRows): |
124 | 9645ea29 | Serge Torres | for cIndex in xrange(0, numCols): |
125 | 9645ea29 | Serge Torres | floatBasis[rIndex,cIndex] = \ |
126 | 9645ea29 | Serge Torres | monomialsList[rIndex](realField(pointsList[cIndex])) |
127 | 9645ea29 | Serge Torres | return floatBasis |
128 | 9645ea29 | Serge Torres | # End cvp_float_basis |
129 | 9645ea29 | Serge Torres | # |
130 | 9645ea29 | Serge Torres | def cvp_float_vector_for_approx(func, |
131 | 9645ea29 | Serge Torres | basisPointsList, |
132 | 9645ea29 | Serge Torres | realField): |
133 | 9645ea29 | Serge Torres | """ |
134 | 9645ea29 | Serge Torres | Compute a floating-point vector for the function and the points list. |
135 | 9645ea29 | Serge Torres | """ |
136 | 9645ea29 | Serge Torres | # |
137 | 9645ea29 | Serge Torres | ## Some local variables. |
138 | 9645ea29 | Serge Torres | basisPointsNum = len(basisPointsList) |
139 | 9645ea29 | Serge Torres | # |
140 | 9645ea29 | Serge Torres | ## |
141 | 9645ea29 | Serge Torres | vVect = vector(realField, basisPointsNum) |
142 | 9645ea29 | Serge Torres | for vIndex in xrange(0,basisPointsNum): |
143 | 9645ea29 | Serge Torres | vVect[vIndex] = \ |
144 | 9645ea29 | Serge Torres | func(basisPointsList[vIndex]) |
145 | 9645ea29 | Serge Torres | return vVect |
146 | 9645ea29 | Serge Torres | # End cvp_float_vector_for_approx. |
147 | 9645ea29 | Serge Torres | # |
148 | 9645ea29 | Serge Torres | def cvp_hkz_reduce(intBasis): |
149 | 9645ea29 | Serge Torres | """ |
150 | 9645ea29 | Serge Torres | Thin and simplistic wrapper the HKZ function of the FP_LLL module. |
151 | 9645ea29 | Serge Torres | """ |
152 | 9645ea29 | Serge Torres | fplllIntBasis = FP_LLL(intBasis) |
153 | 9645ea29 | Serge Torres | fplllIntBasis.HKZ() |
154 | 9645ea29 | Serge Torres | return fplllIntBasis._sage_() |
155 | 9645ea29 | Serge Torres | # End cvp_hkz_reduce. |
156 | 9645ea29 | Serge Torres | # |
157 | 62861417 | Serge Torres | def cvp_int_basis(floatBasis, |
158 | 62861417 | Serge Torres | commonScalingExp, |
159 | 62861417 | Serge Torres | extraScalingExpsList): |
160 | 9645ea29 | Serge Torres | """ |
161 | 62861417 | Serge Torres | From the float basis, the common scaling factor and the extra exponents |
162 | 62861417 | Serge Torres | compute the integral basis. |
163 | 9645ea29 | Serge Torres | """ |
164 | 62861417 | Serge Torres | ## Checking arguments. |
165 | 62861417 | Serge Torres | if floatBasis.nrows() != len(extraScalingExpsList): |
166 | 62861417 | Serge Torres | return None |
167 | 9645ea29 | Serge Torres | intBasis = matrix(ZZ, floatBasis.nrows(), floatBasis.ncols()) |
168 | 9645ea29 | Serge Torres | for rIndex in xrange(0, floatBasis.nrows()): |
169 | 9645ea29 | Serge Torres | for cIndex in xrange(0, floatBasis.ncols()): |
170 | 9645ea29 | Serge Torres | intBasis[rIndex, cIndex] = \ |
171 | 62861417 | Serge Torres | floatBasis[rIndex, cIndex] * \ |
172 | 62861417 | Serge Torres | 2^(commonScalingExp + extraScalingExpsList[rIndex]) |
173 | 9645ea29 | Serge Torres | return intBasis |
174 | 9645ea29 | Serge Torres | # End cvp_int_basis. |
175 | 9645ea29 | Serge Torres | # |
176 | 62861417 | Serge Torres | def cvp_int_vector_for_approx(floatVect, commonScalingExp, extraScalingExp): |
177 | 62861417 | Serge Torres | totalScalingFactor = 2^(commonScalingExp + extraScalingExp) |
178 | 9645ea29 | Serge Torres | intVect = vector(ZZ, len(floatVect)) |
179 | 9645ea29 | Serge Torres | for index in xrange(0, len(floatVect)): |
180 | 9645ea29 | Serge Torres | intVect[index] = (floatVect[index] * totalScalingFactor).round() |
181 | 9645ea29 | Serge Torres | return intVect |
182 | 9645ea29 | Serge Torres | # End cvp_int_vector_for_approx. |
183 | 9645ea29 | Serge Torres | # |
184 | 9645ea29 | Serge Torres | def cvp_lll_reduce(intBasis): |
185 | 9645ea29 | Serge Torres | """ |
186 | 9645ea29 | Serge Torres | Thin and simplistic wrapper around the LLL function |
187 | 9645ea29 | Serge Torres | """ |
188 | 9645ea29 | Serge Torres | return intBasis.LLL() |
189 | 9645ea29 | Serge Torres | # End cvp_lll_reduce. |
190 | 9645ea29 | Serge Torres | # |
191 | 9645ea29 | Serge Torres | def cvp_monomials_list(exponentsList, varName = None): |
192 | 9645ea29 | Serge Torres | """ |
193 | 9645ea29 | Serge Torres | Create a list of monomials corresponding to the given exponentsList. |
194 | 9645ea29 | Serge Torres | Monomials are defined as functions. |
195 | 9645ea29 | Serge Torres | """ |
196 | 9645ea29 | Serge Torres | monomialsList = [] |
197 | 9645ea29 | Serge Torres | for exponent in exponentsList: |
198 | 9645ea29 | Serge Torres | if varName is None: |
199 | 9645ea29 | Serge Torres | monomialsList.append((x^exponent).function(x)) |
200 | 9645ea29 | Serge Torres | else: |
201 | 9645ea29 | Serge Torres | monomialsList.append((varName^exponent).function(varName)) |
202 | 9645ea29 | Serge Torres | return monomialsList |
203 | 9645ea29 | Serge Torres | # End cvp_monomials_list. |
204 | 9645ea29 | Serge Torres | # |
205 | 62861417 | Serge Torres | def cvp_polynomial_coeffs_from_vect(cvpVectInBasis, |
206 | 62861417 | Serge Torres | coeffsPrecList, |
207 | 62861417 | Serge Torres | minCoeffsExpList, |
208 | 62861417 | Serge Torres | extraFuncScalingExp): |
209 | 62861417 | Serge Torres | numElements = len(cvpVectInBasis) |
210 | 62861417 | Serge Torres | ## Arguments check. |
211 | 62861417 | Serge Torres | if numElements != len(minCoeffsExpList) or \ |
212 | 62861417 | Serge Torres | numElements != len(coeffsPrecList): |
213 | 62861417 | Serge Torres | return None |
214 | 62861417 | Serge Torres | polynomialCoeffsList = [] |
215 | 62861417 | Serge Torres | for index in xrange(0, numElements): |
216 | 62861417 | Serge Torres | currentCoeff = cvp_round_to_bits(cvpVectInBasis[index], |
217 | 62861417 | Serge Torres | coeffsPrecList[index]) |
218 | 62861417 | Serge Torres | print "cvp_polynomial_coeffs - current coefficient rounded:", currentCoeff |
219 | 62861417 | Serge Torres | currentCoeff *= 2^(minCoeffsExpList[index]) |
220 | 62861417 | Serge Torres | print "cvp_polynomial_coeffs - current coefficient scaled :", currentCoeff |
221 | 62861417 | Serge Torres | currentCoeff *= 2^(-coeffsPrecList[index]) |
222 | 62861417 | Serge Torres | print "cvp_polynomial_coeffs - current coefficient prec corrected :", currentCoeff |
223 | 62861417 | Serge Torres | currentCoeff *= 2^(-extraFuncScalingExp) |
224 | 62861417 | Serge Torres | print "cvp_polynomial_coeffs - current coefficient extra func scaled :", currentCoeff |
225 | 62861417 | Serge Torres | polynomialCoeffsList.append(currentCoeff) |
226 | 62861417 | Serge Torres | return polynomialCoeffsList |
227 | 62861417 | Serge Torres | # En polynomial_coeffs_from_vect. |
228 | 62861417 | Serge Torres | # |
229 | 62861417 | Serge Torres | def cvp_round_to_bits(num, numBits): |
230 | 62861417 | Serge Torres | """ |
231 | 62861417 | Serge Torres | Round "num" to "numBits" bits. |
232 | 62861417 | Serge Torres | @param num : the number to round; |
233 | 62861417 | Serge Torres | @param numBits: the number of bits to round to. |
234 | 62861417 | Serge Torres | """ |
235 | 62861417 | Serge Torres | if num == 0: |
236 | 62861417 | Serge Torres | return num |
237 | 62861417 | Serge Torres | log2ofNum = 0 |
238 | 62861417 | Serge Torres | numRounded = 0 |
239 | 62861417 | Serge Torres | ## Avoid conversion to floating-point if not necessary. |
240 | 62861417 | Serge Torres | try: |
241 | 62861417 | Serge Torres | log2OfNum = num.abs().log2() |
242 | 62861417 | Serge Torres | except: |
243 | 62861417 | Serge Torres | log2OfNum = RR(num).abs().log2() |
244 | 62861417 | Serge Torres | ## Works equally well for num >= 1 and num < 1. |
245 | 62861417 | Serge Torres | log2OfNum = ceil(log2OfNum) |
246 | 62861417 | Serge Torres | # print "cvp_round_to_bits - Log2OfNum:", log2OfNum |
247 | 62861417 | Serge Torres | divMult = log2OfNum - numBits |
248 | 62861417 | Serge Torres | #print "cvp_round_to_bits - DivMult:", divMult |
249 | 62861417 | Serge Torres | if divMult != 0: |
250 | 62861417 | Serge Torres | numRounded = round(num/2^divMult) * 2^divMult |
251 | 62861417 | Serge Torres | else: |
252 | 62861417 | Serge Torres | numRounded = num |
253 | 62861417 | Serge Torres | return numRounded |
254 | 62861417 | Serge Torres | # End cvp_round_to_bits |
255 | 62861417 | Serge Torres | # |
256 | 9645ea29 | Serge Torres | def cvp_vector_in_basis(vect, basis): |
257 | 9645ea29 | Serge Torres | """ |
258 | 9645ea29 | Serge Torres | Compute the coordinates of "vect" in "basis" by |
259 | 9645ea29 | Serge Torres | solving a linear system. |
260 | 9645ea29 | Serge Torres | @param vect : the vector we want to compute the coordinates of |
261 | 9645ea29 | Serge Torres | in coordinates of the ambient space; |
262 | 9645ea29 | Serge Torres | @param basis: the basis we want to compute the coordinates in |
263 | 9645ea29 | Serge Torres | as a matrix relative to the ambient space. |
264 | 9645ea29 | Serge Torres | """ |
265 | 9645ea29 | Serge Torres | ## Create the variables for the linear equations. |
266 | 9645ea29 | Serge Torres | varDeclString = "" |
267 | 9645ea29 | Serge Torres | basisIterationsRange = xrange(0, basis.nrows()) |
268 | 9645ea29 | Serge Torres | ### Building variables declaration string. |
269 | 9645ea29 | Serge Torres | for index in basisIterationsRange: |
270 | 9645ea29 | Serge Torres | varName = "a" + str(index) |
271 | 9645ea29 | Serge Torres | if varDeclString == "": |
272 | 9645ea29 | Serge Torres | varDeclString += varName |
273 | 9645ea29 | Serge Torres | else: |
274 | 9645ea29 | Serge Torres | varDeclString += "," + varName |
275 | 9645ea29 | Serge Torres | ### Variables declaration |
276 | 9645ea29 | Serge Torres | varsList = var(varDeclString) |
277 | 9645ea29 | Serge Torres | sage_eval("var('" + varDeclString + "')") |
278 | 9645ea29 | Serge Torres | ## Create the equations |
279 | 9645ea29 | Serge Torres | equationString = "" |
280 | 9645ea29 | Serge Torres | equationsList = [] |
281 | 9645ea29 | Serge Torres | for vIndex in xrange(0, len(vect)): |
282 | 9645ea29 | Serge Torres | equationString = "" |
283 | 9645ea29 | Serge Torres | for bIndex in basisIterationsRange: |
284 | 9645ea29 | Serge Torres | if equationString != "": |
285 | 9645ea29 | Serge Torres | equationString += "+" |
286 | 9645ea29 | Serge Torres | equationString += str(varsList[bIndex]) + "*" + str(basis[bIndex,vIndex]) |
287 | 9645ea29 | Serge Torres | equationString += " == " + str(vect[vIndex]) |
288 | 9645ea29 | Serge Torres | equationsList.append(sage_eval(equationString)) |
289 | 9645ea29 | Serge Torres | ## Solve the equations system. The solution dictionnary is needed |
290 | 9645ea29 | Serge Torres | # to recover the values of the solutions. |
291 | 9645ea29 | Serge Torres | solutions = solve(equationsList,varsList, solution_dict=True) |
292 | 9645ea29 | Serge Torres | #print "Solutions:", s |
293 | 9645ea29 | Serge Torres | ## Recover solutions in rational components vector. |
294 | 9645ea29 | Serge Torres | vectInBasis = vector(QQ, basis.nrows()) |
295 | 9645ea29 | Serge Torres | ### There can be several solution, in the general case. |
296 | 9645ea29 | Serge Torres | # Here, there is only one. For each solution, each |
297 | 9645ea29 | Serge Torres | # variable has to be searched for. |
298 | 9645ea29 | Serge Torres | for sol in solutions: |
299 | 9645ea29 | Serge Torres | for bIndex in basisIterationsRange: |
300 | 9645ea29 | Serge Torres | vectInBasis[bIndex] = sol[varsList[bIndex]] |
301 | 9645ea29 | Serge Torres | return vectInBasis |
302 | 9645ea29 | Serge Torres | # End cpv_vector_in_basis. |
303 | 9645ea29 | Serge Torres | # |
304 | 9645ea29 | Serge Torres | print "... functions for CVP loaded." |