scipy ode求解器中的绑定解

时间:2014-12-20 17:21:42

标签: python scipy range ode odeint

我想在python中解决大量的双线性ODE系统。衍生物是这样的:

def x_(x, t, growth, connections):
    return x * growth + np.dot(connections, x) * x 

我对非常​​准确的结果不感兴趣,但对定性行为感兴趣,即组件是否归零。

因为我必须解决如此大量的高分辨率系统,所以我想使用尽可能大的步长。

由于步长大,可能会发生ODE在零下的一个组件中。这是不可能的,因为(由于特定ODE的结构)每个组件都以零为界。因此 - 为了防止出现错误的结果 - 我想在每个组件低于手动时将其手动设置为零。

此外,在我想要解决的系统中,解决方案可能会爆发。我想通过设置上限来防止这种情况,即如果某个值超出限制,则将其设置回绑定值。

我希望我可以让我的目标可以理解,为您提供以下我想要做的伪代码:

for t in range(0, tEnd, dt):
    $ compute x(t) using x(t-dt) $
    x(t) = np.minimum(np.maximum(x(t), 0), upperBound)

我使用Runge-Kutta算法实现了这一点。一切正常。只是表现不好。因此,我更喜欢使用预先实现的方法,如scipy.integrate.odeint。

因此,我不知道如何设置这样的界限。我试过的一个选项是以这种方式操纵ODE,一旦x高于界限,导数变为0,而一旦x低于0,则导出(正)。另外,为了防止在一个时间步内跳得太高,我也是限制了衍生物:

def x_(x, t, growth, connections, bound):
    return (x > 0) * np.minimum((x < bound) * \
           ( x * growth + np.dot(connections, x) * x ), bound) + (x < 0)

虽然这个解决方案(特别是对于零界限)非常难看,但只要它有效就足够了。不幸的是,它不起作用。使用odeint

x = scipy.integrate.odeint(x_, x0, timesteps, param)

我经常遇到这两个错误中的一个:

Repeated convergence failures (perhaps bad Jacobian or tolerances).

Excess work done on this call (perhaps wrong Dfun type).

他们可能是由于我操纵的ODE的不连续性。互联网上有很多关于这些错误消息的主题,但它们对我没有帮助。例如。增加允许的步数既不能阻止这个问题,也不是一个很好的解决方案,因为我需要使用大步长。此外,通过雅各布也没有帮助。

查看解决方案后,可以看到发生错误时会发生两种奇怪的行为:

  1. 解决方案在一个单一的时间步长内吹到+ -1e250(这应该是不可能的,因为dx / dt是有界的)。
  2. 它首先到达界限但再次下降(这应该是不可能的,因为x在界限处,因此x_为0)。
  3. 我很感激有关如何解决问题的所有提示 - 无论是否有帮助

    • 如何防止odeint中的错误
    • 如何正确操作ODE或
    • 如何编写一个非常快速的ODE解算器,我可以直接实现我的需求。

    我提前谢谢你了!

    修改

    我被问到一个最小的例子:

    import numpy as np
    import random as rd
    rd.seed()
    import scipy.integrate
    
    def simulate(simParam, dim = 20, connectivity = .8, conRange = 1, threshold = 1E-3, 
                 constGrowing=None):
        """
        Creates the random system matrix and starts a simulation
        """
    
        x0 = np.zeros(dim, dtype='float') + 1
        connections = np.zeros(shape=(dim, dim), dtype='float')
    
        growth = np.zeros(dim, dtype='float') + 
                        (constGrowing if not constGrowing == None else 0)
    
    
        for i in range(dim):        
            for j in range(dim):
                if i != j: 
                    connections[i][j] = rd.uniform(-conRange, conRange)
    
        tend, step = simParam
        return RK4NumPy(x_, (growth, connections), x0, 0, tend, step)
    
    
    def x_(x, t, growth, connections, bound):
        """
        Derivative of the ODE
        """
        return (x > 0) * np.minimum((x < bound) * 
                    (x * growth + np.dot(connections, x) * x), bound) + (x < 0)
    
    
    def RK4NumPy(x_, param, x0, t0, tend, step, maxV = 1.0E2, silent=True):
        """
        solving method
        """
        param = param + (maxV,)
        timesteps = np.arange(t0 + step, tend, step)
    
        return scipy.integrate.odeint(x_, x0, timesteps, param)
    
    
    simulate((300, 0.5))
    

    要查看解决方案,必须绘制x。使用给定的参数,我经常得到上面提到的错误

    Excess work done on this call (perhaps wrong Dfun type).
    Run with full_output = 1 to get quantitative information.
    

0 个答案:

没有答案