From b23d83b9da037dace578ebb492c105054615ef67 Mon Sep 17 00:00:00 2001 From: Bertrand Benjamin Date: Tue, 13 Nov 2018 16:19:02 +0100 Subject: [PATCH] Feat(Compute): Add polynoms with polynoms --- mapytex/calculus/core/MO/polynomial.py | 16 +- mapytex/calculus/core/compute/add.py | 458 +++++++++++++++++++++++-- 2 files changed, 446 insertions(+), 28 deletions(-) diff --git a/mapytex/calculus/core/MO/polynomial.py b/mapytex/calculus/core/MO/polynomial.py index 2f1b414..0893180 100644 --- a/mapytex/calculus/core/MO/polynomial.py +++ b/mapytex/calculus/core/MO/polynomial.py @@ -53,16 +53,16 @@ class MOpolynomial(MO): raise TypeError("Coefs needs to be a dictionnary or a list") self._coefs = _coefs - monomials = [] + monomials = {} for deg, coef in self._coefs.items(): if deg == 0: - monomials.append(coef) + monomials[deg] = coef else: - monomials.append( - MOMonomial(coef, self._variable, deg) - ) + monomials[deg] = MOMonomial(coef, self._variable, deg) - tree = Tree.from_list("+", monomials[::-1]) + self._monomials = monomials + + tree = Tree.from_list("+", list(self._monomials.values())[::-1]) MO.__init__(self, tree) @property @@ -77,6 +77,10 @@ class MOpolynomial(MO): def coefficients(self): return self._coefs + @property + def monomials(self): + return self._monomials + # ----------------------------- # Reglages pour 'vim' diff --git a/mapytex/calculus/core/compute/add.py b/mapytex/calculus/core/compute/add.py index 35695b4..55a6c6a 100644 --- a/mapytex/calculus/core/compute/add.py +++ b/mapytex/calculus/core/compute/add.py @@ -55,6 +55,11 @@ def add_filter(left, right): return left except TypeError: pass + try: + if left.variable != right.variable: + raise NotImplementedError("Can't add 2 polynomes with not same letter") + except AttributeError: + pass @add.register(MOnumber, MOnumber) @special_case(add_filter) @@ -231,21 +236,216 @@ def mostrpower_mostrpower(left, right): >>> add(a, b) """ - if left.variable != right.variable: - raise NotImplementedError("Can't add 2 MOstrPower with not same letter") if left.power != right.power: raise NotImplementedError("Can't add 2 MOstrPower with not same power") return MOMonomial(2, left.variable, left.power) @add.register((MOnumber, MOFraction), MOpolynomial) @special_case(add_filter) -def monumber_mofraction(left, right): +def moscalar_mopolynomial(left, right): """ Add a scalar to a polynomial :example: >>> a = MOnumber(1) >>> b = MOpolynomial("x", [2, 3, 4]) >>> print(add(a, b)) + + + > * + | > 4 + | > ^ + | | > x + | | > 2 + > + + | > * + | | > 3 + | | > x + | > + + | | > 1 + | | > 2 + """ + if 0 not in right.coefficients.keys(): + raise NotImplementedError("Polynomial with no constant, no calculus to do") + + right_const = right.monomials[0] + right_top = [mo for deg, mo in right.monomials.items() if deg > 0][::-1] + + adds = right_top + [Tree("+", left, right_const)] + return Tree.from_list('+', adds) + +@add.register(MOpolynomial, (MOnumber, MOFraction)) +@special_case(add_filter) +def mopolynomial_moscalar(left, right): + """ Add a scalar to a polynomial + + :example: + >>> a = MOpolynomial("x", [2, 3, 4]) + >>> b = MOnumber(1) + >>> print(add(a, b)) + + + > * + | > 4 + | > ^ + | | > x + | | > 2 + > + + | > * + | | > 3 + | | > x + | > + + | | > 2 + | | > 1 + """ + if 0 not in left.coefficients.keys(): + raise NotImplementedError("Polynomial with no constant, no calculus to do") + + left_const = left.monomials[0] + left_top = [mo for deg, mo in left.monomials.items() if deg > 0][::-1] + + adds = left_top + [Tree("+", left_const, right)] + return Tree.from_list('+', adds) + +@add.register(MOstr, MOpolynomial) +@special_case(add_filter) +def mostr_mopolynomial(left, right): + """ Add a str to a polynomial + + :example: + >>> a = MOstr("x") + >>> b = MOpolynomial("x", [2, 3, 4]) + >>> print(add(a, b)) + + + > * + | > 4 + | > ^ + | | > x + | | > 2 + > + + | > + + | | > x + | | > * + | | | > 3 + | | | > x + | > 2 + """ + if 1 not in right.coefficients.keys(): + raise NotImplementedError("Polynomial with no constant, no calculus to do") + + right_coef = right.monomials[1] + add_coefs = Tree("+", left, right_coef) + + right_top = [mo for deg, mo in right.monomials.items() if deg > 1][::-1] + right_bot = [mo for deg, mo in right.monomials.items() if deg < 1][::-1] + + adds = right_top + [add_coefs] + right_bot + + return Tree.from_list("+", adds) + +@add.register(MOpolynomial, MOstr) +@special_case(add_filter) +def mopolynomial_mostr(left, right): + """ Add a str to a polynomial + + :example: + >>> a = MOpolynomial("x", [2, 3, 4]) + >>> b = MOstr("x") + >>> print(add(a, b)) + + + > * + | > 4 + | > ^ + | | > x + | | > 2 + > + + | > + + | | > * + | | | > 3 + | | | > x + | | > x + | > 2 + """ + if 1 not in left.coefficients.keys(): + raise NotImplementedError("No degree in common") + + left_coef = left.monomials[1] + add_coefs = Tree("+", left_coef, right) + + left_top = [mo for deg, mo in left.monomials.items() if deg > 1][::-1] + left_bot = [mo for deg, mo in left.monomials.items() if deg < 1][::-1] + + adds = left_top + [add_coefs] + left_bot + + return Tree.from_list("+", adds) + +@add.register(MOstrPower, MOpolynomial) +@special_case(add_filter) +def mostrpower_mopolynomial(left, right): + """ Add a strpower to a polynomial + + :example: + >>> a = MOstrPower("x", 2) + >>> b = MOpolynomial("x", [2, 3, 4]) + >>> print(add(a, b)) + + + > + + | > ^ + | | > x + | | > 2 + | > * + | | > 4 + | | > ^ + | | | > x + | | | > 2 + > + + | > * + | | > 3 + | | > x + | > 2 + >>> b = MOpolynomial("x", [2, 3, 4, 5]) + >>> print(add(a, b)) + + + > + + | > * + | | > 5 + | | > ^ + | | | > x + | | | > 3 + | > + + | | > ^ + | | | > x + | | | > 2 + | | > * + | | | > 4 + | | | > ^ + | | | | > x + | | | | > 2 + > + + | > * + | | > 3 + | | > x + | > 2 + """ + if left.power not in right.coefficients.keys(): + raise NotImplementedError("No degree in common") + + right_mono = right.monomials[left.power] + add_coefs = Tree("+", left, right_mono) + + right_top = [mo for deg, mo in right.monomials.items() if deg > left.power][::-1] + right_bot = [mo for deg, mo in right.monomials.items() if deg < left.power][::-1] + + adds = right_top + [add_coefs] + right_bot + + return Tree.from_list("+", adds) + +@add.register(MOpolynomial, MOstrPower) +@special_case(add_filter) +def mopolynomial_mostrpower(left, right): + """ Add a strpower to a polynomial + + :example: + >>> a = MOpolynomial("x", [2, 3, 4]) + >>> b = MOstrPower("x", 2) + >>> print(add(a, b)) + > + | > * @@ -253,31 +453,124 @@ def monumber_mofraction(left, right): | | > ^ | | | > x | | | > 2 + | > ^ + | | > x + | | > 2 + > + | > * | | > 3 | | > x + | > 2 + >>> a = MOpolynomial("x", [2, 3, 4, 5]) + >>> print(add(a, b)) + + > + - | > 1 + | > * + | | > 5 + | | > ^ + | | | > x + | | | > 3 + | > + + | | > * + | | | > 4 + | | | > ^ + | | | | > x + | | | | > 2 + | | > ^ + | | | > x + | | | > 2 + > + + | > * + | | > 3 + | | > x | > 2 """ - if 0 not in right.coefficients.keys(): - raise NotImplementedError("Polynomial with no constant, no calculus to do") + if right.power not in left.coefficients.keys(): + raise NotImplementedError("No degree in common") - right_const = right.coefficients[0] - right_other = {k:v for k,v in right.coefficients.items() if k != 0} - right_remain = MOpolynomial(right.variable, right_other) + left_mono = left.monomials[right.power] + add_coefs = Tree("+", left_mono, right) - add_consts = Tree("+", left, right_const) - return Tree('+', right_remain, add_consts) + left_top = [mo for deg, mo in left.monomials.items() if deg > right.power][::-1] + left_bot = [mo for deg, mo in left.monomials.items() if deg < right.power][::-1] -@add.register(MOpolynomial, (MOnumber, MOFraction)) + adds = left_top + [add_coefs] + left_bot + + return Tree.from_list("+", adds) + +@add.register(MOMonomial, MOpolynomial) @special_case(add_filter) -def monumber_mofraction(left, right): - """ Add a scalar to a polynomial +def momonomial_mopolynomial(left, right): + """ Add a monomial to a polynomial + + :example: + >>> a = MOMonomial(10, "x", 2) + >>> b = MOpolynomial("x", [2, 3, 4]) + >>> print(add(a, b)) + + + > + + | > * + | | > 10 + | | > ^ + | | | > x + | | | > 2 + | > * + | | > 4 + | | > ^ + | | | > x + | | | > 2 + > + + | > * + | | > 3 + | | > x + | > 2 + >>> b = MOpolynomial("x", [2, 3, 4, 5]) + >>> print(add(a, b)) + + + > + + | > * + | | > 5 + | | > ^ + | | | > x + | | | > 3 + | > + + | | > * + | | | > 10 + | | | > ^ + | | | | > x + | | | | > 2 + | | > * + | | | > 4 + | | | > ^ + | | | | > x + | | | | > 2 + > + + | > * + | | > 3 + | | > x + | > 2 + """ + if left.power not in right.coefficients.keys(): + raise NotImplementedError("No degree in common") + + right_mono = right.monomials[left.power] + add_coefs = Tree("+", left, right_mono) + + right_top = [mo for deg, mo in right.monomials.items() if deg > left.power][::-1] + right_bot = [mo for deg, mo in right.monomials.items() if deg < left.power][::-1] + + adds = right_top + [add_coefs] + right_bot + + return Tree.from_list("+", adds) + +@add.register(MOpolynomial, MOMonomial) +@special_case(add_filter) +def mopolynomial_momonomial(left, right): + """ Add a monomial to a polynomial :example: >>> a = MOpolynomial("x", [2, 3, 4]) - >>> b = MOnumber(1) + >>> b = MOMonomial(10, "x", 2) >>> print(add(a, b)) + > + @@ -287,21 +580,142 @@ def monumber_mofraction(left, right): | | | > x | | | > 2 | > * + | | > 10 + | | > ^ + | | | > x + | | | > 2 + > + + | > * | | > 3 | | > x + | > 2 + >>> a = MOpolynomial("x", [2, 3, 4, 5]) + >>> print(add(a, b)) + + > + - | > 1 + | > * + | | > 5 + | | > ^ + | | | > x + | | | > 3 + | > + + | | > * + | | | > 4 + | | | > ^ + | | | | > x + | | | | > 2 + | | > * + | | | > 10 + | | | > ^ + | | | | > x + | | | | > 2 + > + + | > * + | | > 3 + | | > x | > 2 """ - if 0 not in left.coefficients.keys(): + if right.power not in left.coefficients.keys(): + raise NotImplementedError("No degree in common") + + left_mono = left.monomials[right.power] + add_coefs = Tree("+", left_mono, right) + + left_top = [mo for deg, mo in left.monomials.items() if deg > right.power][::-1] + left_bot = [mo for deg, mo in left.monomials.items() if deg < right.power][::-1] + + adds = left_top + [add_coefs] + left_bot + + return Tree.from_list("+", adds) + +@add.register(MOpolynomial, MOpolynomial) +@special_case(add_filter) +def mopolynomial_mopolynomial(left, right): + """ Add a polynomial to a polynomial + + :example: + >>> a = MOpolynomial("x", [2, 3, 4]) + >>> b = MOpolynomial("x", [5, 6, 7]) + >>> print(add(a, b)) + + + > + + | > * + | | > 4 + | | > ^ + | | | > x + | | | > 2 + | > * + | | > 7 + | | > ^ + | | | > x + | | | > 2 + > + + | > + + | | > * + | | | > 3 + | | | > x + | | > * + | | | > 6 + | | | > x + | > + + | | > 2 + | | > 5 + >>> b = MOpolynomial("x", [0, 3, 4]) + >>> print(add(a, b)) + + + > + + | > * + | | > 4 + | | > ^ + | | | > x + | | | > 2 + | > * + | | > 4 + | | > ^ + | | | > x + | | | > 2 + > + + | > + + | | > * + | | | > 3 + | | | > x + | | > * + | | | > 3 + | | | > x + | > 2 + >>> b = MOpolynomial("x", [0, 3, 0, 5]) + >>> print(add(a, b)) + + + > + + | > * + | | > 5 + | | > ^ + | | | > x + | | | > 3 + | > * + | | > 4 + | | > ^ + | | | > x + | | | > 2 + > + + | > + + | | > * + | | | > 3 + | | | > x + | | > * + | | | > 3 + | | | > x + | > 2 + """ + common_degree = set(left.monomials.keys()).intersection(right.monomials.keys()) + if not common_degree: raise NotImplementedError("Polynomial with no constant, no calculus to do") - left_const = left.coefficients[0] - left_other = {k:v for k,v in left.coefficients.items() if k != 0} - left_remain = MOpolynomial(left.variable, left_other) + merge_monomials = {**left.monomials, **right.monomials} + for deg in common_degree: + merge_monomials[deg] = Tree("+", left.monomials[deg], right.monomials[deg]) - add_consts = Tree("+", right, left_const) - return Tree('+', left_remain, add_consts) + return Tree.from_list("+", list(merge_monomials.values())[::-1]) # ----------------------------- # Reglages pour 'vim'