SymPy dsolve returns 数学上等效的微分方程的不同结果
SymPy dsolve returns different results for mathematically equivalent differential equations
这是我的脚本内容:
from sympy import *
x = symbols('x')
init_printing(use_unicode=True)
f = symbols('f', cls=Function)
diffeq = Eq(x**2 * f(x).diff(x, x) + x * f(x).diff(x) - f(x) , 1/((1+x**2)**(3)) )
print dsolve(diffeq, f(x))
这个程序 return 的输出如下:
Eq(f(x), (C1*x**2 + C1 + C2*x**4 + C2*x**2 - 15*x**4*atan(x) - 15*x**3 - 18*x**2*atan(x) - 13*x - 3*atan(x))/(16*x*(x**2 + 1)))
但是当我这样定义变量 diffeq
时:
diffeq = Eq(f(x).diff(x, x) + f(x).diff(x)/x - f(x)/x**(2) , 1 / ((1+x**2)**(3) * x**(2)) )
然后我收到输出:
Traceback (most recent call last):
File "/home/foo/odeSympyTrial01.py", line 12, in <module>
print dsolve(diffeq, f(x))
File "/usr/lib/python2.7/dist-packages/sympy/solvers/ode.py", line 625, in dsolve
x0=x0, n=n, **kwargs)
File "/usr/lib/python2.7/dist-packages/sympy/solvers/deutils.py", line 235, in _desolve
raise NotImplementedError(dummy + "solve" + ": Cannot solve " + str(eq))
NotImplementedError: solve: Cannot solve Derivative(f(x), x, x) + Derivative(f(x), x)/x - f(x)/x**2 - 1/(x**2*(x**2 + 1)**3)
当我这样定义变量 diffeq
时:
diffeq = Eq(f(x).diff(x, x) * x**(2) + f(x).diff(x) * x**(2) /x - f(x) * x**(2) /x**(2) , 1* x**(2)/((1+x**2)**(3) * x**(2)) )
然后我收到输出:
Eq(f(x), (C1*x**2 + C1 + C2*x**4 + C2*x**2 - 15*x**4*atan(x) - 15*x**3 - 18*x**2*atan(x) - 13*x - 3*atan(x))/(16*x*(x**2 + 1)))
在每一种情况下,微分方程 diffeq
在数学上都是相等的。因此在我看来 dsolve()
应该 return 每个案例的输出相同。有人请帮助我理解为什么 dsolve()
return 在第二种情况下是错误的。非齐次线性常微分方程如何表达才能保证dsolve()
不return错误?
简短说明:SymPy ODE 模块的逻辑往往很幼稚,有时甚至是不正确的。
如前所述,
x**2 * f(x).diff(x, x) + x * f(x).diff(x) - f(x)
这符合Cauchy–Euler equation的形式(又称欧拉方程):各系数中x的次方为导数的阶数。 SymPy 检测此结构并应用适当的方法。但如果除以 x**2
、
f(x).diff(x, x) + f(x).diff(x)/x - f(x)/x**(2)
情况不再如此:二阶导数没有 x**2
的幂,因此匹配失败。更仔细的检查可以在这里检测到潜在的 Cauchy-Euler 结构,但是没有实现,正如通过查看 source 可以看到的那样。
您可以检查
确实是这样
classify_ode(diffeq, f(x))
在第一种情况下会 return 'nth_linear_euler_eq_nonhomogeneous_variation_of_parameters' 而在第二种情况下不会。
在查看源码的同时,还可以看到一个逻辑错误的例子。
if coeff.is_Mul:
if coeff.has(f(x)):
return False
return x**order in coeff.args
例如,x**2*sin(x)
将通过 order=2 的检查,这意味着 SymPy 会将 x**2*sin(x)*f(x).diff(x, x) - f(x) = 0
误认为欧拉方程。事实上,
dsolve(x**2*sin(x)*f(x).diff(x, x) - f(x), f(x))
"solves"等式不正确。不要相信 SymPy 的 ODE 解决方案。
这是我的脚本内容:
from sympy import *
x = symbols('x')
init_printing(use_unicode=True)
f = symbols('f', cls=Function)
diffeq = Eq(x**2 * f(x).diff(x, x) + x * f(x).diff(x) - f(x) , 1/((1+x**2)**(3)) )
print dsolve(diffeq, f(x))
这个程序 return 的输出如下:
Eq(f(x), (C1*x**2 + C1 + C2*x**4 + C2*x**2 - 15*x**4*atan(x) - 15*x**3 - 18*x**2*atan(x) - 13*x - 3*atan(x))/(16*x*(x**2 + 1)))
但是当我这样定义变量 diffeq
时:
diffeq = Eq(f(x).diff(x, x) + f(x).diff(x)/x - f(x)/x**(2) , 1 / ((1+x**2)**(3) * x**(2)) )
然后我收到输出:
Traceback (most recent call last):
File "/home/foo/odeSympyTrial01.py", line 12, in <module>
print dsolve(diffeq, f(x))
File "/usr/lib/python2.7/dist-packages/sympy/solvers/ode.py", line 625, in dsolve
x0=x0, n=n, **kwargs)
File "/usr/lib/python2.7/dist-packages/sympy/solvers/deutils.py", line 235, in _desolve
raise NotImplementedError(dummy + "solve" + ": Cannot solve " + str(eq))
NotImplementedError: solve: Cannot solve Derivative(f(x), x, x) + Derivative(f(x), x)/x - f(x)/x**2 - 1/(x**2*(x**2 + 1)**3)
当我这样定义变量 diffeq
时:
diffeq = Eq(f(x).diff(x, x) * x**(2) + f(x).diff(x) * x**(2) /x - f(x) * x**(2) /x**(2) , 1* x**(2)/((1+x**2)**(3) * x**(2)) )
然后我收到输出:
Eq(f(x), (C1*x**2 + C1 + C2*x**4 + C2*x**2 - 15*x**4*atan(x) - 15*x**3 - 18*x**2*atan(x) - 13*x - 3*atan(x))/(16*x*(x**2 + 1)))
在每一种情况下,微分方程 diffeq
在数学上都是相等的。因此在我看来 dsolve()
应该 return 每个案例的输出相同。有人请帮助我理解为什么 dsolve()
return 在第二种情况下是错误的。非齐次线性常微分方程如何表达才能保证dsolve()
不return错误?
简短说明:SymPy ODE 模块的逻辑往往很幼稚,有时甚至是不正确的。
如前所述,
x**2 * f(x).diff(x, x) + x * f(x).diff(x) - f(x)
这符合Cauchy–Euler equation的形式(又称欧拉方程):各系数中x的次方为导数的阶数。 SymPy 检测此结构并应用适当的方法。但如果除以 x**2
、
f(x).diff(x, x) + f(x).diff(x)/x - f(x)/x**(2)
情况不再如此:二阶导数没有 x**2
的幂,因此匹配失败。更仔细的检查可以在这里检测到潜在的 Cauchy-Euler 结构,但是没有实现,正如通过查看 source 可以看到的那样。
您可以检查
确实是这样classify_ode(diffeq, f(x))
在第一种情况下会 return 'nth_linear_euler_eq_nonhomogeneous_variation_of_parameters' 而在第二种情况下不会。
在查看源码的同时,还可以看到一个逻辑错误的例子。
if coeff.is_Mul:
if coeff.has(f(x)):
return False
return x**order in coeff.args
例如,x**2*sin(x)
将通过 order=2 的检查,这意味着 SymPy 会将 x**2*sin(x)*f(x).diff(x, x) - f(x) = 0
误认为欧拉方程。事实上,
dsolve(x**2*sin(x)*f(x).diff(x, x) - f(x), f(x))
"solves"等式不正确。不要相信 SymPy 的 ODE 解决方案。