Fix(API): Rewrite tree apply_on_last_level and reorganise simplify

This commit is contained in:
Bertrand Benjamin 2018-11-19 12:23:37 +01:00
parent 6edf4fe5b4
commit e37a8a5a2e
4 changed files with 67 additions and 29 deletions

View File

@ -21,6 +21,7 @@ Generate and compute like a student!
2 + 12 2 + 12
14 14
>>> e = Expression.from_str("2+3/2") >>> e = Expression.from_str("2+3/2")
>>> e_simplified = e.simplify() >>> e_simplified = e.simplify()
>>> print(e_simplified) >>> print(e_simplified)
@ -34,6 +35,20 @@ Generate and compute like a student!
(4 + 3) / 2 (4 + 3) / 2
7 / 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 = Expression.from_str("(2/3)^4")
>>> e_simplified = e.simplify() >>> e_simplified = e.simplify()
>>> print(e_simplified) >>> print(e_simplified)
@ -54,10 +69,28 @@ x^2 * x * x^4
x^3 * x^4 x^3 * x^4
x^(3 + 4) x^(3 + 4)
x^7 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 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' # Reglages pour 'vim'

View File

@ -10,7 +10,7 @@
Expression Expression
""" """
from ..core import AssocialTree, Tree, compute, typing from ..core import AssocialTree, Tree, compute, typing, TypingError
from .renders import renders from .renders import renders
class Expression(object): class Expression(object):
@ -104,20 +104,31 @@ class Expression(object):
>>> f._ancestor >>> f._ancestor
<Exp: 2 + 12> <Exp: 2 + 12>
""" """
t = self._tree
if optimize: if optimize:
try: try:
# TODO: need to test exclude_nodes |ven. oct. 5 08:51:02 CEST 2018 # TODO: need to test exclude_nodes |ven. oct. 5 08:51:02 CEST 2018
self._tree = self._tree.balance( t = t.balance(
exclude_nodes=["\\", "**"] exclude_nodes=["\\", "**"]
) )
except AttributeError: except AttributeError:
pass 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: try:
t = self._tree.apply_on_last_level(compute, typing) t = t.apply_on_last_level(compute)
except AttributeError: except AttributeError:
return self return self
except NotImplementedError:
return self
else: else:
e = Expression(t, ancestor=self) e = Expression(t, ancestor=self)
return e.simplify(optimize=optimize) return e.simplify(optimize=optimize)

View File

@ -18,7 +18,7 @@ Abstracts tools for calculs manipulations
> * > *
| > 3 | > 3
| > 4 | > 4
>>> print(t.apply_on_last_level(compute, typing)) >>> print(t.apply_on_last_level(compute))
+ +
> 2 > 2
> 12 > 12
@ -34,7 +34,12 @@ Abstracts tools for calculs manipulations
> / > /
| > 3 | > 3
| > 4 | > 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 | > 2
@ -42,7 +47,12 @@ Abstracts tools for calculs manipulations
> / > /
| > 3 | > 3
| > 4 | > 4
>>> type(t.right_value)
<class 'mapytex.calculus.core.tree.Tree'>
>>> type(tt.right_value)
<class 'mapytex.calculus.core.MO.fraction.MOFraction'>
>>> tt.right_value
<MOFraction 3 / 4>
>>> t = Tree.from_str("2+3x") >>> t = Tree.from_str("2+3x")
>>> print(t) >>> print(t)
@ -56,7 +66,7 @@ Abstracts tools for calculs manipulations
from .tree import Tree, AssocialTree from .tree import Tree, AssocialTree
from .compute import compute from .compute import compute
from .typing import typing from .typing import typing, TypingError
from .renders import tree2txt, tree2tex from .renders import tree2txt, tree2tex

View File

@ -294,13 +294,10 @@ class Tree(object):
return Tree(self.node, left_applied, right_applied) return Tree(self.node, left_applied, right_applied)
def apply_on_last_level(self, def apply_on_last_level(self, function):
function,
fallback = lambda n,l,r: Tree(n,l,r)):
""" Apply the function on last level of the tree before leaf """ Apply the function on last level of the tree before leaf
:param function: (op, a, a) -> b function to apply on last level :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 :returns: b if it is a 1 level Tree, Tree otherwise
@ -330,30 +327,17 @@ class Tree(object):
""" """
left_is_leaf = 0 left_is_leaf = 0
right_is_leaf = 0
try: try:
left_applied = self.left_value.\ left_applied = self.left_value.\
apply_on_last_level(function, fallback) apply_on_last_level(function)
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)
except AttributeError: except AttributeError:
left_applied = self.left_value left_applied = self.left_value
left_is_leaf = 1 left_is_leaf = 1
right_is_leaf = 0
try: try:
right_applied = self.right_value.\ right_applied = self.right_value.\
apply_on_last_level(function, fallback) apply_on_last_level(function)
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)
except AttributeError: except AttributeError:
right_applied = self.right_value right_applied = self.right_value
right_is_leaf = 1 right_is_leaf = 1