Style: apply black
This commit is contained in:
		| @@ -15,6 +15,7 @@ from ..coroutine import coroutine, STOOOP | ||||
|  | ||||
| __all__ = ["moify", "MOnumber", "MOstr"] | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| def moify(target): | ||||
|     """ Coroutine which try to convert a parsed token into an MO  | ||||
| @@ -47,6 +48,7 @@ def moify(target): | ||||
|     except STOOOP as err: | ||||
|         yield target_.throw(err) | ||||
|  | ||||
|  | ||||
| @total_ordering | ||||
| class MOnumber(Atom): | ||||
|  | ||||
| @@ -116,8 +118,10 @@ class MOnumber(Atom): | ||||
|         elif isinstance(value, float): | ||||
|             Atom.__init__(self, Decimal(value)) | ||||
|         else: | ||||
|             raise MOError("The value of an MOnumber need to be a int, a float or a Decimal", | ||||
|                             f"(got {type(value)})") | ||||
|             raise MOError( | ||||
|                 "The value of an MOnumber need to be a int, a float or a Decimal", | ||||
|                 f"(got {type(value)})", | ||||
|             ) | ||||
|  | ||||
|         self._signature = "scalar" | ||||
|  | ||||
| @@ -215,9 +219,13 @@ class MOstr(Atom): | ||||
|             val = value | ||||
|  | ||||
|         if not isinstance(val, str): | ||||
|             raise MOError(f"An MOstr should be initiate with a string - the unknown, got {val}") | ||||
|             raise MOError( | ||||
|                 f"An MOstr should be initiate with a string - the unknown, got {val}" | ||||
|             ) | ||||
|         if len(val) != 1: | ||||
|             raise MOError(f"An MOstr should be initiate with a single caracter string, got {val}") | ||||
|             raise MOError( | ||||
|                 f"An MOstr should be initiate with a single caracter string, got {val}" | ||||
|             ) | ||||
|         if not val.isalpha(): | ||||
|             raise MOError(f"An MOstr should be initiate with a alpha string, got {val}") | ||||
|  | ||||
|   | ||||
| @@ -10,6 +10,7 @@ | ||||
| Exceptions for core tools | ||||
| """ | ||||
|  | ||||
|  | ||||
| class MOError(Exception): | ||||
|     pass | ||||
|  | ||||
|   | ||||
| @@ -11,6 +11,7 @@ from .mo import Molecule, MO | ||||
|  | ||||
| __all__ = ["MOFraction"] | ||||
|  | ||||
|  | ||||
| class MOFraction(Molecule): | ||||
|  | ||||
|     """ Fraction math object""" | ||||
| @@ -42,10 +43,7 @@ class MOFraction(Molecule): | ||||
|         """ | ||||
|         _numerator = MO.factory(numerator) | ||||
|         _denominator = MO.factory(denominator) | ||||
|         base_tree = Tree("/", | ||||
|                           _numerator, | ||||
|                           _denominator, | ||||
|                          ) | ||||
|         base_tree = Tree("/", _numerator, _denominator) | ||||
|         if negative: | ||||
|             tree = Tree("-", None, base_tree) | ||||
|         else: | ||||
| @@ -71,9 +69,8 @@ class MOFraction(Molecule): | ||||
|  | ||||
|     def inverse(self): | ||||
|         """ return the inverse fraction """ | ||||
|         return MOFraction(self._denominator, | ||||
|                 self._numerator,  | ||||
|                 self.negative) | ||||
|         return MOFraction(self._denominator, self._numerator, self.negative) | ||||
|  | ||||
|  | ||||
| # ----------------------------- | ||||
| # Reglages pour 'vim' | ||||
|   | ||||
| @@ -12,6 +12,7 @@ from ..renders import tree2txt, tree2tex | ||||
|  | ||||
| __all__ = ["MO"] | ||||
|  | ||||
|  | ||||
| class MO(ABC): | ||||
|  | ||||
|     """MO for math object | ||||
| @@ -50,7 +51,6 @@ class MO(ABC): | ||||
|  | ||||
|         return Atom.factory(value) | ||||
|  | ||||
|  | ||||
|     @abstractmethod | ||||
|     def content(self): | ||||
|         """ content of the mo """ | ||||
| @@ -97,6 +97,7 @@ class MO(ABC): | ||||
|         """ | ||||
|         return self._signature | ||||
|  | ||||
|  | ||||
| class Atom(MO): | ||||
|  | ||||
|     """ Base Math Object with only one component. | ||||
| @@ -196,8 +197,6 @@ class Molecule(MO): | ||||
|         return tree2tex(self._tree) | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| # ----------------------------- | ||||
| # Reglages pour 'vim' | ||||
| # vim:set autoindent expandtab tabstop=4 shiftwidth=4: | ||||
|   | ||||
| @@ -13,6 +13,7 @@ from .exceptions import MOError | ||||
|  | ||||
| __all__ = ["MOMonomial"] | ||||
|  | ||||
|  | ||||
| class MOstrPower(Molecule): | ||||
|  | ||||
|     """ Power of a MOstr """ | ||||
| @@ -68,10 +69,7 @@ class MOstrPower(Molecule): | ||||
|             raise MOError("The power of a monomial should be a integer") | ||||
|         self._power = _power | ||||
|  | ||||
|         _tree = Tree("^", | ||||
|                      self._variable, | ||||
|                      self._power, | ||||
|                      ) | ||||
|         _tree = Tree("^", self._variable, self._power) | ||||
|  | ||||
|         Molecule.__init__(self, _tree) | ||||
|  | ||||
| @@ -113,6 +111,7 @@ class MOstrPower(Molecule): | ||||
|         """ | ||||
|         return f"monome{self.power}" | ||||
|  | ||||
|  | ||||
| class MOMonomial(Molecule): | ||||
|  | ||||
|     """ Monomial math object""" | ||||
| @@ -164,7 +163,9 @@ class MOMonomial(Molecule): | ||||
|         if coefficient == 0: | ||||
|             raise MOError("The coefficient of a monomial should not be 0") | ||||
|         elif coefficient == 1: | ||||
|             raise MOError("The coefficient of a monomial should not be 1, it is a MOstrPower or MOstr") | ||||
|             raise MOError( | ||||
|                 "The coefficient of a monomial should not be 1, it is a MOstrPower or MOstr" | ||||
|             ) | ||||
|         self._coefficient = _coefficient | ||||
|  | ||||
|         _variable = MO.factory(variable) | ||||
| @@ -174,7 +175,9 @@ class MOMonomial(Molecule): | ||||
|         elif isinstance(_variable, MOstr): | ||||
|             _power = MO.factory(power) | ||||
|         else: | ||||
|             raise MOError(f"variable need to be a MOstrPower or a MOstr. Got {type(variable)}.") | ||||
|             raise MOError( | ||||
|                 f"variable need to be a MOstrPower or a MOstr. Got {type(variable)}." | ||||
|             ) | ||||
|  | ||||
|         self._variable = _variable | ||||
|         self._power = _power | ||||
| @@ -187,10 +190,8 @@ class MOMonomial(Molecule): | ||||
|         except AttributeError: | ||||
|             _tree = Tree("*", self._coefficient, self.strpower) | ||||
|  | ||||
|  | ||||
|         Molecule.__init__(self, _tree) | ||||
|  | ||||
|  | ||||
|     def __str__(self): | ||||
|         if self._coefficient != -1: | ||||
|             return super(MOMonomial, self).__str__() | ||||
| @@ -244,6 +245,7 @@ class MOMonomial(Molecule): | ||||
|     @property | ||||
|     def degree(self): | ||||
|         return self._power.value | ||||
|  | ||||
|     @property | ||||
|     def signature(self): | ||||
|         """ Name of the mo in the API | ||||
| @@ -256,6 +258,7 @@ class MOMonomial(Molecule): | ||||
|         """ | ||||
|         return f"monome{self.power}" | ||||
|  | ||||
|  | ||||
| # ----------------------------- | ||||
| # Reglages pour 'vim' | ||||
| # vim:set autoindent expandtab tabstop=4 shiftwidth=4: | ||||
|   | ||||
| @@ -14,6 +14,7 @@ from .monomial import MOMonomial, MOstrPower | ||||
|  | ||||
| __all__ = ["MOpolynomial"] | ||||
|  | ||||
|  | ||||
| class MOpolynomial(Molecule): | ||||
|  | ||||
|     """ MO polynomial""" | ||||
| @@ -45,11 +46,13 @@ class MOpolynomial(Molecule): | ||||
|         self._variable = _variable | ||||
|  | ||||
|         if isinstance(coefs, dict): | ||||
|             _coefs = {MO.factory(d): MO.factory(c) for (d, c) in coefs.items() | ||||
|                       if c != 0 } | ||||
|             _coefs = { | ||||
|                 MO.factory(d): MO.factory(c) for (d, c) in coefs.items() if c != 0 | ||||
|             } | ||||
|         elif isinstance(coefs, list): | ||||
|             _coefs = {MO.factory(d): MO.factory(c) for (d, c) in enumerate(coefs) | ||||
|                       if c != 0 } | ||||
|             _coefs = { | ||||
|                 MO.factory(d): MO.factory(c) for (d, c) in enumerate(coefs) if c != 0 | ||||
|             } | ||||
|         else: | ||||
|             raise TypeError("Coefs needs to be a dictionnary or a list") | ||||
|         self._coefs = _coefs | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
| # encoding: utf-8 | ||||
|  | ||||
|  | ||||
| __all__ = ['gcd'] | ||||
| __all__ = ["gcd"] | ||||
|  | ||||
|  | ||||
| def gcd(a, b): | ||||
| @@ -28,7 +28,7 @@ def gcd(a, b): | ||||
|         pos_a, _a = (a >= 0), abs(a) | ||||
|         pos_b, _b = (b >= 0), abs(b) | ||||
|  | ||||
|         gcd_sgn = (-1 + 2 * (pos_a or pos_b)) | ||||
|         gcd_sgn = -1 + 2 * (pos_a or pos_b) | ||||
|     except TypeError: | ||||
|         _a = a | ||||
|         _b = b | ||||
| @@ -48,6 +48,7 @@ def gcd(a, b): | ||||
|     else: | ||||
|         return gcd_sgn * gcd(min(_a, _b), c) | ||||
|  | ||||
|  | ||||
| def lcm(a, b): | ||||
|     """Compute lcm(a,b) | ||||
|  | ||||
| @@ -69,7 +70,8 @@ def lcm(a, b): | ||||
|     """ | ||||
|     return (a * b) // gcd(a, b) | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     print(gcd(3, 15)) | ||||
|     print(gcd(3, 15)) | ||||
|     print(gcd(-15, -3)) | ||||
|   | ||||
| @@ -25,15 +25,10 @@ from ..MO.polynomial import MOpolynomial | ||||
| from itertools import product | ||||
| from tabulate import tabulate | ||||
|  | ||||
| MOS = [ MOnumber, MOstr, MOFraction, MOstrPower, MOMonomial, MOpolynomial] | ||||
| MOS = [MOnumber, MOstr, MOFraction, MOstrPower, MOMonomial, MOpolynomial] | ||||
|  | ||||
| OPERATIONS = {"+": add, "-": minus, "*": multiply, "/": divide, "^": power} | ||||
|  | ||||
| OPERATIONS = { | ||||
|         "+": add, | ||||
|         "-": minus, | ||||
|         "*": multiply, | ||||
|         "/": divide, | ||||
|         "^": power, | ||||
|         } | ||||
|  | ||||
| def compute(node, left_v, right_v): | ||||
|     """  | ||||
| @@ -60,6 +55,7 @@ def compute(node, left_v, right_v): | ||||
|  | ||||
|     return operation(left_v, right_v) | ||||
|  | ||||
|  | ||||
| def compute_capacities(node): | ||||
|     """ Test an operation through all MOs  | ||||
|  | ||||
| @@ -72,21 +68,19 @@ def compute_capacities(node): | ||||
|  | ||||
|     """ | ||||
|     op = OPERATIONS[node] | ||||
|     lines =  [[node] + [mo.__name__ for mo in MOS]] | ||||
|     lines = [[node] + [mo.__name__ for mo in MOS]] | ||||
|     for left_mo in MOS: | ||||
|        lines.append( | ||||
|            [left_mo.__name__] + \ | ||||
|            [(left_mo, i) in op.funcs for i in MOS] | ||||
|        ) | ||||
|         lines.append([left_mo.__name__] + [(left_mo, i) in op.funcs for i in MOS]) | ||||
|     return lines | ||||
|  | ||||
|  | ||||
| def describe_compute(): | ||||
|     """ Explain which operation are handle by compue """ | ||||
|  | ||||
|     ans = "Implemented compute operations among MOs" | ||||
|     for op in OPERATIONS: | ||||
|         ans += "\n" | ||||
|         ans += tabulate(compute_capacities(op), tablefmt='grid') | ||||
|         ans += tabulate(compute_capacities(op), tablefmt="grid") | ||||
|     return ans | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -29,6 +29,7 @@ add_doc = """ Adding MOs | ||||
|  | ||||
| add = Dispatcher("add", doc=add_doc) | ||||
|  | ||||
|  | ||||
| def add_filter(left, right): | ||||
|     """ Automatic add on MO | ||||
|  | ||||
| @@ -59,6 +60,7 @@ def add_filter(left, right): | ||||
|     except AttributeError: | ||||
|         pass | ||||
|  | ||||
|  | ||||
| @add.register(MOnumber, MOnumber) | ||||
| @special_case(add_filter) | ||||
| def monumber_monumber(left, right): | ||||
| @@ -72,6 +74,7 @@ def monumber_monumber(left, right): | ||||
|     """ | ||||
|     return MO.factory(left.value + right.value) | ||||
|  | ||||
|  | ||||
| @add.register(MOnumber, MOFraction) | ||||
| @special_case(add_filter) | ||||
| def monumber_mofraction(left, right): | ||||
| @@ -87,6 +90,7 @@ def monumber_mofraction(left, right): | ||||
|     left_fraction = MOFraction(left, MOnumber(1)) | ||||
|     return Tree("+", left_fraction, right) | ||||
|  | ||||
|  | ||||
| @add.register(MOFraction, MOnumber) | ||||
| @special_case(add_filter) | ||||
| def mofraction_monumber(left, right): | ||||
| @@ -103,6 +107,7 @@ def mofraction_monumber(left, right): | ||||
|     right_fraction = MOFraction(right, MOnumber(1)) | ||||
|     return Tree("+", left, right_fraction) | ||||
|  | ||||
|  | ||||
| @add.register(MOFraction, MOFraction) | ||||
| @special_case(add_filter) | ||||
| def mofraction_mofraction(left, right): | ||||
| @@ -200,6 +205,7 @@ def mofraction_mofraction(left, right): | ||||
|  | ||||
|     return Tree("+", left_frac, right_frac) | ||||
|  | ||||
|  | ||||
| @add.register(MOstr, MOstr) | ||||
| @special_case(add_filter) | ||||
| def mostr_mostr(left, right): | ||||
| @@ -215,6 +221,7 @@ def mostr_mostr(left, right): | ||||
|         raise NotImplementedError("Can't add 2 MOstr with not same letter") | ||||
|     return MOMonomial(2, left) | ||||
|  | ||||
|  | ||||
| @add.register(MOstrPower, MOstrPower) | ||||
| @special_case(add_filter) | ||||
| def mostrpower_mostrpower(left, right): | ||||
| @@ -230,6 +237,7 @@ def mostrpower_mostrpower(left, right): | ||||
|         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 moscalar_mopolynomial(left, right): | ||||
| @@ -254,7 +262,8 @@ def moscalar_mopolynomial(left, right): | ||||
|     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) | ||||
|     return Tree.from_list("+", adds) | ||||
|  | ||||
|  | ||||
| @add.register(MOpolynomial, (MOnumber, MOFraction)) | ||||
| @special_case(add_filter) | ||||
| @@ -280,7 +289,8 @@ def mopolynomial_moscalar(left, right): | ||||
|     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) | ||||
|     return Tree.from_list("+", adds) | ||||
|  | ||||
|  | ||||
| @add.register(MOstr, MOpolynomial) | ||||
| @special_case(add_filter) | ||||
| @@ -313,6 +323,7 @@ def mostr_mopolynomial(left, right): | ||||
|  | ||||
|     return Tree.from_list("+", adds) | ||||
|  | ||||
|  | ||||
| @add.register(MOpolynomial, MOstr) | ||||
| @special_case(add_filter) | ||||
| def mopolynomial_mostr(left, right): | ||||
| @@ -344,6 +355,7 @@ def mopolynomial_mostr(left, right): | ||||
|  | ||||
|     return Tree.from_list("+", adds) | ||||
|  | ||||
|  | ||||
| @add.register(MOstrPower, MOpolynomial) | ||||
| @special_case(add_filter) | ||||
| def mostrpower_mopolynomial(left, right): | ||||
| @@ -387,6 +399,7 @@ def mostrpower_mopolynomial(left, right): | ||||
|  | ||||
|     return Tree.from_list("+", adds) | ||||
|  | ||||
|  | ||||
| @add.register(MOpolynomial, MOstrPower) | ||||
| @special_case(add_filter) | ||||
| def mopolynomial_mostrpower(left, right): | ||||
| @@ -431,6 +444,7 @@ def mopolynomial_mostrpower(left, right): | ||||
|  | ||||
|     return Tree.from_list("+", adds) | ||||
|  | ||||
|  | ||||
| @add.register(MOMonomial, MOpolynomial) | ||||
| @special_case(add_filter) | ||||
| def momonomial_mopolynomial(left, right): | ||||
| @@ -474,6 +488,7 @@ def momonomial_mopolynomial(left, right): | ||||
|  | ||||
|     return Tree.from_list("+", adds) | ||||
|  | ||||
|  | ||||
| @add.register(MOpolynomial, MOMonomial) | ||||
| @special_case(add_filter) | ||||
| def mopolynomial_momonomial(left, right): | ||||
| @@ -517,6 +532,7 @@ def mopolynomial_momonomial(left, right): | ||||
|  | ||||
|     return Tree.from_list("+", adds) | ||||
|  | ||||
|  | ||||
| @add.register(MOpolynomial, MOpolynomial) | ||||
| @special_case(add_filter) | ||||
| def mopolynomial_mopolynomial(left, right): | ||||
| @@ -563,7 +579,7 @@ def mopolynomial_mopolynomial(left, right): | ||||
|      | > 2 | ||||
|  | ||||
|     """ | ||||
|     common_degree = set(left.monomials.keys()).intersection(right.monomials.keys())  | ||||
|     common_degree = set(left.monomials.keys()).intersection(right.monomials.keys()) | ||||
|     if not common_degree: | ||||
|         raise NotImplementedError("No degree in common, no calculus to do") | ||||
|  | ||||
| @@ -573,6 +589,7 @@ def mopolynomial_mopolynomial(left, right): | ||||
|  | ||||
|     return Tree.from_list("+", list(merge_monomials.values())[::-1]) | ||||
|  | ||||
|  | ||||
| @add.register(MOstr, MOMonomial) | ||||
| @special_case(add_filter) | ||||
| def mostr_momonomial(left, right): | ||||
| @@ -593,6 +610,7 @@ def mostr_momonomial(left, right): | ||||
|     add_scal = Tree("+", 1, right.coefficient) | ||||
|     return Tree("*", add_scal, left) | ||||
|  | ||||
|  | ||||
| @add.register(MOMonomial, MOstr) | ||||
| @special_case(add_filter) | ||||
| def momonomial_mostr(left, right): | ||||
| @@ -613,6 +631,7 @@ def momonomial_mostr(left, right): | ||||
|     add_scal = Tree("+", left.coefficient, 1) | ||||
|     return Tree("*", add_scal, right) | ||||
|  | ||||
|  | ||||
| @add.register(MOstrPower, MOMonomial) | ||||
| @special_case(add_filter) | ||||
| def mostrpower_momonomial(left, right): | ||||
| @@ -633,6 +652,7 @@ def mostrpower_momonomial(left, right): | ||||
|     add_scal = Tree("+", 1, right.coefficient) | ||||
|     return Tree("*", add_scal, left) | ||||
|  | ||||
|  | ||||
| @add.register(MOMonomial, MOstrPower) | ||||
| @special_case(add_filter) | ||||
| def momonomial_mostrpower(left, right): | ||||
| @@ -653,6 +673,7 @@ def momonomial_mostrpower(left, right): | ||||
|     add_scal = Tree("+", left.coefficient, 1) | ||||
|     return Tree("*", add_scal, right) | ||||
|  | ||||
|  | ||||
| @add.register(MOMonomial, MOMonomial) | ||||
| @special_case(add_filter) | ||||
| def momonomial_momonomial(left, right): | ||||
|   | ||||
| @@ -28,6 +28,7 @@ divide_doc = """ Dividing MOs | ||||
|  | ||||
| divide = Dispatcher("divide", doc=divide_doc) | ||||
|  | ||||
|  | ||||
| def divide_filter(left, right): | ||||
|     """ Automatic divide on MO | ||||
|  | ||||
| @@ -62,6 +63,7 @@ def divide_filter(left, right): | ||||
|     except TypeError: | ||||
|         pass | ||||
|  | ||||
|  | ||||
| @divide.register(MOnumber, MOnumber) | ||||
| @special_case(divide_filter) | ||||
| def monumber_monumber(left, right): | ||||
| @@ -78,11 +80,13 @@ def monumber_monumber(left, right): | ||||
|     ... | ||||
|     NotImplementedError: Can't divide 2 int. Need to create a Fraction instead | ||||
|     """ | ||||
|     if type(left.value) in [float, Decimal] or \ | ||||
|             type(right.value) in [float, Decimal]: | ||||
|     if type(left.value) in [float, Decimal] or type(right.value) in [float, Decimal]: | ||||
|         return MO.factory(left.value / right.value) | ||||
|     else: | ||||
|         raise NotImplementedError("Can't divide 2 int. Need to create a Fraction instead") | ||||
|         raise NotImplementedError( | ||||
|             "Can't divide 2 int. Need to create a Fraction instead" | ||||
|         ) | ||||
|  | ||||
|  | ||||
| @divide.register(MOnumber, MOFraction) | ||||
| @special_case(divide_filter) | ||||
| @@ -103,6 +107,7 @@ def monumber_mofraction(left, right): | ||||
|     """ | ||||
|     return Tree("*", left, right.inverse()) | ||||
|  | ||||
|  | ||||
| @divide.register(MOFraction, MOnumber) | ||||
| @special_case(divide_filter) | ||||
| def mofraction_monumber(left, right): | ||||
| @@ -119,6 +124,7 @@ def mofraction_monumber(left, right): | ||||
|     right_fraction = MOFraction(MOnumber(1), right) | ||||
|     return Tree("*", left, right_fraction) | ||||
|  | ||||
|  | ||||
| @divide.register(MOFraction, MOFraction) | ||||
| @special_case(divide_filter) | ||||
| def mofraction_mofraction(left, right): | ||||
| @@ -134,6 +140,7 @@ def mofraction_mofraction(left, right): | ||||
|     """ | ||||
|     return Tree("*", left, right.inverse()) | ||||
|  | ||||
|  | ||||
| # ----------------------------- | ||||
| # Reglages pour 'vim' | ||||
| # vim:set autoindent expandtab tabstop=4 shiftwidth=4: | ||||
|   | ||||
| @@ -10,18 +10,23 @@ | ||||
| Exceptions for computing  | ||||
| """ | ||||
|  | ||||
|  | ||||
| class ComputeError(Exception): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class AddError(ComputeError): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class MinusError(ComputeError): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class MultiplyError(ComputeError): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class DivideError(ComputeError): | ||||
|     pass | ||||
|  | ||||
|   | ||||
| @@ -13,6 +13,7 @@ Decorator to filter MO before operate | ||||
| from functools import wraps | ||||
| from .exceptions import ComputeError | ||||
|  | ||||
|  | ||||
| def args_are(left_type, right_type): | ||||
|     """ Decorator which filter arguments type | ||||
|  | ||||
| @@ -21,21 +22,27 @@ def args_are(left_type, right_type): | ||||
|     :returns: a decorator which will allow only some type | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     def type_filter(func): | ||||
|         @wraps(func) | ||||
|         def filtered_func(left, right): | ||||
|             if not isinstance(left, left_type): | ||||
|                 raise ComputeError("Wrong type for left argument" | ||||
|                                    f"Require {left_type}, got {left.__class__.__name__}" | ||||
|                                    ) | ||||
|                 raise ComputeError( | ||||
|                     "Wrong type for left argument" | ||||
|                     f"Require {left_type}, got {left.__class__.__name__}" | ||||
|                 ) | ||||
|             if not isinstance(right, right_type): | ||||
|                 raise ComputeError("Wrong type for right argument" | ||||
|                                    f"Require {right_type}, got {right.__class__.__name__}" | ||||
|                                    ) | ||||
|                 raise ComputeError( | ||||
|                     "Wrong type for right argument" | ||||
|                     f"Require {right_type}, got {right.__class__.__name__}" | ||||
|                 ) | ||||
|             return func(left, right) | ||||
|  | ||||
|         return filtered_func | ||||
|  | ||||
|     return type_filter | ||||
|  | ||||
|  | ||||
| def special_case(filter): | ||||
|     """ Decorate operation to filter special cases before call the function | ||||
|  | ||||
| @@ -43,6 +50,7 @@ def special_case(filter): | ||||
|     :returns: decorator | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     def decorator(func): | ||||
|         @wraps(func) | ||||
|         def _func(left, right): | ||||
| @@ -50,9 +58,12 @@ def special_case(filter): | ||||
|             if ans is None: | ||||
|                 return func(left, right) | ||||
|             return ans | ||||
|  | ||||
|         return _func | ||||
|  | ||||
|     return decorator | ||||
|  | ||||
|  | ||||
| # ----------------------------- | ||||
| # Reglages pour 'vim' | ||||
| # vim:set autoindent expandtab tabstop=4 shiftwidth=4: | ||||
|   | ||||
| @@ -28,6 +28,7 @@ minus_doc = """ Opposite of a MO | ||||
|  | ||||
| minus = Dispatcher("minus", doc=minus_doc) | ||||
|  | ||||
|  | ||||
| @minus.register(type(None), MOnumber) | ||||
| def monumber(_, right): | ||||
|     """ | ||||
| @@ -37,7 +38,8 @@ def monumber(_, right): | ||||
|     <MOnumber - 4> | ||||
|  | ||||
|     """ | ||||
|     return MO.factory(- right.value) | ||||
|     return MO.factory(-right.value) | ||||
|  | ||||
|  | ||||
| @minus.register(type(None), MOFraction) | ||||
| def mofraction(_, right): | ||||
| @@ -84,6 +86,7 @@ def mofraction(_, right): | ||||
|  | ||||
|     return MOFraction(right._numerator, right._denominator, True) | ||||
|  | ||||
|  | ||||
| @minus.register(type(None), MOstr) | ||||
| def mostr(_, right): | ||||
|     """ Opposite of 'x' is '-x' | ||||
| @@ -95,6 +98,7 @@ def mostr(_, right): | ||||
|     """ | ||||
|     return MOMonomial(-1, right) | ||||
|  | ||||
|  | ||||
| @minus.register(type(None), MOstrPower) | ||||
| def mostrpower(_, right): | ||||
|     """ Opposite of 'x^n' is '-x^n' | ||||
| @@ -106,6 +110,7 @@ def mostrpower(_, right): | ||||
|     """ | ||||
|     return MOMonomial(-1, right.variable, right.power) | ||||
|  | ||||
|  | ||||
| @minus.register(type(None), MOMonomial) | ||||
| def momonomial(_, right): | ||||
|     """ Opposite of 'ax^n' is '-ax^n' | ||||
| @@ -121,6 +126,7 @@ def momonomial(_, right): | ||||
|         coef = Tree("-", None, right.coefficient) | ||||
|         return Tree("*", coef, right.strpower) | ||||
|  | ||||
|  | ||||
| @minus.register(type(None), MOpolynomial) | ||||
| def mopolynomial(_, right): | ||||
|     """ Opposite of a polynomial | ||||
| @@ -133,6 +139,7 @@ def mopolynomial(_, right): | ||||
|     neg_coefs = {p: -c.value for (p, c) in right.coefficients.items()} | ||||
|     return MOpolynomial(right.variable, neg_coefs) | ||||
|  | ||||
|  | ||||
| # ----------------------------- | ||||
| # Reglages pour 'vim' | ||||
| # vim:set autoindent expandtab tabstop=4 shiftwidth=4: | ||||
|   | ||||
| @@ -28,6 +28,7 @@ multiply_doc = """ Multiply MOs | ||||
|  | ||||
| multiply = Dispatcher("multiply", doc=multiply_doc) | ||||
|  | ||||
|  | ||||
| def multiply_filter(left, right): | ||||
|     """ Automatic multiply on MO | ||||
|  | ||||
| @@ -68,6 +69,7 @@ def multiply_filter(left, right): | ||||
|     except TypeError: | ||||
|         pass | ||||
|  | ||||
|  | ||||
| @multiply.register(MOnumber, MOnumber) | ||||
| @special_case(multiply_filter) | ||||
| def monumber_monumber(left, right): | ||||
| @@ -81,6 +83,7 @@ def monumber_monumber(left, right): | ||||
|     """ | ||||
|     return MO.factory(left.value * right.value) | ||||
|  | ||||
|  | ||||
| @multiply.register(MOnumber, MOFraction) | ||||
| @special_case(multiply_filter) | ||||
| def monumber_mofraction(left, right): | ||||
| @@ -108,6 +111,7 @@ def monumber_mofraction(left, right): | ||||
|     num = Tree("*", left, right.numerator) | ||||
|     return Tree("/", num, right._denominator) | ||||
|  | ||||
|  | ||||
| @multiply.register(MOFraction, MOnumber) | ||||
| @special_case(multiply_filter) | ||||
| def mofraction_monumber(left, right): | ||||
| @@ -125,6 +129,7 @@ def mofraction_monumber(left, right): | ||||
|     num = Tree("*", left.numerator, right) | ||||
|     return Tree("/", num, left._denominator) | ||||
|  | ||||
|  | ||||
| @multiply.register(MOFraction, MOFraction) | ||||
| @special_case(multiply_filter) | ||||
| def mofraction_mofraction(left, right): | ||||
| @@ -145,6 +150,7 @@ def mofraction_mofraction(left, right): | ||||
|     denom = Tree("*", left.denominator, right.denominator) | ||||
|     return Tree("/", num, denom) | ||||
|  | ||||
|  | ||||
| @multiply.register((MOnumber, MOFraction), MOMonomial) | ||||
| @special_case(multiply_filter) | ||||
| def moscalar_monomonial(left, right): | ||||
| @@ -161,8 +167,9 @@ def moscalar_monomonial(left, right): | ||||
|      > x^4 | ||||
|  | ||||
|     """ | ||||
|     coefficient = Tree('*', left, right.coefficient) | ||||
|     return Tree('*', coefficient, right.strpower) | ||||
|     coefficient = Tree("*", left, right.coefficient) | ||||
|     return Tree("*", coefficient, right.strpower) | ||||
|  | ||||
|  | ||||
| @multiply.register(MOMonomial, (MOnumber, MOFraction)) | ||||
| @special_case(multiply_filter) | ||||
| @@ -180,8 +187,9 @@ def monomonial_moscalar(left, right): | ||||
|      > x^4 | ||||
|  | ||||
|     """ | ||||
|     coefficient = Tree('*', right, left.coefficient) | ||||
|     return Tree('*', coefficient, left.strpower) | ||||
|     coefficient = Tree("*", right, left.coefficient) | ||||
|     return Tree("*", coefficient, left.strpower) | ||||
|  | ||||
|  | ||||
| @multiply.register(MOstr, MOstrPower) | ||||
| @special_case(multiply_filter) | ||||
| @@ -200,9 +208,12 @@ def mostr_mostrpower(left, right): | ||||
|     NotImplementedError: Can't multiply MOstr and MOstrPower if they don'thave same variable (got x and y) | ||||
|     """ | ||||
|     if left.variable != right.variable: | ||||
|         raise NotImplementedError("Can't multiply MOstr and MOstrPower if they don't" | ||||
|                 f"have same variable (got {left.variable} and {right.variable})") | ||||
|     return MOstrPower(left.variable, right.power.value+1) | ||||
|         raise NotImplementedError( | ||||
|             "Can't multiply MOstr and MOstrPower if they don't" | ||||
|             f"have same variable (got {left.variable} and {right.variable})" | ||||
|         ) | ||||
|     return MOstrPower(left.variable, right.power.value + 1) | ||||
|  | ||||
|  | ||||
| @multiply.register(MOstrPower, MOstr) | ||||
| @special_case(multiply_filter) | ||||
| @@ -221,9 +232,12 @@ def mostr_mostrpower(left, right): | ||||
|     NotImplementedError: Can't multiply MOstr and MOstrPower if they don'thave same variable (got x and y) | ||||
|     """ | ||||
|     if left.variable != right.variable: | ||||
|         raise NotImplementedError("Can't multiply MOstr and MOstrPower if they don't" | ||||
|                 f"have same variable (got {left.variable} and {right.variable})") | ||||
|     return MOstrPower(left.variable, left.power.value+1) | ||||
|         raise NotImplementedError( | ||||
|             "Can't multiply MOstr and MOstrPower if they don't" | ||||
|             f"have same variable (got {left.variable} and {right.variable})" | ||||
|         ) | ||||
|     return MOstrPower(left.variable, left.power.value + 1) | ||||
|  | ||||
|  | ||||
| @multiply.register(MOstr, MOstr) | ||||
| @special_case(multiply_filter) | ||||
| @@ -243,10 +257,13 @@ def mostr_mostr(left, right): | ||||
|     NotImplementedError: Can't multiply MOstr and MOstr if they don'thave same variable (got y and x) | ||||
|     """ | ||||
|     if left.variable != right.variable: | ||||
|         raise NotImplementedError("Can't multiply MOstr and MOstr if they don't" | ||||
|                 f"have same variable (got {left.variable} and {right.variable})") | ||||
|         raise NotImplementedError( | ||||
|             "Can't multiply MOstr and MOstr if they don't" | ||||
|             f"have same variable (got {left.variable} and {right.variable})" | ||||
|         ) | ||||
|     return MOstrPower(left.variable, 2) | ||||
|  | ||||
|  | ||||
| @multiply.register(MOstrPower, MOstrPower) | ||||
| @special_case(multiply_filter) | ||||
| def mostr_mostrpower(left, right): | ||||
| @@ -268,11 +285,14 @@ def mostr_mostrpower(left, right): | ||||
|     NotImplementedError: Can't multiply MOstrPower and MOstrPower if they don'thave same variable (got x and y) | ||||
|     """ | ||||
|     if left.variable != right.variable: | ||||
|         raise NotImplementedError("Can't multiply MOstrPower and MOstrPower if they don't" | ||||
|                 f"have same variable (got {left.variable} and {right.variable})") | ||||
|         raise NotImplementedError( | ||||
|             "Can't multiply MOstrPower and MOstrPower if they don't" | ||||
|             f"have same variable (got {left.variable} and {right.variable})" | ||||
|         ) | ||||
|     power = Tree("+", left.power, right.power) | ||||
|     return Tree("^", left.variable, power) | ||||
|  | ||||
|  | ||||
| @multiply.register(MOstrPower, MOMonomial) | ||||
| @special_case(multiply_filter) | ||||
| def mostrpower_momonomial(left, right): | ||||
| @@ -296,12 +316,15 @@ def mostrpower_momonomial(left, right): | ||||
|     NotImplementedError: Can't multiply MOstrPower and Monomial if they don'thave same variable (got x and y) | ||||
|     """ | ||||
|     if left.variable != right.variable: | ||||
|         raise NotImplementedError("Can't multiply MOstrPower and Monomial if they don't" | ||||
|                 f"have same variable (got {left.variable} and {right.variable})") | ||||
|         raise NotImplementedError( | ||||
|             "Can't multiply MOstrPower and Monomial if they don't" | ||||
|             f"have same variable (got {left.variable} and {right.variable})" | ||||
|         ) | ||||
|     power = Tree("+", left.power, right.power) | ||||
|     monome = Tree("^", left.variable, power) | ||||
|     return Tree("*", right.coefficient, monome) | ||||
|  | ||||
|  | ||||
| @multiply.register(MOMonomial, MOstrPower) | ||||
| @special_case(multiply_filter) | ||||
| def momonomial_mostr(left, right): | ||||
| @@ -326,12 +349,15 @@ def momonomial_mostr(left, right): | ||||
|  | ||||
|     """ | ||||
|     if left.variable != right.variable: | ||||
|         raise NotImplementedError("Can't multiply MOstrPower and Monomial if they don't" | ||||
|                 f"have same variable (got {left.variable} and {right.variable})") | ||||
|         raise NotImplementedError( | ||||
|             "Can't multiply MOstrPower and Monomial if they don't" | ||||
|             f"have same variable (got {left.variable} and {right.variable})" | ||||
|         ) | ||||
|     power = Tree("+", left.power, right.power) | ||||
|     monome = Tree("^", left.variable, power) | ||||
|     return Tree("*", left.coefficient, monome) | ||||
|  | ||||
|  | ||||
| @multiply.register(MOstr, MOMonomial) | ||||
| @special_case(multiply_filter) | ||||
| def mostr_momonomial(left, right): | ||||
| @@ -349,9 +375,12 @@ def mostr_momonomial(left, right): | ||||
|     NotImplementedError: Can't multiply MOstr and Monomial if they don'thave same variable (got x and y) | ||||
|     """ | ||||
|     if left.variable != right.variable: | ||||
|         raise NotImplementedError("Can't multiply MOstr and Monomial if they don't" | ||||
|                 f"have same variable (got {left.variable} and {right.variable})") | ||||
|     return MOMonomial(right.coefficient, right.variable, right.power.value+1) | ||||
|         raise NotImplementedError( | ||||
|             "Can't multiply MOstr and Monomial if they don't" | ||||
|             f"have same variable (got {left.variable} and {right.variable})" | ||||
|         ) | ||||
|     return MOMonomial(right.coefficient, right.variable, right.power.value + 1) | ||||
|  | ||||
|  | ||||
| @multiply.register(MOMonomial, MOstr) | ||||
| @special_case(multiply_filter) | ||||
| @@ -371,9 +400,12 @@ def momonomial_mostr(left, right): | ||||
|  | ||||
|     """ | ||||
|     if left.variable != right.variable: | ||||
|         raise NotImplementedError("Can't multiply MOstr and Monomial if they don't" | ||||
|                 f"have same variable (got {left.variable} and {right.variable})") | ||||
|     return MOMonomial(left.coefficient, left.variable, left.power.value+1) | ||||
|         raise NotImplementedError( | ||||
|             "Can't multiply MOstr and Monomial if they don't" | ||||
|             f"have same variable (got {left.variable} and {right.variable})" | ||||
|         ) | ||||
|     return MOMonomial(left.coefficient, left.variable, left.power.value + 1) | ||||
|  | ||||
|  | ||||
| @multiply.register(MOMonomial, MOMonomial) | ||||
| @special_case(multiply_filter) | ||||
| @@ -401,15 +433,17 @@ def momonomial_momonomial(left, right): | ||||
|  | ||||
|     """ | ||||
|     if left.variable != right.variable: | ||||
|         raise NotImplementedError("Can't multiply MOMonomial and Monomial if they don't" | ||||
|                 f"have same variable (got {left.variable} and {right.variable})") | ||||
|         raise NotImplementedError( | ||||
|             "Can't multiply MOMonomial and Monomial if they don't" | ||||
|             f"have same variable (got {left.variable} and {right.variable})" | ||||
|         ) | ||||
|     powers = Tree("+", left.power, right.power) | ||||
|     monome = Tree("^", left.variable, powers) | ||||
|     coefs = Tree("*", left.coefficient, right.coefficient) | ||||
|     return Tree("*", coefs, monome) | ||||
|  | ||||
| @multiply.register((MOnumber, MOFraction, MOstr, MOstrPower, MOMonomial), \ | ||||
|                    MOpolynomial) | ||||
|  | ||||
| @multiply.register((MOnumber, MOFraction, MOstr, MOstrPower, MOMonomial), MOpolynomial) | ||||
| @special_case(multiply_filter) | ||||
| def lotsmo_mopolynomial(left, right): | ||||
|     """ Multiply a scalar and a MOMonomial | ||||
| @@ -492,13 +526,11 @@ def lotsmo_mopolynomial(left, right): | ||||
|  | ||||
|  | ||||
|     """ | ||||
|     coefs = [Tree("*", left, monom) \ | ||||
|              for monom in list(right.monomials.values())[::-1]\ | ||||
|              ] | ||||
|     coefs = [Tree("*", left, monom) for monom in list(right.monomials.values())[::-1]] | ||||
|     return Tree.from_list("+", coefs) | ||||
|  | ||||
| @multiply.register(MOpolynomial, \ | ||||
|                    (MOnumber, MOFraction, MOstr, MOstrPower, MOMonomial)) | ||||
|  | ||||
| @multiply.register(MOpolynomial, (MOnumber, MOFraction, MOstr, MOstrPower, MOMonomial)) | ||||
| @special_case(multiply_filter) | ||||
| def mopolynomial_lotsmo(left, right): | ||||
|     """ Multiply a MOpolynomial with nearly everything | ||||
| @@ -581,11 +613,10 @@ def mopolynomial_lotsmo(left, right): | ||||
|      | | > 3x^2 | ||||
|  | ||||
|     """ | ||||
|     coefs = [Tree("*", monom, right) \ | ||||
|              for monom in list(left.monomials.values())[::-1] \ | ||||
|              ] | ||||
|     coefs = [Tree("*", monom, right) for monom in list(left.monomials.values())[::-1]] | ||||
|     return Tree.from_list("+", coefs) | ||||
|  | ||||
|  | ||||
| @multiply.register(MOpolynomial, MOpolynomial) | ||||
| @special_case(multiply_filter) | ||||
| def mopolynomial_mopolynomial(left, right): | ||||
| @@ -619,10 +650,11 @@ def mopolynomial_mopolynomial(left, right): | ||||
|      | | | > 4 | ||||
|  | ||||
|     """ | ||||
|     coefs = [Tree("*", l_monom, r_monom) \ | ||||
|              for l_monom in list(left.monomials.values())[::-1] \ | ||||
|              for r_monom in list(right.monomials.values())[::-1] \ | ||||
|              ] | ||||
|     coefs = [ | ||||
|         Tree("*", l_monom, r_monom) | ||||
|         for l_monom in list(left.monomials.values())[::-1] | ||||
|         for r_monom in list(right.monomials.values())[::-1] | ||||
|     ] | ||||
|     return Tree.from_list("+", coefs) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -28,6 +28,7 @@ power_doc = """ Power of MOs | ||||
|  | ||||
| power = Dispatcher("power", doc=power_doc) | ||||
|  | ||||
|  | ||||
| def power_filter(left, right): | ||||
|     """ Automatic power on MO | ||||
|  | ||||
| @@ -60,6 +61,7 @@ def power_filter(left, right): | ||||
|     except TypeError: | ||||
|         pass | ||||
|  | ||||
|  | ||||
| @power.register(MOnumber, MOnumber) | ||||
| @special_case(power_filter) | ||||
| def monumber_monumber(left, right): | ||||
| @@ -73,6 +75,7 @@ def monumber_monumber(left, right): | ||||
|     """ | ||||
|     return MO.factory(left.value ** right.value) | ||||
|  | ||||
|  | ||||
| @power.register(MOFraction, MOnumber) | ||||
| @special_case(power_filter) | ||||
| def mofraction_monumber(left, right): | ||||
| @@ -93,6 +96,7 @@ def mofraction_monumber(left, right): | ||||
|     denom = Tree("^", left.denominator, right) | ||||
|     return Tree("/", num, denom) | ||||
|  | ||||
|  | ||||
| @power.register(MOstrPower, MOnumber) | ||||
| @special_case(power_filter) | ||||
| def mostrpower_monumber(left, right): | ||||
| @@ -110,6 +114,7 @@ def mostrpower_monumber(left, right): | ||||
|     power = Tree("*", left.power, right) | ||||
|     return Tree("^", left.variable, power) | ||||
|  | ||||
|  | ||||
| @power.register(MOMonomial, MOnumber) | ||||
| @special_case(power_filter) | ||||
| def mostrpower_monumber(left, right): | ||||
| @@ -133,6 +138,7 @@ def mostrpower_monumber(left, right): | ||||
|     strpower = Tree("^", left.variable, power) | ||||
|     return Tree("*", coef, strpower) | ||||
|  | ||||
|  | ||||
| @power.register(MOpolynomial, MOnumber) | ||||
| @special_case(power_filter) | ||||
| def mopolynomial_monumber(left, right): | ||||
| @@ -145,8 +151,7 @@ def mopolynomial_monumber(left, right): | ||||
|      > 3x^2 - 2x + 1 | ||||
|      > 3x^2 - 2x + 1 | ||||
|     """ | ||||
|     return Tree.from_list("*", [left]*right.value) | ||||
|  | ||||
|     return Tree.from_list("*", [left] * right.value) | ||||
|  | ||||
|  | ||||
| # ----------------------------- | ||||
|   | ||||
| @@ -14,17 +14,23 @@ from functools import wraps | ||||
|  | ||||
| __all__ = ["coroutine", "STOOOP", "RESTAAART"] | ||||
|  | ||||
|  | ||||
| def coroutine(func): | ||||
|     @wraps(func) | ||||
|     def start(*args, **kwargs): | ||||
|         cr = func(*args, **kwargs) | ||||
|         next(cr) | ||||
|         return cr | ||||
|  | ||||
|     return start | ||||
|  | ||||
| class STOOOP(Exception): pass | ||||
| class RESTAAART(Exception): pass | ||||
|  | ||||
| class STOOOP(Exception): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class RESTAAART(Exception): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| # ----------------------------- | ||||
|   | ||||
| @@ -8,32 +8,20 @@ | ||||
|  | ||||
| __all__ = ["OperatorError", "OPERATORS", "is_operator"] | ||||
|  | ||||
|  | ||||
| class OperatorError(Exception): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| OPERATORS = { | ||||
|     "+": {'repr': "+", | ||||
|           'arity': 2, | ||||
|           'precedence': 0, | ||||
|          }, | ||||
|     "-": {'repr': "-", | ||||
|           'arity': 1, | ||||
|           'precedence': 1, | ||||
|          }, | ||||
|     "*": {'repr': "*", | ||||
|           'arity': 2, | ||||
|           'precedence': 2, | ||||
|          }, | ||||
|     "/": {'repr': "/", | ||||
|           'arity': 2, | ||||
|           'precedence': 3, | ||||
|          }, | ||||
|     "^": {'repr': "^", | ||||
|           'arity': 2, | ||||
|           'precedence': 4, | ||||
|          }, | ||||
|     "+": {"repr": "+", "arity": 2, "precedence": 0}, | ||||
|     "-": {"repr": "-", "arity": 1, "precedence": 1}, | ||||
|     "*": {"repr": "*", "arity": 2, "precedence": 2}, | ||||
|     "/": {"repr": "/", "arity": 2, "precedence": 3}, | ||||
|     "^": {"repr": "^", "arity": 2, "precedence": 4}, | ||||
| } | ||||
|  | ||||
|  | ||||
| def is_operator(string): | ||||
|     """ Return whether a string is an operator or not | ||||
|  | ||||
|   | ||||
| @@ -14,11 +14,8 @@ import random | ||||
|  | ||||
| __all__ = ["reject_random", "filter_random", "FilterRandom"] | ||||
|  | ||||
| def reject_random(min_value = -10,  | ||||
|            max_value = 10, | ||||
|            rejected = [0, 1], | ||||
|            accept_callbacks=[], | ||||
|            ): | ||||
|  | ||||
| def reject_random(min_value=-10, max_value=10, rejected=[0, 1], accept_callbacks=[]): | ||||
|     """ Generate a random integer with the rejection method | ||||
|  | ||||
|         :param name: name of the Integer | ||||
| @@ -61,11 +58,8 @@ def reject_random(min_value = -10, | ||||
|  | ||||
|     return candidate | ||||
|  | ||||
| def filter_random(min_value = -10, | ||||
|            max_value = 10, | ||||
|            rejected = [0, 1], | ||||
|            accept_callbacks=[], | ||||
|            ): | ||||
|  | ||||
| def filter_random(min_value=-10, max_value=10, rejected=[0, 1], accept_callbacks=[]): | ||||
|     """ Generate a random integer by filtering then choosing a candidate | ||||
|  | ||||
|         :param name: name of the Integer | ||||
| @@ -99,37 +93,44 @@ def filter_random(min_value = -10, | ||||
|         >>> filter_random() | ||||
|         6 | ||||
|     """ | ||||
|     candidates = set(range(min_value, max_value+1)) | ||||
|     candidates = set(range(min_value, max_value + 1)) | ||||
|     candidates = {c for c in candidates if c not in rejected} | ||||
|  | ||||
|     candidates = [candidate for candidate in candidates \ | ||||
|                   if all(c(candidate) for c in accept_callbacks)] | ||||
|     candidates = [ | ||||
|         candidate | ||||
|         for candidate in candidates | ||||
|         if all(c(candidate) for c in accept_callbacks) | ||||
|     ] | ||||
|  | ||||
|     if len(candidates) == 0: | ||||
|         raise OverflowError("There is no candidates for this range and those conditions") | ||||
|         raise OverflowError( | ||||
|             "There is no candidates for this range and those conditions" | ||||
|         ) | ||||
|     return random.choice(candidates) | ||||
|  | ||||
|  | ||||
| class FilterRandom(object): | ||||
|  | ||||
|     """ Integer random generator which filter then choose candidate | ||||
|     """ | ||||
|  | ||||
|     # TODO: Faire un cache pour éviter de reconstruire les listes à chaque fois |ven. déc. 21 19:07:42 CET 2018 | ||||
|  | ||||
|     def __init__(self, | ||||
|                  rejected = [0, 1], | ||||
|                  accept_callbacks=[], | ||||
|                  min_value = -10,  | ||||
|                  max_value = 10, | ||||
|                  ): | ||||
|     def __init__( | ||||
|         self, rejected=[0, 1], accept_callbacks=[], min_value=-10, max_value=10 | ||||
|     ): | ||||
|         self.conditions = (lambda x: x not in rejected,) + tuple(accept_callbacks) | ||||
|  | ||||
|         self._min = min_value | ||||
|         self._max = max_value | ||||
|  | ||||
|         candidates = set(range(self._min, self._max+1)) | ||||
|         candidates = set(range(self._min, self._max + 1)) | ||||
|  | ||||
|         self._candidates = { candidate for candidate in candidates \ | ||||
|             if all(c(candidate) for c in self.conditions) } | ||||
|         self._candidates = { | ||||
|             candidate | ||||
|             for candidate in candidates | ||||
|             if all(c(candidate) for c in self.conditions) | ||||
|         } | ||||
|  | ||||
|     def add_candidates(self, low, high): | ||||
|         """ Add candidates between low and high to _candidates """ | ||||
| @@ -144,13 +145,16 @@ class FilterRandom(object): | ||||
|         else: | ||||
|             useless_high = True | ||||
|  | ||||
|         if not(useless_low and useless_high): | ||||
|             candidates = set(range(low, high+1)) | ||||
|         if not (useless_low and useless_high): | ||||
|             candidates = set(range(low, high + 1)) | ||||
|  | ||||
|             self._candidates = self._candidates.union({ | ||||
|                 candidate for candidate in candidates \ | ||||
|                 if all(c(candidate) for c in self.conditions) \ | ||||
|             }) | ||||
|             self._candidates = self._candidates.union( | ||||
|                 { | ||||
|                     candidate | ||||
|                     for candidate in candidates | ||||
|                     if all(c(candidate) for c in self.conditions) | ||||
|                 } | ||||
|             ) | ||||
|  | ||||
|     def candidates(self, min_value=-10, max_value=10): | ||||
|         """ Return candidates between min_value and max_value """ | ||||
|   | ||||
| @@ -8,7 +8,8 @@ | ||||
|  | ||||
| from mapytex.calculus.core.operator import OPERATORS | ||||
|  | ||||
| __all__ = ['tree2tex'] | ||||
| __all__ = ["tree2tex"] | ||||
|  | ||||
|  | ||||
| def plus2tex(left, right): | ||||
|     r""" + rendering | ||||
| @@ -51,6 +52,7 @@ def plus2tex(left, right): | ||||
|  | ||||
|     return f"{left_} {right_}" | ||||
|  | ||||
|  | ||||
| def minus2tex(left, right): | ||||
|     r""" - rendering | ||||
|  | ||||
| @@ -64,7 +66,7 @@ def minus2tex(left, right): | ||||
|     """ | ||||
|     try: | ||||
|         right_need_parenthesis = False | ||||
|         if OPERATORS[right.node]["precedence"] < OPERATORS['-']["precedence"]: | ||||
|         if OPERATORS[right.node]["precedence"] < OPERATORS["-"]["precedence"]: | ||||
|             right_need_parenthesis = True | ||||
|     except AttributeError: | ||||
|         right_ = right.__tex__ | ||||
| @@ -76,6 +78,7 @@ def minus2tex(left, right): | ||||
|  | ||||
|     return f"- {right_}" | ||||
|  | ||||
|  | ||||
| def mul2tex(left, right): | ||||
|     r""" * rendering | ||||
|  | ||||
| @@ -101,14 +104,16 @@ def mul2tex(left, right): | ||||
|     right_ = render_with_parenthesis(right, "*") | ||||
|  | ||||
|     display_time = True | ||||
|     if (right_[0].isalpha() and (left_.isnumeric() or left_.isdecimal())) or \ | ||||
|             right_[0] == '(': | ||||
|             display_time = False | ||||
|     if (right_[0].isalpha() and (left_.isnumeric() or left_.isdecimal())) or right_[ | ||||
|         0 | ||||
|     ] == "(": | ||||
|         display_time = False | ||||
|  | ||||
|     if display_time: | ||||
|         return f"{left_} \\times {right_}" | ||||
|     return f"{left_}{right_}" | ||||
|  | ||||
|  | ||||
| def div2tex(left, right): | ||||
|     r""" / rendering | ||||
|  | ||||
| @@ -137,6 +142,7 @@ def div2tex(left, right): | ||||
|  | ||||
|     return "\\frac{" + left_ + "}{" + right_ + "}" | ||||
|  | ||||
|  | ||||
| def pow2tex(left, right): | ||||
|     r""" ^ rendering | ||||
|  | ||||
| @@ -159,7 +165,7 @@ def pow2tex(left, right): | ||||
|     """ | ||||
|     try: | ||||
|         left_need_parenthesis = False | ||||
|         if OPERATORS[left.node]["precedence"] < OPERATORS['^']["precedence"]: | ||||
|         if OPERATORS[left.node]["precedence"] < OPERATORS["^"]["precedence"]: | ||||
|             left_need_parenthesis = True | ||||
|     except AttributeError: | ||||
|         left_ = left.__tex__ | ||||
| @@ -185,7 +191,10 @@ def render_with_parenthesis(subtree, operator): | ||||
|         subtree.node | ||||
|     except AttributeError: | ||||
|         try: | ||||
|             if OPERATORS[subtree.MAINOP]["precedence"] < OPERATORS[operator]["precedence"]: | ||||
|             if ( | ||||
|                 OPERATORS[subtree.MAINOP]["precedence"] | ||||
|                 < OPERATORS[operator]["precedence"] | ||||
|             ): | ||||
|                 subtree_need_parenthesis = True | ||||
|         except (AttributeError, KeyError): | ||||
|             pass | ||||
| @@ -200,13 +209,8 @@ def render_with_parenthesis(subtree, operator): | ||||
|     return subtree_ | ||||
|  | ||||
|  | ||||
| OPERATOR2TEX = { | ||||
|     "+": plus2tex, | ||||
|     "-": minus2tex, | ||||
|     "*": mul2tex, | ||||
|     "/": div2tex, | ||||
|     "^": pow2tex, | ||||
| } | ||||
| OPERATOR2TEX = {"+": plus2tex, "-": minus2tex, "*": mul2tex, "/": div2tex, "^": pow2tex} | ||||
|  | ||||
|  | ||||
| def tree2tex(tree): | ||||
|     r""" Convert a tree into its tex version | ||||
|   | ||||
| @@ -8,7 +8,8 @@ | ||||
|  | ||||
| from ..operator import OPERATORS | ||||
|  | ||||
| __all__ = ['tree2txt'] | ||||
| __all__ = ["tree2txt"] | ||||
|  | ||||
|  | ||||
| def plus2txt(left, right): | ||||
|     """ + rendering | ||||
| @@ -41,6 +42,7 @@ def plus2txt(left, right): | ||||
|  | ||||
|     return f"{left_} {right_}" | ||||
|  | ||||
|  | ||||
| def minus2txt(left, right): | ||||
|     """ - rendering | ||||
|  | ||||
| @@ -54,7 +56,7 @@ def minus2txt(left, right): | ||||
|     """ | ||||
|     try: | ||||
|         right_need_parenthesis = False | ||||
|         if OPERATORS[right.node]["precedence"] < OPERATORS['-']["precedence"]: | ||||
|         if OPERATORS[right.node]["precedence"] < OPERATORS["-"]["precedence"]: | ||||
|             right_need_parenthesis = True | ||||
|     except AttributeError: | ||||
|         right_ = right.__txt__ | ||||
| @@ -66,6 +68,7 @@ def minus2txt(left, right): | ||||
|  | ||||
|     return f"- {right_}" | ||||
|  | ||||
|  | ||||
| def mul2txt(left, right): | ||||
|     """ * rendering | ||||
|  | ||||
| @@ -96,9 +99,9 @@ def mul2txt(left, right): | ||||
|  | ||||
|     if right_[0].isalpha(): | ||||
|         # TODO: C'est bien beurk en dessous... |ven. déc. 21 12:03:07 CET 2018 | ||||
|         if type(left).__name__ == 'MOnumber': | ||||
|         if type(left).__name__ == "MOnumber": | ||||
|             display_time = False | ||||
|     elif right_[0] == '(': | ||||
|     elif right_[0] == "(": | ||||
|         display_time = False | ||||
|  | ||||
|     if display_time: | ||||
| @@ -106,6 +109,7 @@ def mul2txt(left, right): | ||||
|     else: | ||||
|         return f"{left_}{right_}" | ||||
|  | ||||
|  | ||||
| def div2txt(left, right): | ||||
|     """ / rendering | ||||
|  | ||||
| @@ -125,7 +129,7 @@ def div2txt(left, right): | ||||
|     """ | ||||
|     try: | ||||
|         left_need_parenthesis = False | ||||
|         if OPERATORS[left.node]["precedence"] < OPERATORS['/']["precedence"]: | ||||
|         if OPERATORS[left.node]["precedence"] < OPERATORS["/"]["precedence"]: | ||||
|             left_need_parenthesis = True | ||||
|     except AttributeError: | ||||
|         left_ = left.__txt__ | ||||
| @@ -136,7 +140,7 @@ def div2txt(left, right): | ||||
|             left_ = tree2txt(left) | ||||
|     try: | ||||
|         right_need_parenthesis = False | ||||
|         if OPERATORS[right.node]["precedence"] < OPERATORS['/']["precedence"]: | ||||
|         if OPERATORS[right.node]["precedence"] < OPERATORS["/"]["precedence"]: | ||||
|             right_need_parenthesis = True | ||||
|     except AttributeError: | ||||
|         right_ = right.__txt__ | ||||
| @@ -148,6 +152,7 @@ def div2txt(left, right): | ||||
|  | ||||
|     return f"{left_} / {right_}" | ||||
|  | ||||
|  | ||||
| def pow2txt(left, right): | ||||
|     """ ^ rendering | ||||
|  | ||||
| @@ -169,7 +174,7 @@ def pow2txt(left, right): | ||||
|  | ||||
|     try: | ||||
|         right_need_parenthesis = False | ||||
|         if OPERATORS[right.node]["precedence"] < OPERATORS['^']["precedence"]: | ||||
|         if OPERATORS[right.node]["precedence"] < OPERATORS["^"]["precedence"]: | ||||
|             right_need_parenthesis = True | ||||
|     except AttributeError: | ||||
|         right_ = right.__txt__ | ||||
| @@ -181,13 +186,17 @@ def pow2txt(left, right): | ||||
|  | ||||
|     return f"{left_}^{right_}" | ||||
|  | ||||
|  | ||||
| def render_with_parenthesis(subtree, operator): | ||||
|     subtree_need_parenthesis = False | ||||
|     try: | ||||
|         subtree.node | ||||
|     except AttributeError: | ||||
|         try: | ||||
|             if OPERATORS[subtree.MAINOP]["precedence"] < OPERATORS[operator]["precedence"]: | ||||
|             if ( | ||||
|                 OPERATORS[subtree.MAINOP]["precedence"] | ||||
|                 < OPERATORS[operator]["precedence"] | ||||
|             ): | ||||
|                 subtree_need_parenthesis = True | ||||
|         except (AttributeError, KeyError): | ||||
|             pass | ||||
| @@ -201,13 +210,9 @@ def render_with_parenthesis(subtree, operator): | ||||
|         return f"({subtree_})" | ||||
|     return subtree_ | ||||
|  | ||||
| OPERATOR2TXT = { | ||||
|     "+": plus2txt, | ||||
|     "-": minus2txt, | ||||
|     "*": mul2txt, | ||||
|     "/": div2txt, | ||||
|     "^": pow2txt, | ||||
| } | ||||
|  | ||||
| OPERATOR2TXT = {"+": plus2txt, "-": minus2txt, "*": mul2txt, "/": div2txt, "^": pow2txt} | ||||
|  | ||||
|  | ||||
| def tree2txt(tree): | ||||
|     """ Convert a tree into its txt version | ||||
| @@ -224,6 +229,7 @@ def tree2txt(tree): | ||||
|     '2 + 3 * 4' | ||||
|     """ | ||||
|     from ..tree import Tree | ||||
|  | ||||
|     if not isinstance(tree, Tree): | ||||
|         raise ValueError(f"Can only render a Tree (got {type(tree).__name__}: {tree})") | ||||
|     return OPERATOR2TXT[tree.node](tree.left_value, tree.right_value) | ||||
|   | ||||
| @@ -16,7 +16,8 @@ from .coroutine import * | ||||
| from .operator import is_operator | ||||
| from .MO import moify | ||||
|  | ||||
| __all__ = ["str2", ] | ||||
| __all__ = ["str2"] | ||||
|  | ||||
|  | ||||
| class ParsingError(Exception): | ||||
|     pass | ||||
| @@ -44,6 +45,7 @@ def maybe_it_is(cara): | ||||
|     >>> it_is_iuo("uo") | ||||
|     False | ||||
|     """ | ||||
|  | ||||
|     def func(c): | ||||
|         if c == cara: | ||||
|             return True | ||||
| @@ -51,20 +53,25 @@ def maybe_it_is(cara): | ||||
|             return "maybe" | ||||
|         else: | ||||
|             return False | ||||
|  | ||||
|     return func | ||||
|  | ||||
|  | ||||
| def something_in(cara_list): | ||||
|     """ Return a function which sais whether a caracter is in cara_list or not | ||||
|     """ | ||||
|  | ||||
|     def func(c): | ||||
|         if c in cara_list: | ||||
|             return True | ||||
|         else: | ||||
|             return False | ||||
|  | ||||
|     return func | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| def lookfor(condition, replace = lambda x:''.join(x)): | ||||
| def lookfor(condition, replace=lambda x: "".join(x)): | ||||
|     """ Sink which is looking for term and yield replace founded patern  | ||||
|     with the lenght of the accumulation. | ||||
|  | ||||
| @@ -165,7 +172,7 @@ def lookfor(condition, replace = lambda x:''.join(x)): | ||||
|         else: | ||||
|             if c is not None: | ||||
|                 acc.append(c) | ||||
|             found = condition(''.join([str(i) for i in acc])) | ||||
|             found = condition("".join([str(i) for i in acc])) | ||||
|             if found == "maybe": | ||||
|                 ans = "maybe" | ||||
|             elif found: | ||||
| @@ -175,6 +182,7 @@ def lookfor(condition, replace = lambda x:''.join(x)): | ||||
|                 ans = False | ||||
|                 acc = [] | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| def remember_lookfor(lookfor): | ||||
|     """ Coroutine which remember sent value before the lookfor finds something | ||||
| @@ -235,8 +243,9 @@ def remember_lookfor(lookfor): | ||||
|                 acc.append(c) | ||||
|                 ans = False | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| def concurent_broadcast(target, lookfors = []): | ||||
| def concurent_broadcast(target, lookfors=[]): | ||||
|     """ Coroutine which broadcasts multiple lookfor coroutines and reinitializes | ||||
|     them when one found something | ||||
|  | ||||
| @@ -316,6 +325,7 @@ def concurent_broadcast(target, lookfors = []): | ||||
|             target_.send(i) | ||||
|         yield target_.throw(err) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| def missing_times(target): | ||||
|     """ Coroutine which send a "*" when it's missing | ||||
| @@ -379,15 +389,14 @@ def missing_times(target): | ||||
|                 previous = None | ||||
|  | ||||
|                 if isinstance(tok, str): | ||||
|                     if tok == '(': | ||||
|                     if tok == "(": | ||||
|                         target_.send("*") | ||||
|                     elif not is_operator(tok) and tok != ')': | ||||
|                     elif not is_operator(tok) and tok != ")": | ||||
|                         target_.send("*") | ||||
|  | ||||
|             if isinstance(tok, int) or \ | ||||
|                     (isinstance(tok, str) and \ | ||||
|                     not is_operator(tok) and \ | ||||
|                     not tok == '('): | ||||
|             if isinstance(tok, int) or ( | ||||
|                 isinstance(tok, str) and not is_operator(tok) and not tok == "(" | ||||
|             ): | ||||
|                 previous = tok | ||||
|  | ||||
|             target_.send(tok) | ||||
| @@ -395,6 +404,7 @@ def missing_times(target): | ||||
|     except STOOOP as err: | ||||
|         yield target_.throw(err) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| def lookforNumbers(target): | ||||
|     """ Coroutine which parse numbers | ||||
| @@ -467,12 +477,12 @@ def lookforNumbers(target): | ||||
|                 try: | ||||
|                     int(tok) | ||||
|                 except ValueError: | ||||
|                     if tok == '.': | ||||
|                     if tok == ".": | ||||
|                         if current.replace("-", "", 1).isdigit(): | ||||
|                             current += tok | ||||
|                         else: | ||||
|                             raise ParsingError(f"Can't build decimal with '{current}'") | ||||
|                     elif tok == '-': | ||||
|                     elif tok == "-": | ||||
|                         if current == "": | ||||
|                             current = tok | ||||
|                         elif current == ("("): | ||||
| @@ -489,13 +499,15 @@ def lookforNumbers(target): | ||||
|                                 target_.send(typifiy_numbers(current)) | ||||
|                             except InvalidOperation: | ||||
|                                 target_.send(current) | ||||
|                             target_.send('+') | ||||
|                             target_.send("+") | ||||
|                             current = tok | ||||
|                     else: | ||||
|                         if current == "": | ||||
|                             current = tok | ||||
|                         elif is_operator(current) and is_operator(tok): | ||||
|                             raise ParsingError(f"Can't parse with 2 operators next to each other") | ||||
|                             raise ParsingError( | ||||
|                                 f"Can't parse with 2 operators next to each other" | ||||
|                             ) | ||||
|                         else: | ||||
|                             try: | ||||
|                                 target_.send(typifiy_numbers(current)) | ||||
| @@ -522,6 +534,7 @@ def lookforNumbers(target): | ||||
|                 target_.send(current) | ||||
|         yield target_.throw(err) | ||||
|  | ||||
|  | ||||
| def typifiy_numbers(number): | ||||
|     """ Transform a str number into a integer or a decimal """ | ||||
|     try: | ||||
| @@ -529,6 +542,7 @@ def typifiy_numbers(number): | ||||
|     except ValueError: | ||||
|         return Decimal(number) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| def pparser(target): | ||||
|     """ Parenthesis parser sink | ||||
| @@ -565,6 +579,7 @@ def pparser(target): | ||||
|     except STOOOP as err: | ||||
|         yield target_.throw(err) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| def list_sink(): | ||||
|     """  Testing sink for coroutines | ||||
| @@ -588,6 +603,7 @@ def list_sink(): | ||||
|     except STOOOP: | ||||
|         yield ans | ||||
|  | ||||
|  | ||||
| def str2(sink, convert_to_mo=True): | ||||
|     """ Return a pipeline which parse an expression with the sink as an endpont | ||||
|  | ||||
| @@ -776,13 +792,16 @@ def str2(sink, convert_to_mo=True): | ||||
|     """ | ||||
|     lfop = lookfor(is_operator) | ||||
|     operator_corout = partial(concurent_broadcast, lookfors=[lfop]) | ||||
|  | ||||
|     def pipeline(expression): | ||||
|         if convert_to_mo: | ||||
|             str2_corout = lookforNumbers(operator_corout(missing_times(moify(pparser(sink))))) | ||||
|             str2_corout = lookforNumbers( | ||||
|                 operator_corout(missing_times(moify(pparser(sink)))) | ||||
|             ) | ||||
|         else: | ||||
|             str2_corout = lookforNumbers(operator_corout(missing_times(pparser(sink)))) | ||||
|  | ||||
|         for i in expression.replace(" ",""): | ||||
|         for i in expression.replace(" ", ""): | ||||
|             str2_corout.send(i) | ||||
|         a = str2_corout.throw(STOOOP) | ||||
|  | ||||
|   | ||||
| @@ -9,10 +9,7 @@ Tree class | ||||
|  | ||||
| """ | ||||
|  | ||||
| from .tree_tools import (to_nested_parenthesis, | ||||
|                          postfix_concatenate, | ||||
|                          show_tree, | ||||
|                         ) | ||||
| from .tree_tools import to_nested_parenthesis, postfix_concatenate, show_tree | ||||
| from .coroutine import coroutine, STOOOP | ||||
| from .str2 import str2 | ||||
| from .operator import OPERATORS, is_operator | ||||
| @@ -20,7 +17,7 @@ from .operator import OPERATORS, is_operator | ||||
| __all__ = ["Tree", "MutableTree"] | ||||
|  | ||||
|  | ||||
| class Tree(): | ||||
| class Tree: | ||||
|  | ||||
|     """ | ||||
|     Binary tree | ||||
| @@ -118,9 +115,8 @@ class Tree(): | ||||
|         except TypeError: | ||||
|             raise ValueError("Nested parenthesis are not composed of lists") | ||||
|  | ||||
|         if nested_len != 2 and \ | ||||
|             num_len != 2: | ||||
|                 raise ValueError("Nested parenthesis don't have right shape") | ||||
|         if nested_len != 2 and num_len != 2: | ||||
|             raise ValueError("Nested parenthesis don't have right shape") | ||||
|  | ||||
|         node = nested_parenthesis[0] | ||||
|  | ||||
| @@ -185,8 +181,8 @@ class Tree(): | ||||
|             l_value = leafs[0] | ||||
|             r_value = cls.from_list(node, leafs[1:]) | ||||
|         else: | ||||
|             l_value = cls.from_list(node, leafs[:len_leafs//2]) | ||||
|             r_value = cls.from_list(node, leafs[len_leafs//2:]) | ||||
|             l_value = cls.from_list(node, leafs[: len_leafs // 2]) | ||||
|             r_value = cls.from_list(node, leafs[len_leafs // 2 :]) | ||||
|         return cls(node, l_value, r_value) | ||||
|  | ||||
|     @classmethod | ||||
| @@ -241,9 +237,10 @@ class Tree(): | ||||
|         left_value = tree.left_value | ||||
|         right_value = tree.right_value | ||||
|  | ||||
|         if node is None or \ | ||||
|                 right_value is None: | ||||
|                     raise TypeError(f"Tree can't have empty node or leaf. Got node = {node} and right_value = {right_value}") | ||||
|         if node is None or right_value is None: | ||||
|             raise TypeError( | ||||
|                 f"Tree can't have empty node or leaf. Got node = {node} and right_value = {right_value}" | ||||
|             ) | ||||
|  | ||||
|         try: | ||||
|             left_value.IMLEAF | ||||
| @@ -336,16 +333,14 @@ class Tree(): | ||||
|  | ||||
|         left_is_leaf = 0 | ||||
|         try: | ||||
|             left_applied = self.left_value.\ | ||||
|                 apply_on_last_level(function) | ||||
|             left_applied = self.left_value.apply_on_last_level(function) | ||||
|         except AttributeError: | ||||
|             left_applied = self.left_value | ||||
|             left_is_leaf = 1 | ||||
|  | ||||
|         right_is_leaf = 0 | ||||
|         try: | ||||
|             right_applied = self.right_value.\ | ||||
|                 apply_on_last_level(function) | ||||
|             right_applied = self.right_value.apply_on_last_level(function) | ||||
|         except AttributeError: | ||||
|             right_applied = self.right_value | ||||
|             right_is_leaf = 1 | ||||
| @@ -401,7 +396,7 @@ class Tree(): | ||||
|         except NotImplementedError: | ||||
|             return Tree(self.node, left_value, right_value) | ||||
|  | ||||
|     def get_leafs(self, callback=lambda x:x): | ||||
|     def get_leafs(self, callback=lambda x: x): | ||||
|         """ Generator which yield all the leaf value of the tree. | ||||
|         Callback act on every leaf. | ||||
|  | ||||
| @@ -424,7 +419,7 @@ class Tree(): | ||||
|         except AttributeError: | ||||
|             yield callback(self.right_value) | ||||
|  | ||||
|     def get_nodes(self, callback=lambda x:x): | ||||
|     def get_nodes(self, callback=lambda x: x): | ||||
|         """ Generator which yield all nodes of the tree. | ||||
|         Callback act on every nodes. | ||||
|  | ||||
| @@ -653,7 +648,7 @@ class Tree(): | ||||
|         else: | ||||
|             return self.left_value | ||||
|  | ||||
|     def balance(self, exclude_nodes = []): | ||||
|     def balance(self, exclude_nodes=[]): | ||||
|         """ Recursively balance the tree without permutting different nodes | ||||
|  | ||||
|         :return: balanced tree | ||||
| @@ -836,22 +831,22 @@ class Tree(): | ||||
|         except AttributeError: | ||||
|             r_depth = 1 | ||||
|  | ||||
|         if l_depth > r_depth+1 and\ | ||||
|                 self.node == self.left_value.node and \ | ||||
|                 self.node not in exclude_nodes: | ||||
|         if ( | ||||
|             l_depth > r_depth + 1 | ||||
|             and self.node == self.left_value.node | ||||
|             and self.node not in exclude_nodes | ||||
|         ): | ||||
|             new_left = self.left_value.long_branch | ||||
|             new_right = Tree(self.node, | ||||
|                              self.left_value.short_branch, | ||||
|                              self.right_value) | ||||
|             new_right = Tree(self.node, self.left_value.short_branch, self.right_value) | ||||
|             return Tree(self.node, new_left, new_right).balance(exclude_nodes) | ||||
|  | ||||
|         if r_depth > l_depth+1 and\ | ||||
|                 self.node == self.right_value.node and \ | ||||
|                 self.node not in exclude_nodes: | ||||
|         if ( | ||||
|             r_depth > l_depth + 1 | ||||
|             and self.node == self.right_value.node | ||||
|             and self.node not in exclude_nodes | ||||
|         ): | ||||
|             new_right = self.right_value.long_branch | ||||
|             new_left = Tree(self.node, | ||||
|                              self.left_value, | ||||
|                              self.right_value.short_branch) | ||||
|             new_left = Tree(self.node, self.left_value, self.right_value.short_branch) | ||||
|             return Tree(self.node, new_left, new_right).balance(exclude_nodes) | ||||
|  | ||||
|         try: | ||||
| @@ -874,10 +869,8 @@ class MutableTree(Tree): | ||||
|     It is used to build a new tree before fixing it into a Tree | ||||
|  | ||||
|     """ | ||||
|     def __init__(self, | ||||
|             node = None, | ||||
|             left_value = None, | ||||
|             right_value = None): | ||||
|  | ||||
|     def __init__(self, node=None, left_value=None, right_value=None): | ||||
|         """ | ||||
|         Initiate a tree with potentialy None values | ||||
|  | ||||
| @@ -1024,7 +1017,10 @@ class MutableTree(Tree): | ||||
|                         try: | ||||
|                             ans.set_node(c) | ||||
|                         except ValueError: | ||||
|                             if OPERATORS[c]["precedence"] > OPERATORS[ans.node]["precedence"]: | ||||
|                             if ( | ||||
|                                 OPERATORS[c]["precedence"] | ||||
|                                 > OPERATORS[ans.node]["precedence"] | ||||
|                             ): | ||||
|                                 # the operation has to be done first | ||||
|                                 if nested_tree is not None: | ||||
|                                     b_tree = cls(c, nested_tree, None) | ||||
| @@ -1124,7 +1120,9 @@ class MutableTree(Tree): | ||||
|             try: | ||||
|                 self.right_value.append(value) | ||||
|             except AttributeError: | ||||
|                 raise ValueError("The right branch is full, use append_top or append_bot") | ||||
|                 raise ValueError( | ||||
|                     "The right branch is full, use append_top or append_bot" | ||||
|                 ) | ||||
|  | ||||
|     def append(self, value): | ||||
|         """ Append the value at the bottom of the tree. | ||||
| @@ -1196,7 +1194,7 @@ class MutableTree(Tree): | ||||
|          > None | ||||
|         """ | ||||
|  | ||||
|         #self_cp = MutableTree.from_any_tree(self) | ||||
|         # self_cp = MutableTree.from_any_tree(self) | ||||
|         self_cp = MutableTree() | ||||
|         self_cp.set_node(self.node) | ||||
|         self_cp.set_left_value(self.left_value) | ||||
| @@ -1272,6 +1270,7 @@ class AssocialTree(Tree): | ||||
|     """ Tree which concider every subtree with a node different from itself | ||||
|     as a Leaf | ||||
|     """ | ||||
|  | ||||
|     def map_on_leaf(self, function): | ||||
|         """ Map on leafs a function | ||||
|  | ||||
| @@ -1492,10 +1491,9 @@ class AssocialTree(Tree): | ||||
|         t = Tree.from_list(self.node, balanced_leafs) | ||||
|         return t | ||||
|  | ||||
|     def organise_by(self,  | ||||
|                     signature=lambda x: type(x), | ||||
|                     recursive=True, | ||||
|                     exclude_nodes=[]): | ||||
|     def organise_by( | ||||
|         self, signature=lambda x: type(x), recursive=True, exclude_nodes=[] | ||||
|     ): | ||||
|         """ Reoganise AssocialTree base on self order and groups by signature | ||||
|  | ||||
|         :param signature: grouping function (default type) | ||||
| @@ -1648,11 +1646,11 @@ class AssocialTree(Tree): | ||||
|                 except AttributeError: | ||||
|                     return leaf | ||||
|  | ||||
|             return AssocialTree.from_any_tree(tree).\ | ||||
|                 map_on_leaf(contaminate_organise) | ||||
|             return AssocialTree.from_any_tree(tree).map_on_leaf(contaminate_organise) | ||||
|  | ||||
|         return tree | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     a = MutableTree.from_str("(1+2)*3") | ||||
|     print(a) | ||||
|   | ||||
| @@ -17,6 +17,7 @@ __all__ = [] | ||||
|  | ||||
| # Functions on (op, left, right) | ||||
|  | ||||
|  | ||||
| def to_nested_parenthesis(op, left, right): | ||||
|     """ Get nested form for arguments | ||||
|  | ||||
| @@ -27,6 +28,7 @@ def to_nested_parenthesis(op, left, right): | ||||
|     """ | ||||
|     return (op, (left, right)) | ||||
|  | ||||
|  | ||||
| def infix_str_concatenate(op, left, right): | ||||
|     """ Concatenate arguments placing op on the middle. | ||||
|  | ||||
| @@ -37,6 +39,7 @@ def infix_str_concatenate(op, left, right): | ||||
|     """ | ||||
|     return f"{left} {op} {right}" | ||||
|  | ||||
|  | ||||
| def postfix_concatenate(op, left, right): | ||||
|     """ Concatenate arguments placing op on the middle. | ||||
|  | ||||
| @@ -61,6 +64,7 @@ def postfix_concatenate(op, left, right): | ||||
|  | ||||
|     return left_tokens + right_tokens + [op] | ||||
|  | ||||
|  | ||||
| def show_tree(op, left, right, sep="|", node_caracter=">"): | ||||
|     """ Shape argument to make nice Tree display | ||||
|  | ||||
| @@ -85,6 +89,7 @@ def show_tree(op, left, right, sep="|", node_caracter=">"): | ||||
|     right_slided = leaf_suffix.join(str(right).splitlines()) | ||||
|     return node_suffix.join([op, left_slided, right_slided]) | ||||
|  | ||||
|  | ||||
| # ----------------------------- | ||||
| # Reglages pour 'vim' | ||||
| # vim:set autoindent expandtab tabstop=4 shiftwidth=4: | ||||
|   | ||||
| @@ -12,6 +12,7 @@ Typing with MO | ||||
|  | ||||
| from .exceptions import TypingError | ||||
| from .add import add | ||||
|  | ||||
| # from .minus import minus | ||||
| from .multiply import multiply | ||||
| from .divide import divide | ||||
| @@ -25,18 +26,18 @@ from ..MO.polynomial import MOpolynomial | ||||
| from itertools import product | ||||
| from tabulate import tabulate | ||||
|  | ||||
| MOS = [ MOnumber, MOstr, MOFraction, MOstrPower, MOMonomial, MOpolynomial] | ||||
| MOS = [MOnumber, MOstr, MOFraction, MOstrPower, MOMonomial, MOpolynomial] | ||||
|  | ||||
| OPERATIONS = { | ||||
|         "+": add, | ||||
|         # "-": minus,  | ||||
|         "*": multiply, | ||||
|         "/": divide, | ||||
|         "^": power, | ||||
|         } | ||||
|     "+": add, | ||||
|     # "-": minus, | ||||
|     "*": multiply, | ||||
|     "/": divide, | ||||
|     "^": power, | ||||
| } | ||||
|  | ||||
| def typing(node, left_v, right_v,\ | ||||
|            raiseTypingError = True): | ||||
|  | ||||
| def typing(node, left_v, right_v, raiseTypingError=True): | ||||
|     """ | ||||
|     Typing a try base on his root node | ||||
|  | ||||
| @@ -47,6 +48,7 @@ def typing(node, left_v, right_v,\ | ||||
|         raise NotImplementedError(f"Unknown operation ({node}) in typing") | ||||
|     return operation(left_v, right_v) | ||||
|  | ||||
|  | ||||
| def typing_capacities(node): | ||||
|     """ Test an operation through all MOs | ||||
|  | ||||
| @@ -59,21 +61,19 @@ def typing_capacities(node): | ||||
|  | ||||
|     """ | ||||
|     op = OPERATIONS[node] | ||||
|     lines =  [[node] + [mo.__name__ for mo in MOS]] | ||||
|     lines = [[node] + [mo.__name__ for mo in MOS]] | ||||
|     for left_mo in MOS: | ||||
|        lines.append( | ||||
|            [left_mo.__name__] + \ | ||||
|            [(left_mo, i) in op.funcs for i in MOS] | ||||
|        ) | ||||
|         lines.append([left_mo.__name__] + [(left_mo, i) in op.funcs for i in MOS]) | ||||
|     return lines | ||||
|  | ||||
|  | ||||
| def describe_typing(): | ||||
|     """ Explain which operations are handle by typing """ | ||||
|  | ||||
|     ans = "Implemented typing operations among MOs\n" | ||||
|     for op in OPERATIONS: | ||||
|         ans += "\n" | ||||
|         ans += tabulate(typing_capacities(op), tablefmt='grid') | ||||
|         ans += tabulate(typing_capacities(op), tablefmt="grid") | ||||
|  | ||||
|     return ans | ||||
|  | ||||
|   | ||||
| @@ -27,6 +27,7 @@ add_doc = """ Add MOs | ||||
|  | ||||
| add = Dispatcher("add", doc=add_doc) | ||||
|  | ||||
|  | ||||
| @add.register((MOnumber, MOFraction), MOstr) | ||||
| def moscalar_mostr(left, right): | ||||
|     """ add a scalar with a letter to create a MOpolynomial | ||||
| @@ -41,6 +42,7 @@ def moscalar_mostr(left, right): | ||||
|     """ | ||||
|     return MOpolynomial(right, [left, 1]) | ||||
|  | ||||
|  | ||||
| @add.register(MOstr, (MOnumber, MOFraction)) | ||||
| def mostr_moscalar(left, right): | ||||
|     """ add a scalar with a letter to create a MOpolynomial | ||||
| @@ -55,6 +57,7 @@ def mostr_moscalar(left, right): | ||||
|     """ | ||||
|     return MOpolynomial(left, [right, 1]) | ||||
|  | ||||
|  | ||||
| @add.register((MOnumber, MOFraction), MOstrPower) | ||||
| def moscalar_mostrpower(left, right): | ||||
|     """ add a scalar with a letter to create a MOpolynomial | ||||
| @@ -69,6 +72,7 @@ def moscalar_mostrpower(left, right): | ||||
|     """ | ||||
|     return MOpolynomial(right.variable, {0: left, right.power: 1}) | ||||
|  | ||||
|  | ||||
| @add.register(MOstrPower, (MOnumber, MOFraction)) | ||||
| def mostrpower_moscalar(left, right): | ||||
|     """ add a scalar with a letter to create a MOpolynomial | ||||
| @@ -83,6 +87,7 @@ def mostrpower_moscalar(left, right): | ||||
|     """ | ||||
|     return MOpolynomial(left.variable, {0: right, left.power: 1}) | ||||
|  | ||||
|  | ||||
| @add.register((MOnumber, MOFraction), MOMonomial) | ||||
| def moscalar_momonomial(left, right): | ||||
|     """ add a scalar with a MOMonomial to create a MOpolynomial | ||||
| @@ -95,9 +100,8 @@ def moscalar_momonomial(left, right): | ||||
|     >>> add(a, b) | ||||
|     <MOpolynomial 1 / 5 + 3x^4> | ||||
|     """ | ||||
|     return MOpolynomial(right.variable,  | ||||
|                         {right.power: right.coefficient, 0: left} | ||||
|                         ) | ||||
|     return MOpolynomial(right.variable, {right.power: right.coefficient, 0: left}) | ||||
|  | ||||
|  | ||||
| @add.register(MOMonomial, (MOnumber, MOFraction)) | ||||
| def momonial_moscalar(left, right): | ||||
| @@ -112,9 +116,8 @@ def momonial_moscalar(left, right): | ||||
|     <MOpolynomial 3x^4 + 1 / 5> | ||||
|  | ||||
|     """ | ||||
|     return MOpolynomial(left.variable, | ||||
|                         {0: right, left.power: left.coefficient} | ||||
|                         ) | ||||
|     return MOpolynomial(left.variable, {0: right, left.power: left.coefficient}) | ||||
|  | ||||
|  | ||||
| @add.register((MOnumber, MOFraction), MOpolynomial) | ||||
| def moscalar_mopolynomial(left, right): | ||||
| @@ -129,13 +132,16 @@ def moscalar_mopolynomial(left, right): | ||||
|     <MOpolynomial 1 / 5 + 3x^2 + 2x> | ||||
|     """ | ||||
|     if 0 in right.coefficients.keys(): | ||||
|         raise NotImplementedError(f"Polynomial with constant ({right.coefficients[0]}), calculus to do") | ||||
|         raise NotImplementedError( | ||||
|             f"Polynomial with constant ({right.coefficients[0]}), calculus to do" | ||||
|         ) | ||||
|  | ||||
|     new_coefs = {**right.coefficients} | ||||
|     #! Need to be add at the end to be printed at the beginning | ||||
|     new_coefs[0] = left | ||||
|     return MOpolynomial(right.variable, new_coefs) | ||||
|  | ||||
|  | ||||
| @add.register(MOpolynomial, (MOnumber, MOFraction)) | ||||
| def mopolynomial_moscalar(left, right): | ||||
|     """ add a scalar with a MOpolynomial to create a MOpolynomial | ||||
| @@ -156,6 +162,7 @@ def mopolynomial_moscalar(left, right): | ||||
|     new_coefs = {**new_coefs, **left.coefficients} | ||||
|     return MOpolynomial(left.variable, new_coefs) | ||||
|  | ||||
|  | ||||
| @add.register(MOstr, MOstr) | ||||
| def mostr_mostr(left, right): | ||||
|     """ add 2 mostr | ||||
| @@ -167,7 +174,8 @@ def mostr_mostr(left, right): | ||||
|     """ | ||||
|     if left != right: | ||||
|         raise NotImplementedError("Can't add 2 Mostr without same letter") | ||||
|     return MOMonomial(2, left)  | ||||
|     return MOMonomial(2, left) | ||||
|  | ||||
|  | ||||
| @add.register(MOstr, MOstrPower) | ||||
| def mostr_mostrpower(left, right): | ||||
| @@ -182,8 +190,9 @@ def mostr_mostrpower(left, right): | ||||
|     <MOpolynomial x^2 + x> | ||||
|     """ | ||||
|     if left != right.variable: | ||||
|         raise  | ||||
|     return MOpolynomial(left , {1: 1, right.power: 1}) | ||||
|         raise | ||||
|     return MOpolynomial(left, {1: 1, right.power: 1}) | ||||
|  | ||||
|  | ||||
| @add.register(MOstrPower, MOstr) | ||||
| def mostrpower_mostr(left, right): | ||||
| @@ -198,8 +207,9 @@ def mostrpower_mostr(left, right): | ||||
|     <MOpolynomial x^2 + x> | ||||
|     """ | ||||
|     if right != left.variable: | ||||
|         raise  | ||||
|     return MOpolynomial(right , {1: 1, left.power: 1}) | ||||
|         raise | ||||
|     return MOpolynomial(right, {1: 1, left.power: 1}) | ||||
|  | ||||
|  | ||||
| @add.register(MOstrPower, MOstrPower) | ||||
| def mostrpower_mostrpower(left, right): | ||||
| @@ -213,9 +223,12 @@ def mostrpower_mostrpower(left, right): | ||||
|     if left.variable != right.variable: | ||||
|         raise NotImplementedError("Can't add 2 Mostrpower without same letter") | ||||
|     if left.power != right.power: | ||||
|         raise NotImplementedError("Can't add 2 Mostrpower with compute if not same degree") | ||||
|         raise NotImplementedError( | ||||
|             "Can't add 2 Mostrpower with compute if not same degree" | ||||
|         ) | ||||
|  | ||||
|     return MOMonomial(2, left.variable, left.power) | ||||
|  | ||||
|     return MOMonomial(2, left.variable, left.power)  | ||||
|  | ||||
| @add.register(MOstr, MOpolynomial) | ||||
| def mostr_mopolynomial(left, right): | ||||
| @@ -234,6 +247,7 @@ def mostr_mopolynomial(left, right): | ||||
|     new_coefs[1] = 1 | ||||
|     return MOpolynomial(right.variable, new_coefs) | ||||
|  | ||||
|  | ||||
| @add.register(MOpolynomial, MOstr) | ||||
| def mopolynomial_mostr(left, right): | ||||
|     """ add a str with a MOpolynomial to create a MOpolynomial | ||||
| @@ -250,6 +264,7 @@ def mopolynomial_mostr(left, right): | ||||
|     new_coefs = {**new_coefs, **left.coefficients} | ||||
|     return MOpolynomial(left.variable, new_coefs) | ||||
|  | ||||
|  | ||||
| @add.register(MOstrPower, MOpolynomial) | ||||
| def mostrpower_mopolynomial(left, right): | ||||
|     """ add a strPower with a MOpolynomial to create a MOpolynomial | ||||
| @@ -267,6 +282,7 @@ def mostrpower_mopolynomial(left, right): | ||||
|     new_coefs[left.power] = 1 | ||||
|     return MOpolynomial(right.variable, new_coefs) | ||||
|  | ||||
|  | ||||
| @add.register(MOpolynomial, MOstrPower) | ||||
| def mopolynomial_mostrpower(left, right): | ||||
|     """ add a strPower with a MOpolynomial to create a MOpolynomial | ||||
| @@ -283,6 +299,7 @@ def mopolynomial_mostrpower(left, right): | ||||
|     new_coefs = {**new_coefs, **left.coefficients} | ||||
|     return MOpolynomial(left.variable, new_coefs) | ||||
|  | ||||
|  | ||||
| @add.register(MOMonomial, MOpolynomial) | ||||
| def momonomial_mopolynomial(left, right): | ||||
|     """ add a Monomial with a MOpolynomial to create a MOpolynomial | ||||
| @@ -300,6 +317,7 @@ def momonomial_mopolynomial(left, right): | ||||
|     new_coefs[left.power] = left.coefficient | ||||
|     return MOpolynomial(right.variable, new_coefs) | ||||
|  | ||||
|  | ||||
| @add.register(MOpolynomial, MOMonomial) | ||||
| def mopolynomial_momonomial(left, right): | ||||
|     """ add a Monomial with a MOpolynomial to create a MOpolynomial | ||||
| @@ -316,6 +334,7 @@ def mopolynomial_momonomial(left, right): | ||||
|     new_coefs = {**new_coefs, **left.coefficients} | ||||
|     return MOpolynomial(left.variable, new_coefs) | ||||
|  | ||||
|  | ||||
| @add.register(MOpolynomial, MOpolynomial) | ||||
| def mopolynomial_mopolynomial(left, right): | ||||
|     """ add a polynomial with a MOpolynomial to create a MOpolynomial | ||||
| @@ -327,13 +346,14 @@ def mopolynomial_mopolynomial(left, right): | ||||
|     >>> add(b, a) | ||||
|     <MOpolynomial 4x^3 + 2x + 3x^2 + 1> | ||||
|     """ | ||||
|     common_degree = set(left.monomials.keys()).intersection(right.monomials.keys())  | ||||
|     common_degree = set(left.monomials.keys()).intersection(right.monomials.keys()) | ||||
|     if common_degree: | ||||
|         raise NotImplementedError("Degree in common, need to compute") | ||||
|  | ||||
|     new_coefs = {**right.coefficients, **left.coefficients} | ||||
|     return MOpolynomial(right.variable, new_coefs) | ||||
|  | ||||
|  | ||||
| @add.register(MOstr, MOMonomial) | ||||
| def mostr_monomial(left, right): | ||||
|     """ add a mostr with a MOMonomial to create a MOpolynomial | ||||
| @@ -346,9 +366,8 @@ def mostr_monomial(left, right): | ||||
|     if right.power == 1: | ||||
|         raise NotImplementedError("Monomial is deg 1, need to compute") | ||||
|  | ||||
|     return MOpolynomial(right.variable,  | ||||
|                         {right.power: right.coefficient, 1: 1} | ||||
|                         ) | ||||
|     return MOpolynomial(right.variable, {right.power: right.coefficient, 1: 1}) | ||||
|  | ||||
|  | ||||
| @add.register(MOMonomial, MOstr) | ||||
| def monomial_mostr(left, right): | ||||
| @@ -362,9 +381,8 @@ def monomial_mostr(left, right): | ||||
|     if left.power == 1: | ||||
|         raise NotImplementedError("Monomial is deg 1, need to compute") | ||||
|  | ||||
|     return MOpolynomial(left.variable,  | ||||
|                         {1: 1, left.power: left.coefficient} | ||||
|                         ) | ||||
|     return MOpolynomial(left.variable, {1: 1, left.power: left.coefficient}) | ||||
|  | ||||
|  | ||||
| @add.register(MOstrPower, MOMonomial) | ||||
| def mostrpower_monomial(left, right): | ||||
| @@ -376,11 +394,12 @@ def mostrpower_monomial(left, right): | ||||
|     <MOpolynomial x^2 + 3x^4> | ||||
|     """ | ||||
|     if left.power == right.power: | ||||
|         raise NotImplementedError("MostrPower and MOMonomial are same degree, need to compute") | ||||
|         raise NotImplementedError( | ||||
|             "MostrPower and MOMonomial are same degree, need to compute" | ||||
|         ) | ||||
|  | ||||
|     return MOpolynomial(right.variable, {right.power: right.coefficient, left.power: 1}) | ||||
|  | ||||
|     return MOpolynomial(right.variable,  | ||||
|                         {right.power: right.coefficient, left.power: 1} | ||||
|                         ) | ||||
|  | ||||
| @add.register(MOMonomial, MOstrPower) | ||||
| def monomial_mostrpower(left, right): | ||||
| @@ -392,11 +411,12 @@ def monomial_mostrpower(left, right): | ||||
|     <MOpolynomial 3x^4 + x^3> | ||||
|     """ | ||||
|     if left.power == right.power: | ||||
|         raise NotImplementedError("MostrPower and MOMonomial are same degree, need to compute") | ||||
|         raise NotImplementedError( | ||||
|             "MostrPower and MOMonomial are same degree, need to compute" | ||||
|         ) | ||||
|  | ||||
|     return MOpolynomial(left.variable, {right.power: 1, left.power: left.coefficient}) | ||||
|  | ||||
|     return MOpolynomial(left.variable,  | ||||
|                         {right.power: 1, left.power: left.coefficient} | ||||
|                         ) | ||||
|  | ||||
| @add.register(MOMonomial, MOMonomial) | ||||
| def monomial_momonomial(left, right): | ||||
| @@ -410,9 +430,9 @@ def monomial_momonomial(left, right): | ||||
|     if left.power == right.power: | ||||
|         raise NotImplementedError("MOMonomials are same degree, need to compute") | ||||
|  | ||||
|     return MOpolynomial(left.variable,  | ||||
|                         {right.power: right.coefficient, left.power: left.coefficient} | ||||
|                         ) | ||||
|     return MOpolynomial( | ||||
|         left.variable, {right.power: right.coefficient, left.power: left.coefficient} | ||||
|     ) | ||||
|  | ||||
|  | ||||
| # ----------------------------- | ||||
|   | ||||
| @@ -24,6 +24,7 @@ divide_doc = """ Typing trees a divide root | ||||
|  | ||||
| divide = Dispatcher("divide", doc=divide_doc) | ||||
|  | ||||
|  | ||||
| @divide.register(MOnumber, MOnumber) | ||||
| def monumber_monumber(left, right): | ||||
|     """ A divide tree with 2 MOnumbers is a MOFraction | ||||
|   | ||||
| @@ -10,9 +10,11 @@ | ||||
| Exceptions for typing trees  | ||||
| """ | ||||
|  | ||||
|  | ||||
| class TypingError(Exception): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| # ----------------------------- | ||||
| # Reglages pour 'vim' | ||||
| # vim:set autoindent expandtab tabstop=4 shiftwidth=4: | ||||
|   | ||||
| @@ -26,6 +26,7 @@ multiply_doc = """ Multiply MOs | ||||
|  | ||||
| multiply = Dispatcher("multiply", doc=multiply_doc) | ||||
|  | ||||
|  | ||||
| @multiply.register((MOnumber, MOFraction), MOstr) | ||||
| def moscalar_mostr(left, right): | ||||
|     """ Multiply a scalar with a letter to create a MOMonomial | ||||
| @@ -40,6 +41,7 @@ def moscalar_mostr(left, right): | ||||
|     """ | ||||
|     return MOMonomial(left, right) | ||||
|  | ||||
|  | ||||
| @multiply.register(MOstr, (MOnumber, MOFraction)) | ||||
| def mostr_moscalar(left, right): | ||||
|     """ Multiply a scalar with a letter to create a MOMonomial | ||||
| @@ -54,6 +56,7 @@ def mostr_moscalar(left, right): | ||||
|     """ | ||||
|     return MOMonomial(right, left) | ||||
|  | ||||
|  | ||||
| @multiply.register((MOnumber, MOFraction), MOstrPower) | ||||
| def moscalar_mostrpower(left, right): | ||||
|     """ Multiply a scalar with a MOstrPower | ||||
| @@ -66,6 +69,7 @@ def moscalar_mostrpower(left, right): | ||||
|     """ | ||||
|     return MOMonomial(left, right) | ||||
|  | ||||
|  | ||||
| @multiply.register(MOstrPower, (MOnumber, MOFraction)) | ||||
| def mostrpower_moscalar(left, right): | ||||
|     """ Multiply a MOstrPower with a scalar | ||||
| @@ -78,6 +82,7 @@ def mostrpower_moscalar(left, right): | ||||
|     """ | ||||
|     return MOMonomial(right, left) | ||||
|  | ||||
|  | ||||
| # ----------------------------- | ||||
| # Reglages pour 'vim' | ||||
| # vim:set autoindent expandtab tabstop=4 shiftwidth=4: | ||||
|   | ||||
| @@ -25,6 +25,7 @@ power_doc = """ Typing Power of MOs | ||||
|  | ||||
| power = Dispatcher("power", doc=power_doc) | ||||
|  | ||||
|  | ||||
| @power.register(MOstr, MOnumber) | ||||
| def mostr_monumber(left, right): | ||||
|     """ Create MOstrPower over powered MOstr | ||||
| @@ -38,7 +39,6 @@ def mostr_monumber(left, right): | ||||
|     return MOstrPower(left, right) | ||||
|  | ||||
|  | ||||
|  | ||||
| # ----------------------------- | ||||
| # Reglages pour 'vim' | ||||
| # vim:set autoindent expandtab tabstop=4 shiftwidth=4: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user