Feat(API): use balance before computing to optimize calculus

This commit is contained in:
Bertrand Benjamin 2018-10-01 16:14:04 +02:00
parent 1266a2331b
commit e9a865a14a
2 changed files with 141 additions and 4 deletions

View File

@ -10,7 +10,7 @@
Expression Expression
""" """
from ..core import Tree, compute, typing from ..core import AssocialTree, Tree, compute, typing
from .renders import renders from .renders import renders
class Expression(object): class Expression(object):
@ -88,9 +88,99 @@ class Expression(object):
def __repr__(self): def __repr__(self):
return f"<Exp: {renders[self.RENDER](self._tree)}>" return f"<Exp: {renders[self.RENDER](self._tree)}>"
def simplify(self): def balance(self):
""" Balance selt._tree in order to optimize end tree number
# TODO: their will be issue with / which is not commutative |lun. oct. 1 15:03:21 CEST 2018
:return: optmized version of self
:example:
>>> t = Expression.from_str("1+2+3+4+5+6+7+8+9")
>>> print(t._tree)
+
> +
| > +
| | > +
| | | > +
| | | | > +
| | | | | > +
| | | | | | > +
| | | | | | | > 1
| | | | | | | > 2
| | | | | | > 3
| | | | | > 4
| | | | > 5
| | | > 6
| | > 7
| > 8
> 9
>>> t.balance()
>>> print(t._tree)
+
> +
| > +
| | > 1
| | > 2
| > +
| | > 3
| | > 4
> +
| > +
| | > 5
| | > 6
| > +
| | > 7
| | > +
| | | > 8
| | | > 9
>>> t = Expression.from_str("1+2+3+4+5*6*7*8*9")
>>> print(t._tree)
+
> +
| > +
| | > +
| | | > 1
| | | > 2
| | > 3
| > 4
> *
| > *
| | > *
| | | > *
| | | | > 5
| | | | > 6
| | | > 7
| | > 8
| > 9
>>> t.balance()
>>> print(t._tree)
+
> +
| > 1
| > 2
> +
| > 3
| > +
| | > 4
| | > *
| | | > *
| | | | > 5
| | | | > 6
| | | > *
| | | | > 7
| | | | > *
| | | | | > 8
| | | | | > 9
"""
self._tree = AssocialTree.from_any_tree(self._tree).balance()
def simplify(self, optimize=True):
""" Compute as much as possible the expression """ Compute as much as possible the expression
:param optimize: bool to optimize tree when it's possible
:return: an expression :return: an expression
:example: :example:
@ -103,6 +193,11 @@ class Expression(object):
>>> f._ancestor >>> f._ancestor
<Exp: 2 + 12> <Exp: 2 + 12>
""" """
if optimize:
try:
self.balance()
except AttributeError:
pass
try: try:
t = self._tree.apply_on_last_level(compute, typing) t = self._tree.apply_on_last_level(compute, typing)
except AttributeError: except AttributeError:
@ -111,7 +206,7 @@ class Expression(object):
return self return self
else: else:
e = Expression(t, ancestor=self) e = Expression(t, ancestor=self)
return e.simplify() return e.simplify(optimize=optimize)
def explain(self): def explain(self):
""" Yield every calculus step which have lead to self """ Yield every calculus step which have lead to self
@ -124,6 +219,48 @@ class Expression(object):
2 + 3 * 4 2 + 3 * 4
2 + 12 2 + 12
14 14
>>> e = Expression.from_str("1+2+3+4+5+6+7+8+9")
>>> f = e.simplify()
>>> for s in f.explain():
... print(s)
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9
3 + 7 + 11 + 7 + 17
10 + 11 + 24
10 + 35
45
>>> e = Expression.from_str("1+2+3+4+5+6+7+8+9")
>>> f_no_balance = e.simplify(optimize=False)
>>> for s in f_no_balance.explain():
... print(s)
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9
3 + 3 + 4 + 5 + 6 + 7 + 8 + 9
6 + 4 + 5 + 6 + 7 + 8 + 9
10 + 5 + 6 + 7 + 8 + 9
15 + 6 + 7 + 8 + 9
21 + 7 + 8 + 9
28 + 8 + 9
36 + 9
45
>>> e = Expression.from_str("1+2+3+4+5*6*7*8*9")
>>> f = e.simplify()
>>> for s in f.explain():
... print(s)
1 + 2 + 3 + 4 + 5 * 6 * 7 * 8 * 9
3 + 3 + 4 + 30 * 7 * 72
6 + 4 + 30 * 504
6 + 4 + 15120
6 + 15124
15130
>>> e = Expression.from_str("1+2+3+4+5*6*7*8*9")
>>> f_no_balance = e.simplify(optimize=False)
>>> for s in f_no_balance.explain():
... print(s)
1 + 2 + 3 + 4 + 5 * 6 * 7 * 8 * 9
3 + 3 + 4 + 30 * 7 * 8 * 9
6 + 4 + 210 * 8 * 9
10 + 1680 * 9
10 + 15120
15130
""" """
try: try:
yield from self._ancestor.explain() yield from self._ancestor.explain()

View File

@ -54,7 +54,7 @@ Abstracts tools for calculs manipulations
""" """
from .tree import Tree from .tree import Tree, AssocialTree
from .compute import compute from .compute import compute
from .typing import typing from .typing import typing
from .renders import tree2txt, tree2tex from .renders import tree2txt, tree2tex