Sympy linsolve/solve 性能差

5
我正在使用sympy解决一个简单的线性方程组。
它是一个耦合的ODE,其中包含变量的时间导数,并且我需要解决具有最高导数的方程组。 由于sympy不允许我解决像phi_1.diff(t)这样的语句,因此我已经用占位符符号替换了所有导数。
例如: phi.diff(t).diff(t) + phi(t) = 0 变成了 ddphi + phi(t) = 0
这很好用。解决方案是正确的,我可以模拟系统 - 这是一个振荡器:https://youtu.be/Gc_V2FussNk 问题在于解决方程组(使用linsolve)太慢了。
对于只有2个方程,需要2秒钟。 对于3个方程,仍在计算中(超过10分钟后)。

编辑:@asmeurer建议我尝试使用solve。

对于n=3,linsolve大约需要34分钟-我只进行了一次测量。solve花费31秒(平均分布在3次运行中)。

然而,我相信一个线性的3x3系统应该在几分之一秒内解决。

而对于n=4,solve也变得难以忍受地缓慢(仍在计算中)。

我已经格式化了代码并创建了一个iPython笔记本:http://nbviewer.jupyter.org/gist/lhk/bec52b222d1d8d28e0d1baf77d545ec5 如果您向下滚动一点,您可以看到方程组的格式化输出,并直接在其下面调用linsolve

这些方程式相当长,但严格是第二个导数的线性形式。 我相信这个系统可以被解决。 我所需要做的就是解决一个3x3的线性方程组,其中系数可能是符号。

有更高效的方法来做这件事吗?


如果您希望解决方案更具性能,还应该向 odeint 提供雅可比矩阵。 - mtadd
1
你的微分方程看起来对我来说不是线性的。在你的一组方程中,phi的某些一阶导数项被平方了。 - mtadd
1
看起来solvelinsolve更快。 - asmeurer
1
问题在于 linsolve 调用了 simplify,这会导致速度变慢,并且没有办法禁用它。不过,solve 有一个标志可以使用,即 simplify=False。这个能帮到你吗? - asmeurer
1
你可以尝试使用其他标志来解决问题。我对此并不是专家。 - asmeurer
显示剩余5条评论
2个回答

9

solve(而不是linsolve)有一些可以设置的标识,可以使其更快:

  • simplify=False:禁用结果的简化。
  • rational=False:禁用将浮点数自动转换为有理数。

solve文档字符串中有一个警告,即rational=False可能会导致某些方程无法解决,因为在多项式中存在问题,所以请注意这是一个潜在的问题。


指出理性的危险是很重要的。一开始我也很警惕。 - lhk
我相信最坏的情况是,如果 rational=False 失败,你将从 solve 中得到一个异常。 - asmeurer
在我的情况下(具有许多变量的简单线性方程),'simplify=False' 提高了100倍的速度,结果相同。太棒了! - Bernardo Costa

2
我发现如果你在方程式之前运行了sp.init_printing(),在jupyter笔记本中使用solve可能会非常慢。我有一个名为"equations"的模块,我在其中编写并解决我的方程式。
这样做速度更快:
import sympy as sp
import equations
sp.init_printing()

最初的回答:
比这个更好:
import sympy as sp
sp.init_printing()
import equations

这听起来像是应该报告为错误的事情。 - drewcassidy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接