def solve(self, qr_reduction=True, reducedGroebner=True): ''' The main function. Initializes the matrix, adds the phi's and r's, and then reduces it. Repeats until the reduction no longer adds any more polynomials to the matrix. Print statements let us see the progress of the code. ''' MultiCheb.clearTime() MultiPower.clearTime() startTime = time.time() polys_were_added = True i = 1 #Tracks what loop we are on. while polys_were_added: #print("Starting Loop #"+str(i)) #print("Num Polys - ", len(self.new_polys + self.old_polys)) self.initialize_np_matrix() self.add_phi_to_matrix() self.add_r_to_matrix() self.create_matrix() #print(self.np_matrix.shape) polys_were_added = self.reduce_matrix( qr_reduction=qr_reduction, triangular_solve=False ) #Get rid of triangular solve when done testing i += 1 #print("Basis found!") self.get_groebner() if reducedGroebner: self.reduce_groebner_basis() endTime = time.time() #print("WE WIN") print("Run time was {} seconds".format(endTime - startTime)) print(times) MultiCheb.printTime() MultiPower.printTime() #print("Basis - ") #for poly in self.groebner_basis: # print(poly.coeff) #break #print just one return self.groebner_basis
def roots(polys, method='Groebner'): ''' Finds the roots of the given list of polynomials parameters ---------- polys : list of polynomial objects polynomials to find the common roots of returns ------- list of numpy arrays the common roots of the polynomials ''' times["reducePoly"] = 0 Polynomial.clearTime() startTime = time.time() # Determine polynomial type poly_type = '' if (all(type(p) == MultiCheb for p in polys)): poly_type = 'MultiCheb' elif (all(type(p) == MultiPower for p in polys)): poly_type = 'MultiPower' else: raise ValueError('All polynomials must be the same type') # Calculate groebner basis startBasis = time.time() if method == 'Groebner': G = Groebner(polys) GB = G.solve() else: GB = Macaulay(polys) endBasis = time.time() times["basis"] = (endBasis - startBasis) dim = max(g.dim for g in GB) # dimension of the polynomials # Check for no solutions if len(GB) == 1 and all([i == 1 for i in GB[0].coeff.shape]): print("No solutions") return -1 startRandPoly = time.time() # Make sure ideal is zero-dimensional and get random polynomial f, var_list = _random_poly(poly_type, dim) if not _test_zero_dimensional(var_list, GB): print("Ideal is not zero-dimensional; cannot calculate roots.") return -1 endRandPoly = time.time() times["randPoly"] = (endRandPoly - startRandPoly) # Get multiplication matrix startVectorBasis = time.time() VB, var_dict = vectorSpaceBasis(GB) endVectorBasis = time.time() times["vectorBasis"] = (endVectorBasis - startVectorBasis) #print("VB:", VB) #print("var_dict:", var_dict) startMultMatrix = time.time() m_f = multMatrix(f, GB, VB) endMultMatrix = time.time() times["multMatrix"] = (endMultMatrix - startMultMatrix) startEndStuff = time.time() # Get list of indexes of single variables and store vars that were not # in the vector space basis. var_indexes = np.array([-1 for i in range(dim)]) vars_not_in_basis = {} for i in range(len(var_list)): var = var_list[i] # x_i if var in var_dict: var_indexes[i] = var_dict[var] else: # maps the position in the root to its variable vars_not_in_basis[i] = var vnib = False if len(vars_not_in_basis) != 0: vnib = True # Get left eigenvectors eig = np.linalg.eig(m_f.T)[1] num_vectors = eig.shape[1] eig_vectors = [eig[:, i].tolist() for i in range(num_vectors)] # columns of eig roots = [] for v in eig_vectors: root = np.zeros(dim, dtype=complex) # This will always work because var_indexes and root have the # same length - dim - and var_indexes has the variables in the # order they should be in the root for i in range(dim): x_i_pos = var_indexes[i] if x_i_pos != -1: root[i] = v[x_i_pos] / v[0] if vnib: # Go through the indexes of variables not in the basis in # decreasing order. It must be done in decreasing order for the # roots to be calculated correctly, since the vars with lower # indexes depend on the ones with higher indexes for pos in list(vars_not_in_basis.keys())[::-1]: GB_poly = _get_poly_with_LT(vars_not_in_basis[pos], GB) var_value = GB_poly.evaluate_at(root) * -1 root[pos] = var_value roots.append(root) endEndStuff = time.time() times["endStuff"] = (endEndStuff - startEndStuff) endTime = time.time() totalTime = (endTime - startTime) print("Total run time for roots is {}".format(totalTime)) print(times) MultiCheb.printTime() MultiPower.printTime() Polynomial.printTime() print((times["basis"] + times["multMatrix"]) / totalTime) return roots
def Macaulay(initial_poly_list, global_accuracy = 1.e-10): """ Macaulay will take a list of polynomials and use them to construct a Macaulay matrix. parameters -------- initial_poly_list: A list of polynomials global_accuracy: How small we want a number to be before assuming it is zero. -------- Returns ----------- Reduced Macaulay matrix that can be passed into the root finder. ----------- """ times = {} startTime = time.time() MultiCheb.clearTime() MultiPower.clearTime() Power = bool if all([type(p) == MultiPower for p in initial_poly_list]): Power = True elif all([type(p) == MultiCheb for p in initial_poly_list]): Power = False else: print([type(p) == MultiPower for p in initial_poly_list]) raise ValueError('Bad polynomials in list') poly_list = [] degree = find_degree(initial_poly_list) startAdding = time.time() for i in initial_poly_list: poly_list = add_polys(degree, i, poly_list) endAdding = time.time() times["adding polys"] = (endAdding - startAdding) startCreate = time.time() matrix, matrix_terms = create_matrix(poly_list) endCreate = time.time() times["create matrix"] = (endCreate - startCreate) #plt.matshow([i==0 for i in matrix]) startReduce = time.time() matrix = rrqr_reduce(matrix) matrix = clean_zeros_from_matrix(matrix) non_zero_rows = np.sum(abs(matrix),axis=1) != 0 matrix = matrix[non_zero_rows,:] #Only keeps the non_zero_polymonials endReduce = time.time() times["reduce matrix"] = (endReduce - startReduce) #plt.matshow([i==0 for i in matrix]) startTri = time.time() matrix = triangular_solve(matrix) matrix = clean_zeros_from_matrix(matrix) endTri = time.time() times["triangular solve"] = (endTri - startTri) #plt.matshow([i==0 for i in matrix]) startGetPolys = time.time() rows = get_good_rows(matrix, matrix_terms) final_polys = get_poly_from_matrix(rows,matrix,matrix_terms,Power) endGetPolys = time.time() times["get polys"] = (endGetPolys - startGetPolys) endTime = time.time() print("Macaulay run time is {} seconds".format(endTime-startTime)) print(times) MultiCheb.printTime() MultiPower.printTime() #for poly in final_polys: # print(poly.lead_term) return final_polys
# decreasing order. It must be done in decreasing order for the # roots to be calculated correctly, since the vars with lower # indexes depend on the ones with higher indexes for pos in list(vars_not_in_basis.keys())[::-1]: GB_poly = _get_poly_with_LT(vars_not_in_basis[pos], GB) var_value = GB_poly.evaluate_at(root) * -1 root[pos] = var_value roots.append(root) endEndStuff = time.time() times["endStuff"] = (endEndStuff - startEndStuff) endTime = time.time() totalTime = (endTime - startTime) print("Total run time for roots is {}".format(totalTime)) print(times) MultiCheb.printTime() MultiPower.printTime() Polynomial.printTime() print((times["basis"]+times["multMatrix"])/totalTime) return roots def multMatrix(poly, GB, basis): ''' Finds the matrix of the linear operator m_f on A = C[x_1,...,x_n]/I where f is the polynomial argument. The linear operator m_f is defined as m_f([g]) = [f]*[g] where [f] represents the coset of f in A. Since m_f is a linear operator on A, it can be represented by its matrix with respect to the vector space basis. parameters ---------- poly : polynomial object