def full_cheb_approximate(f, a, b, deg, tol=1.e-8): """Gives the full chebyshev approximation and checks if it's good enough. Called recursively. Parameters ---------- f : function The function we approximate. a : numpy array The lower bound on the interval. b : numpy array The upper bound on the interval. deg : int The degree to approximate with. tol : float How small the high degree terms must be to consider the approximation accurate. Returns ------- coeff : numpy array The coefficient array of the interpolation. If it can't get a good approximation and needs to subdivide, returns None. """ dim = len(a) degs = np.array([deg] * dim) coeff = interval_approximate_nd(f, a, b, degs) coeff2 = interval_approximate_nd(f, a, b, degs * 2) coeff2[slice_top(coeff)] -= coeff clean_zeros_from_matrix(coeff2, 1.e-16) if np.sum(np.abs(coeff2)) > tol: return None else: return coeff
def _mon_mult1(initial_matrix, idx, dim_mult): """ Executes monomial multiplication in one dimension. Parameters ---------- initial_matrix : array_like Matrix of coefficients that represent a Chebyshev polynomial. idx : tuple of ints The index of a monomial of one variable to multiply by initial_matrix. dim_mult : int The location of the non-zero value in idx. Returns ------- ndarray Coeff that are the result of the one dimensial monomial multiplication. """ p1 = np.zeros(initial_matrix.shape + idx) p1[slice_bottom(initial_matrix)] = initial_matrix largest_idx = [i - 1 for i in initial_matrix.shape] new_shape = [ max(i, j) for i, j in itertools.zip_longest(largest_idx, idx, fillvalue=0) ] #finds the largest length in each dimmension if initial_matrix.shape[dim_mult] <= idx[dim_mult]: add_a = [ i - j for i, j in itertools.zip_longest( new_shape, largest_idx, fillvalue=0) ] add_a_list = np.zeros((len(new_shape), 2)) #changes the second column to the values of add_a and add_b. add_a_list[:, 1] = add_a #uses add_a_list and add_b_list to pad each polynomial appropriately. initial_matrix = np.pad(initial_matrix, add_a_list.astype(int), 'constant') number_of_dim = initial_matrix.ndim shape_of_self = initial_matrix.shape #Loop iterates through each dimension of the polynomial and folds in that dimension for i in range(number_of_dim): if idx[i] != 0: initial_matrix = MultiCheb._fold_in_i_dir( initial_matrix, number_of_dim, i, shape_of_self[i], idx[i]) if p1.shape != initial_matrix.shape: idx = [i - j for i, j in zip(p1.shape, initial_matrix.shape)] result = np.zeros(np.array(initial_matrix.shape) + idx) result[slice_top(initial_matrix)] = initial_matrix initial_matrix = result Pf = p1 + initial_matrix return .5 * Pf
def create_matrix(matrix_polys, matrix_terms=None): ''' Builds a Macaulay matrix. If there is only one term in the matrix it won't work. Parameters ---------- matrix_polys : list. Contains numpy arrays that hold the polynomials to be put in the matrix. matrix_terms : ndarray The terms that will exist in the matrix. Not sorted yet. Defaults to None, in which case it will be found in the function. Returns ------- matrix : ndarray The Macaulay matrix. ''' bigShape = np.maximum.reduce([p.coeff.shape for p in matrix_polys]) if matrix_terms is None: #Finds the matrix terms. non_zeroSet = set() for poly in matrix_polys: for term in zip(*np.where(poly.coeff != 0)): non_zeroSet.add(term) matrix_terms = np.array(non_zeroSet.pop()) for term in non_zeroSet: matrix_terms = np.vstack((matrix_terms, term)) matrix_terms = sort_matrix_terms(matrix_terms) #Get the slices needed to pull the matrix_terms from the coeff matrix. matrix_term_indexes = list() for i in range(len(bigShape)): matrix_term_indexes.append(matrix_terms.T[i]) #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 poly in matrix_polys: coeff = poly.coeff slices = slice_top(coeff) added_zeros[slices] = coeff flat_polys.append(added_zeros[matrix_term_indexes]) added_zeros[slices] = np.zeros_like(coeff) #Make the matrix matrix = np.vstack(flat_polys[::-1]) #Sorts the rows of the matrix so it is close to upper triangular. matrix = utils.row_swap_matrix(matrix) return matrix, matrix_terms
def create_matrix(poly_coeffs, degree, dim): ''' Builds a Telen Van Barel 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 TVB Matrix dim : int The dimension of the polynomials going into the matrix. Returns ------- matrix : 2D numpy array The Telen Van Barel 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 = sorted_matrix_terms(degree, dim) #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[matrix_term_indexes]) added_zeros[slices] = np.zeros_like(coeff) coeff = 0 poly_coeffs = 0 #Make the matrix. Reshape is faster than stacking. matrix = np.reshape(flat_polys, (len(flat_polys),len(matrix_terms))) #if cuts[0] > matrix.shape[0]: #The matrix isn't tall enough, these can't all be pivot columns. # raise TVBError("HIGHEST NOT FULL RANK. TRY HIGHER DEGREE") #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, 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 TVB 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. Returns ------- matrix : 2D numpy array The Telen Van Barel 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, degree) #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[matrix_term_indexes]) added_zeros[slices] = np.zeros_like(coeff) coeff = 0 poly_coeffs = 0 #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): ''' Builds a Macaulay matrix. Parameters ---------- poly_coeffs : list Contains numpy arrays that hold the coefficients of the polynomials to be put in the matrix. Returns ------- matrix : (M,N) ndarray The Macaulay matrix. ''' bigShape = np.maximum.reduce([p.shape for p in poly_coeffs]) #Finds the matrix terms. non_zeroSet = set() for coeff in poly_coeffs: for term in zip(*np.where(coeff != 0)): non_zeroSet.add(term) matrix_terms = np.array(non_zeroSet.pop()) for term in non_zeroSet: matrix_terms = np.vstack((matrix_terms, term)) matrix_terms = sort_matrix_terms(matrix_terms) #Get the slices needed to pull the matrix_terms from the coeff matrix. matrix_term_indexes = list() for i in range(len(bigShape)): matrix_term_indexes.append(matrix_terms.T[i]) #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[matrix_term_indexes]) added_zeros[slices] = np.zeros_like(coeff) coeff = 0 poly_coeffs = 0 #Make the matrix matrix = np.vstack(flat_polys[::-1]) flat_polys = 0 #Sorts the rows of the matrix so it is close to upper triangular. matrix = utils.row_swap_matrix(matrix) return matrix, matrix_terms
def construction(polys, degree, dim): ''' Builds a Telen Van Barel matrix using fast construction in the Chebyshev basis. Parameters ---------- polys : list. Contains numpy arrays that hold the coefficients of the polynomials to be put in the matrix. degree : int The degree of the TVB Matrix dim : int The dimension of the polynomials going into the matrix. Returns ------- matrix : 2D numpy array The Telen Van Barel 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 = sorted_matrix_terms(degree, dim) #print(matrix_shape_stuff) matrix_term_indexes = list() for row in matrix_terms.T: matrix_term_indexes.append(row) permutations = all_permutations_cheb(degree - np.min([poly.degree for poly in polys]), dim, degree) #print(permutations) added_zeros = np.zeros(bigShape) flat_polys = list() i = 0; for poly in polys: slices = slice_top(poly.coeff) added_zeros[slices] = poly.coeff array = added_zeros[matrix_term_indexes] added_zeros[slices] = np.zeros_like(poly.coeff) #print(array) #flat_polys.append(array[np.vstack(permutations.values())]) degreeNeeded = degree - poly.degree mons = mons_ordered(dim,degreeNeeded) mons = np.pad(mons, (0,1), 'constant', constant_values = i) i += 1 flat_polys.append(array) for mon in mons[1:-1]: result = np.copy(array) for i in range(dim): if mon[i] != 0: mult = [0]*dim mult[i] = mon[i] result = np.sum(result[permutations[tuple(mult)]], axis = 0) flat_polys.append(result) #print(flat_polys) matrix = np.vstack(flat_polys) if matrix_shape_stuff[0] > matrix.shape[0]: #The matrix isn't tall enough, these can't all be pivot columns. raise TVBError("HIGHEST NOT FULL RANK. TRY HIGHER DEGREE") matrix = row_swap_matrix(matrix) #print(matrix) return matrix, matrix_terms, cuts
def createMatrixFast(polys, degree, dim): ''' Builds a Telen Van Barel matrix using fast construction. 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 TVB Matrix dim : int The dimension of the polynomials going into the matrix. Returns ------- matrix : 2D numpy array The Telen Van Barel 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 = sorted_matrix_terms(degree, dim) columns = len(matrix_terms) range_split = [num_mons_full(degree-poly.degree,dim) for poly in polys] rows = np.sum(range_split) ranges = get_ranges(range_split) #How to slice the poly into the matrix rows. matrix = np.zeros((rows,columns)) curr = 0 #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) permutations = None currentDegree = 2 #Adds the poly_coeffs to flat_polys, using added_zeros to make sure every term is in there. added_zeros = np.zeros(bigShape) for poly,matrix_range in zip(polys,ranges): slices = slice_top(poly.coeff) added_zeros[slices] = poly.coeff array = added_zeros[matrix_term_indexes] added_zeros[slices] = np.zeros_like(poly.coeff) permutations = memoized_all_permutations(degree - poly.degree, dim, degree, permutations, currentDegree) currentDegree = degree - poly.degree permList = list(permutations.values()) temp = array[np.reshape(permList, (len(permList), columns))[::-1]] matrix[matrix_range] = temp if matrix_shape_stuff[0] > matrix.shape[0]: #The matrix isn't tall enough, these can't all be pivot columns. raise TVBError("HIGHEST NOT FULL RANK. TRY HIGHER DEGREE") #Sorts the rows of the matrix so it is close to upper triangular. if not checkEqual([poly.degree for poly in polys]): #Will need some switching possibly if some degrees are different. matrix = row_swap_matrix(matrix) return matrix, matrix_terms, cuts
def create_matrix(poly_coeffs, degree, dim, divisor_var, get_divvar_coord_from_eigval=False): ''' 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. get_divvar_coord_from_eigval: bool Whether the divisor_var-coordinate of the roots is calculated from the eigenvalue or eigenvector. More stable to use the eigenvector. Defaults to false 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 #If you get_divvar_coord_from_eigval, then you should not include_divvar_squared in the basis, and vice versa include_divvar_squared = not get_divvar_coord_from_eigval matrix_terms, cuts = get_matrix_terms(poly_coeffs, dim, divisor_var, degree, include_divvar_squared) #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[matrix_term_indexes]) added_zeros[slices] = np.zeros_like(coeff) coeff = 0 poly_coeffs = 0 #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