def short_vector_list_up_to_length(self, len_bound, up_to_sign_flag=False): """ Return a list of lists of short vectors `v`, sorted by length, with Q(`v`) < len_bound. INPUT: - ``len_bound`` -- bound for the length of the vectors. - ``up_to_sign_flag`` -- (default: ``False``) if set to True, then only one of the vectors of the pair `[v, -v]` is listed. OUTPUT: A list of lists of vectors such that entry `[i]` contains all vectors of length `i`. EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: Q.short_vector_list_up_to_length(3) [[(0, 0, 0, 0)], [(1, 0, 0, 0), (-1, 0, 0, 0)], []] sage: Q.short_vector_list_up_to_length(4) [[(0, 0, 0, 0)], [(1, 0, 0, 0), (-1, 0, 0, 0)], [], [(0, 1, 0, 0), (0, -1, 0, 0)]] sage: Q.short_vector_list_up_to_length(5) [[(0, 0, 0, 0)], [(1, 0, 0, 0), (-1, 0, 0, 0)], [], [(0, 1, 0, 0), (0, -1, 0, 0)], [(1, 1, 0, 0), (-1, -1, 0, 0), (-1, 1, 0, 0), (1, -1, 0, 0), (2, 0, 0, 0), (-2, 0, 0, 0)]] sage: Q.short_vector_list_up_to_length(5, True) [[(0, 0, 0, 0)], [(1, 0, 0, 0)], [], [(0, 1, 0, 0)], [(1, 1, 0, 0), (-1, 1, 0, 0), (2, 0, 0, 0)]] sage: Q = QuadraticForm(matrix(6, [2, 1, 1, 1, -1, -1, 1, 2, 1, 1, -1, -1, 1, 1, 2, 0, -1, -1, 1, 1, 0, 2, 0, -1, -1, -1, -1, 0, 2, 1, -1, -1, -1, -1, 1, 2])) sage: vs = Q.short_vector_list_up_to_length(8) sage: [len(vs[i]) for i in range(len(vs))] [1, 72, 270, 720, 936, 2160, 2214, 3600] sage: vs = Q.short_vector_list_up_to_length(30) # long time (28s on sage.math, 2014) sage: [len(vs[i]) for i in range(len(vs))] # long time [1, 72, 270, 720, 936, 2160, 2214, 3600, 4590, 6552, 5184, 10800, 9360, 12240, 13500, 17712, 14760, 25920, 19710, 26064, 28080, 36000, 25920, 47520, 37638, 43272, 45900, 59040, 46800, 75600] The cases of ``len_bound < 2`` led to exception or infinite runtime before. :: sage: Q.short_vector_list_up_to_length(-1) [] sage: Q.short_vector_list_up_to_length(0) [] sage: Q.short_vector_list_up_to_length(1) [[(0, 0, 0, 0, 0, 0)]] In the case of quadratic forms that are not positive definite an error is raised. :: sage: QuadraticForm(matrix(2, [2, 0, 0, -2])).short_vector_list_up_to_length(3) Traceback (most recent call last): ... ValueError: Quadratic form must be positive definite in order to enumerate short vectors Sometimes, PARI does not compute short vectors correctly. It returns too long vectors. :: sage: Q = QuadraticForm(matrix(2, [72, 12, 12, 120])) sage: len_bound_pari = 2*22953421 - 2; len_bound_pari 45906840 sage: vs = list(Q._pari_().qfminim(len_bound_pari)[2]) # long time (18s on sage.math, 2014) sage: v = vs[0]; v # long time [-65, 623]~ sage: v.Vec() * Q._pari_() * v # long time 45907800 """ if not self.is_positive_definite(): raise ValueError("Quadratic form must be positive definite in order to enumerate short vectors") if len_bound <= 0: return [] # Free module in which the vectors live V = FreeModule(ZZ, self.dim()) # Adjust length for PARI. We need to subtract 1 because PARI returns # returns vectors of length less than or equal to b, but we want # strictly less. We need to double because the matrix is doubled. len_bound_pari = 2 * (len_bound - 1) # Call PARI's qfminim() parilist = self._pari_().qfminim(len_bound_pari)[2].Vec() # List of lengths parilens = pari(r"(M,v) -> vector(#v, i, (v[i]~ * M * v[i])\2)")(self, parilist) # Sort the vectors into lists by their length vec_sorted_list = [list() for i in range(len_bound)] for i in range(len(parilist)): length = ZZ(parilens[i]) # PARI can sometimes return longer vectors than requested. # E.g. : self.matrix() == matrix(2, [72, 12, 12, 120]) # len_bound = 22953421 # gives maximal length 22955664 if length < len_bound: v = parilist[i] sagevec = V(list(parilist[i])) vec_sorted_list[length].append(sagevec) if not up_to_sign_flag: vec_sorted_list[length].append(-sagevec) # Add the zero vector by hand vec_sorted_list[0].append(V.zero_vector()) return vec_sorted_list
def short_vector_list_up_to_length(self, len_bound, up_to_sign_flag=False): """ Return a list of lists of short vectors `v`, sorted by length, with Q(`v`) < len_bound. INPUT: - ``len_bound`` -- bound for the length of the vectors. - ``up_to_sign_flag`` -- (default: ``False``) if set to True, then only one of the vectors of the pair `[v, -v]` is listed. OUTPUT: A list of lists of vectors such that entry `[i]` contains all vectors of length `i`. EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: Q.short_vector_list_up_to_length(3) [[(0, 0, 0, 0)], [(1, 0, 0, 0), (-1, 0, 0, 0)], []] sage: Q.short_vector_list_up_to_length(4) [[(0, 0, 0, 0)], [(1, 0, 0, 0), (-1, 0, 0, 0)], [], [(0, 1, 0, 0), (0, -1, 0, 0)]] sage: Q.short_vector_list_up_to_length(5) [[(0, 0, 0, 0)], [(1, 0, 0, 0), (-1, 0, 0, 0)], [], [(0, 1, 0, 0), (0, -1, 0, 0)], [(1, 1, 0, 0), (-1, -1, 0, 0), (-1, 1, 0, 0), (1, -1, 0, 0), (2, 0, 0, 0), (-2, 0, 0, 0)]] sage: Q.short_vector_list_up_to_length(5, True) [[(0, 0, 0, 0)], [(1, 0, 0, 0)], [], [(0, 1, 0, 0)], [(1, 1, 0, 0), (-1, 1, 0, 0), (2, 0, 0, 0)]] sage: Q = QuadraticForm(matrix(6, [2, 1, 1, 1, -1, -1, 1, 2, 1, 1, -1, -1, 1, 1, 2, 0, -1, -1, 1, 1, 0, 2, 0, -1, -1, -1, -1, 0, 2, 1, -1, -1, -1, -1, 1, 2])) sage: vs = Q.short_vector_list_up_to_length(8) sage: [len(vs[i]) for i in range(len(vs))] [1, 72, 270, 720, 936, 2160, 2214, 3600] sage: vs = Q.short_vector_list_up_to_length(30) # long time (28s on sage.math, 2014) sage: [len(vs[i]) for i in range(len(vs))] # long time [1, 72, 270, 720, 936, 2160, 2214, 3600, 4590, 6552, 5184, 10800, 9360, 12240, 13500, 17712, 14760, 25920, 19710, 26064, 28080, 36000, 25920, 47520, 37638, 43272, 45900, 59040, 46800, 75600] The cases of ``len_bound < 2`` led to exception or infinite runtime before. :: sage: Q.short_vector_list_up_to_length(-1) [] sage: Q.short_vector_list_up_to_length(0) [] sage: Q.short_vector_list_up_to_length(1) [[(0, 0, 0, 0, 0, 0)]] In the case of quadratic forms that are not positive definite an error is raised. :: sage: QuadraticForm(matrix(2, [2, 0, 0, -2])).short_vector_list_up_to_length(3) Traceback (most recent call last): ... ValueError: Quadratic form must be positive definite in order to enumerate short vectors Sometimes, PARI does not compute short vectors correctly. It returns too long vectors. :: sage: Q = QuadraticForm(matrix(2, [72, 12, 12, 120])) sage: len_bound_pari = 2*22953421 - 2; len_bound_pari 45906840 sage: vs = list(Q._pari_().qfminim(len_bound_pari)[2]) # long time (18s on sage.math, 2014) sage: v = vs[0]; v # long time [-65, 623]~ sage: v.Vec() * Q._pari_() * v # long time 45907800 """ if not self.is_positive_definite() : raise ValueError( "Quadratic form must be positive definite in order to enumerate short vectors" ) if len_bound <= 0: return [] # Free module in which the vectors live V = FreeModule(ZZ, self.dim()) # Adjust length for PARI. We need to subtract 1 because PARI returns # returns vectors of length less than or equal to b, but we want # strictly less. We need to double because the matrix is doubled. len_bound_pari = 2*(len_bound - 1) # Call PARI's qfminim() parilist = self._pari_().qfminim(len_bound_pari)[2].Vec() # List of lengths parilens = pari(r"(M,v) -> vector(#v, i, (v[i]~ * M * v[i])\2)")(self, parilist) # Sort the vectors into lists by their length vec_sorted_list = [list() for i in range(len_bound)] for i in range(len(parilist)): length = ZZ(parilens[i]) # PARI can sometimes return longer vectors than requested. # E.g. : self.matrix() == matrix(2, [72, 12, 12, 120]) # len_bound = 22953421 # gives maximal length 22955664 if length < len_bound: v = parilist[i] sagevec = V(list(parilist[i])) vec_sorted_list[length].append(sagevec) if not up_to_sign_flag : vec_sorted_list[length].append(-sagevec) # Add the zero vector by hand vec_sorted_list[0].append(V.zero_vector()) return vec_sorted_list