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