I'm facing problems using python sympy.
The problem is reduced to very minimal working examples
import sympy as sp
from sympy import *
x, xb, xi, alpha = sp.symbols('x xbar xi alpha')
Eqxb = sp.Eq(xb, (x+xi) )
problemExpr = (xb*cos(alpha))**2
# Following is zero for sure
display( problemExpr.diff(xi) )
# Naive approach
out = problemExpr.subs(xb, Eqxb.rhs).diff(xi).subs(Eqxb.rhs, xb)
display( out ) # gives (2x + 2 xi)*cos^2(alpha)
# Want I want is 2*xb*cos^(alpha)
# Some simple tests
test1 = (Eqxb.rhs + xb)
display(test1.subs(Eqxb.rhs, xb)) # gives 2*xbar | -> good
#
test2 = 2*(Eqxb.rhs + xb)
display(test2.subs(Eqxb.rhs, xb)) # gives 2*x + 2*xbar + 2*xi | -> not good
#
test3 = 2*x + 2*xi
display(test3.subs(Eqxb.rhs, xb)) # gives 2*x + 2*xi | -> not good
# test 4, explicit version
display(test3.subs( { x+xi : xb })) # gives 2*x + 2*xi | -> not good
Questions 1:
Why is the expression x+xi
not properly substituted with xb
. Am I using this function wrong? At least in test1
it works as expected.
Question 2: Here, this is a simple function with only one substitution. How is this performed, if multiple subs are necessary? This step of subs and re-subs seems like there should be at least one more elegant way.
What about keeping a dictionary of things that you want to be able to differentiate but also want to represent as a simpler expression (like xb
). Use a function of xb
to do this as follows:
import sympy as sp
from sympy import *
x, xi, alpha = sp.symbols('x xi alpha')
xb = Function('xb')(x)
f = {xb: (x+xi)}
d = {k.diff(x):v.diff(x) for k,v in f.items()}
eq = (xb*cos(alpha))**2
>>> eq.diff(x)
2*xb(x)*cos(alpha)**2*Derivative(xb(x), x)
>>> eq.diff(x).subs(d)
2*xb(x)*cos(alpha)**2
>>> eq.diff(x).subs(d).subs(f)
2*(x + xi)*cos(alpha)**2
The issue of trying to replace a sum with a symbol is an often asked question. Unless the sum appears exactly as given in subs -- not with a constant multiplying each term -- the substitution will fail. Solving for one of the symbols in the sum other than the one you want to have in the final expression is the usual solution, e.g.
>>> from sympy.abc import y
>>> rep= solve(Eq(x + xi, y),exclude=[y],dict=True)[0]
>>> (2*x + 2*xi).subs(rep)
2*y