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)
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))
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()
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())
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
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
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)
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))
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
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)
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]))
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)
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
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)
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)
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
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
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
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)
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))
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])
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
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)
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)