diff --git a/mapytex/calculus/API/__init__.py b/mapytex/calculus/API/__init__.py index 1215e64..7291016 100644 --- a/mapytex/calculus/API/__init__.py +++ b/mapytex/calculus/API/__init__.py @@ -21,6 +21,7 @@ Generate and compute like a student! 2 + 12 14 + >>> e = Expression.from_str("2+3/2") >>> e_simplified = e.simplify() >>> print(e_simplified) @@ -34,6 +35,20 @@ Generate and compute like a student! (4 + 3) / 2 7 / 2 +>>> e = Expression.from_str("(2+3)/2 + 1") +>>> e_simplified = e.simplify() +>>> print(e_simplified) +7 / 2 +>>> for s in e_simplified.explain(): +... print(s) +(2 + 3) / 2 + 1 +5 / 2 + 1 +5 / 2 + 1 / 1 +5 / 2 + (1 * 2) / (1 * 2) +5 / 2 + 2 / 2 +(5 + 2) / 2 +7 / 2 + >>> e = Expression.from_str("(2/3)^4") >>> e_simplified = e.simplify() >>> print(e_simplified) @@ -54,10 +69,28 @@ x^2 * x * x^4 x^3 * x^4 x^(3 + 4) x^7 + +>>> e = Expression.from_str("2x+2+3x") +>>> e_simplified = e.simplify() +>>> print(e_simplified) +5x + 2 +>>> for s in e_simplified.explain(): +... print(s) +2x + 2 + 3x +2x + 3x + 2 +(2 + 3) * x + 2 +5x + 2 """ from .expression import Expression +if __name__ == "__main__": + e = Expression.from_str("2x+2+3x") + print(e) + e_simplified = e.simplify() + print(e_simplified) + + # ----------------------------- # Reglages pour 'vim' diff --git a/mapytex/calculus/API/expression.py b/mapytex/calculus/API/expression.py index 36def04..5112fa7 100644 --- a/mapytex/calculus/API/expression.py +++ b/mapytex/calculus/API/expression.py @@ -10,7 +10,7 @@ Expression """ -from ..core import AssocialTree, Tree, compute, typing +from ..core import AssocialTree, Tree, compute, typing, TypingError from .renders import renders class Expression(object): @@ -104,20 +104,31 @@ class Expression(object): >>> f._ancestor """ + t = self._tree if optimize: try: # TODO: need to test exclude_nodes |ven. oct. 5 08:51:02 CEST 2018 - self._tree = self._tree.balance( + t = t.balance( exclude_nodes=["\\", "**"] ) except AttributeError: pass + + more_typing = 1 + while more_typing: + try: + t = t.apply_on_last_level(typing) + except TypingError: + more_typing = 0 + except NotImplementedError: + more_typing = 0 + except AttributeError: + more_typing = 0 + try: - t = self._tree.apply_on_last_level(compute, typing) + t = t.apply_on_last_level(compute) except AttributeError: return self - except NotImplementedError: - return self else: e = Expression(t, ancestor=self) return e.simplify(optimize=optimize) diff --git a/mapytex/calculus/core/__init__.py b/mapytex/calculus/core/__init__.py index a83b987..1adcf5c 100644 --- a/mapytex/calculus/core/__init__.py +++ b/mapytex/calculus/core/__init__.py @@ -18,7 +18,7 @@ Abstracts tools for calculs manipulations > * | > 3 | > 4 ->>> print(t.apply_on_last_level(compute, typing)) +>>> print(t.apply_on_last_level(compute)) + > 2 > 12 @@ -34,7 +34,12 @@ Abstracts tools for calculs manipulations > / | > 3 | > 4 ->>> print(t.apply_on_last_level(compute, typing)) +>>> print(t.apply_on_last_level(compute)) +Traceback (most recent call last): + ... +NotImplementedError: Can't divide 2 int. Need to create a Fraction instead +>>> tt = t.apply_on_last_level(typing) +>>> print(tt.apply_on_last_level(compute)) + > / | > 2 @@ -42,7 +47,12 @@ Abstracts tools for calculs manipulations > / | > 3 | > 4 - +>>> type(t.right_value) + +>>> type(tt.right_value) + +>>> tt.right_value + >>> t = Tree.from_str("2+3x") >>> print(t) @@ -56,7 +66,7 @@ Abstracts tools for calculs manipulations from .tree import Tree, AssocialTree from .compute import compute -from .typing import typing +from .typing import typing, TypingError from .renders import tree2txt, tree2tex diff --git a/mapytex/calculus/core/tree.py b/mapytex/calculus/core/tree.py index 29f0da8..4068d57 100644 --- a/mapytex/calculus/core/tree.py +++ b/mapytex/calculus/core/tree.py @@ -294,13 +294,10 @@ class Tree(object): return Tree(self.node, left_applied, right_applied) - def apply_on_last_level(self, - function, - fallback = lambda n,l,r: Tree(n,l,r)): + def apply_on_last_level(self, function): """ Apply the function on last level of the tree before leaf :param function: (op, a, a) -> b function to apply on last level - :param fallback: (op, a, a) -> b fallback function to apply on subtree which raise a NotImplementedError. The return value will be concidered as an leaf :returns: b if it is a 1 level Tree, Tree otherwise @@ -330,30 +327,17 @@ class Tree(object): """ left_is_leaf = 0 - right_is_leaf = 0 try: left_applied = self.left_value.\ - apply_on_last_level(function, fallback) - except NotImplementedError: - # TODO: overload __getitem__ to ease unpacking |dim. sept. 23 19:17:50 CEST 2018 - left_is_leaf = 1 - left_tree = self.left_value - left_applied = fallback(left_tree.node, - left_tree.left_value, - left_tree.right_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, fallback) - except NotImplementedError: - right_is_leaf = 1 - right_tree = self.right_value - right_applied = fallback(right_tree.node, - right_tree.left_value, - right_tree.right_value) + apply_on_last_level(function) except AttributeError: right_applied = self.right_value right_is_leaf = 1