def _add_poly_to_matrix(self, p, adding_r=False): ''' Saves the polynomial to the set of polynomials that will be used in create_matrix. Also updates the list of leading terms and monomials in the matrix with the new values. adding_r is only true when the r's are being added, this way it knows to keep adding new monomials to the heap for further r calculation ''' startTime = time.time() if p is None: return self.matrix_polys.append(p) self.lead_term_set.add(Term(p.lead_term)) for idx in zip(*np.where(p.coeff != 0)): idx_term = Term(tuple(idx)) #Get a term object if idx_term not in self.term_set: self.term_set.add(idx_term) #If r's being added, adds new monomial to the heap if adding_r: if (idx_term not in self.lead_term_set): self.monheap.heappush(idx_term) endTime = time.time() times["_add_poly_to_matrix"] += (endTime - startTime) return
def initialize_np_matrix(new_polys, old_polys, items): ''' Initialzes self.np_matrix to having just old_polys and new_polys in it matrix_terms is the header of the matrix, it lines up each column with a monomial ''' # Added new things into the dictionary of constantly changing variables. items.update({ 'np_matrix': np.array([]), 'original_lms': set(), 'original_lm_dict': {}, 'lead_term_set': set(), 'term_set': set(), 'matrix_terms': [], 'duplicate_lms': set(), 'not_needed_lms': set() }) for p in new_polys + old_polys: if p.lead_term != None: items['original_lms'].add(Term(p.lead_term)) items['original_lm_dict'][Term(p.lead_term)] = p items = _add_poly_to_matrix(new_polys + old_polys, items) return items
def _add_poly_to_matrix(p_list, items, adding_r=False): ''' Takes in a single polynomial and adds it to the state matrix First adds a row of zeros, then goes through each monomial in the polynomial and puts it's coefficient in adding new columns as needed when new monomials are added. adding_r is only true when the r's are being added, this way it knows to keep adding new monomials to the heap for further r calculation returns the new lead_term_set ''' for p in p_list: items['lead_term_set'].add(Term(p.lead_term)) #Adds a new row of 0's if the matrix has any width if (items['np_matrix'].shape[0] != 0): zero_poly = np.zeros((1, items['np_matrix'].shape[1])) items['np_matrix'] = np.vstack((items['np_matrix'], zero_poly)) for idx in zip(*np.where(p.coeff != 0)): idx_term = Term(tuple(idx)) #Get a term object # Grab each non-zero element, put it into matrix. idx_term.val = tuple(map(lambda i: int(i), idx_term.val)) coeff_val = p.coeff[idx_term.val] # If already in term_set if idx_term in items['term_set']: # get index of label and np matrix to put into idx_where = np.argmax( [i.val == idx_term.val for i in items['matrix_terms']]) items['np_matrix'][-1, idx_where] = coeff_val # If new column needed else: # Make new column items['term_set'].add(idx_term) #If r's being added, adds new monomial to the heap if adding_r: if (idx_term not in items['lead_term_set']): items['monheap'].heappush(idx_term) #print(idx_term.val) length_of_matrix = items['np_matrix'].shape[0] if length_of_matrix == 0: items['np_matrix'] = np.zeros((1, 1)) else: zeros = np.zeros((length_of_matrix, 1)) items['np_matrix'] = np.hstack((items['np_matrix'], zeros)) items['matrix_terms'].append(idx_term) items['np_matrix'][-1, -1] = coeff_val print("np_matrix:\n", items['np_matrix']) return items
def calc_phi(a, b, items): '''Calculates the phi-polynomial's of the polynomials a and b. Returns: A tuple of the calculated phi's. ''' lcm = _lcm(a, b) #updated to use monomial multiplication. Will crash for MultiCheb until that gets added a_diff = tuple([i - j for i, j in zip(lcm, a.lead_term)]) b_diff = tuple([i - j for i, j in zip(lcm, b.lead_term)]) #Keeping track of lead_terms if sum(a_diff) == 0 and sum(b_diff) == 0: items['duplicate_lms'].add(Term(a.lead_term)) elif sum(a_diff) == 0: items['not_needed_lms'].add(Term(a.lead_term)) elif sum(b_diff) == 0: items['not_needed_lms'].add(Term(b.lead_term)) return a.mon_mult(a_diff), b.mon_mult(b_diff), items
def test_push_pop(): a0 = Term((0, 0, 1, 0, 0)) a1 = Term((0, 1, 1, 3, 1)) a2 = Term((0, 1, 1, 3, 0, 0, 0, 1)) a3 = Term((2, 2, 2, 3, 4, 1, 4, 3)) a4 = Term((0, 1, 1, 2, 2)) maxh = MaxHeap() maxh.heappush(a1) maxh.heappush(a3) maxh.heappush(a0) maxh.heappush(a2) maxh.heappush(a4) assert maxh.heappop() == a3 assert maxh.heappop() == a2 maxh.heappush(a3) maxh.heappush(a3) assert maxh.heappop() == a3 assert maxh.heappop() == a1 assert maxh.heappop() == a4 assert maxh.heappop() == a0
def update_lead_term(self, start=None): startTime = time.time() found = False non_zeros = set() for i in zip(*np.where(self.coeff != 0)): non_zeros.add(Term(i)) if len(non_zeros) != 0: self.lead_term = max(non_zeros).val self.degree = sum(self.lead_term) self.lead_coeff = self.coeff[tuple(self.lead_term)] else: self.lead_term = None self.lead_coeff = 0 endTime = time.time() times["leadTermCount"] += 1 times["updateLeadTerm"] += (endTime - startTime) """ THE GENERATOR IS BROKEN RIGHT NOW. UNTIL FIXED USE THIS NEW, ALTHOUGH POSSIBLY SLOWER CODE.
def monomialList(self): ''' return ------ monomials : list of tuples list of monomials that make up the polynomial in degrevlex order ''' start = time.time() monomialTerms = list() for i in zip(*np.where(self.coeff != 0)): monomialTerms.append(Term(i)) monomialTerms.sort() monomials = list() for i in monomialTerms[::-1]: monomials.append(i.val) end = time.time() times["monomialsList"] += (end - start) self.sortedMonomials = monomials return monomials
def create_matrix(self): startTime = time.time() biggest_shape = np.maximum.reduce( [p.coeff.shape for p in self.matrix_polys]) if self.power: biggest = MultiPower(np.zeros(biggest_shape), clean_zeros=False) else: biggest = MultiCheb(np.zeros(biggest_shape), clean_zeros=False) self.np_matrix = biggest.coeff.flatten() self.np_matrix = np.array(self.np_matrix, dtype=np.longdouble) flat_polys = list() for poly in self.matrix_polys: startFill = time.time() newMatrix = self.fill_size(biggest.coeff, poly.coeff) flat_polys.append(newMatrix.ravel()) endFill = time.time() times["fill"] += (endFill - startFill) self.np_matrix = np.vstack(flat_polys[::-1]) terms = np.zeros(biggest_shape, dtype=Term) startTerms = time.time() for i, j in np.ndenumerate(terms): terms[i] = Term(i) endTerms = time.time() times["terms"] += (endTerms - startTerms) self.matrix_terms = terms.flatten() self.sort_matrix() self.clean_matrix() self.np_matrix = self.row_swap_matrix(self.np_matrix) endTime = time.time() times["create_matrix"] += (endTime - startTime) pass
def create_matrix(polys): ''' Takes a list of polynomial objects (polys) and uses them to create a matrix. That is ordered by the monomial ordering. Returns the matrix and the matrix_terms, a list of the monomials corresponding to the rows of the matrix. ''' #Gets an empty polynomial whose lm all other polynomial divide into. bigShape = np.maximum.reduce([p.coeff.shape for p in polys]) #Gets a list of all the flattened polynomials. flat_polys = list() for poly in polys: #Gets a matrix that is padded so it is the same size as biggest, and flattens it. This is so #all flattened polynomials look the same. newMatrix = fill_size(bigShape, poly.coeff) flat_polys.append(newMatrix.ravel()) #Make the matrix matrix = np.vstack(flat_polys[::-1]) #Makes matrix_terms, a list of all the terms in the matrix. terms = np.zeros(bigShape, dtype = Term) for i,j in np.ndenumerate(terms): terms[i] = Term(i) matrix_terms = terms.ravel() #Sorts the matrix and matrix_terms by term order. matrix, matrix_terms = sort_matrix(matrix, matrix_terms) #Gets rid of any columns that are all 0. matrix, matrix_terms = clean_matrix(matrix, matrix_terms) #print(matrix) #print(matrix_terms) #Sorts the rows of the matrix so it is close to upper triangular. matrix = row_swap_matrix(matrix) return matrix, matrix_terms
def initialize_np_matrix(self, final_time=False): ''' Initialzes self.np_matrix to having just old_polys and new_polys in it matrix_terms is the header of the matrix, it lines up each column with a monomial Now it sorts through the polynomials and if a polynomial is going to be reduced this time through it adds it and it's reducer to the matrix but doesn't use it for phi or r calculations. This makes the code WAY faster. ''' startTime = time.time() self.matrix_terms = [] self.np_matrix = np.array([]) self.term_set = set() self.lead_term_set = set() self.original_lms = set() self.matrix_polys = list() if final_time: self._add_polys(self.new_polys + self.old_polys) for poly in self.new_polys + self.old_polys: self.original_lms.add(Term(poly.lead_term)) else: old_polys = self.old_polys new_polys = self.new_polys polys = old_polys + new_polys polys = self.sorted_polys_monomial(polys) self.old_polys = list() self.new_polys = list() lms = defaultdict(list) for p in polys: lms[p.lead_term].append(p) pass polys_with_unique_lm = list() for i in lms: if len(lms[i]) > 1: #It's duplicated #self.duplicate_lms.add(Term(i)) self.new_polys.append(lms[i][0]) polys_with_unique_lm.append(lms[i][0]) lms[i].remove(lms[i][0]) self._add_polys( lms[i] ) #Still lets stuff be reduced if a poly reduces all of them. else: polys_with_unique_lm.append(lms[i][0]) divides_out = list() for i, j in itertools.permutations(polys_with_unique_lm, 2): if i in divides_out: continue if self.divides(i, j): # j divides into i startStuff = time.time() divides_out.append(i) self._add_poly_to_matrix(i) self._add_poly_to_matrix( j.mon_mult( tuple(a - b for a, b in zip(i.lead_term, j.lead_term)))) pass for i in polys_with_unique_lm: if i not in divides_out: self._add_poly_to_matrix(i) if i in old_polys: self.old_polys.append(i) elif i in new_polys: self.new_polys.append(i) else: raise ValueError("Where did this poly come from?") endTime = time.time() times["initialize"] += (endTime - startTime) pass