Statistiques
| Branche: | Révision :

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."