SymPy调用doit()后导数结果异常为0的原因咨询
Sympy链式求导subs后调用doit()结果异常问题
问题复现
首先执行以下代码实现链式求导:
from sympy import Function, symbols, diff, cos, sin x,y = symbols('x y') f, g = symbols("f g", cls=Function) g = g(x) f = f(g) # 定义复合函数 dfdx = diff(f, x) # 应用链式法则
此时输出为链式求导的标准形式:Subs(Derivative(f(_xi), _xi), _xi, g(x))*Derivative(g(x), x)(即f’(g(x))·g’(x))。
接着执行替换操作:
xi = symbols('xi') dfdx.subs([(xi, sin(x)), (f, cos(xi)),(g, sin(x))])
替换后的表达式为:Subs(Derivative(cos(xi), xi), xi, sin(x))*Derivative(sin(x), x)。
但调用doit()后结果为0:
dfdx.subs([(xi, sin(x)), (f, cos(xi)),(g, sin(x))]).doit()
这与手动计算的预期结果cos(x)*(-sin(sin(x)))不符。
问题原因
核心问题出在函数符号的覆盖和替换逻辑错误:
- 你最初定义
f为Function类型的符号(代表任意函数),但随后执行f = f(g),这会把f从函数符号覆盖为复合函数表达式f(g(x))。 - 当你在
subs中写(f, cos(xi))时,Sympy会把表达式f(g(x))整体替换成cos(xi),而非替换函数符号f本身。 - 替换后,
dfdx中的Derivative(f(g(x)), x)变成Derivative(cos(xi), x)——此时cos(xi)里的xi和x是独立符号,对x求导结果自然为0,后续替换xi为sin(x)也无法改变这个结果。
解决方法
保留原始的函数符号,不要用表达式覆盖它:
from sympy import Function, symbols, diff, cos, sin x,y = symbols('x y') f, g = symbols("f g", cls=Function) g_expr = g(x) f_expr = f(g_expr) # 用新变量存储复合函数,保留f作为函数符号 dfdx = diff(f_expr, x) xi = symbols('xi') # 替换函数符号f为cos,同时替换g为sin(x) result = dfdx.subs([(f, lambda t: cos(t)), (g, lambda t: sin(t))]).doit() print(result) # 输出:-sin(sin(x))*cos(x)
或者直接替换函数符号对应的表达式:
result = dfdx.subs([(f, cos), (g(x), sin(x))]).doit()
内容的提问来源于stack exchange,提问作者Herman Jaramillo
相关产品推荐
相关产品推荐

