Python Forum
Get the variables in a sympy expression - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/Forum-Python-Coding)
+--- Forum: General Coding Help (https://python-forum.io/Forum-General-Coding-Help)
+--- Thread: Get the variables in a sympy expression (/Thread-Get-the-variables-in-a-sympy-expression)



Get the variables in a sympy expression - SJ001 - Feb-12-2019

Hello! I have some equations which I read from a file, and then turn into sympy expressions and I need the variables that appear in each equation. However, for the purpose of my project, I need them in the order in which they appear in the equation. So if the equation is 'a+b*c' I need a program which gives me: a,b,c but not a,c,b or any other combination. Here is what I tried, based on what I found online:

from sympy import *
from sympy.parsing.sympy_parser import parse_expr

eq1 = "x1**(-1.0)*x2" # I normally read this from a file
eq1 = parse_expr(eq1)

print(eq1,eq1.free_symbols)
So, normally, eq1.free_symbols should give me a set of the variables in my expression. However after I ran this code (and other equations, too, with the same problem) several times, I got this output:

x1**(-1.0)*x2 {x1, x2}
x1**(-1.0)*x2 {x1, x2}
x1**(-1.0)*x2 {x2, x1}
x1**(-1.0)*x2 {x2, x1}
x1**(-1.0)*x2 {x2, x1}
x1**(-1.0)*x2 {x2, x1}
x1**(-1.0)*x2 {x1, x2}

So the equation looks fine, but the order of the variables seem to change randomly and this makes it useless for what I need. Can someone tell me how to pick the variables in the order I want (actually any order would be good as long as it doesn't randomly change)? Thank you!


RE: Get the variables in a sympy expression - ichabod801 - Feb-12-2019

It looks like free_symbols is a set, which has no intrinsic ordering. If you want a consistent ordering you would need to convert it to a list and sort it (sorted(eq1.free_symbols)).


RE: Get the variables in a sympy expression - SJ001 - Feb-12-2019

(Feb-12-2019, 06:44 AM)ichabod801 Wrote: It looks like free_symbols is a set, which has no intrinsic ordering. If you want a consistent ordering you would need to convert it to a list and sort it (sorted(eq1.free_symbols)).
This doesn't really work. I am getting this error: TypeError: cannot determine truth value of Relational. I assume it is because there is no intrinsic ordering to variables... Also I am a bit confused about this ".free_symbols" function. I understand that mathematically the order doesn't matter in a set. But here the set must be generated somehow (an iterator for example). So shouldn't the generation method at least be consistent?


RE: Get the variables in a sympy expression - ichabod801 - Feb-12-2019

It's not a function, it's an attribute. I looked at the documentation and it didn't clearly state that it is a set, so there may be something else going on. What does print(type(eq1.free_symbols)) say?

It doesn't matter if the generation order is consistent. The "order" in the set is determined by the hash function and any hash collisions. The hash function is not guaranteed to be consistent across runs.


RE: Get the variables in a sympy expression - SJ001 - Feb-12-2019

(Feb-12-2019, 06:57 AM)ichabod801 Wrote: print(type(eq1.free_symbols))
It says: <class 'set'>

Is there a more consistent way to read the variables in an expression?


RE: Get the variables in a sympy expression - ichabod801 - Feb-12-2019

Then the 'Relational' in your error must refer to the elements of the set: x1 and x2. They are apparently not sortable, although I would expect a different error. It doesn't look to be a solvable problem, although I must admit that I have no experience with the sympy module.


RE: Get the variables in a sympy expression - SJ001 - Feb-12-2019

(Feb-12-2019, 07:04 AM)ichabod801 Wrote: Then the 'Relational' in your error must refer to the elements of the set: x1 and x2. They are apparently not sortable, although I would expect a different error. It doesn't look to be a solvable problem, although I must admit that I have no experience with the sympy module.
Is there any other package that can do this? It seems like something not too complex to implement. If they are able to find the variables, I assume they go through the expression from left to right, so why not save them in the order they are discovered?


RE: Get the variables in a sympy expression - ichabod801 - Feb-12-2019

(Feb-12-2019, 07:07 AM)SJ001 Wrote: why not save them in the order they are discovered?

They probably are, but they are using a set to avoid duplicates of the same symbol. Anyway, I figured it out:

free_syms = sorted(eq1.free_symbols, key = lambda symbol: symbol.name)
Tested it with your code and it works.


RE: Get the variables in a sympy expression - SJ001 - Feb-12-2019

(Feb-12-2019, 07:16 AM)ichabod801 Wrote: free_syms = sorted(eq1.free_symbols, key = lambda symbol: symbol.name)
Thanks a lot! It's working!