예제 #1
0
def test_TVB_paper_example():

    #Power form of the polys
    p1 = MultiPower(np.array([[1, -4, 0], [0, 3, 0], [1, 0,
                                                      0]]))  #y^2 + 3xy - 4x +1
    p2 = MultiPower(np.array([[3, 0, -2], [6, -6, 0],
                              [0, 0, 0]]))  #-6xy -2x^2 + 6y +3

    #Cheb form of the polys
    c1 = MultiCheb(np.array([[2, 0, -1], [6, -6, 0], [0, 0,
                                                      0]]))  #p1 in Cheb form
    c2 = MultiCheb(np.array([[1.5, -4, 0], [0, 3, 0], [.5, 0,
                                                       0]]))  #p2 in Cheb form

    #Homogenous power form
    p1 = MultiPower(np.array([[1, -4, 0], [0, 3, 0], [1, 0,
                                                      0]]))  #y^2 + 3xy - 4x +1
    p2 = MultiPower(np.array([[3, 0, -2], [6, -6, 0],
                              [0, 0, 0]]))  #-6xy -2x^2 + 6y +3

    right_number_of_roots = 4

    power_roots = tvb.solve([p1, p2], verbose=True)
    assert len(power_roots) == right_number_of_roots
    for root in power_roots:
        assert np.isclose(0, p1(root), atol=1.e-8)
        assert np.isclose(0, p2(root), atol=1.e-8)

    cheb_roots = tvb.solve([c1, c2], verbose=True)
    assert len(cheb_roots) == right_number_of_roots
    for root in cheb_roots:
        assert np.isclose(0, c1(root), atol=1.e-8)
        assert np.isclose(0, c1(root), atol=1.e-8)
예제 #2
0
def test_evaluate_grid1():
    poly = MultiCheb(np.array([[2, 0, 3], [0, -1, 0], [0, 1, 0]]))
    x = np.arange(3)
    xy = np.column_stack([x, x])

    sol = np.polynomial.chebyshev.chebgrid2d(x, x, poly.coeff)

    assert (np.all(poly.evaluate_grid(xy) == sol))
예제 #3
0
def test_add():
    """Test Multivariate Chebyshev polynomial addition."""
    t = np.arange(27).reshape((3, 3, 3))
    poly1 = MultiCheb(t)
    poly2 = MultiCheb(np.ones((3, 3, 3)))
    S = poly1 + poly2  # the sum of the polynomials
    result = (S.coeff == (poly1.coeff + poly2.coeff))
    assert result.all()
예제 #4
0
def testCoordinateVector():
    poly = MultiCheb(np.array([[0, 1, 0], [0, 0, 1], [1, 0, 0]]))
    VB = [(2, 0), (1, 2), (0, 1), (1, 0)]
    GB = [MultiCheb(np.array([[0, 0, 0], [0, 0, 0],
                              [0, 0,
                               1]]))]  # LT is big so nothing gets reduced

    slices = ([2, 1, 0, 1], [0, 2, 1, 0])

    cv = rf.coordinateVector(poly, GB, set(VB), slices)
    print(cv)
    assert ((cv == np.array([1, 1, 1, 0])).all())
예제 #5
0
def test_find_degree():
    '''Test Case #1 - 2,3,4, and 5 2D Polynomials of degree 3'''
    degree3Coeff = np.array([
                    [1,1,1,1],
                    [1,1,1,0],
                    [1,1,0,0],
                    [1,0,0,0]])
    A = MultiPower(degree3Coeff)
    B = MultiPower(degree3Coeff)
    C = MultiPower(degree3Coeff)
    D = MultiPower(degree3Coeff)
    E = MultiPower(degree3Coeff)
    assert(find_degree([A,B]) == 5)
    assert(find_degree([A,B,C]) == 7)
    assert(find_degree([A,B,C,D]) == 9)
    assert(find_degree([A,B,C,D,E]) == 11)

    '''Test Case #2 - A 2D polynomials of degree 3 and one of degree 5'''
    degree5Coeff = np.array([
                    [1,1,1,1,1,1],
                    [1,1,1,1,1,0],
                    [1,1,1,1,0,0],
                    [1,1,1,0,0,0],
                    [1,1,0,0,0,0],
                    [1,0,0,0,0,0]])
    F = MultiPower(degree5Coeff)
    assert(find_degree([A,F]) == 7)

    ''' Test Case #3 - Two 3D polynomials of degree 15'''
    G = MultiPower(np.random.rand(6,6,6))
    H = MultiPower(np.random.rand(6,6,6))
    assert(find_degree([G,H]) == 29)

    #Test 3 - Simple Example in 2D
    poly1 = MultiPower(np.array([[3,0,1],[0,0,0],[0,0,1]]))
    poly2 = MultiPower(np.array([[3,0],[1,1],[0,1]]))
    found_degree = find_degree([poly1,poly2])
    correct_degree = 6
    assert found_degree == correct_degree

    #Test 4 - Simple Example in 3D
    a = np.zeros((4,4,4))
    a[3,3,3] = 1
    poly1 = MultiCheb(a)
    poly2 = MultiCheb(np.ones((3,5,4)))
    poly3 = MultiCheb(np.ones((2,4,5)))
    found_degree1 = find_degree([poly1,poly2,poly3])
    correct_degree1 = 24
    assert found_degree1 == correct_degree1
예제 #6
0
def Mxi_Matrix(i, basisDict, VB, dim, poly_type, verbose=False):
    '''
    Uses the reduced Macaulay matrix to construct the Moller-Stetter matrix M_xi, which
    represents the linear map of multiplying by xi in the space C[x1, ..., xn]/I.

    Parameters
    ----------
    i : int
        The index of the variable xi to make the Moller-Stetter matrix of, where variables
        are indexed as x1, x2, ..., xn.
    basisDict: dictionary
        A dictionary which maps monomials not in the basis to linear combinations
        of monomials in the basis. Generated using the TVB method.
    VB: numpy array
        Represents a vector basis for the space C[x1, ..., xn]/I created with the TVB method.
        Each row represents a monomial in the basis as the degrees of each variable.
        For example, x^2y^5 would be represented as [2,5].
    dim: int
        The dimension of the system (n)
    verbose : bool
        Prints information about how the roots are computed.

    Returns
    -------
    Mxi : 2D numpy array
        The Moller-Stetter matrix which represents multiplying by xi
    '''
    VB = VB.tolist() #convert to list bc numpy's __contains__() function is broken

    #Construct the polynomial to create the MS Matrix of (xi)
    xi_ind = np.zeros(dim, dtype=int)
    xi_ind[i-1] = 1
    coef = np.zeros((2,)*dim)
    coef[tuple(xi_ind)] = 1
    if poly_type == "MultiPower":
        xi = MultiPower(np.array(coef))
    elif poly_type == "MultiCheb":
        xi = MultiCheb(np.array(coef))

    if verbose:
        print("\nCoefficients of polynomial whose Moller-Stetter matrix we construt\n", xi.coeff)

    # Build multiplication matrix M_xi
    Mxi = np.zeros((len(VB), len(VB)))
    for j in range(len(VB)): #multiply each monomial in the basis by xi
        product_coef = xi.mon_mult(VB[j], returnType = 'Matrix')
        for monomial in zip(*np.where(product_coef != 0)):
            if list(monomial) in VB: #convert to list to test if list of lists
                Mxi[VB.index(list(monomial))][j] += product_coef[monomial]
            else:
                Mxi[:,j] -= product_coef[monomial]*basisDict[monomial]

    # Construct var_dict
    var_dict = {}
    for i in range(len(VB)):
        mon = VB[i]
        if np.sum(mon) == 1 or np.sum(mon) == 0:
            var_dict[tuple(mon)] = i

    return Mxi
예제 #7
0
def triangular_cheb_approx(poly,
                           hyperplane,
                           inv_rotation,
                           dim,
                           deg,
                           accuracy=1.e-10):
    '''Gives an n-dimensional triangular interpolation of polynomial on a given hyperplace after a given rotation.
    
    It calls the normal nD-interpolation, but then cuts off the small non-triangular part to make it triangular.
    
    Parameters
    ----------
    poly : Polynomial
        This is one of the given polynomials in projective space. So it must be projected into proejective space first.
    hyperplace : int
        Which hyperplance we want to approximate in. Between 0 and n inclusive when the original polynomials are n-1
        dimensional. So the projective space polynomials are n dimensional. n is the original space.
    inv_rotation : numpy array
        The inverse of the rotation of the projective space.
    dim : int
        The dimension of the chebysehv polynomial we want.
    deg : int
        The degree of the chebyshev polynomial we want.

    Returns
    -------
    triangular_cheb_approx : MultiCheb
        The chebyshev polynomial we want.
    '''
    cheb = cheb_interpND(poly, hyperplane, inv_rotation, dim, deg)
    clean_zeros_from_matrix(cheb)
    return MultiCheb(cheb)
예제 #8
0
def test_evaluate():
    cheb = MultiCheb(np.array([[0,0,0,1],[0,0,0,0],[0,0,1,0]]))
    value = cheb((2,5))
    assert(value == 828)

    value = cheb((.25,.5))
    assert(np.isclose(value, -.5625))
예제 #9
0
def _random_poly(_type, dim):
    '''
    Generates a random polynomial that has the form
    c_1x_1 + c_2x_2 + ... + c_nx_n where n = dim and each c_i is a randomly
    chosen integer between 0 and 1000.

    Parameters
    ----------
    _type : string
        Type of Polynomial to generate. "MultiCheb" or "MultiPower".
    dim : int
        Degree of polynomial to generate (?).

    Returns
    -------
    Polynomial
        Randomly generated Polynomial.
    '''
    _vars = get_var_list(dim)

    random_poly_shape = [2 for i in range(dim)]

    random_poly_coeff = np.zeros(tuple(random_poly_shape), dtype=int)
    for var in _vars:
        random_poly_coeff[var] = np.random.randint(1000)

    if _type == 'MultiCheb':
        return MultiCheb(random_poly_coeff), _vars
    else:
        return MultiPower(random_poly_coeff), _vars
예제 #10
0
def getPoly(deg, power):
    '''
    A helper function for testing. Returns a random 1D polynomial of the given degree.
    power is a boolean indicating whether or not the polynomial should be MultiPower.
    '''
    coeff = np.random.random_sample(deg+1)
    if power:
        return MultiPower(coeff)
    else:
        return MultiCheb(coeff)
예제 #11
0
def test_evaluate():
    cheb = MultiCheb(np.array([[0, 0, 0, 1], [0, 0, 0, 0], [0, 0, 1, 0]]))
    value = cheb((2, 5))
    assert (value == 828)

    value = cheb((.25, .5))
    assert (np.isclose(value, -.5625))

    values = cheb([[.25, .5], [1.2, 2.2]])
    print(values)
    assert (np.allclose(values, [-0.5625, 52.3104]))
예제 #12
0
def getPoly(deg, dim):
    '''
    A helper function for testing. Returns a random upper triangular polynomial of the given dimension and degree.
    power is a boolean indicating whether or not the polynomial should be MultiPower.
    '''
    deg += 1
    ACoeff = np.random.random_sample(deg * np.ones(dim, dtype=int))
    for i, j in np.ndenumerate(ACoeff):
        if np.sum(i) >= deg:
            ACoeff[i] = 0
    return MultiCheb(ACoeff)
예제 #13
0
def get_polys_from_matrix(matrix, matrix_terms, rows, power, r_type="poly"):
    '''Creates polynomial objects from the specified rows of the given matrix.

    Parameters
    ----------
    matrix : (M,N) ndarray
        The matrix with rows corresponding to polynomials, columns corresponding
        to monomials, and entries corresponding to coefficients.
    matrix_terms : array-like
        The column labels for matrix in order. Contains Term objects.
    rows : iterable
        The rows for which to create polynomial objects. Contains integers.
    power : bool
        If true, the polynomials returned will be MultiPower objects.
        Otherwise, they will be MultiCheb.

    Returns
    -------
    poly_list : list
        Polynomial objects corresponding to the specified rows.
    '''

    shape = []
    p_list = []
    shape = np.maximum.reduce([term for term in matrix_terms])
    shape += np.ones_like(shape)
    spots = list()
    for dim in range(matrix_terms.shape[1]):
        spots.append(matrix_terms.T[dim])

    # Grabs each polynomial, makes coeff matrix and constructs object
    for i in rows:
        p = matrix[i]
        coeff = np.zeros(shape)
        coeff[spots] = p
        if r_type == "poly":
            if power:
                poly = MultiPower(coeff)
            else:
                poly = MultiCheb(coeff)
            if poly.lead_term != None:
                p_list.append(poly)
        else:
            p_list.append(coeff)
    return p_list
예제 #14
0
def test_cheb2poly():
    c1 = MultiCheb(np.array([[0, 0, 0], [0, 0, 0], [0, 1, 1]]))
    c2 = cheb2poly(c1)
    truth = np.array([[1, -1, -2], [0, 0, 0], [-2, 2, 4]])
    assert np.allclose(truth, c2.coeff)

    #test2
    c3 = MultiCheb(np.array([[3, 1, 4, 7], [8, 3, 1, 2], [0, 5, 6, 2]]))
    c4 = cheb2poly(c3)
    truth2 = np.array([[5, -19, -4, 20], [7, -3, 2, 8], [-12, -2, 24, 16]])
    assert np.allclose(truth2, c4.coeff)

    c4_1 = poly2cheb(c4)
    assert np.allclose(c3.coeff, c4_1.coeff)

    #Test3
    c5 = MultiCheb(
        np.array([[3, 1, 3, 4, 6], [2, 0, 0, 2, 0], [3, 1, 5, 1, 8]]))
    c6 = cheb2poly(c5)
    truth3 = np.array([[0, -9, 12, 12, -16], [2, -6, 0, 8, 0],
                       [12, -4, -108, 8, 128]])
    assert np.allclose(truth3, c6.coeff)

    #test4 - Random 1D
    matrix2 = np.random.randint(1, 100, random.randint(1, 10))
    c7 = MultiCheb(matrix2)
    c8 = cheb2poly(c7)
    c9 = poly2cheb(c8)
    assert np.allclose(c7.coeff, c9.coeff)

    #Test5 - Random 2D
    shape = list()
    for i in range(2):
        shape.append(random.randint(2, 10))
    matrix1 = np.random.randint(1, 50, (shape))
    c10 = MultiCheb(matrix1)
    c11 = cheb2poly(c10)
    c12 = poly2cheb(c11)
    assert np.allclose(c10.coeff, c12.coeff)

    #Test6 - Random 4D
    shape = list()
    for i in range(4):
        shape.append(random.randint(2, 10))
    matrix1 = np.random.randint(1, 50, (shape))
    c13 = MultiCheb(matrix1)
    c14 = cheb2poly(c13)
    c15 = poly2cheb(c14)
    assert np.allclose(c13.coeff, c15.coeff)
예제 #15
0
def project(poly):
    '''Projects a polynomial into projective space.
    
    Parameters
    ----------
    poly : Polynomial
        The polynomial to project.

    Returns
    -------
    project : Polynomial
        The same polynomail in projective space.
    '''
    Pcoeff = np.zeros([poly.degree + 1] * (poly.dim + 1))
    for spot in zip(*np.where(poly.coeff != 0)):
        new_spot = list(spot)
        new_spot = new_spot + [poly.degree - np.sum(spot)]
        Pcoeff[tuple(new_spot)] = poly.coeff[spot]
    if isinstance(poly, MultiPower):
        return MultiPower(Pcoeff)
    else:
        return MultiCheb(Pcoeff)
예제 #16
0
def subdivision_solve_nd(funcs, a, b, deg):
    """Finds the common zeros of the given functions.
    
    Parameters
    ----------
    funcs : list
        Each element of the list is a callable function.
    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 in the chebyshev approximation.
    
    Returns
    -------
    good_zeros : numpy array
        The real zero in [-1,1] of the input zeros.
    """
    dim = funcs[0].dim
    chebs = list()
    for func in funcs:
        coeff = full_cheb_approximate(func, a, b, deg=deg)

        #Subdivides if needed.
        if coeff is None:
            intervals = get_subintervals(a, b, np.arange(dim))
            return np.vstack([
                subdivision_solve_nd(funcs, interval[0], interval[1], deg)
                for interval in intervals
            ])

        coeff = trim_coeff(coeff)
        chebs.append(MultiCheb(coeff))
    zeros = np.array(division_cheb(chebs))
    zeros = transform(good_zeros_nd(zeros), a, b)
    return zeros
예제 #17
0
def run_n_dimension(args, radius, eigvals):
    num_points = args.num_points
    eps = args.eps
    power = args.power
    real = args.real
    by_coeffs = args.coeffs
    dim = args.dimension

    root_pts = {}
    residuals = {}
    powerpolys = []
    chebpolys = []
    if by_coeffs:
        for i in range(dim):
            from numalgsolve.polynomial import getPoly
            powerpolys.append(getPoly(num_points, dim, power=True))
            chebpolys.append(getPoly(num_points, dim, power=False))
    else:
        r = np.random.random((num_points, dim)) * radius + eps
        roots = 2 * r - radius

        root_pts = {'roots': np.array(list(product(*np.rot90(roots))))}

        for i in range(dim):
            coeffs = np.zeros((num_points + 1, ) * dim)
            idx = [
                slice(None),
            ] * dim
            idx[i] = 0
            coeffs[tuple(idx)] = polyfromroots(roots[:, i])
            lt = [0] * dim
            lt[i] = num_points
            powerpolys.append(
                MultiPower(coeffs))  #, lead_term=lt, clean_zeros=False))

            coeffs[tuple(idx)] = chebfromroots(roots[:, i])
            chebpolys.append(
                MultiCheb(coeffs))  #, lead_term=lt, clean_zeros=False))
            # plt.subplot(121);plt.imshow(coeffs);plt.subplot(122);plt.imshow(chebpolys[0].coeff);plt.show()

    for solver in all_solvers:
        if not isinstance(solver, OneDSolver) and solver.basis in [
                'power', 'both'
        ]:
            # if ((not eigvals) or solver.eigvals):
            name = str(solver) + ' Power'
            root_pts[name] = solver(powerpolys)
            residuals[name] = maximal_residual(powerpolys, root_pts[name])

    for solver in all_solvers:
        if not isinstance(solver, OneDSolver) and solver.basis in [
                'cheb', 'both'
        ]:
            # if ((not eigvals) or solver.eigvals):
            name = str(solver) + ' Cheb'
            root_pts[name] = solver(chebpolys)
            residuals[name] = maximal_residual(chebpolys, root_pts[name])

    if args.hist:
        evaluations = {}
        for k, v in root_pts.items():
            if k == 'roots': continue
            # evaluations[k] = []
            polys = powerpolys if 'Power' in k else chebpolys
            # for poly in polys:
            evaluations[k] = sum(np.abs(poly(root_pts[k])) for poly in polys)
        ncols = len(evaluations)
        # plt.figure(figsize=(12,6))
        fig, ax = plt.subplots(1, ncols, sharey=True, figsize=(12, 4))
        minimal = -15
        maximal = 1
        for i, (k, v) in enumerate(evaluations.items()):
            ax[i].hist(np.clip(np.log10(v), minimal, maximal),
                       range=(minimal, maximal),
                       bins=40)
            ax[i].set_xlabel(r'$log_{10}(p(r_i))$')
            ax[i].set_title(k)
        plt.suptitle("Eigenvalues" if eigvals else "Eigenvectors")
        plt.show()

    return root_pts, residuals
예제 #18
0
def run_one_dimension(args, radius, eigvals):
    num_points = args.num_points
    eps = args.eps
    power = args.power
    real = args.real
    by_coeffs = args.coeffs

    root_pts = {}
    residuals = {}
    if by_coeffs:
        coeffs = (np.random.random(num_points + 1) * 2 - 1) * radius
        powerpoly = MultiPower(coeffs)
        chebpoly = MultiCheb(coeffs)
    else:
        r = np.sqrt(np.random.random(num_points)) * radius + eps
        angles = 2 * np.pi * np.random.random(num_points)
        if power and not real:
            roots = r * np.exp(angles * 1j)
        else:
            roots = 2 * r - radius
        root_pts = {'roots': roots}

        powerpoly = MultiPower(polyfromroots(roots))
        chebpoly = MultiCheb(chebfromroots(roots))
    n = 1000
    x = np.linspace(-1, 1, n)
    X, Y = np.meshgrid(x, 1j * x)

    for solver in all_solvers:
        if isinstance(solver, OneDSolver):
            if (solver.basis == 'cheb' and args.cheb) and ((not eigvals)
                                                           or solver.eigvals):
                name = str(solver)
                root_pts[name] = solver(chebpoly, eigvals)
                residuals[name] = maximal_residual(chebpoly, root_pts[name])
            if (solver.basis == 'power'
                    and args.power) and ((not eigvals) or solver.eigvals):
                name = str(solver)
                root_pts[name] = solver(powerpoly, eigvals)
                residuals[name] = maximal_residual(powerpoly, root_pts[name])

    if args.hist:
        evaluations = {}
        for k, v in root_pts.items():
            if k == 'roots': continue
            poly = powerpoly if 'power' in k else chebpoly
            evaluations[k] = np.abs(poly(root_pts[k]))
        ncols = len(evaluations)
        fig, ax = plt.subplots(1, ncols, sharey=True, figsize=(12, 4))
        minimal = -20
        maximal = 1
        for i, (k, v) in enumerate(evaluations.items()):
            ax[i].hist(np.clip(np.log10(v), minimal, maximal),
                       range=(minimal, maximal),
                       bins=40)
            ax[i].set_xlabel(r'$log_{10}(p(r_i))$')
            ax[i].set_title(k)
        plt.suptitle("Eigenvalues" if eigvals else "Eigenvectors")
        plt.show()

    return root_pts, residuals
예제 #19
0
def curvature_check(coeff):
    poly = MultiCheb(coeff)
    a = np.array([-1.] * poly.dim)
    b = np.array([1.] * poly.dim)
    return not can_eliminate(poly, a, b)
예제 #20
0
def test_evaluate2():
    cheb = MultiCheb(np.array([[0, 0, 0, 1], [0, 0, 0, 0], [0, 0, .5, 0]]))
    value = cheb((2, 5))
    assert (np.isclose(value, 656.5))
예제 #21
0
def subdivision_solve_nd(funcs,
                         a,
                         b,
                         deg,
                         interval_results,
                         interval_checks=[],
                         subinterval_checks=[],
                         tol=1.e-3):
    """Finds the common zeros of the given functions.

    Parameters
    ----------
    funcs : list
        Each element of the list is a callable function.
    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 in the chebyshev approximation.

    Returns
    -------
    good_zeros : numpy array
        The real zero in [-1,1] of the input zeros.
    """
    division_var = 0
    cheb_approx_list = []
    try:
        if np.random.rand() > .999:
            print("Interval - ", a, b)
        dim = len(a)
        for func in funcs:
            coeff = full_cheb_approximate(func, a, b, deg, tol=tol)

            #Subdivides if needed.
            if coeff is None:
                intervals = get_subintervals(a, b, np.arange(dim), None, None,
                                             None)

                return np.vstack([subdivision_solve_nd(funcs,interval[0],interval[1],deg,interval_results\
                                                       ,interval_checks,subinterval_checks,tol=tol)
                                  for interval in intervals])
            else:
                coeff = trim_coeff(coeff, tol=tol)
                #Run checks to try and throw out the interval
                for func_num, func in enumerate(interval_checks):
                    if not func(coeff):
                        interval_results[func_num].append([a, b])
                        return np.zeros([0, dim])
                cheb_approx_list.append(MultiCheb(coeff))

        zeros = np.array(
            division(cheb_approx_list,
                     get_divvar_coord_from_eigval=True,
                     divisor_var=0,
                     tol=1.e-6))
        interval_results[-1].append([a, b])
        if len(zeros) == 0:
            return np.zeros([0, dim])
        return transform(good_zeros_nd(zeros), a, b)

    except np.linalg.LinAlgError as e:
        while division_var < len(a):
            try:
                zeros = np.array(
                    division(cheb_approx_list,
                             get_divvar_coord_from_eigval=True,
                             divisor_var=0,
                             tol=1.e-6))
                return zeros
            except np.linalg.LinAlgError as e:
                division_var += 1

        #Subdivide but run some checks on the intervals first
        intervals = get_subintervals(a,b,np.arange(dim),subinterval_checks,interval_results\
                                     ,cheb_approx_list,check_subintervals=True)
        if len(intervals) == 0:
            return np.zeros([0, dim])
        else:
            return np.vstack([subdivision_solve_nd(funcs,interval[0],interval[1],deg,interval_results\
                                               ,interval_checks,subinterval_checks,tol=tol)
                          for interval in intervals])
예제 #22
0
def MSMultMatrix(polys, poly_type, number_of_roots, verbose=False, MSmatrix=0):
    '''
    Finds the multiplication matrix using the reduced Macaulay matrix.

    Parameters
    ----------
    polys : array-like
        The polynomials to find the common zeros of
    poly_type : string
        The type of the polynomials in polys
    MSmatrix : int
        Controls which Moller-Stetter matrix is constructed. The options are:
            0 (default) -- The Moller-Stetter matrix of a random polynomial
            Some positive integer i < dimension -- The Moller-Stetter matrix of x_i
    verbose : bool
        Prints information about how the roots are computed.

    Returns
    -------
    multiplicationMatrix : 2D numpy array
        The multiplication matrix for a random polynomial f
    var_dict : dictionary
        Maps each variable to its position in the vector space basis
    '''
    basisDict, VB = MacaulayReduction(polys, number_of_roots, verbose=verbose)

    dim = max(f.dim for f in polys)

    # Get the polynomial to make the MS matrix of
    if MSmatrix == 0:  #random poly
        f = _random_poly(poly_type, dim)[0]
    else:  #multiply by x_i where i is determined by MSmatrix
        xi_ind = np.zeros(dim, dtype=int)
        xi_ind[MSmatrix - 1] = 1
        coef = np.zeros((2, ) * dim)
        coef[tuple(xi_ind)] = 1
        if poly_type == "MultiPower":
            f = MultiPower(np.array(coef))
        elif poly_type == "MultiCheb":
            f = MultiCheb(np.array(coef))
        else:
            raise ValueError()
    if verbose:
        print(
            "\nCoefficients of polynomial whose Moller-Stetter matrix we construt\n",
            f.coeff)

    #Dictionary of terms in the vector basis their spots in the matrix.
    VBdict = {}
    spot = 0
    for row in VB:
        VBdict[tuple(row)] = spot
        spot += 1

    # Build multiplication matrix m_f
    mMatrix = np.zeros((len(VB), len(VB)))
    for i in range(VB.shape[0]):
        f_coeff = f.mon_mult(VB[i], returnType='Matrix')
        for term in zip(*np.where(f_coeff != 0)):
            if term in VBdict:
                mMatrix[VBdict[term]][i] += f_coeff[term]
            else:
                mMatrix[:, i] -= f_coeff[term] * basisDict[term]

    # Construct var_dict
    var_dict = {}
    for i in range(len(VB)):
        mon = VB[i]
        if np.sum(mon) == 1 or np.sum(mon) == 0:
            var_dict[tuple(mon)] = i

    return mMatrix, var_dict
예제 #23
0
def test_mon_mult():
    """
    Tests monomial multiplication using normal polynomial multiplication.
    """

    np.random.seed(4)

    #Simple 2D test cases
    cheb1 = MultiCheb(np.array([[0, 0, 0], [0, 0, 0], [0, 0, 1]]))
    mon1 = (1, 1)
    result1 = cheb1.mon_mult(mon1)
    truth1 = np.array([[0, 0, 0, 0], [0, 0.25, 0, 0.25], [0, 0, 0, 0],
                       [0, 0.25, 0, 0.25]])

    assert np.allclose(result1.coeff, truth1)

    #test with random matrices
    cheb2 = np.random.randint(-9, 9, (4, 4))
    C1 = MultiCheb(cheb2)
    C2 = cheb2poly(C1)
    C3 = MultiCheb.mon_mult(C1, (1, 1))
    C4 = MultiPower.mon_mult(C2, (1, 1))
    C5 = poly2cheb(C4)

    assert np.allclose(C3.coeff, C5.coeff)

    # test results of chebyshev mult compared to power multiplication
    cheb3 = np.random.randn(5, 4)
    c1 = MultiCheb(cheb3)
    c2 = MultiCheb(np.ones((4, 2)))
    for index, i in np.ndenumerate(c2.coeff):
        if sum(index) == 0:
            c3 = c1.mon_mult(index)
        else:
            c3 = c3 + c1.mon_mult(index)
    p1 = cheb2poly(c1)
    p2 = cheb2poly(c2)
    p3 = p1 * p2
    p4 = cheb2poly(c3)
    assert np.allclose(p3.coeff, p4.coeff)

    # test results of chebyshev mult compared to power multiplication in 3D
    cheb4 = np.random.randn(3, 3, 3)
    a1 = MultiCheb(cheb4)
    a2 = MultiCheb(np.ones((3, 3, 3)))
    for index, i in np.ndenumerate(a2.coeff):
        if sum(index) == 0:
            a3 = a1.mon_mult(index)
        else:
            a3 = a3 + a1.mon_mult(index)
    q1 = cheb2poly(a1)
    q2 = cheb2poly(a2)
    q3 = q1 * q2
    q4 = cheb2poly(a3)
    assert np.allclose(q3.coeff, q4.coeff)
예제 #24
0
def test_paper_example():

    #Power form of the polys
    p1 = MultiPower(np.array([[1, -4, 0], [0, 3, 0], [1, 0,
                                                      0]]))  #y^2 + 3xy - 4x +1
    p2 = MultiPower(np.array([[3, 0, -2], [6, -6, 0],
                              [0, 0, 0]]))  #-6xy -2x^2 + 6y +3

    #Cheb form of the polys
    c1 = MultiCheb(np.array([[2, 0, -1], [6, -6, 0], [0, 0,
                                                      0]]))  #p1 in Cheb form
    c2 = MultiCheb(np.array([[1.5, -4, 0], [0, 3, 0], [.5, 0,
                                                       0]]))  #p2 in Cheb form

    right_number_of_roots = 4

    #~ ~ ~ Power Form, Mx Matrix ~ ~ ~
    power_mult_roots = pr.solve([p1, p2], MSmatrix=1)
    assert len(power_mult_roots) == right_number_of_roots
    for root in power_mult_roots:
        assert np.isclose(0, p1(root), atol=1.e-8)
        assert np.isclose(0, p2(root), atol=1.e-8)

    #~ ~ ~ Cheb Form, Mx Matrix ~ ~ ~
    cheb_mult_roots = pr.solve([c1, c2], MSmatrix=1)
    assert len(cheb_mult_roots) == right_number_of_roots
    for root in cheb_mult_roots:
        assert np.isclose(0, c1(root), atol=1.e-8)
        assert np.isclose(0, c1(root), atol=1.e-8)

    #~ ~ ~ Power Form, My Matrix ~ ~ ~
    power_multR_roots = pr.solve([p1, p2], MSmatrix=2)
    assert len(power_multR_roots) == right_number_of_roots
    for root in power_multR_roots:
        assert np.isclose(0, p1(root), atol=1.e-8)
        assert np.isclose(0, p2(root), atol=1.e-8)

    #~ ~ ~ Cheb Form, My Matrix ~ ~ ~
    cheb_multR_roots = pr.solve([c1, c2], MSmatrix=2)
    assert len(cheb_multR_roots) == right_number_of_roots
    for root in cheb_multR_roots:
        assert np.isclose(0, c1(root), atol=1.e-8)
        assert np.isclose(0, c1(root), atol=1.e-8)

    #~ ~ ~ Power Form, Pseudorandom Multiplication Matrix ~ ~ ~
    power_multrand_roots = pr.solve([p1, p2], MSmatrix=0)
    assert len(power_multrand_roots) == right_number_of_roots
    for root in power_multrand_roots:
        assert np.isclose(0, p1(root), atol=1.e-8)
        assert np.isclose(0, p2(root), atol=1.e-8)

    #~ ~ ~ Cheb Form, Pseudorandom Multiplication Matrix ~ ~ ~
    cheb_multrand_roots = pr.solve([c1, c2], MSmatrix=0)
    assert len(cheb_multrand_roots) == right_number_of_roots
    for root in cheb_multrand_roots:
        assert np.isclose(0, c1(root), atol=1.e-8)
        assert np.isclose(0, c1(root), atol=1.e-8)

    #~ ~ ~ Power Form, Division Matrix ~ ~ ~
    power_div_roots = pr.solve([p1, p2], MSmatrix=-1)
    assert len(power_div_roots) == right_number_of_roots
    for root in power_div_roots:
        assert np.isclose(0, p1(root), atol=1.e-8)
        assert np.isclose(0, p2(root), atol=1.e-8)

    #~ ~ ~ Cheb Form, Division Matrix ~ ~ ~
    cheb_div_roots = pr.solve([c1, c2], MSmatrix=-1)
    assert len(cheb_div_roots) == right_number_of_roots
    for root in cheb_div_roots:
        assert np.isclose(0, c1(root), atol=1.e-8)
        assert np.isclose(0, c2(root), atol=1.e-8)