cvp / src / functions_for_cvp.sage @ 9645ea29
Historique | Voir | Annoter | Télécharger (8,82 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 | 9645ea29 | Serge Torres | print "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 | 9645ea29 | Serge Torres | # |
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 | 9645ea29 | Serge Torres | |
36 | 9645ea29 | Serge Torres | def cvp_common_scaling_factor(floatBasis, |
37 | 9645ea29 | Serge Torres | funcVect, |
38 | 9645ea29 | Serge Torres | precision , |
39 | 9645ea29 | Serge Torres | precisionFraction = None): |
40 | 9645ea29 | Serge Torres | """ |
41 | 9645ea29 | Serge Torres | Compute the common scaling factor (a power of 2). |
42 | 9645ea29 | Serge Torres | The exponent is made of: |
43 | ada40619 | Serge Torres | - a fraction of the precision; |
44 | ada40619 | Serge Torres | - an integer depending on the smallest norm of the vectors of the basis. |
45 | 9645ea29 | Serge Torres | """ |
46 | 9645ea29 | Serge Torres | ## Set a default value for the precisionFraction to 1/2. |
47 | 9645ea29 | Serge Torres | if precisionFraction is None: |
48 | 9645ea29 | Serge Torres | precisionFraction = 1/2 |
49 | 9645ea29 | Serge Torres | ## Compute the norms of the vectors and get the smallest one. |
50 | 9645ea29 | Serge Torres | # Start with "oo" (+Infinty) |
51 | 9645ea29 | Serge Torres | minBasisVectsNorm = oo |
52 | 9645ea29 | Serge Torres | currentNorm = 0 |
53 | 9645ea29 | Serge Torres | for vect in floatBasis.rows(): |
54 | 9645ea29 | Serge Torres | currentNorm = vect.norm() |
55 | 9645ea29 | Serge Torres | print "Current norm:", currentNorm |
56 | 9645ea29 | Serge Torres | if currentNorm < minBasisVectsNorm: |
57 | 9645ea29 | Serge Torres | minBasisVectsNorm = currentNorm |
58 | 9645ea29 | Serge Torres | currentNorm = funcVect.norm() |
59 | 9645ea29 | Serge Torres | print "Current norm:", currentNorm |
60 | 9645ea29 | Serge Torres | if currentNorm < minBasisVectsNorm: |
61 | 9645ea29 | Serge Torres | minBasisVectsNorm = currentNorm |
62 | 9645ea29 | Serge Torres | ## Check if a push is need because the smallest norm is below 0. |
63 | 9645ea29 | Serge Torres | powerForMinNorm = floor(log(minBasisVectsNorm)/log2) |
64 | 9645ea29 | Serge Torres | print "Power for min norm :", powerForMinNorm |
65 | 9645ea29 | Serge Torres | print "Power for precision:", ceil(precision*precisionFraction) |
66 | 9645ea29 | Serge Torres | if powerForMinNorm < 0: |
67 | 9645ea29 | Serge Torres | return 2^(ceil(precision*precisionFraction) - powerFromMinNorm) |
68 | 9645ea29 | Serge Torres | else: |
69 | 9645ea29 | Serge Torres | return 2^(ceil(precision*precisionFraction)) |
70 | 9645ea29 | Serge Torres | # End cvp_common_scaling_factor. |
71 | 9645ea29 | Serge Torres | # |
72 | 9645ea29 | Serge Torres | def cvp_extra_scaling_factor(floatBasis, |
73 | 9645ea29 | Serge Torres | funcVect, |
74 | 9645ea29 | Serge Torres | coeffsPrecList, |
75 | 9645ea29 | Serge Torres | minExponentsList): |
76 | 9645ea29 | Serge Torres | """ |
77 | 9645ea29 | Serge Torres | Compute the extra scaling factor for each element of the basis. |
78 | 9645ea29 | Serge Torres | """ |
79 | 9645ea29 | Serge Torres | if floatBasis.nrows() == 0 or \ |
80 | 9645ea29 | Serge Torres | floatBasis.ncols() == 0 or \ |
81 | 9645ea29 | Serge Torres | len(funcVect) == 0: |
82 | 9645ea29 | Serge Torres | return 0 |
83 | 9645ea29 | Serge Torres | ## Compute the norm of the function vector. |
84 | 9645ea29 | Serge Torres | funcVectNorm = funcVect.norm() |
85 | 9645ea29 | Serge Torres | ## Compute the extra scaling factor for each vector of the basis. |
86 | 9645ea29 | Serge Torres | ### Pass #1 for norms ratios an minExponentsList |
87 | 9645ea29 | Serge Torres | scalingPowers = [] |
88 | 9645ea29 | Serge Torres | normsRatio = 0 |
89 | 9645ea29 | Serge Torres | for (row, maxExp) in zip(floatBasis.rows(),minExponentsList): |
90 | 9645ea29 | Serge Torres | normsRatio = funcVectNorm / row.norm() |
91 | 9645ea29 | Serge Torres | normsRatioLog2 = normsRatio.log2().floor() |
92 | 9645ea29 | Serge Torres | print "Current norms ratio:", normsRatio, normsRatioLog2 |
93 | 9645ea29 | Serge Torres | scalingPower = normsRatioLog2 + maxExp |
94 | 9645ea29 | Serge Torres | print "Current scaling power:", scalingPower |
95 | 9645ea29 | Serge Torres | scalingPowers.append(scalingPower) |
96 | 9645ea29 | Serge Torres | ### Pass #2 for coefficients precision. |
97 | 9645ea29 | Serge Torres | minScalingPower = oo |
98 | 9645ea29 | Serge Torres | for index in xrange(0,len(scalingPowers)): |
99 | 9645ea29 | Serge Torres | scalingPowers[index] -= coeffsPrecList[index] |
100 | 9645ea29 | Serge Torres | if scalingPowers[index] < minScalingPower: |
101 | 9645ea29 | Serge Torres | minScalingPower = scalingPowers[index] |
102 | 9645ea29 | Serge Torres | print "Current scaling power:", scalingPowers[index] |
103 | 9645ea29 | Serge Torres | if minScalingPower < 0: |
104 | 9645ea29 | Serge Torres | scalingFactor = 2^(-minScalingPower) |
105 | 9645ea29 | Serge Torres | else: |
106 | 9645ea29 | Serge Torres | scalingFactor = 1 |
107 | 9645ea29 | Serge Torres | return (scalingFactor, scalingPowers) |
108 | 9645ea29 | Serge Torres | # End cvp_extra_scaling_factor. |
109 | 9645ea29 | Serge Torres | # |
110 | 9645ea29 | Serge Torres | def cvp_float_basis(monomialsList, pointsList, realField): |
111 | 9645ea29 | Serge Torres | """ |
112 | 9645ea29 | Serge Torres | For a given monomials list and points list, compute the floating-point |
113 | 9645ea29 | Serge Torres | basis matrix. |
114 | 9645ea29 | Serge Torres | """ |
115 | 9645ea29 | Serge Torres | numRows = len(monomialsList) |
116 | 9645ea29 | Serge Torres | numCols = len(pointsList) |
117 | 9645ea29 | Serge Torres | if numRows == 0 or numCols == 0: |
118 | 9645ea29 | Serge Torres | return matrix(realField, 0, 0) |
119 | 9645ea29 | Serge Torres | # |
120 | 9645ea29 | Serge Torres | floatBasis = matrix(realField, numRows, numCols) |
121 | 9645ea29 | Serge Torres | for rIndex in xrange(0, numRows): |
122 | 9645ea29 | Serge Torres | for cIndex in xrange(0, numCols): |
123 | 9645ea29 | Serge Torres | floatBasis[rIndex,cIndex] = \ |
124 | 9645ea29 | Serge Torres | monomialsList[rIndex](realField(pointsList[cIndex])) |
125 | 9645ea29 | Serge Torres | return floatBasis |
126 | 9645ea29 | Serge Torres | # End cvp_float_basis |
127 | 9645ea29 | Serge Torres | # |
128 | 9645ea29 | Serge Torres | def cvp_float_vector_for_approx(func, |
129 | 9645ea29 | Serge Torres | basisPointsList, |
130 | 9645ea29 | Serge Torres | realField): |
131 | 9645ea29 | Serge Torres | """ |
132 | 9645ea29 | Serge Torres | Compute a floating-point vector for the function and the points list. |
133 | 9645ea29 | Serge Torres | """ |
134 | 9645ea29 | Serge Torres | # |
135 | 9645ea29 | Serge Torres | ## Some local variables. |
136 | 9645ea29 | Serge Torres | basisPointsNum = len(basisPointsList) |
137 | 9645ea29 | Serge Torres | # |
138 | 9645ea29 | Serge Torres | ## |
139 | 9645ea29 | Serge Torres | vVect = vector(realField, basisPointsNum) |
140 | 9645ea29 | Serge Torres | for vIndex in xrange(0,basisPointsNum): |
141 | 9645ea29 | Serge Torres | vVect[vIndex] = \ |
142 | 9645ea29 | Serge Torres | func(basisPointsList[vIndex]) |
143 | 9645ea29 | Serge Torres | return vVect |
144 | 9645ea29 | Serge Torres | # End cvp_float_vector_for_approx. |
145 | 9645ea29 | Serge Torres | # |
146 | 9645ea29 | Serge Torres | def cvp_hkz_reduce(intBasis): |
147 | 9645ea29 | Serge Torres | """ |
148 | 9645ea29 | Serge Torres | Thin and simplistic wrapper the HKZ function of the FP_LLL module. |
149 | 9645ea29 | Serge Torres | """ |
150 | 9645ea29 | Serge Torres | fplllIntBasis = FP_LLL(intBasis) |
151 | 9645ea29 | Serge Torres | fplllIntBasis.HKZ() |
152 | 9645ea29 | Serge Torres | return fplllIntBasis._sage_() |
153 | 9645ea29 | Serge Torres | # End cvp_hkz_reduce. |
154 | 9645ea29 | Serge Torres | # |
155 | 9645ea29 | Serge Torres | def cvp_int_basis(floatBasis, commonScalingFactor): |
156 | 9645ea29 | Serge Torres | """ |
157 | 9645ea29 | Serge Torres | From the float basis and the common scaling factor, compute the |
158 | 9645ea29 | Serge Torres | integral basis. |
159 | 9645ea29 | Serge Torres | """ |
160 | 9645ea29 | Serge Torres | intBasis = matrix(ZZ, floatBasis.nrows(), floatBasis.ncols()) |
161 | 9645ea29 | Serge Torres | for rIndex in xrange(0, floatBasis.nrows()): |
162 | 9645ea29 | Serge Torres | for cIndex in xrange(0, floatBasis.ncols()): |
163 | 9645ea29 | Serge Torres | intBasis[rIndex, cIndex] = \ |
164 | 9645ea29 | Serge Torres | floatBasis[rIndex, cIndex] * commonScalingFactor |
165 | 9645ea29 | Serge Torres | return intBasis |
166 | 9645ea29 | Serge Torres | # End cvp_int_basis. |
167 | 9645ea29 | Serge Torres | # |
168 | 9645ea29 | Serge Torres | def cvp_int_vector_for_approx(floatVect, commonScalingFactor, extraScalingFactor): |
169 | 9645ea29 | Serge Torres | totalScalingFactor = commonScalingFactor * extraScalingFactor |
170 | 9645ea29 | Serge Torres | intVect = vector(ZZ, len(floatVect)) |
171 | 9645ea29 | Serge Torres | for index in xrange(0, len(floatVect)): |
172 | 9645ea29 | Serge Torres | intVect[index] = (floatVect[index] * totalScalingFactor).round() |
173 | 9645ea29 | Serge Torres | return intVect |
174 | 9645ea29 | Serge Torres | # End cvp_int_vector_for_approx. |
175 | 9645ea29 | Serge Torres | # |
176 | 9645ea29 | Serge Torres | def cvp_lll_reduce(intBasis): |
177 | 9645ea29 | Serge Torres | """ |
178 | 9645ea29 | Serge Torres | Thin and simplistic wrapper around the LLL function |
179 | 9645ea29 | Serge Torres | """ |
180 | 9645ea29 | Serge Torres | return intBasis.LLL() |
181 | 9645ea29 | Serge Torres | # End cvp_lll_reduce. |
182 | 9645ea29 | Serge Torres | # |
183 | 9645ea29 | Serge Torres | def cvp_monomials_list(exponentsList, varName = None): |
184 | 9645ea29 | Serge Torres | """ |
185 | 9645ea29 | Serge Torres | Create a list of monomials corresponding to the given exponentsList. |
186 | 9645ea29 | Serge Torres | Monomials are defined as functions. |
187 | 9645ea29 | Serge Torres | """ |
188 | 9645ea29 | Serge Torres | monomialsList = [] |
189 | 9645ea29 | Serge Torres | for exponent in exponentsList: |
190 | 9645ea29 | Serge Torres | if varName is None: |
191 | 9645ea29 | Serge Torres | monomialsList.append((x^exponent).function(x)) |
192 | 9645ea29 | Serge Torres | else: |
193 | 9645ea29 | Serge Torres | monomialsList.append((varName^exponent).function(varName)) |
194 | 9645ea29 | Serge Torres | return monomialsList |
195 | 9645ea29 | Serge Torres | # End cvp_monomials_list. |
196 | 9645ea29 | Serge Torres | # |
197 | 9645ea29 | Serge Torres | def cvp_vector_in_basis(vect, basis): |
198 | 9645ea29 | Serge Torres | """ |
199 | 9645ea29 | Serge Torres | Compute the coordinates of "vect" in "basis" by |
200 | 9645ea29 | Serge Torres | solving a linear system. |
201 | 9645ea29 | Serge Torres | @param vect : the vector we want to compute the coordinates of |
202 | 9645ea29 | Serge Torres | in coordinates of the ambient space; |
203 | 9645ea29 | Serge Torres | @param basis: the basis we want to compute the coordinates in |
204 | 9645ea29 | Serge Torres | as a matrix relative to the ambient space. |
205 | 9645ea29 | Serge Torres | """ |
206 | 9645ea29 | Serge Torres | ## Create the variables for the linear equations. |
207 | 9645ea29 | Serge Torres | varDeclString = "" |
208 | 9645ea29 | Serge Torres | basisIterationsRange = xrange(0, basis.nrows()) |
209 | 9645ea29 | Serge Torres | ### Building variables declaration string. |
210 | 9645ea29 | Serge Torres | for index in basisIterationsRange: |
211 | 9645ea29 | Serge Torres | varName = "a" + str(index) |
212 | 9645ea29 | Serge Torres | if varDeclString == "": |
213 | 9645ea29 | Serge Torres | varDeclString += varName |
214 | 9645ea29 | Serge Torres | else: |
215 | 9645ea29 | Serge Torres | varDeclString += "," + varName |
216 | 9645ea29 | Serge Torres | ### Variables declaration |
217 | 9645ea29 | Serge Torres | varsList = var(varDeclString) |
218 | 9645ea29 | Serge Torres | sage_eval("var('" + varDeclString + "')") |
219 | 9645ea29 | Serge Torres | ## Create the equations |
220 | 9645ea29 | Serge Torres | equationString = "" |
221 | 9645ea29 | Serge Torres | equationsList = [] |
222 | 9645ea29 | Serge Torres | for vIndex in xrange(0, len(vect)): |
223 | 9645ea29 | Serge Torres | equationString = "" |
224 | 9645ea29 | Serge Torres | for bIndex in basisIterationsRange: |
225 | 9645ea29 | Serge Torres | if equationString != "": |
226 | 9645ea29 | Serge Torres | equationString += "+" |
227 | 9645ea29 | Serge Torres | equationString += str(varsList[bIndex]) + "*" + str(basis[bIndex,vIndex]) |
228 | 9645ea29 | Serge Torres | equationString += " == " + str(vect[vIndex]) |
229 | 9645ea29 | Serge Torres | equationsList.append(sage_eval(equationString)) |
230 | 9645ea29 | Serge Torres | ## Solve the equations system. The solution dictionnary is needed |
231 | 9645ea29 | Serge Torres | # to recover the values of the solutions. |
232 | 9645ea29 | Serge Torres | solutions = solve(equationsList,varsList, solution_dict=True) |
233 | 9645ea29 | Serge Torres | #print "Solutions:", s |
234 | 9645ea29 | Serge Torres | ## Recover solutions in rational components vector. |
235 | 9645ea29 | Serge Torres | vectInBasis = vector(QQ, basis.nrows()) |
236 | 9645ea29 | Serge Torres | ### There can be several solution, in the general case. |
237 | 9645ea29 | Serge Torres | # Here, there is only one. For each solution, each |
238 | 9645ea29 | Serge Torres | # variable has to be searched for. |
239 | 9645ea29 | Serge Torres | for sol in solutions: |
240 | 9645ea29 | Serge Torres | for bIndex in basisIterationsRange: |
241 | 9645ea29 | Serge Torres | vectInBasis[bIndex] = sol[varsList[bIndex]] |
242 | 9645ea29 | Serge Torres | return vectInBasis |
243 | 9645ea29 | Serge Torres | # End cpv_vector_in_basis. |
244 | 9645ea29 | Serge Torres | # |
245 | 9645ea29 | Serge Torres | print "... functions for CVP loaded." |