def basis_of_short_vectors(self, show_lengths=False, safe_flag=True): """ Return a basis for `ZZ^n` made of vectors with minimal lengths Q(`v`). The safe_flag allows us to select whether we want a copy of the output, or the original output. By default safe_flag = True, so we return a copy of the cached information. If this is set to False, then the routine is much faster but the return values are vulnerable to being corrupted by the user. OUTPUT: a list of vectors, and optionally a list of values for each vector. EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: Q.basis_of_short_vectors() [(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)] sage: Q.basis_of_short_vectors(True) ([(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)], [1, 3, 5, 7]) """ ## Try to use the cached results try: ## Return the appropriate result if show_lengths: if safe_flag: return deep_copy(self.__basis_of_short_vectors), deepcopy(self.__basis_of_short_vectors_lengths) else: return self.__basis_of_short_vectors, self.__basis_of_short_vectors_lengths else: if safe_flag: return deepcopy(self.__basis_of_short_vectors) else: return deepcopy(self.__basis_of_short_vectors) except Exception: pass ## Set an upper bound for the number of vectors to consider Max_number_of_vectors = 10000 ## Generate a PARI matrix string for the associated Hessian matrix M_str = str(gp(self.matrix())) ## Run through all possible minimal lengths to find a spanning set of vectors n = self.dim() # MS = MatrixSpace(QQ, n) M1 = Matrix([[0]]) vec_len = 0 while M1.rank() < n: ## DIAGONSTIC # print # print "Starting with vec_len = ", vec_len # print "M_str = ", M_str vec_len += 1 gp_mat = gp.qfminim(M_str, vec_len, Max_number_of_vectors)[3].mattranspose() number_of_vecs = ZZ(gp_mat.matsize()[1]) vector_list = [] for i in range(number_of_vecs): # print "List at", i, ":", list(gp_mat[i+1,]) new_vec = vector([ZZ(x) for x in list(gp_mat[i + 1,])]) vector_list.append(new_vec) ## DIAGNOSTIC # print "number_of_vecs = ", number_of_vecs # print "vector_list = ", vector_list ## Make a matrix from the short vectors if len(vector_list) > 0: M1 = Matrix(vector_list) ## DIAGNOSTIC # print "matrix of vectors = \n", M1 # print "rank of the matrix = ", M1.rank() # print " vec_len = ", vec_len # print M1 ## Organize these vectors by length (and also introduce their negatives) max_len = vec_len / 2 vector_list_by_length = [[] for _ in range(max_len + 1)] for v in vector_list: l = self(v) vector_list_by_length[l].append(v) vector_list_by_length[l].append(vector([-x for x in v])) ## Make a matrix from the column vectors (in order of ascending length). sorted_list = [] for i in range(len(vector_list_by_length)): for v in vector_list_by_length[i]: sorted_list.append(v) sorted_matrix = Matrix(sorted_list).transpose() ## Determine a basis of vectors of minimal length pivots = sorted_matrix.pivots() basis = [sorted_matrix.column(i) for i in pivots] pivot_lengths = [self(v) for v in basis] ## DIAGNOSTIC # print "basis = ", basis # print "pivot_lengths = ", pivot_lengths ## Cache the result self.__basis_of_short_vectors = basis self.__basis_of_short_vectors_lenghts = pivot_lengths ## Return the appropriate result if show_lengths: return basis, pivot_lengths else: return basis
def basis_of_short_vectors(self, show_lengths=False, safe_flag=None): """ Return a basis for `ZZ^n` made of vectors with minimal lengths Q(`v`). OUTPUT: a tuple of vectors, and optionally a tuple of values for each vector. EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: Q.basis_of_short_vectors() ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)) sage: Q.basis_of_short_vectors(True) (((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)), (1, 3, 5, 7)) The returned vectors are immutable:: sage: v = Q.basis_of_short_vectors()[0] sage: v (1, 0, 0, 0) sage: v[0] = 0 Traceback (most recent call last): ... ValueError: vector is immutable; please change a copy instead (use copy()) """ if safe_flag is not None: from sage.misc.superseded import deprecation deprecation( 18673, "The safe_flag argument to basis_of_short_vectors() is deprecated and no longer used" ) ## Set an upper bound for the number of vectors to consider Max_number_of_vectors = 10000 ## Generate a PARI matrix for the associated Hessian matrix M_pari = self._pari_() ## Run through all possible minimal lengths to find a spanning set of vectors n = self.dim() M1 = Matrix([[0]]) vec_len = 0 while M1.rank() < n: vec_len += 1 pari_mat = M_pari.qfminim(vec_len, Max_number_of_vectors)[2] number_of_vecs = ZZ(pari_mat.matsize()[1]) vector_list = [] for i in range(number_of_vecs): new_vec = vector([ZZ(x) for x in list(pari_mat[i])]) vector_list.append(new_vec) ## Make a matrix from the short vectors if len(vector_list) > 0: M1 = Matrix(vector_list) ## Organize these vectors by length (and also introduce their negatives) max_len = vec_len // 2 vector_list_by_length = [[] for _ in range(max_len + 1)] for v in vector_list: l = self(v) vector_list_by_length[l].append(v) vector_list_by_length[l].append(vector([-x for x in v])) ## Make a matrix from the column vectors (in order of ascending length). sorted_list = [] for i in range(len(vector_list_by_length)): for v in vector_list_by_length[i]: sorted_list.append(v) sorted_matrix = Matrix(sorted_list).transpose() ## Determine a basis of vectors of minimal length pivots = sorted_matrix.pivots() basis = tuple(sorted_matrix.column(i) for i in pivots) for v in basis: v.set_immutable() ## Return the appropriate result if show_lengths: pivot_lengths = tuple(self(v) for v in basis) return basis, pivot_lengths else: return basis
def basis_of_short_vectors(self, show_lengths=False, safe_flag=True): """ Return a basis for `ZZ^n` made of vectors with minimal lengths Q(`v`). The safe_flag allows us to select whether we want a copy of the output, or the original output. By default safe_flag = True, so we return a copy of the cached information. If this is set to False, then the routine is much faster but the return values are vulnerable to being corrupted by the user. OUTPUT: a list of vectors, and optionally a list of values for each vector. EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: Q.basis_of_short_vectors() [(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)] sage: Q.basis_of_short_vectors(True) ([(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)], [1, 3, 5, 7]) """ ## Try to use the cached results try: ## Return the appropriate result if show_lengths: if safe_flag: return deep_copy(self.__basis_of_short_vectors), deepcopy(self.__basis_of_short_vectors_lengths) else: return self.__basis_of_short_vectors, self.__basis_of_short_vectors_lengths else: if safe_flag: return deepcopy(self.__basis_of_short_vectors) else: return deepcopy(self.__basis_of_short_vectors) except Exception: pass ## Set an upper bound for the number of vectors to consider Max_number_of_vectors = 10000 ## Generate a PARI matrix string for the associated Hessian matrix M_str = str(gp(self.matrix())) ## Run through all possible minimal lengths to find a spanning set of vectors n = self.dim() #MS = MatrixSpace(QQ, n) M1 = Matrix([[0]]) vec_len = 0 while M1.rank() < n: ## DIAGONSTIC #print #print "Starting with vec_len = ", vec_len #print "M_str = ", M_str vec_len += 1 gp_mat = gp.qfminim(M_str, vec_len, Max_number_of_vectors)[3].mattranspose() number_of_vecs = ZZ(gp_mat.matsize()[1]) vector_list = [] for i in range(number_of_vecs): #print "List at", i, ":", list(gp_mat[i+1,]) new_vec = vector([ZZ(x) for x in list(gp_mat[i+1,])]) vector_list.append(new_vec) ## DIAGNOSTIC #print "number_of_vecs = ", number_of_vecs #print "vector_list = ", vector_list ## Make a matrix from the short vectors if len(vector_list) > 0: M1 = Matrix(vector_list) ## DIAGNOSTIC #print "matrix of vectors = \n", M1 #print "rank of the matrix = ", M1.rank() #print " vec_len = ", vec_len #print M1 ## Organize these vectors by length (and also introduce their negatives) max_len = vec_len // 2 vector_list_by_length = [[] for _ in range(max_len + 1)] for v in vector_list: l = self(v) vector_list_by_length[l].append(v) vector_list_by_length[l].append(vector([-x for x in v])) ## Make a matrix from the column vectors (in order of ascending length). sorted_list = [] for i in range(len(vector_list_by_length)): for v in vector_list_by_length[i]: sorted_list.append(v) sorted_matrix = Matrix(sorted_list).transpose() ## Determine a basis of vectors of minimal length pivots = sorted_matrix.pivots() basis = [sorted_matrix.column(i) for i in pivots] pivot_lengths = [self(v) for v in basis] ## DIAGNOSTIC #print "basis = ", basis #print "pivot_lengths = ", pivot_lengths ## Cache the result self.__basis_of_short_vectors = basis self.__basis_of_short_vectors_lenghts = pivot_lengths ## Return the appropriate result if show_lengths: return basis, pivot_lengths else: return basis
def basis_of_short_vectors(self, show_lengths=False, safe_flag=None): """ Return a basis for `ZZ^n` made of vectors with minimal lengths Q(`v`). OUTPUT: a tuple of vectors, and optionally a tuple of values for each vector. EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) sage: Q.basis_of_short_vectors() ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)) sage: Q.basis_of_short_vectors(True) (((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)), (1, 3, 5, 7)) The returned vectors are immutable:: sage: v = Q.basis_of_short_vectors()[0] sage: v (1, 0, 0, 0) sage: v[0] = 0 Traceback (most recent call last): ... ValueError: vector is immutable; please change a copy instead (use copy()) """ if safe_flag is not None: from sage.misc.superseded import deprecation deprecation(18673, "The safe_flag argument to basis_of_short_vectors() is deprecated and no longer used") ## Set an upper bound for the number of vectors to consider Max_number_of_vectors = 10000 ## Generate a PARI matrix for the associated Hessian matrix M_pari = self.__pari__() ## Run through all possible minimal lengths to find a spanning set of vectors n = self.dim() M1 = Matrix([[0]]) vec_len = 0 while M1.rank() < n: vec_len += 1 pari_mat = M_pari.qfminim(vec_len, Max_number_of_vectors)[2] number_of_vecs = ZZ(pari_mat.matsize()[1]) vector_list = [] for i in range(number_of_vecs): new_vec = vector([ZZ(x) for x in list(pari_mat[i])]) vector_list.append(new_vec) ## Make a matrix from the short vectors if len(vector_list) > 0: M1 = Matrix(vector_list) ## Organize these vectors by length (and also introduce their negatives) max_len = vec_len // 2 vector_list_by_length = [[] for _ in range(max_len + 1)] for v in vector_list: l = self(v) vector_list_by_length[l].append(v) vector_list_by_length[l].append(vector([-x for x in v])) ## Make a matrix from the column vectors (in order of ascending length). sorted_list = [] for i in range(len(vector_list_by_length)): for v in vector_list_by_length[i]: sorted_list.append(v) sorted_matrix = Matrix(sorted_list).transpose() ## Determine a basis of vectors of minimal length pivots = sorted_matrix.pivots() basis = tuple(sorted_matrix.column(i) for i in pivots) for v in basis: v.set_immutable() ## Return the appropriate result if show_lengths: pivot_lengths = tuple(self(v) for v in basis) return basis, pivot_lengths else: return basis