예제 #1
0
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
예제 #3
0
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')
예제 #4
0
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
예제 #6
0
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,
    )
예제 #7
0
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
예제 #8
0
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
예제 #9
0
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,
    )
예제 #11
0
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
예제 #12
0
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
예제 #13
0
    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