Esempio n. 1
0
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
Esempio n. 2
0
    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
Esempio n. 3
0
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
Esempio n. 5
0
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
Esempio n. 6
0
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
Esempio n. 9
0
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