Reputation: 113
I have a situation where I'm assigning expressions to many symbols in SymPy. They reference each other, and I want to be able to evaluate one of the higher-level expressions in terms of some starting parameters which determine everything else.
Here is my example code:
In [1]: from sympy import *
In [2]: x, y, z = symbols('x y z')
In [3]: z = x+y
In [4]: x=y
In [5]: z.subs({y: 2})
Out[5]: x + 2
I would expect to get 4
, since x
should be evaluated to be 2
. What am I missing and how can I evaluate z
"all the way"?
In my actual code, I want to be able to evaluate things "all the way" even when multiple layers of evaluation are required. Of course, in the real code, I can't just do z.subs({y: 2, x: y})
, since the relationships between x
and y
are complicated.
The real code happens to be this:
In [1]: from sympy import *
...: y, q, c, F, M, cr, ct, bst, kq, kF, kM = symbols('y q c F M cr ct bst kq
...: kF kM')
...: c = cr + y*(cr+ct)/(bst/2)
...: q = kq*c
...: F = integrate(q, y) + kF
...: kF = -(F-kF).subs({y: bst/2}) # BC: F=0 when y=bst/2
...: M = integrate(F, y) + kM
...: kM = -(M-kM).subs({y: bst/2}) # BC: M=0 when y=bst/2
...:
...: LV3parms = {cr: 18, ct: 5, kq: 1, bst: 6.42}
...: M.subs(LV3parms)
Out[1]: kF*y + kM + 1.19418483904465*y**3 + 9*y**2
Upvotes: 1
Views: 874
Reputation: 577
Your lines In[3] and In[4] both create new immutable expressions and do not change their right side expressions in any way. So the call in In[5] is in no way related to your In[4] where you set x=y, which only changes x and in In[5] you operate on z.
You simply need to chain the expressions properly:
x,y,z = symbols('x y z')
x = y
z = x+y
z.subs({y: 2})
This outputs 4 as you would expect.
Upvotes: 2