def rrqr_reduceMacaulayFullRank(matrix, matrix_terms, cuts, accuracy=1.e-10): ''' Reduces a Macaulay matrix, BYU style. This function does the same thing as rrqr_reduceMacaulay2 but only works if the matrix is full rank AND if the top left corner (the square of side length cut[0]) is invertible. In this case it is faster. 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. accuracy : float What is determined to be 0. Returns ------- matrix : numpy array The reduced matrix. matrix_terms: numpy array The resorted matrix_terms. ''' C1,matrix[:cuts[0],:cuts[0]] = qr_multiply(matrix[:cuts[0],:cuts[0]],\ matrix[:cuts[0],cuts[0]:].T, mode = 'right') matrix[:cuts[0], cuts[0]:] = C1.T C1 = 0 #check if there are zeros along the diagonal of R1 if any(np.isclose(np.diag(matrix[:, :cuts[0]]), 0, atol=accuracy)): raise MacaulayError("R1 IS NOT FULL RANK") #if abs(matrix[:,:cuts[0]].diagonal()[-1]) < accuracy: # raise MacaulayError("HIGHEST NOT FULL RANK") C,matrix[cuts[0]:,cuts[0]:cuts[1]],P = qr_multiply(matrix[cuts[0]:,cuts[0]:cuts[1]],\ matrix[cuts[0]:,cuts[1]:].T, mode = 'right', pivoting = True) matrix[cuts[0]:, cuts[1]:] = C.T C = 0 #Shifts the columns of B. matrix[:cuts[0], cuts[0]:cuts[1]] = matrix[:cuts[0], cuts[0]:cuts[1]][:, P] matrix_terms[cuts[0]:cuts[1]] = matrix_terms[cuts[0]:cuts[1]][P] P = 0 return matrix, matrix_terms
def rrqr_reduceTelenVanBarelFullRank(matrix, matrix_terms, cuts, accuracy = 1.e-10): ''' Reduces a Telen Van Barel Macaulay matrix. This function does the same thing as rrqr_reduceTelenVanBarel2 but only works if the matrix is full rank. In this case it is faster. Parameters ---------- matrix : numpy array. The Macaulay matrix, sorted in TVB 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. accuracy : float What is determined to be 0. Returns ------- matrix : numpy array The reduced matrix. matrix_terms: numpy array The resorted matrix_terms. ''' C1,matrix[:cuts[0],:cuts[0]],P1 = qr_multiply(matrix[:cuts[0],:cuts[0]],\ matrix[:cuts[0],cuts[0]:].T, mode = 'right', pivoting = True) matrix[:cuts[0],cuts[0]:] = C1.T C1 = 0 #if abs(matrix[:,:cuts[0]].diagonal()[-1]) < accuracy: # raise TVBError("HIGHEST NOT FULL RANK") matrix_terms[:cuts[0]] = matrix_terms[:cuts[0]][P1] P1 = 0 C,matrix[cuts[0]:,cuts[0]:cuts[1]],P = qr_multiply(matrix[cuts[0]:,cuts[0]:cuts[1]],\ matrix[cuts[0]:,cuts[1]:].T, mode = 'right', pivoting = True) matrix[cuts[0]:,cuts[1]:] = C.T C,R = 0,0 #Shifts the columns of B. matrix[:cuts[0],cuts[0]:cuts[1]] = matrix[:cuts[0],cuts[0]:cuts[1]][:,P] matrix_terms[cuts[0]:cuts[1]] = matrix_terms[cuts[0]:cuts[1]][P] P = 0 return matrix, matrix_terms
def solve_mat(A, b_mat, method='ridge'): """ Returns the solution for the least squares problem |Ax - b_i|^2. """ if method == 'fast': #return linalg.solve(A.T.dot(A), A.T.dot(b_mat), sym_pos=True) return direct_solve(A.T.dot(A), A.T.dot(b_mat)) elif method == 'ridge': X = np.dot(A.T, A) X.flat[::A.shape[1] + 1] += alpha Xy = np.dot(A.T, b_mat) #return linalg.solve(X, Xy, sym_pos=True, overwrite_a=True) return direct_solve(X, Xy) elif method == 'qr': cq, r = linalg.qr_multiply(A, b_mat) return linalg.solve_triangular(r, cq) elif method == 'cho': c, l = linalg.cho_factor(A.T.dot(A)) return linalg.cho_solve((c, l), A.T.dot(b_mat)) elif method == 'lstsq': return np.linalg.lstsq(A, b_mat)[0] elif method == 'lasso': import sklearn.linear_model as lm s = lm.Lasso(fit_intercept=False) s.alpha = alpha s.fit(A, b_mat) return s.coef_.T elif method == 'enet': import sklearn.linear_model as lm s = lm.ElasticNet(fit_intercept=False, l1_ratio=0.2) s.alpha = alpha s.fit(A, b_mat) return s.coef_.T else: raise ValueError('Unknow lsq method, use ridge, qr, fast or lasso')
def solve_mat(A, b_mat, method='ridge'): """ Returns the solution for the least squares problem |Ax - b_i|^2. """ if method == 'fast': #return linalg.solve(A.T.dot(A), A.T.dot(b_mat), sym_pos=True) return direct_solve(A.T.dot(A), A.T.dot(b_mat)) elif method == 'ridge': X = np.dot(A.T, A) X.flat[::A.shape[1] + 1] += alpha Xy = np.dot(A.T, b_mat) #return linalg.solve(X, Xy, sym_pos=True, overwrite_a=True) return direct_solve(X, Xy) elif method == 'qr': cq, r = linalg.qr_multiply(A, b_mat) return linalg.solve_triangular(r, cq) elif method == 'cho': c, l = linalg.cho_factor( A.T.dot(A)) return linalg.cho_solve((c, l), A.T.dot(b_mat)) elif method == 'lstsq': return np.linalg.lstsq(A, b_mat)[0] elif method == 'lasso': import sklearn.linear_model as lm s = lm.Lasso(fit_intercept=False) s.alpha = alpha s.fit(A, b_mat) return s.coef_.T elif method == 'enet': import sklearn.linear_model as lm s = lm.ElasticNet(fit_intercept=False, l1_ratio=0.2) s.alpha = alpha s.fit(A, b_mat) return s.coef_.T else: raise ValueError('Unknow lsq method, use ridge, qr, fast or lasso')
def rrqr_reduceTelenVanBarel2(matrix, matrix_terms, cuts, accuracy = 1.e-10): ''' Reduces a Telen Van Barel Macaulay matrix. This function does the same thing as rrqr_reduceTelenVanBarel but uses qr_multiply instead of qr and a multiplication to make the function faster and more memory efficient. Parameters ---------- matrix : numpy array. The Macaulay matrix, sorted in TVB 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. accuracy : float What is determined to be 0. Returns ------- matrix : numpy array The reduced matrix. matrix_terms: numpy array The resorted matrix_terms. ''' C1,matrix[:cuts[0],:cuts[0]],P1 = qr_multiply(matrix[:,:cuts[0]], matrix[:,cuts[0]:].T, mode = 'right', pivoting = True) matrix[:cuts[0],cuts[0]:] = C1.T C1 = 0 if abs(matrix[:,:cuts[0]].diagonal()[-1]) < accuracy: raise TVBError("HIGHEST NOT FULL RANK") matrix[:cuts[0],cuts[0]:] = solve_triangular(matrix[:cuts[0],:cuts[0]],matrix[:cuts[0],cuts[0]:]) matrix[:cuts[0],:cuts[0]] = np.eye(cuts[0]) matrix[cuts[0]:,cuts[0]:] -= (matrix[cuts[0]:,:cuts[0]][:,P1])@matrix[:cuts[0],cuts[0]:] matrix_terms[:cuts[0]] = matrix_terms[:cuts[0]][P1] P1 = 0 C,R,P = qr_multiply(matrix[cuts[0]:,cuts[0]:cuts[1]], matrix[cuts[0]:,cuts[1]:].T, mode = 'right', pivoting = True) matrix = matrix[:R.shape[0]+cuts[0]] matrix[cuts[0]:,:cuts[0]] = np.zeros_like(matrix[cuts[0]:,:cuts[0]]) matrix[cuts[0]:,cuts[0]:cuts[0]+R.shape[1]] = R matrix[cuts[0]:,cuts[0]+R.shape[1]:] = C.T C,R = 0,0 #Shifts the columns of B. matrix[:cuts[0],cuts[0]:cuts[1]] = matrix[:cuts[0],cuts[0]:cuts[1]][:,P] matrix_terms[cuts[0]:cuts[1]] = matrix_terms[cuts[0]:cuts[1]][P] P = 0 # Check if there are no solutions rank = np.sum(np.abs(matrix.diagonal())>accuracy) # extra_block = matrix[rank:, -matrix_shape_stuff[2]:] # Q,R = qr(extra_block) # if np.sum(np.abs(R.diagonal())>accuracy) == matrix_shape_stuff[2]: # raise ValueError("The system given has no roots.") #Get rid of 0 rows at the bottom. matrix = matrix[:rank] return matrix, matrix_terms
def get_interpolation_matrices_residual_model( history, x_accepted, model_indices, delta, c2, theta2, n_maxinterp, n_modelpoints, ): """Obtain matrices that will be used for interpolating the residual model. Args: history (class): Class storing history of xs, residuals, and critvals. x_accepted (np.ndarray): Accepted solution vector of the subproblem. Shape (n,). model_indices (np.ndarray): Indices of the candidates of x that are currently in the model. Shape (2 * n + 1,). delta (float): Delta, current trust-region radius. c2 (int): Threshold for acceptance of the norm of our current x candidate. Equal to 10 by default. theta2 (float): Threshold for adding the current x candidate to the model. n_maxinterp (int): Maximum number of interpolation points. n_modelpoints (int): Current number of model points. Returns: Tuple: - x_sample_monomial_basis (np.ndarray): Sample of xs used for building the monomial basis. When taken together, they form a basis for the linear space of quadratics in n variables. Shape(n_maxinterp, n * (n + 1) / 2). - monomial_basis (np.ndarray): Monomial basis for quadratic functions of x. Shape(n_maxinterp, n * (n + 1) / 2). - basis_null_space (np.ndarray): Basis for the null space of xs that form the monomial basis. Shape(n_maxinterp, len(n + 1 : n_modelpoints)). - lower_triangular (np.ndarray): Lower triangular matrix of xs that form the monomial basis. Shape(n_maxinterp, n * (n + 1) / 2). - n_modelpoints (int): Current number of model points. """ n = x_accepted.shape[0] x_sample_monomial_basis = np.zeros((n_maxinterp, n + 1)) x_sample_monomial_basis[:, 0] = 1 monomial_basis = np.zeros((n_maxinterp, int(n * (n + 1) / 2))) center_info = {"x": x_accepted, "radius": delta} for i in range(n + 1): x_sample_monomial_basis[i, 1:] = history.get_centered_xs( center_info, index=model_indices[i]) monomial_basis[i, :] = _get_monomial_basis(x_sample_monomial_basis[i, 1:]) # Now we add points until we have n_maxinterp starting with the most recent ones point = history.get_n_fun() - 1 n_modelpoints = n + 1 while (n_modelpoints < n_maxinterp) and (point >= 0): reject = False # Reject any points already in the model for i in range(n + 1): if point == model_indices[i]: reject = True break if reject is False: candidate_x = history.get_centered_xs(center_info, index=point) candidate_norm = np.linalg.norm(candidate_x) if candidate_norm > c2: reject = True if reject is True: point -= 1 continue x_sample_monomial_basis[n_modelpoints, 1:] = history.get_centered_xs(center_info, index=point) monomial_basis[n_modelpoints, :] = _get_monomial_basis( x_sample_monomial_basis[n_modelpoints, 1:]) x_sample_full_with_zeros = np.zeros((n_maxinterp, n_maxinterp)) x_sample_full_with_zeros[:n_maxinterp, :n + 1] = x_sample_monomial_basis lower_triangular_temporary, _ = qr_multiply( x_sample_full_with_zeros[:n_modelpoints + 1, :], monomial_basis.T[:int(n * (n + 1) / 2), :n_modelpoints + 1], ) beta = np.linalg.svd(lower_triangular_temporary.T[n + 1:], compute_uv=False) if beta[min(n_modelpoints - n, int(n * (n + 1) / 2)) - 1] > theta2: # Accept point model_indices[n_modelpoints] = point lower_triangular = lower_triangular_temporary n_modelpoints += 1 point -= 1 # Orthogonal basis for the null space of M, where M is the # sample of xs forming the monomial basis basis_null_space, _ = qr_multiply( x_sample_full_with_zeros[:n_modelpoints, :], np.eye(n_maxinterp)[:, :n_modelpoints], ) basis_null_space = basis_null_space[:, n + 1:n_modelpoints] if n_modelpoints == (n + 1): lower_triangular = np.zeros((n_maxinterp, int(n * (n + 1) / 2))) lower_triangular[:n, :n] = np.eye(n) return ( x_sample_monomial_basis, monomial_basis, basis_null_space, lower_triangular, n_modelpoints, )
def add_points_to_make_main_model_fully_linear( history, main_model, model_improving_points, model_indices, x_accepted, n_modelpoints, delta, criterion, lower_bounds, upper_bounds, batch_evaluator, n_cores, ): """Add points until main model is fully linear. Args: history (class): Class storing history of xs, residuals, and critvals. main_model (dict): Dictionary containing the parameters of the main model, i.e. "linear_terms" and "square terms". model_improving_points (np.ndarray): Array of shape (n, n) including points to improve the main model. model_indices (np.ndarray): Indices of the candidates of x that are currently in the main model. Shape (2 * n + 1,). x_accepted (np.ndarray): Accepted solution vector of the subproblem. Shape (n,). n_modelpoints (int): Current number of model points. delta (float): Delta, current trust-region radius. criterion (callable): Criterion function. lower_bounds (np.ndarray): Lower bounds. Must have same length as the initial guess of the parameter vector. Equal to -1 if not provided by the user. upper_bounds (np.ndarray): Upper bounds. Must have same length as the initial guess of the parameter vector. Equal to 1 if not provided by the user. batch_evaluator (str or callable): Name of a pre-implemented batch evaluator (currently 'joblib' and 'pathos_mp') or Callable with the same interface as the estimagic batch_evaluators. n_cores (int): Number of processes used to parallelize the function evaluations. Returns: Tuple: - history (class): Class storing history of xs, residuals, and critvals. - model_indices (np.ndarray): Indices of the candidates of x that are currently in the main model. Shape (2 * n + 1,). """ n = x_accepted.shape[0] current_history = history.get_n_fun() linear_terms = main_model["linear_terms"] x_candidate = np.zeros(n) x_candidates_list = [] criterion_candidates_list = [] model_improving_points, _ = qr_multiply(model_improving_points, np.eye(3)) for i in range(n_modelpoints, n): change_direction = np.dot(model_improving_points[:, i], linear_terms) if change_direction > 0: model_improving_points[:, i] *= -1 x_candidate = delta * model_improving_points[:, i] + x_accepted # Project into feasible region if lower_bounds is not None and upper_bounds is not None: x_candidate = np.median(np.stack( [lower_bounds, x_candidate, upper_bounds]), axis=0) x_candidates_list.append(x_candidate) model_indices[i] = current_history + i - n_modelpoints criterion_candidates_list = batch_evaluator(criterion, arguments=x_candidates_list, n_cores=n_cores) history.add_entries(x_candidates_list, criterion_candidates_list) return history, model_indices
def find_affine_points( history, x_accepted, model_improving_points, project_x_onto_null, delta, theta1, c, model_indices, n_modelpoints, ): """Find affine points. Args: history (class): Class storing history of xs, residuals, and critvals. x_accepted (np.ndarray): Accepted solution vector of the subproblem. Shape (n,). model_improving_points (np.ndarray): Array of shape (n, n) including points to improve the main model, i.e. make the main model fully linear. If *project_x_onto_null* is False, it is an array filled with zeros. project_x_onto_null (int): Indicator whether to calculate the QR decomposition of *model_improving_points* and multiply it with vector *x_projected*. delta (float): Delta, current trust-region radius. theta1 (float): Threshold for adding the current x candidate to the model. c (float): Threshold for acceptance of the norm of our current x candidate. model_indices (np.ndarray): Indices related to the candidates of x that are currently in the main model. Shape (2 *n* + 1,). n_modelpoints (int): Current number of model points. Returns: Tuple: - model_improving_points (np.ndarray): Array of shape (n, n) including points to improve the main model, i.e. make the main model fully linear. - model_indices (np.ndarray): Indices related to the candidates of x that are currently in the main model. Shape (2 *n* + 1,). - n_modelpoints (int): Current number of model points. - project_x_onto_null (int): Indicator whether to calculate the QR decomposition of *model_improving_points* and multiply it with vector *x_projected*. Relevant for next call of *find_affine_points()*. """ n = x_accepted.shape[0] for i in range(history.get_n_fun() - 1, -1, -1): center_info = {"x": x_accepted, "radius": delta} x_candidate = history.get_centered_xs(center_info, index=i) candidate_norm = np.linalg.norm(x_candidate) x_projected = x_candidate if candidate_norm <= c: if project_x_onto_null is True: x_projected, _ = qr_multiply(model_improving_points, x_projected) proj = np.linalg.norm(x_projected[n_modelpoints:]) # Add this index to the model if proj >= theta1: model_indices[n_modelpoints] = i model_improving_points[:, n_modelpoints] = x_candidate project_x_onto_null = True n_modelpoints += 1 if n_modelpoints == n: break return model_improving_points, model_indices, n_modelpoints, project_x_onto_null
def TVB_MacaulayReduction(initial_poly_list, accuracy = 1.e-10, verbose=False): ''' Reduces the Macaulay matrix to find a vector basis for the system of polynomials. Parameters -------- polys: list The polynomials in the system we are solving. accuracy: float How small we want a number to be before assuming it is zero. Returns ----------- basisDict : dict A dictionary of terms not in the vector basis a matrixes of things in the vector basis that the term can be reduced to. VB : nparray The terms in the vector basis, each list being a term. ''' power = is_power(initial_poly_list) dim = initial_poly_list[0].dim poly_coeff_list = [] degree = find_degree(initial_poly_list) initial_poly_list = sort_polys_by_degree(initial_poly_list, ascending = False) for poly in initial_poly_list: poly_coeff_list = add_polys(degree, poly, poly_coeff_list) #Creates the matrix for either of the above two methods. Comment out if using the third method. matrix, matrix_terms, cuts = create_matrix(poly_coeff_list, degree, dim) if verbose: np.set_printoptions(suppress=False, linewidth=200) print('\nStarting Macaulay Matrix\n', matrix) print('\nColumns in Macaulay Matrix\nFirst element in tuple is degree of x monomial, Second element is degree of y monomial\n', matrix_terms) print('\nLocation of Cuts in the Macaulay Matrix into [ Mb | M1* | M2* ]\n', cuts) #First QR reduction #If bottom left is zero only does the first QR reduction on top part of matrix (for speed). Otherwise does it on the whole thing if np.allclose(matrix[cuts[0]:,:cuts[0]], 0): #RRQR reduces A and D without pivoting, sticking the result in it's place and multiplying the rest of the matrix by Q.T C1,matrix[:cuts[0],:cuts[0]] = qr_multiply(matrix[:,:cuts[0]], matrix[:,cuts[0]:].T, mode = 'right') matrix[:cuts[0],cuts[0]:] = C1.T C1 = 0 #check if there are zeros along the diagonal of R1 if any(np.isclose(np.diag(matrix[:,:cuts[0]]),0, rtol=accuracy)): raise MacaulayError("R1 IS NOT FULL RANK") #set small values to zero before backsolving matrix[np.isclose(matrix, 0, rtol=accuracy)] = 0 matrix[:cuts[0],cuts[0]:] = solve_triangular(matrix[:cuts[0],:cuts[0]],matrix[:cuts[0],cuts[0]:]) matrix[:cuts[0],:cuts[0]] = np.eye(cuts[0]) matrix[cuts[0]:,cuts[0]:] -= (matrix[cuts[0]:,:cuts[0]])@matrix[:cuts[0],cuts[0]:] #? else: #RRQR reduces A and D without pivoting, sticking the result in it's place. Q1,matrix[:,:cuts[0]] = qr(matrix[:,:cuts[0]]) #check if there are zeros along the diagonal of R1 if any(np.isclose(np.diag(matrix[:,:cuts[0]]),0, rtol=accuracy)): raise MacaulayError("R1 IS NOT FULL RANK") #Multiplying the rest of the matrix by Q.T matrix[:,cuts[0]:] = Q1.T@matrix[:,cuts[0]:] Q1 = 0 #Get rid of Q1 for memory purposes. #Second QR reduction on all the rest of the matrix matrix[cuts[0]:,cuts[0]:],P = qr(matrix[cuts[0]:,cuts[0]:], mode = 'r', pivoting = True) #Shift around the top right columns matrix[:cuts[0],cuts[0]:] = matrix[:cuts[0],cuts[0]:][:,P] #Shift around the columns labels matrix_terms[cuts[0]:] = matrix_terms[cuts[0]:][P] P = 0 #set small values to zero matrix[np.isclose(matrix, 0, rtol=accuracy)] = 0 #eliminate zero rows from the bottom of the matrix. Zero rows above #nonzero elements are not eliminated. This saves time since Macaulay matrices #we deal with are only zero at the very bottom #matrix = row_swap_matrix(matrix) #not for TVB's method needed bc QRP is on the whole matrix for row in matrix[::-1]: if np.allclose(row, 0): matrix = matrix[:-1] else: break height = matrix.shape[0] matrix[:,height:] = solve_triangular(matrix[:,:height],matrix[:,height:]) matrix[:,:height] = np.eye(height) #return np.vstack((matrix[:,height:].T,np.eye(height))), matrix_terms if verbose: np.set_printoptions(suppress=True, linewidth=200) print("\nFinal Macaulay Matrix\n", matrix) print("\nColumns in Macaulay Matrix\n", matrix_terms) VB = matrix_terms[height:] basisDict = makeBasisDict(matrix, matrix_terms, VB, power) return basisDict, VB
def get_feature_matrices_residual_model(history, x_accepted, model_indices, delta, c2, theta2, n_maxinterp): """Obtain the feature matrices for fitting the residual model. Pounders uses underdetermined sample sets, with at most n_maxinterp points in the model. Hence, the fitting method is interpolation, where the solution represents the quadratic whose Hessian matrix is of minimum Frobenius norm. For a mathematical exposition see :cite:`Wild2008`, p. 3-5. Args: history (LeastSquaresHistory): Class storing history of xs, residuals, and critvals. x_accepted (np.ndarray): Accepted solution vector of the subproblem. Shape (n_params,). model_indices (np.ndarray): Indices of the candidates of x that are currently in the model. Shape (2 * n_params + 1,). delta (float): Delta, current trust-region radius. c2 (int): Threshold for acceptance of the norm of our current x candidate. Equal to 10 by default. theta2 (float): Threshold for adding the current x candidate to the model. n_maxinterp (int): Maximum number of interpolation points. By default, 2 * n_params + 1 points. Returns: Tuple: - m_mat (np.ndarray): Polynomial feature matrix of the linear terms. Shape(n_params + 1, n_params + 1). - n_mat (np.ndarray): Polynomial feature matrix of the square terms. Shape(n_modelpoints, n_poly_features). - z_mat (np.ndarray): Basis for the null space of m_mat. Shape(n_modelpoints, n_modelpoints - n_params - 1). - n_z_mat (np.ndarray): Lower triangular matrix of xs that form the monomial basis. Shape(n_poly_features, n_modelpoints - n_params - 1). - n_modelpoints (int): Current number of model points. """ n_params = len(x_accepted) n_poly_features = n_params * (n_params + 1) // 2 m_mat = np.zeros((n_maxinterp, n_params + 1)) m_mat[:, 0] = 1 m_mat_pad = np.zeros((n_maxinterp, n_maxinterp)) m_mat_pad[:n_maxinterp, :n_params + 1] = m_mat n_mat = np.zeros((n_maxinterp, n_poly_features)) center_info = {"x": x_accepted, "radius": delta} for i in range(n_params + 1): m_mat[i, 1:] = history.get_centered_xs(center_info, index=model_indices[i]) n_mat[i, :] = _get_monomial_basis(m_mat[i, 1:]) point = history.get_n_fun() - 1 n_modelpoints = n_params + 1 while (n_modelpoints < n_maxinterp) and (point >= 0): reject = False # Reject any points already in the model for i in range(n_params + 1): if point == model_indices[i]: reject = True break if reject is False: candidate_x = history.get_centered_xs(center_info, index=point) candidate_norm = np.linalg.norm(candidate_x) if candidate_norm > c2: reject = True if reject is True: point -= 1 continue m_mat[n_modelpoints, 1:] = history.get_centered_xs(center_info, index=point) n_mat[n_modelpoints, :] = _get_monomial_basis(m_mat[n_modelpoints, 1:]) m_mat_pad = np.zeros((n_maxinterp, n_maxinterp)) m_mat_pad[:n_maxinterp, :n_params + 1] = m_mat _n_z_mat, _ = qr_multiply( m_mat_pad[:n_modelpoints + 1, :], n_mat.T[:n_poly_features, :n_modelpoints + 1], ) beta = np.linalg.svd(_n_z_mat.T[n_params + 1:], compute_uv=False) if beta[min(n_modelpoints - n_params, n_poly_features) - 1] > theta2: # Accept point model_indices[n_modelpoints] = point n_z_mat = _n_z_mat n_modelpoints += 1 point -= 1 z_mat, _ = qr_multiply( m_mat_pad[:n_modelpoints, :], np.eye(n_maxinterp)[:, :n_modelpoints], ) # Just-identified case if n_modelpoints == (n_params + 1): n_z_mat = np.zeros((n_maxinterp, n_poly_features)) n_z_mat[:n_params, :n_params] = np.eye(n_params) return ( m_mat[:n_params + 1, :n_params + 1], n_mat[:n_modelpoints], z_mat[:n_modelpoints, n_params + 1:n_modelpoints], n_z_mat[:, n_params + 1:n_modelpoints], n_modelpoints, )
def rrqr_reduceMacaulay2(matrix, matrix_terms, cuts, number_of_roots, accuracy=1.e-10): ''' Reduces a Macaulay matrix, BYU style This function does the same thing as rrqr_reduceMacaulay but uses qr_multiply instead of qr and a multiplication to make the function faster and more memory efficient. This function only works properly if the bottom left (D) part of the matrix is zero 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. accuracy : float What is determined to be 0. Returns ------- matrix : numpy array The reduced matrix. matrix_terms: numpy array The resorted matrix_terms. ''' #print("Starting matrix.shape:\n", matrix.shape) #RRQR reduces A and D without pivoting sticking the result in it's place. C1, matrix[:cuts[0], :cuts[0]] = qr_multiply(matrix[:, :cuts[0]], matrix[:, cuts[0]:].T, mode='right') matrix[:cuts[0], cuts[0]:] = C1.T C1 = 0 #check if there are zeros along the diagonal of R1 if any(np.isclose(np.diag(matrix[:, :cuts[0]]), 0, atol=accuracy)): raise MacaulayError("R1 IS NOT FULL RANK") #if abs(matrix[:,:cuts[0]].diagonal()[-1]) < accuracy: # raise MacaulayError("HIGHEST NOT FULL RANK") #set small values to zero before backsolving matrix[np.isclose(matrix, 0, atol=accuracy)] = 0 matrix[:cuts[0], cuts[0]:] = solve_triangular(matrix[:cuts[0], :cuts[0]], matrix[:cuts[0], cuts[0]:]) matrix[:cuts[0], :cuts[0]] = np.eye(cuts[0]) matrix[cuts[0]:, cuts[0]:] -= (matrix[cuts[0]:, :cuts[0]]) @ matrix[:cuts[0], cuts[0]:] #? C, R, P = qr_multiply(matrix[cuts[0]:, cuts[0]:cuts[1]], matrix[cuts[0]:, cuts[1]:].T, mode='right', pivoting=True) matrix = matrix[:R.shape[0] + cuts[0]] #matrix[cuts[0]:,:cuts[0]] = np.zeros_like(matrix[cuts[0]:,:cuts[0]]) matrix[cuts[0]:, cuts[0]:cuts[0] + R.shape[1]] = R matrix[cuts[0]:, cuts[0] + R.shape[1]:] = C.T C, R = 0, 0 #Shifts the columns of B. matrix[:cuts[0], cuts[0]:cuts[1]] = matrix[:cuts[0], cuts[0]:cuts[1]][:, P] matrix_terms[cuts[0]:cuts[1]] = matrix_terms[cuts[0]:cuts[1]][P] P = 0 # Check if there are no solutions #rank = np.sum(np.abs(matrix.diagonal())>accuracy) # extra_block = matrix[rank:, -matrix_shape_stuff[2]:] # Q,R = qr(extra_block) # if np.sum(np.abs(R.diagonal())>accuracy) == matrix_shape_stuff[2]: # raise ValueError("The system given has no roots.") #Get rid of 0 rows at the bottom. #matrix = matrix[:rank] #eliminates rows we don't care about-- those at the bottom of the matrix #since the top corner is a square identity matrix, always_useful_rows + number_of_roots is the width of the Macaulay matrix always_useful_rows = matrix.shape[1] - number_of_roots #matrix = matrix[:useful_rows,:] #set small values in the matrix to zero now, after the QR reduction matrix[np.isclose(matrix, 0, atol=accuracy)] = 0 #eliminate zero rows from the bottom of the matrix. Zero rows above #nonzero elements are not eliminated. This saves time since Macaulay matrices #we deal with are only zero at the very bottom matrix = row_swap_matrix(matrix) for row in matrix[::-1]: if np.allclose(row, 0): matrix = matrix[:-1] else: break return matrix, matrix_terms
def rrqr_reduce_telen_van_barel(matrix, matrix_terms, matrix_shape_stuff, accuracy=1.e-10): ''' Reduces a Macaulay matrix in the TvB way--not pivoting the highest and lowest-degree columns. This function does the same thing as rrqr_reduce_telen_van_barel but uses qr_multiply instead of qr and a multiplication to make the function faster and more memory efficient. Parameters ---------- matrix : numpy array. The Macaulay matrix, sorted in TVB 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. matrix_shape_stuff : tuple Terrible name I know. It has 3 values, the first is how many columnns are in the 'highest' part of the matrix. The second is how many are in the 'others' part of the matrix, and the third is how many are in the 'xs' part. accuracy : float What is determined to be 0. Returns ------- matrix : numpy array The reduced matrix. matrix_terms: numpy array The resorted matrix_terms. ''' highest_num = matrix_shape_stuff[0] others_num = matrix_shape_stuff[1] xs_num = matrix_shape_stuff[2] C1, matrix[:highest_num, :highest_num], P1 = qr_multiply( matrix[:, :highest_num], matrix[:, highest_num:].T, mode='right', pivoting=True) matrix[:highest_num, highest_num:] = C1.T C1 = 0 if abs(matrix[:, :highest_num].diagonal()[-1]) < accuracy: raise TVBError("HIGHEST NOT FULL RANK") matrix[:highest_num, highest_num:] = solve_triangular(matrix[:highest_num, :highest_num], matrix[:highest_num, highest_num:]) matrix[:highest_num, :highest_num] = np.eye(highest_num) matrix[highest_num:, highest_num:] -= (matrix[highest_num:, :highest_num][:, P1] ) @ matrix[:highest_num, highest_num:] matrix_terms[:highest_num] = matrix_terms[:highest_num][P1] P1 = 0 C, R, P = qr_multiply(matrix[highest_num:, highest_num:highest_num + others_num], matrix[highest_num:, highest_num + others_num:].T, mode='right', pivoting=True) matrix = matrix[:R.shape[0] + highest_num] matrix[highest_num:, :highest_num] = np.zeros_like( matrix[highest_num:, :highest_num]) matrix[highest_num:, highest_num:highest_num + R.shape[1]] = R matrix[highest_num:, highest_num + R.shape[1]:] = C.T C, R = 0, 0 #Shifts the columns of B. matrix[:highest_num, highest_num:highest_num + others_num] = matrix[:highest_num, highest_num:highest_num + others_num][:, P] matrix_terms[highest_num:highest_num + others_num] = matrix_terms[highest_num:highest_num + others_num][P] P = 0 #Get rid of 0 rows at the bottom. rank = np.sum(np.abs(matrix.diagonal()) > accuracy) matrix = matrix[:rank] return matrix, matrix_terms
def fit(self, X, y=None): """Generate random weights according to n_features. Parameters ---------- X : {array-like, sparse matrix}, shape (n_samples, n_features) Training data, where n_samples is the number of samples and n_features is the number of features. Returns ------- self : object Returns the transformer. """ random_state = check_random_state(self.random_state) X = check_array(X, accept_sparse=True) n_samples, n_features = X.shape n_stacks = int(np.ceil(self.n_components/n_features)) n_components = n_stacks * n_features if n_components != self.n_components: msg = "n_components is changed from {0} to {1}.".format( self.n_components, n_components ) msg += " You should set n_components to an n-tuple of n_features." warnings.warn(msg) self.n_components = n_components if self.random_fourier and not self.use_offset: n_stacks = int(np.ceil(n_stacks / 2)) n_components = n_stacks*n_features if n_components*2 != self.n_components: msg = "n_components is changed from {0} to {1}.".format( self.n_components, n_components*2 ) msg += " When random_fourier=True and use_offset=False, " msg += " n_components should be larger than 2*n_features." warnings.warn(msg) self.n_components = n_components * 2 if self.gamma == 'auto': gamma = 1.0 / X.shape[1] else: gamma = self.gamma size = (n_features, n_features) if isinstance(self.distribution, str): distribution = _get_random_matrix(self.distribution) else: distribution = self.distribution random_weights_ = [] for _ in range(n_stacks): W = distribution(random_state, size) S = np.diag(chi.rvs(df=n_features, size=n_features, random_state=random_state)) SQ, _ = qr_multiply(W, S) random_weights_ += [SQ] self.random_weights_ = np.vstack(random_weights_).T self.random_offset_ = None if self.random_fourier: self.random_weights_ *= sqrt(2*gamma) if self.use_offset: self.random_offset_ = random_state.uniform( 0, 2*np.pi, size=n_components ) return self