Sympy "wrongly" 求解 ODE 的系统

Sympy "wrongly" solving system of ODEs

我在 sympy 中定义了两个 ODE,如下所示:

import sympy as sp

a = sp.Symbol("a", positive=True)
b = sp.Symbol("b", positive=True)
t = sp.Symbol("t")
x = sp.Function("x")
y = sp.Function("y")

eq = (
    sp.Eq(sp.Derivative(x(t), t), -a * x(t)),
    sp.Eq(sp.Derivative(y(t), t), a * x(t) - b * y(t)),
)

当我尝试使用 dsolve 解决它们时,我得到以下结果:

>>> sp.dsolve(eq)

[Eq(x(t), -C1*(a - b)*exp(-a*t)/a),
 Eq(y(t), C1*exp(-a*t) + C2*exp(-b*t))]

单独求解第一个方程时,我得到以下结果:

>>> sp.dsolve(eq[0])

Eq(x(t), C1*exp(-a*t))

y(t) 中不依赖于第二个 ODE 的第一个 ODE 怎么可能突然包含 b?用 mathematica 解决它似乎给出了正确的结果:

x(t) = C1*exp(-at)
y(t) = C2*exp(-bt) - (a*exp(-at-bt)*(-exp(at)+exp(bt))*C1)/(a-b)

任何帮助 python 解决此问题的人都将不胜感激。

SymPy 的解决方案是正确的。它也等同于 Mathematica 中的一个,只是任意常数的定义不同。您可以替换 C1 -> -C1*(a/(a-b)) 之类的内容以从一种形式转换为另一种形式:

In [49]: sp.dsolve(eq)
Out[49]: 
⎡                    -a⋅t                             ⎤
⎢       -C₁⋅(a - b)⋅ℯ                  -a⋅t       -b⋅t⎥
⎢x(t) = ──────────────────, y(t) = C₁⋅ℯ     + C₂⋅ℯ    ⎥
⎣               a                                     ⎦

如果您改变要求解的函数的顺序,您还可以获得稍微不同的形式:

In [53]: sp.dsolve(eq, [y(t), x(t)])
Out[53]: 
⎡               -a⋅t                            ⎤
⎢         C₁⋅a⋅ℯ           -b⋅t             -a⋅t⎥
⎢y(t) = - ────────── + C₂⋅ℯ    , x(t) = C₁⋅ℯ    ⎥
⎣           a - b                               ⎦

在每个方程中单独exp(-a*t)的系数可以是任意常数。通常其他参数如 ab 可以吸收到任意常数中以简化结果。但是,x 和 y 的解中的系数之间存在约束,因此一个方程的系数必须与另一个方程中的系数相差 -a/(a-b)。这里 SymPy 选择吸收最后一个方程中的参数,但这意味着它们必须重新出现在第一个方程中。

您可以在 Mathematica 显示的输出中看到相同的因子:

⎡                               ⎛   a⋅t    b⋅t⎞  -a⋅t - b⋅t           ⎤
⎢           -a⋅t           C₁⋅a⋅⎝- ℯ    + ℯ   ⎠⋅ℯ                 -b⋅t⎥
⎢x(t) = C₁⋅ℯ    , y(t) = - ──────────────────────────────── + C₂⋅ℯ    ⎥
⎣                                       a - b                         ⎦

所有这些都是原始 ODE 的有效通用解决方案,但在任意常数的定义方式上有所不同,因此这只是您喜欢的口味问题。

我个人最不喜欢 Mathematica 输出,因为它混合了两个指数项的系数。我可以理解它的来源,因为它基本上是矩阵指数的原始输出:

In [60]: M = sp.Matrix([[-a, 0], [a, -b]])

In [60]: (M*t).exp().applyfunc(sp.factor) * sp.Matrix([C1, C2])
Out[60]: 
⎡                    -a⋅t                 ⎤
⎢                C₁⋅ℯ                     ⎥
⎢                                         ⎥
⎢     ⎛ a⋅t    b⋅t⎞  -a⋅t  -b⋅t           ⎥
⎢C₁⋅a⋅⎝ℯ    - ℯ   ⎠⋅ℯ    ⋅ℯ           -b⋅t⎥
⎢────────────────────────────── + C₂⋅ℯ    ⎥
⎣            a - b                        ⎦

SymPy 公式略有不同,使用 Jordan 形式的矩阵指数隐式吸收特征向量矩阵 inv(P) 为常数:

In [63]: P, J = M.jordan_form()

In [64]: P*(J*t).exp() * sp.Matrix([C1, C2])
Out[64]: 
⎡    ⎛     b⎞  -a⋅t ⎤
⎢ C₁⋅⎜-1 + ─⎟⋅ℯ     ⎥
⎢    ⎝     a⎠       ⎥
⎢                   ⎥
⎢    -a⋅t       -b⋅t⎥
⎣C₁⋅ℯ     + C₂⋅ℯ    ⎦