python – SymPy – 在dsolve中使用许多参数时出现问题

前端之家收集整理的这篇文章主要介绍了python – SymPy – 在dsolve中使用许多参数时出现问题前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我正在使用SymPy版本0.7.3,并在使用dsolve函数时遇到一些问题.当输入方程具有太多参数时,似乎dsolve有困难.

我试过解决以下等式:

from sympy import *
p = Function('p')
t,u1,u2,u3,u4,u5 = symbols('t u1 u2 u3 u4 u5')
eq = Eq(Derivative(p(t),t),-(u3 + u4)*p(t) + exp(-t*(u1 + u2)))
eq
     Out: Derivative(p(t),t) == (-u3 - u4)*p(t) + exp(-t*(u1 + u2))
%time dsolve(eq)

得到了:

cpu times: user 213.11 s,sys: 0.00 s,total: 213.11 s
Wall time: 213.12 s
       p(t) == (C1 + Piecewise((t*u1/(u1 + u2) + t*u2/(u1 + u2),u3 == u1 + u2 - u4),(-exp(t*u3)*exp(t*u4)/(u1*exp(t*u1)*exp(t*u2) + u2*exp(t*u1)*exp(t*u2) - u3*exp(t*u1)*exp(t*u2) - u4*exp(t*u1)*ex
p(t*u2)),True)))*exp(-t*(u3 + u4))

(花了213.12秒!)

然后我用u5替换了u1 u2:

eq = Eq(Derivative(p(t),-(u3 + u4)*p(t) + exp(-t*(u1 + u2))).subs(u1+u2,u5)
eq
     Out:Derivative(p(t),t) == (-u3 - u4)*p(t) + exp(-t*u5)
%time dsolve(eq)

得到了:

cpu times: user 1.62 s,total: 1.62 s
Wall time: 1.62 s
        p(t) == (C1 + Piecewise((t,u3 == -u4 + u5),(exp(t*u3)*exp(t*u4)/(u3*exp(t*u5) + u4*exp(t*u5) - u5*exp(t*u5)),True)))*exp(-t*(u3 + u4))

(仅1.62秒!)

我尝试过使用不同的提示,但没有帮助……

我还注意到,在更复杂的函数中,dsolve会崩溃,但是当替换一些常量参数时,它会很快运行.

你知道这种现象的原因是什么吗?
有没有办法自动解决这个问题?

最佳答案
我注意到Mathematica存在同样的问题,限制表达式中的符号数是非常有利的.我认为其原因在于大多数符号计算工具首先通过机械方式应用一般配方来解决问题,然后尽可能简化结果.

在一般解决方案中,简化器可能很难恢复某些符号仅在给定组合中出现,因此可以被视为单个符号.因此,简化器不必要地处理更大的搜索空间.此外,它必须确保它正确处理所有边界情况(u1可能是< 0,> 0,= 0,复杂,……?)

我发现在将问题提供给符号求解器之前,尽可能多地进行手工简化是非常有利的.手动将变量分组(如在您的示例中)是一种有用的技术.另一种技术是计算归一化,或者将一个参数设置为1.例如,当处理多项式a x ^ 2 b x c时,大多数时候问题x ^ 2 B x C等于我们. (因为我们确实确定了一个!= 0,但是忘了告诉求解器,对吧?……)但是对于求解器,如果符号变量的数量减少1,它会产生很大的不同.

在某些时候,这些符号解算器肯定会变得足够聪明,可以在尝试解决问题之前将变量组合在一起.但是,目前看来仍然需要人为干预.

另一方面,很难想象符号解算器会自动识别简化问题的更复杂的变换,例如从笛卡尔坐标转换到极坐标,或者更改变量,例如l = x iy,r = x-嘿,这些都不是很明显,但已知对某些问题有利.

更新

我们可以为这个问题做的最好的事情是设置一个= u3 u4和一个b = u1 u2.除了将参数数量从4减少到2之外,特殊情况现在出现在b == 0时,因此我们可以轻松地指示求解器忽略它:

from sympy import *
p = Function('p')
t,a = symbols('t a')
b = symbols('b',nonzero=True)
eq = Eq(Derivative(p(t),-a*p(t) + exp(-(a + b)*t))
dsolve(eq)
# -> p(t) == (C1 - exp(-b*t)/b)*exp(-a*t)
# (0.75 s)

因此,通过避免特殊情况帮助求解器将解决方案时间再缩短一半(我的系统上的时序与您的相似).如果特殊情况b == 0实际上是相关的,则可以容易地从exp(-b * t)~1-b * t的泰勒级数展开中恢复它.

通常,指定变量是实数,非零,严格大于零等等也非常有用,以避免在特殊情况下使解算器挂起.有时,对于x<单独解决问题实际上更好. 0,x> 0和x == 0(避免臭名昭着的sqrt(x ^ 2)表达式,求解器无法在不知道x的符号的情况下进一步简化).

猜你在找的Python相关文章