abstract syntax tree

79 views
Skip to first unread message

krastano...@gmail.com

unread,
Nov 12, 2011, 12:20:28 PM11/12/11
to sy...@googlegroups.com
Is there any way to get the expression tree from an expression (either using the python abstract syntax tree module or just some tuples):

for example

get_tree( x+y*sin(z) ) would return

(Add, x, (Mul, y, (Sin z)))

or

(BinOp, Add, ((Symbol, x), (BinOp, Mul, (blah blah blah))))

krastano...@gmail.com

unread,
Nov 12, 2011, 12:42:23 PM11/12/11
to sy...@googlegroups.com
This:

import ast
ast.parse(repr(expression))

 will do the trick if repr is well coded.

How much faith should I put in the repr strings in sympy? Or there is another way?

Alexey U. Gudchenko

unread,
Nov 12, 2011, 1:01:10 PM11/12/11
to sy...@googlegroups.com
12.11.2011 21:42, krastano...@gmail.com пишет:

I know only how to obtain the childes:

>>> e = x+y*sin(z) + z
>>> e.args
(y*sin(z), z, x)

>>> e.args[0]
>>> y*sin(z)

>>> e.args[0].args
(y, sin(z))

And test the classes:

>>> e.is_Add
True


In other words, the somewhat tree of the expressions exists.

How to represent expression-tree in other formats (strings or
structures), I do not know.

Regards.

--
Alexey U.

Aaron Meurer

unread,
Nov 12, 2011, 6:42:21 PM11/12/11
to sy...@googlegroups.com
Hi.

As far as I know, we don't have a function that does exactly that,
though I could be wrong. It would be nice to have one, though.

On Sat, Nov 12, 2011 at 11:01 AM, Alexey U. Gudchenko <pr...@goodok.ru> wrote:
> 12.11.2011 21:42, krastano...@gmail.com пишет:
>> This:
>>
>> import ast
>> ast.parse(repr(expression))

If you want a repr() representation, you should instead use srepr().
(repr() is the same as str()).

>>
>>  will do the trick if repr is well coded.

str() is coded so that it returns the same thing back from sympify(),
but it may not give the same thing directly, because you can have
int/int in an expression. srepr() should always give the same thing
back.

>>
>> How much faith should I put in the repr strings in sympy? Or there is
>> another way?
>>
>> On 12 November 2011 18:20, krastano...@gmail.com <
>> krastano...@gmail.com> wrote:
>>
>>> Is there any way to get the expression tree from an expression (either
>>> using the python abstract syntax tree module or just some tuples):
>>>
>>> for example
>>>
>>> get_tree( x+y*sin(z) ) would return
>>>
>>> (Add, x, (Mul, y, (Sin z)))
>>>
>>> or
>>>
>>> (BinOp, Add, ((Symbol, x), (BinOp, Mul, (blah blah blah))))
>>>
>>
>
> I know only how to obtain the childes:
>
>>>> e = x+y*sin(z) + z
>>>> e.args
> (y*sin(z), z, x)
>
>>>> e.args[0]
>>>> y*sin(z)
>
>>>> e.args[0].args
> (y, sin(z))
>
>
>
> And test the classes:
>
>>>> e.is_Add
> True
>

You can get the class name by using .func:

In [25]: e = x + y

In [26]: e.func
Out[26]: sympy.core.add.Add

In [27]: e.func(*e.args)
Out[27]: x + y

The invariant in [27] should always hold (except for possibly some
differences in assumptions).

Aaron Meurer

>
>
>
> In other words, the somewhat tree of the expressions exists.
>
> How to represent expression-tree in other formats (strings or
> structures), I do not know.
>
> Regards.
>
> --
> Alexey U.
>

> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To post to this group, send email to sy...@googlegroups.com.
> To unsubscribe from this group, send email to sympy+un...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/sympy?hl=en.
>
>

krastano...@gmail.com

unread,
Nov 12, 2011, 8:00:06 PM11/12/11
to sy...@googlegroups.com
Ok, but why are those printed differently (ipython --profile=sympy):

In [34]: sin(x).func
Out[34]: sympy.functions.elementary.trigonometric.sin

In [35]: str(sin(x).func)
Out[35]: sin

In [39]: Integral(x, (x,0,1)).func
Out[39]: sympy.integrals.integrals.Integral

In [40]: str(Integral(x, (x,0,1)).func)
Out[40]: <class 'sympy.integrals.integrals.Integral'>

What should I do to have them print in the same manner?

Mateusz Paprocki

unread,
Nov 12, 2011, 8:09:24 PM11/12/11
to sy...@googlegroups.com
Hi,

On 12 November 2011 17:00, krastano...@gmail.com <krastano...@gmail.com> wrote:
Ok, but why are those printed differently (ipython --profile=sympy):

In [34]: sin(x).func
Out[34]: sympy.functions.elementary.trigonometric.sin

In [35]: str(sin(x).func)
Out[35]: sin

In [39]: Integral(x, (x,0,1)).func
Out[39]: sympy.integrals.integrals.Integral

In [40]: str(Integral(x, (x,0,1)).func)
Out[40]: <class 'sympy.integrals.integrals.Integral'>

What should I do to have them print in the same manner?

This seems to be a problem with IPython's printing hooks. In CPython I get:

>>> from sympy import *
>>> init_printing()
>>> var('x')
x
>>> sin(x).func
sin
>>> str(sin(x).func)
sin
>>> Integral(x, (x, 0, 1)).func
<class 'sympy.integrals.integrals.Integral'>
>>> str(Integral(x, (x, 0, 1)).func)
<class 'sympy.integrals.integrals.Integral'>

There reason for different output in IPython is that IPython not always uses SymPy's pretty printer, but sometimes uses its own printing hooks. It's better visible in the notebook where latex output is used (e.g. try to print data structures).

Mateusz

krastano...@gmail.com

unread,
Nov 12, 2011, 8:16:43 PM11/12/11
to sy...@googlegroups.com
Then I suppose I can just call a function that returns a string. Here is the problem I have:

In [42]: lambdarepr(Integral(x, (x,0,1)).func)
Out[42]: <class 'sympy.integrals.integrals.Integral'>

In [43]: lambdarepr(Integral(x, (x,0,1)))
Out[43]: Integral(x, (x, 0, 1))

Why is out[42] not the same style as out[43]. This causes problems with lambdify, so I would be very happy if somebody explains this to me. With 'sin' it gives the same style for both inputs:

In [46]: lambdarepr(sin(x).func)
Out[46]: sin

In [47]: lambdarepr(sin(x))
Out[47]: sin(x)

Is this difference between function and integral expected?

Mateusz Paprocki

unread,
Nov 12, 2011, 8:21:39 PM11/12/11
to sy...@googlegroups.com
Hi,

On 12 November 2011 17:16, krastano...@gmail.com <krastano...@gmail.com> wrote:
Then I suppose I can just call a function that returns a string. Here is the problem I have:

In [42]: lambdarepr(Integral(x, (x,0,1)).func)
Out[42]: <class 'sympy.integrals.integrals.Integral'>

In [43]: lambdarepr(Integral(x, (x,0,1)))
Out[43]: Integral(x, (x, 0, 1))

Why is out[42] not the same style as out[43]. This causes problems with lambdify, so I would be very happy if somebody explains this to me. With 'sin' it gives the same style for both inputs:

In [46]: lambdarepr(sin(x).func)
Out[46]: sin

In [47]: lambdarepr(sin(x))
Out[47]: sin(x)

Because sin is a Function and Function has a custom printer, which is not true for Integral, which is just an ordinary type (default printer).

Mateusz

krastano...@gmail.com

unread,
Nov 12, 2011, 8:25:21 PM11/12/11
to sy...@googlegroups.com
Can the default printer be changed so lambdarepr(SomeClass(args)) and lambdarepr(SomeClass(args).func) give always the same thing.

lambdarepr is using LambdaPrinter. What should be done there (or to a subclass of LambdaPrinter) to ensure the behavior that I desire?

Mateusz Paprocki

unread,
Nov 12, 2011, 8:34:27 PM11/12/11
to sy...@googlegroups.com
Hi,

On 12 November 2011 17:25, krastano...@gmail.com <krastano...@gmail.com> wrote:
Can the default printer be changed so lambdarepr(SomeClass(args)) and lambdarepr(SomeClass(args).func) give always the same thing.

lambdarepr is using LambdaPrinter. What should be done there (or to a subclass of LambdaPrinter) to ensure the behavior that I desire?

So, the difference comes from StrPrinter.emptyPrinter and FunctionClass.__repr__. You can override _print_FunctionClass or emptyPrinter in LambdaReprPrinter to fix the problem.

krastano...@gmail.com

unread,
Nov 12, 2011, 8:48:16 PM11/12/11
to sy...@googlegroups.com
Thank you for the information.
Reply all
Reply to author
Forward
0 new messages