使用SymPy求解含复合符号函数的表达式的导数并简化输出形式
使用SymPy求解含复合符号函数的表达式的导数并简化输出形式
嘿,我懂你想要的效果——当你用SymPy计算包含复合符号函数(比如依赖于$r = \sqrt{x2+y2+z^2}$的$f_A(r)$)的导数时,默认输出会带有Subs这类看起来有点冗余的符号,而你希望得到用$r$和$\frac{df(r)}{dr}$来表示的更简洁、更符合数学书写习惯的结果对吧?
先看你原来的实现代码和遇到的问题:
你写的代码是这样的:
import sympy as sp x, y, z = sp.symbols('x y z') r = sp.sqrt(x**2 + y**2 + z**2) f_A = sp.Function('f_A')(r) V = f_A * x**2 dV_dx = sp.diff(V, x) print(dV_dx)
运行后默认输出的结果是:
x**3*Subs(Derivative(f_A(_xi_1), _xi_1), _xi_1, sqrt(x**2 + y**2 + z**2))/sqrt(x**2 + y**2 + z**2) + 2*x*f_A(sqrt(x**2 + y**2 + z**2))
这个结果数学上是正确的,但确实不够直观,不是我们平时手写的$\frac{x^3}{r} \frac{df(r)}{dr} + 2x f(r)$这种简洁形式。
其实只需要稍微调整一下函数的定义方式,再结合符号替换就能解决这个问题,我给你改了下代码:
import sympy as sp x, y, z = sp.symbols('x y z') r = sp.sqrt(x**2 + y**2 + z**2) # 先单独定义函数符号,不要直接代入r f_A = sp.Function('f_A') # 构造V表达式的时候再把r传入函数 V = f_A(r) * x**2 # 求导 dV_dx = sp.diff(V, x) # 先简化表达式,再把根号形式替换成我们定义的r dV_dx_simplified = sp.simplify(dV_dx).subs(sp.sqrt(x**2 + y**2 + z**2), r) # 利用链式法则,把对x的导数转换为对r的导数乘以x/r,让结果更符合手写习惯 dV_dx_simplified = dV_dx_simplified.subs(sp.Derivative(f_A(r), x), (x/r)*sp.Derivative(f_A(r), r)) print(dV_dx_simplified)
运行这段代码后,输出的结果就是:
2*x*f_A(r) + x**3*Derivative(f_A(r), r)/r
对应的数学形式就是你想要的$\frac{x^3}{r} \frac{df(r)}{dr} + 2x f(r)$,完全是直观的手写风格啦。
原理其实就是利用链式法则:$\frac{df(r)}{dx} = \frac{df(r)}{dr} \cdot \frac{dr}{dx}$,而$\frac{dr}{dx} = \frac{x}{r}$,我们把SymPy生成的对x的导数项替换成这个链式展开的形式,再把所有的$\sqrt{x2+y2+z^2}$替换成预先定义的r,就能得到简洁的结果了。
备注:内容来源于stack exchange,提问作者Hendriksdf5
相关产品推荐
相关产品推荐

