Posts: 6 Threads: 2 Joined: Feb 2019 Reputation: **0** Likes received: 0 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! Posts: 3,336 Threads: 70 Joined: Sep 2016 Reputation: **176** Likes received: 1028 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)` ). Posts: 6 Threads: 2 Joined: Feb 2019 Reputation: **0** Likes received: 0 (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? Posts: 3,336 Threads: 70 Joined: Sep 2016 Reputation: **176** Likes received: 1028 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. Posts: 6 Threads: 2 Joined: Feb 2019 Reputation: **0** Likes received: 0 (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? Posts: 3,336 Threads: 70 Joined: Sep 2016 Reputation: **176** Likes received: 1028 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. Posts: 6 Threads: 2 Joined: Feb 2019 Reputation: **0** Likes received: 0 (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? Posts: 3,336 Threads: 70 Joined: Sep 2016 Reputation: **176** Likes received: 1028 (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. buran likes this post Posts: 6 Threads: 2 Joined: Feb 2019 Reputation: **0** Likes received: 0 (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! |