我想将n阶常微分方程简化为一阶方程组。这是为数值分析做准备。我使用Sympy和Sagemath作为计算机代数,但我没有找到任何函数来进行这种类型的缩减。我不确定是否有其他人可以指出Sympy或Sagemath中是否存在此功能。
这方面的一个例子是减少等式:
x''' - 2x'' + x' = 0
到一阶方程组:
[0 1 0
0 0 1
0 -1 2]
答案 0 :(得分:5)
据我所知,SymPy没有直接执行此功能的功能,但手动操作非常简单。
我假设您总是希望您的两个附加公式为y = x'
和z = y'
。
首先,让我们创建ODE(在SymPy中,表达式自动假设为零,所以为简化起见,让我们不要理会= 0
部分)。我假设您的自变量为t
。
In [4]: t = symbols('t')
In [7]: x, y, z = symbols('x y z', cls=Function)
In [6]: ode = x(t).diff(t, t) - 2*x(t).diff(t) + x(t)
In [13]: ode = x(t).diff(t, 3) - 2*x(t).diff(t, t) + x(t).diff(t)
In [14]: ode
Out[14]:
2 3
d d d
──(x(t)) - 2⋅───(x(t)) + ───(x(t))
dt 2 3
dt dt
现在,如果我们将x'
替换为y
,
In [15]: ode.subs(x(t).diff(t), y(t))
Out[15]:
2
d d
y(t) - 2⋅──(y(t)) + ───(y(t))
dt 2
dt
我们发现它还会将x''
替换为y'
。因此,让y'
代替z
:
In [16]: ode = ode.subs(x(t).diff(t), y(t)).subs(y(t).diff(t), z(t))
In [17]: ode
Out[17]:
d
y(t) - 2⋅z(t) + ──(z(t))
dt
现在我们的系统[x' y' z']
是
In [20]: Matrix([y(t), z(t), solve(ode, z(t).diff(t))[0]])
Out[20]:
⎡ y(t) ⎤
⎢ ⎥
⎢ z(t) ⎥
⎢ ⎥
⎣-y(t) + 2⋅z(t)⎦
请注意,我们已经知道x' = y
和y' = z
,因此我们只是直接使用这些内容,但我们使用solve()
来代替z'
获取替换的ODE。
如果你想要系数,一个简单的技巧是采用雅可比行列式:
In [23]: M = Matrix([y(t), z(t), solve(ode, z(t).diff(t))[0]]).jacobian([x(t), y(t), z(t)])
In [24]: M
Out[24]:
⎡0 1 0⎤
⎢ ⎥
⎢0 0 1⎥
⎢ ⎥
⎣0 -1 2⎦
我将把它包装成单个函数ode_to_system(ode, [x(t), y(t), z(t)])
的任务作为练习给读者。
答案 1 :(得分:3)
问题是,如何将微分方程编码为字符串。因为编码已经比写下一阶系统更复杂了。
一般手动程序是设置x1 = x,x2 = x',x3 = x''然后注意到
x1'=x'=x2
x2'=x''=x3
x3'=x'''= 2*x'' - x' = 2*x3 - x2
然后将生成的系统转换为矩阵形式。
另请参见多项式的伴随矩阵,这是(最多换位)也是您为高阶线性微分方程的系统矩阵获得的一般形式。
答案 2 :(得分:3)
我写了一个实验库来处理常微分方程组:
https://github.com/bjodah/symodesys
它基于同情,不幸的是我没有写太多文档,但我提供了很多例子。我会按如下方式处理你的等式:
from sympy import *
from symodesys.odesys import AnyOrderODESystem
t = Symbol('t')
x = Function('x')(t)
D1x = x.diff(t)
D2x = x.diff(t, 2)
D3x = x.diff(t, 3)
expr = Eq(D3x, 2*D2x - D1x)
odesys = AnyOrderODESystem.from_list_of_eqs([expr])
print(odesys.all_depv)
redsys = odesys.reduce_to_sys_of_first_order()
print(redsys.all_depv)
print(redsys.f)
哪个输出:
[x(t)]
[x(t), x_h1(t), x_h2(t)]
OrderedDict([(x(t), x_h1(t)), (x_h1(t), x_h2(t)), (x_h2(t), -x_h1(t) + 2*x_h2(t))])
添加一些额外的行为您提供了一个尝试初始值问题的gui (参见溶液曲线作为初始值的函数)
from symodesys.gui import get_chaco_viewer
from collections import defaultdict
y0 = defaultdict(int)
y0[redsys['x']] = 3.14
params = {}
t0, tend, N = 0, 10, 100
viewer = get_chaco_viewer(redsys, y0, params, t0, tend, N)
viewer.configure_traits()
viewer.clean_up()
给你:
安装一些依赖项有点棘手,如果需要帮助则添加注释!
答案 3 :(得分:1)
我不使用Sympy或Sagemath。但是在他们的API文档中寻找拉普拉斯或Z变换。
使用拉普拉斯解决差分系统
解决您的问题:
还可以查看here了解其他示例
通过Z
解决差分系统