I am just moving this here from the issues list. It is a
discussion about some of the things to be aware of
when trying to do traversals of SymPy expressions.

>>> from sympy.strategies.traverse import *
>>> def f(x):
...   if x.is_Symbol:
...     x += 1
...   return x
...
>>> bottom_up(f)(x)
x + 1
>>> bottom_up(f)(x**2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "sympy\core\basic.py", line 452, in __repr__
    return sstr(self, order=None)
  File "sympy\printing\str.py", line 670, in sstr
    s = p.doprint(expr)
  File "sympy\printing\printer.py", line 231, in doprint
    return self._str(self._print(expr))
  File "sympy\printing\printer.py", line 255, in _print
    return getattr(self, printmethod)(expr, *args)
  File "sympy\printing\str.py", line 442, in _print_Pow
    if expr.is_commutative:
AttributeError: is_commutative


*Yesterday (35 hours ago) Delete comment Project Member #1 MRocklin*

Traveral strategies use Basic.__new__ to construct the tree without calling 
object constructors.  Many Exprs require construction to function properly. 
 
Mainly this is because they set the is_commutative flag as a field rather 
than as an arg.  As a result, the traversal strategies damage the tree. 

This damage can be fixed with the rebuild rule.
In [1]: def f(x):
   ...:     if x.is_Symbol:
   ...:         return x + 1
   ...:     return x
   ...: 

In [2]: from sympy.strategies.traverse import *
In [3]: bottom_up(f)(x**2)
AttributeError: is_commutative
In [4]: from sympy.strategies import rebuild

In [5]: rebuild(bottom_up(f)(x**2))
Out[5]: 
(x + 1)**2

*Yesterday (21 hours ago) Delete comment Project Member #2 smichr*

How about on this one:

>>> rebuild(bottom_up(lambda x: expand(x))(x+x*(x+1)))
...
  File "sympy\simplify\simplify.py", line 91, in fraction
    if term.is_commutative and (term.is_Pow or term.func is exp):
AttributeError: is_commutative

Part of the motivation for doing this right now (and something that is 
attractive about this bottom_up) is that I can do an operation, get an 
arg count, and then do the rebuild and see if things simplified or not. 
Something like `(x+y)*(x-y) - x**2` would expand to `x**2 + 2*x - y**2 - 
x**2` 
and then on rebuild would drop to 2 terms, representing a favorable 
expansion.

*Today (4 hours ago) Delete comment Project Member #3 MRocklin*

`expand` requires a well formed SymPy tree.  The result from one call to 
expand 
is inappropriate for other calls to `expand`.  

If you'd like to use expand (or really any sympy expr function) in a 
traversal 
it's probably a good idea to chain it with rebuild so that rebuild is 
called every 
time just before expand is called.

>>> expr = x+x*(x+1)
>>> strategy = bottom_up(chain(rebuild, expand))
>>> strategy(expr)
x**2  + 2*x

-- 
You received this message because you are subscribed to the Google Groups 
"sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sympy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to