def __add__(self, other): if type(other) == Polynomial: if len(self.term_matrix[0]) > 1 and len(other.term_matrix[0]) > 1: var_set = set(self.term_matrix[0][1:]).union( set(other.term_matrix[0][1:])) res = [[self.term_matrix[0][0]] + sorted(list(var_set))] elif len(self.term_matrix[0]) > 1 and len( other.term_matrix[0]) < 2: res = [self.term_matrix[0]] elif len(other.term_matrix[0]) > 1 and len( self.term_matrix[0]) < 2: res = [other.term_matrix[0]] else: res = [self.term_matrix[0]] # first add variables to both, then order both, then combine both self_copy, other_copy = Polynomial.combine_variables(self, other) if len(self.term_matrix) != 1: res += self_copy.term_matrix[1:] if len(other.term_matrix) != 1: res += other_copy.term_matrix[1:] res = collect_like_terms(res) res = order(res) res = self.mod_char(res) else: return self + Polynomial(other, self.field_characteristic) return Polynomial(res, self.field_characteristic)
def __iter__(self): """ yields terms of the polynomial as individual polynomials """ terms = iter(self.term_matrix) variables = next(terms) for term in terms: p = [variables, term] yield Polynomial(collect_like_terms(p))
def __call__(self, *args, **kwargs): """ input is variables as key word arguments, e.g. "x = 2, y = 3" """ if self.degree() == 0: return self if args: res = self.copy() for variable_number, v in enumerate(args): if type(v) == Integer or type(v) == Rational or type( v) == int or type(v) == float or type(v) == complex: for i in range(1, len(res.term_matrix)): res.term_matrix[i][0] *= v**res.term_matrix[i][ variable_number + 1] res.term_matrix[i][variable_number + 1] = 0 elif type(v) == Polynomial: kwargs.update({res.term_matrix[0][variable_number + 1]: v}) res.term_matrix = collect_like_terms(res.term_matrix) res.term_matrix = order(res.term_matrix) if len(res.variables) == 0: if res == 0: return 0 return res.term_matrix[1][0] if kwargs: res = self.copy() for v in kwargs: if v in res.term_matrix[0]: j = res.term_matrix[0].index(v) for i in range(1, len(res.term_matrix)): res.term_matrix[i][0] *= kwargs[v]**res.term_matrix[i][ j] res.term_matrix[i][j] = 0 res.term_matrix = collect_like_terms(res.term_matrix) res.term_matrix = order(res.term_matrix) if len(res.variables) == 0: if len(res.term_matrix) < 2: return 0 return res.term_matrix[1][0] return res
def mod_char(self, term_matrix): """ mods the term_matrix by the field characteristic if it's greater than 0 """ if self.field_characteristic > 0: term_matrix_iter = iter(term_matrix) next(term_matrix_iter) for term in term_matrix_iter: term[0] %= self.field_characteristic term_matrix = collect_like_terms(term_matrix) return term_matrix else: return term_matrix
def __mul__(self, other): if type(other) == Polynomial: # first add variables and order self_copy, other_copy = Polynomial.combine_variables(self, other) res = [self_copy.term_matrix[0]] # then distribute that multiplication for term in self_copy.term_matrix[1:]: for other_term in other_copy.term_matrix[1:]: product = list() product.append(term[0] * other_term[0]) for i in range(1, len(term)): product.append(term[i] + other_term[i]) res.append(product) res = collect_like_terms(res) res = order(res) else: return self * Polynomial(other, self.field_characteristic) res = self.mod_char(res) return Polynomial(res, self.field_characteristic)
def derivative(self, var=None): """ returns the (partial) derivative with respect to var """ if not var: var = self.term_matrix[0][1] res = self.copy() # get the index of the variable if var not in res.term_matrix[0]: return Polynomial('0') variable_index = res.term_matrix[0].index(var) # iterate through the terms for i in range(1, len(res.term_matrix)): # if variable power not zero, multiply the constant by the power, lower the power if res.term_matrix[i][variable_index] != 0: res.term_matrix[i][0] *= res.term_matrix[i][variable_index] res.term_matrix[i][variable_index] -= 1 # else, set term equal to zero else: for j in range(len(res.term_matrix[i])): res.term_matrix[i][j] = 0 res.term_matrix = collect_like_terms(res.term_matrix) return res
def isolate(self, variable): """ isolates a single variable, not necessarily in self returns a polynomial of one variable with polynomial constant terms """ poly = self.copy() if variable in poly.variables: i = poly.term_matrix[0].index(variable) else: return self if i != len(poly.variables): remaining_vars = poly.term_matrix[0][:i] + poly.term_matrix[0][i + 1:] else: remaining_vars = poly.term_matrix[0][:i] res = Polynomial([['constant', variable]], poly.field_characteristic) for term in poly.term_matrix[1:]: variable_power = term.pop(i) res.term_matrix += [[ Polynomial(Polynomial.clean([remaining_vars, term])), variable_power ]] res.term_matrix = collect_like_terms(res.term_matrix) return res