def create_matrix(poly_coeffs, degree, dim, divisor_var): ''' Builds a Macaulay matrix for reduction. Parameters ---------- poly_coeffs : list. Contains numpy arrays that hold the coefficients of the polynomials to be put in the matrix. degree : int The degree of the Macaulay Matrix dim : int The dimension of the polynomials going into the matrix. divisor_var : int What variable is being divided by. 0 is x, 1 is y, etc. Defaults to x. Returns ------- matrix : 2D numpy array The Macaulay matrix. matrix_terms : numpy array The ith row is the term represented by the ith column of the matrix. cuts : tuple When the matrix is reduced it is split into 3 parts with restricted pivoting. These numbers indicate where those cuts happen. ''' bigShape = [degree + 1] * dim matrix_terms, cuts = get_matrix_terms(poly_coeffs, dim, divisor_var) #Get the slices needed to pull the matrix_terms from the coeff matrix. matrix_term_indexes = list() for row in matrix_terms.T: matrix_term_indexes.append(row) #Adds the poly_coeffs to flat_polys, using added_zeros to make sure every term is in there. added_zeros = np.zeros(bigShape) flat_polys = list() for coeff in poly_coeffs: slices = slice_top(coeff) added_zeros[slices] = coeff flat_polys.append(added_zeros[tuple(matrix_term_indexes)]) added_zeros[slices] = np.zeros_like(coeff) del poly_coeffs #Make the matrix. Reshape is faster than stacking. matrix = np.reshape(flat_polys, (len(flat_polys), len(matrix_terms))) #Sorts the rows of the matrix so it is close to upper triangular. matrix = row_swap_matrix(matrix) return matrix, matrix_terms, cuts
def create_matrix(poly_coeffs, degree, dim, varsToRemove): ''' Builds a Macaulay matrix. Parameters ---------- poly_coeffs : list. Contains numpy arrays that hold the coefficients of the polynomials to be put in the matrix. degree : int The degree of the Macaulay Matrix dim : int The dimension of the polynomials going into the matrix. varsToRemove : list The variables to remove from the basis because we have linear polysnomials Returns ------- matrix : 2D numpy array The Macaulay matrix. matrix_terms : numpy array The ith row is the term represented by the ith column of the matrix. cut : int Number of monomials of highest degree ''' bigShape = [degree + 1] * dim matrix_terms, cut = sorted_matrix_terms(degree, dim, varsToRemove) #Get the slices needed to pull the matrix_terms from the coeff matrix. matrix_term_indexes = list() for row in matrix_terms.T: matrix_term_indexes.append(row) #Adds the poly_coeffs to flat_polys, using added_zeros to make sure every term is in there. added_zeros = np.zeros(bigShape) flat_polys = list() for coeff in poly_coeffs: slices = slice_top(coeff) added_zeros[slices] = coeff flat_polys.append(added_zeros[tuple(matrix_term_indexes)]) added_zeros[slices] = np.zeros_like(coeff) del poly_coeffs #Make the matrix. Reshape is faster than stacking. matrix = np.reshape(flat_polys, (len(flat_polys), len(matrix_terms))) #Sorts the rows of the matrix so it is close to upper triangular. matrix = row_swap_matrix(matrix) return matrix, matrix_terms, cut
def rrqr_reduceMacaulay(matrix, matrix_terms, cuts, max_cond_num, macaulay_zero_tol, return_perm=False): ''' Reduces a Macaulay matrix, BYU style. The matrix is split into the shape A B C D E F Where A is square and contains all the highest terms, and C contains all the x,y,z etc. terms. The lengths are determined by the matrix_shape_stuff tuple. First A and D are reduced using rrqr without pivoting, and then the rest of the matrix is multiplied by Q.T to change it accordingly. Then E is reduced by rrqr with pivoting, the rows of B are shifted accordingly, and F is multipled by Q.T to change it accordingly. This is all done in place to save memory. Parameters ---------- matrix : numpy array. The Macaulay matrix, sorted in BYU style. matrix_terms: numpy array Each row of the array contains a term in the matrix. The i'th row corresponds to the i'th column in the matrix. cuts : tuple When the matrix is reduced it is split into 3 parts with restricted pivoting. These numbers indicate where those cuts happen. max_cond_num : float Throws an error if the condition number of the backsolve is more than max_cond_num. macaulay_zero_tol : float What is considered to be 0 after the reduction. Specifically, rows where every element has magnitude less that macaulay_zero_tol are removed. return_perm : bool If True, also returns the permutation done by the pivoting. Returns ------- matrix : numpy array The reduced matrix. matrix_terms: numpy array The resorted matrix_terms. perm : numpy array The permutation of the rows from the original. Returned only if return_perm is True. Raises ------ ConditioningError if the conditioning number of the Macaulay matrix after QR is greater than max_cond_num. ''' #controller variables for each part of the matrix AD = matrix[:, :cuts[0]] BCEF = matrix[:, cuts[0]:] # A = matrix[:cuts[0],:cuts[0]] B = matrix[:cuts[0], cuts[0]:cuts[1]] # C = matrix[:cuts[0],cuts[1]:] # D = matrix[cuts[0]:,:cuts[0]] E = matrix[cuts[0]:, cuts[0]:cuts[1]] F = matrix[cuts[0]:, cuts[1]:] #RRQR reduces A and D without pivoting sticking the result in its place. Q1, matrix[:, :cuts[0]] = qr(AD) #Conditioning check cond_num = np.linalg.cond(matrix[:, :cuts[0]]) if cond_num > max_cond_num: raise ConditioningError("Conditioning number of the Macaulay matrix "\ + "after first QR is: " + str(cond_num)) #Multiplying BCEF by Q.T BCEF[...] = Q1.T @ BCEF del Q1 #Get rid of Q1 for memory purposes. #Check to see if E exists if cuts[0] != cuts[1] and cuts[0] < matrix.shape[0]: #RRQR reduces E sticking the result in it's place. Q, E[...], P = qr(E, pivoting=True) #Multiplies F by Q.T. F[...] = Q.T @ F del Q #Get rid of Q for memory purposes. #Permute the columns of B B[...] = B[:, P] #Resorts the matrix_terms. matrix_terms[cuts[0]:cuts[1]] = matrix_terms[cuts[0]:cuts[1]][P] #use the numerical rank to determine how many rows to keep matrix = row_swap_matrix(matrix)[:cuts[1]] s = svd(matrix, compute_uv=False) tol = max(matrix.shape) * s[0] * macheps rank = len(s[s > tol]) matrix = matrix[:rank] #find the condition number of the backsolve s = svd(matrix[:, :rank], compute_uv=False) cond_num = s[0] / s[-1] if cond_num > max_cond_num: raise ConditioningError( "Conditioning number of backsolving the Macaulay is: " + str(cond_num)) #backsolve height = matrix.shape[0] matrix[:, height:] = solve_triangular(matrix[:, :height], matrix[:, height:]) matrix[:, :height] = np.eye(height) if return_perm: perm = np.arange(matrix.shape[1]) perm[cuts[0]:cuts[1]] = perm[cuts[0]:cuts[1]][P] return matrix, matrix_terms, perm return matrix, matrix_terms