def __call__(self, *args, **kwds): if args and kwds: raise TypeError("You can pass either positional or keyword " "arguments, but not both.") elif len(args or kwds) != self.dimension: raise TypeError("You must pass exactly {} " "value(s) ({} given).".format(self.dimension, len(args or kwds))) elif not args and tuple(sorted(iterkeys(kwds))) != self.letters: diff_set = set(iterkeys(kwds)) - set(self.letters) diff_joint = "', '".join(diff_set) raise TypeError("Invalid letter(s): '{}'".format(diff_joint)) if args: for i, l in enumerate(self.letters): kwds[l] = args[i] if any(not isinstance(v, numbers.Number) for v in itervalues(kwds)): sorted_list = sorted(v for v in itervalues(kwds)\ if not isinstance(v, numbers.Number)) inv_joint = "', '".join(sorted_list) raise TypeError("Invalid value for letter(s): " "'{}'".format(inv_joint)) if not self: return 0 elif self.is_constant(): return sum(m[0] for m in self._monomials) return sum(c * functools.reduce(operator.mul, (kwds[x] ** l[x] for x in l), 1)\ for c, l in self._monomials)
def letters(self): if not self: return () letters = [] for c, ls in self._monomials: for l in iterkeys(ls): if l not in letters: letters.append(l) return tuple(sorted(letters))
def gcd(x, y, *args): if args: return gcd(gcd(x, y), args[0], *args[1:]) if not x and not y: return 1 if isinstance(x, float): x = fractions.Fraction(x).limit_denominator() if isinstance(y, float): y = fractions.Fraction(y).limit_denominator() x = abs(x) if isinstance(x, numbers.Real) else x y = abs(y) if isinstance(y, numbers.Real) else y if x == 0: return y elif y == 0: return x elif isinstance(x, complex) and not x.real and not isinstance(y, complex) or\ isinstance(y, complex) and not y.real and not isinstance(x, complex): return 1 try: if x.is_monomial() and y.is_monomial() or x.is_constant() or y.is_constant(): coeff = gcd(x.monomials[0][0], y.monomials[0][0]) letters = {} for l in iterkeys(x.monomials[0][1]): d_x = x.monomials[0][1][l] d_y = y.monomials[0][1].get(l, 0) letters[l] = min((d_x, d_y)) return x.from_iterable([[coeff, letters]]) except AttributeError: pass if (not isinstance(x, numbers.Number)) ^\ (not isinstance(y, numbers.Number)): try: integer, poly = (x, y) if isinstance(x, numbers.Number) else (y, x) return gcd(functools.reduce(gcd, poly.coefficients), integer) except AttributeError: pass while True: r = x % y degree = y.degree if hasattr(y, "degree") else 1 if not r and degree == 1: return y elif not degree: return 1 x, y = y, r
def sort(self, letter=None, reverse=False): if letter is not None and (not is_letter_valid(letter) or\ letter not in self.letters): raise ValueError("The letter must be a single letter from the " "alphabet contained in the Polynomial.") elif len(self) in (0, 1): return elif self.is_constant(): return def _sort(monomials, letter=None): if letter is None: return sorted((m for m in monomials if not m[1]), key=lambda m: m[0], reverse=True) return sorted((m for m in monomials if letter in m[1]), key=lambda m: m[1][letter], reverse=True) degrees = self.all_max_letter_degrees letters = sorted(iterkeys(degrees), key=lambda l: (degrees[l], 255 - ord(l)), reverse=True) preferenced_letters = sorted(l for l in letters\ if l in self.preferenced_letters) if preferenced_letters and letter is None: letter = preferenced_letters.pop(0) elif letter is None: letter = letters[0] letters.remove(letter) lower_letters = [l for l in letters\ if l.islower() and l not in preferenced_letters] upper_letters = [l for l in letters\ if l.isupper() and l not in preferenced_letters] letters = [letter] + preferenced_letters +\ lower_letters + upper_letters monomials = [] for l in letters: for m in _sort(self._monomials, l): if m not in monomials: monomials.append(m) for m in _sort(self._monomials): if m not in monomials: monomials.append(m) if reverse: monomials.reverse() self._monomials = monomials
def __repr__(self): if not self: return "0" poly_str = "" for m in self._monomials: mono_str = ("+ " if m[0] >= 0 and poly_str else "") +\ str(m[0]).replace("-", "- ") if m[1] and m[0] in (1, -1): mono_str = mono_str.replace("1", "") for l in sorted(iterkeys(m[1])): mono_str += l if m[1][l] == 1: continue mono_str += "^" + str(m[1][l]) poly_str += " " + mono_str return poly_str[1:]