使用sagemath或sympy将n阶微分方程简化为一阶方程组
我想把一个n阶常微分方程化为一阶方程组。这是为数值分析做准备。我使用Symphy和Sagemath来计算计算机代数,但我还没有在它们中找到任何函数来进行这种类型的约简。我不确定是否有其他人可以指出Symphy或Sagemath中是否存在此功能 这方面的一个例子是减少等式:使用sagemath或sympy将n阶微分方程简化为一阶方程组,math,numerical-methods,sympy,ode,sage,Math,Numerical Methods,Sympy,Ode,Sage,我想把一个n阶常微分方程化为一阶方程组。这是为数值分析做准备。我使用Symphy和Sagemath来计算计算机代数,但我还没有在它们中找到任何函数来进行这种类型的约简。我不确定是否有其他人可以指出Symphy或Sagemath中是否存在此功能 这方面的一个例子是减少等式: x''' - 2x'' + x' = 0 对于一阶方程组: [0 1 0 0 0 1 0 -1 2] 我不使用Sympy或Sagemath。但是在他们的API文档中寻找拉普拉斯或Z变换 如果找到了,那么你就
x''' - 2x'' + x' = 0
对于一阶方程组:
[0 1 0
0 0 1
0 -1 2]
我不使用Sympy或Sagemath。但是在他们的API文档中寻找拉普拉斯或Z变换
- 如果找到了,那么你就没有那么多工作要做了
- 如果没有,您必须自己找到lib或编写它
- 我有一段时间没用这个了,所以用一些数学书检查一下强>
- 无论如何,如果我没记错的话
- 拉普拉斯变换将积分函数转换为线性函数(时域到s域)
- 微分函数必须有连续的导数/积分才能工作
- 要解决您的问题,请执行以下操作:
- 通过积分将所有微分转换为积分
- 应用拉普拉斯变换
- 这将把微分系统转换成多项式系统
- 解多项式方程组
- 应用拉普拉斯逆变换
- 这将部分结果转换为解决方案的结果
- 通过probem定义的边案例求解积分常数
- 另外再找一个例子
- 关于这个话题,谷歌有很多东西
- 从未这样做过,但如果与拉普拉斯变换的解不同,则应相似
x1'=x'=x2
x2'=x''=x3
x3'=x'''= 2*x'' - x' = 2*x3 - x2
然后将生成的系统转换为矩阵形式
另请参见多项式的伴随矩阵,这也是(直至换位)高阶线性微分方程系统矩阵的一般形式。据我所知,Symphy没有直接执行此操作的函数,但手动执行此操作非常简单 我假设你总是希望你的两个附加方程的形式是
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'
。因此,让我们用z
替换y'
:
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
现在我们的系统是
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_系统(ode[x(t),y(t),z(t)])
留给读者作为练习 我写了一个实验库来处理常微分方程组:
[0 1 0
0 0 1
0 -1 2]
它是基于Symphy的,不幸的是,我没有写太多文档,但我提供了很多示例。我将按如下方式处理你的等式:
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来试验初始值问题
(参见溶液曲线作为初始值的函数)
这给了你:
安装某些依赖项有点棘手,如果需要帮助,请添加注释 尝试搜索拉普拉斯变换或Z变换,这是常用的purpose@Spektre谢谢你的来信。我不确定拉普拉斯变换在这里是否正确。所以我想拿一个二阶或三阶微分方程,把它转换成一阶系统。实际上,我想使用计算机代数工具,如Sympy或Sage,这样我就可以检查自己的代数错误。使用拉普拉斯变换可以作为求解方程的一种方法,但我不确定它能否将三阶齐次微分方程转化为一阶微分方程组。也许你可以解释一下你的意思。补充答案(这确实是一个注释,但在注释中它是不可读的)@Spektre OP正在寻找将一个常微分方程转换为一阶常微分方程组的方法,该方法可以通过数值解算,例如使用特征值方法。有关一些示例,请参见。无需对字符串进行编码。这就是使用SymPy或Sage的全部意义,它可以直接表示符号对象。您需要将ODE编码为某种代码对象,作为输入,以CAS可以解析和解释的形式。也就是说,把方程从纸上转移到计算机上。即使这是微不足道的,根据方法的不同,所做的工作也将相当于手动建立一阶系统。