4

编辑:这个问题是由于一个错误,在 Scipy 0.15 中修复

在开发和测试代码时,我可能会犯一个简单的错误,例如 NameError。当我使用 scipy.integrate.odeint 时,odeint 将打印错误消息,但会在我请求的任何时间步长内继续集成,因此我会收到许多相同的错误消息。我认为它具有这种行为,以便在发生算术错误(例如,除以零)时可以继续,但这对于编程错误是无益的行为。

有没有办法让 scipy 在第一条错误消息后停止?如果我能让它停止错误而不是算术异常,那将是最好的。

4

1 回答 1

2

odeint是 C 代码的 Python 包装器,它调用 LSODA(一个 Fortran 子例程),它调用 C 代码来调用代表 dy/dt 的 Python 回调。LSODA 不会传递 Python 异常,从 C 代码的一个位跳转到另一个 C 代码执行起来很麻烦。

我已经找到了一个令人满意的解决方案,只是使用ode而不是odeint. 我发现ode开始使用比较复杂,但是当 Python 中抛出异常时,它的行为是正确的。下面的fake_odeint()函数是创建一个odeint对我的目的来说足够好的函数的开始,这样我就可以在我现有的代码中将它换掉。使用ode代替的缺点odeint是 LSODA 在每个时间步被调用一次;这个调用发生在 C 中,odeint并且在 Python 中更慢ode

import numpy as np
from scipy.integrate import ode

def fake_odeint(func, y0, t, Dfun=None):
    ig = ode(func, Dfun)
    ig.set_integrator('lsoda',
                       method='adams')
    ig.set_initial_value(y0, t=0.)
    y = []
    for tt in t:
        y.append(ig.integrate(tt))
    return np.array(y)

我在这个 SO question中研究了如何使用 Fortran、C 和 Python 代码来允许odeint与 LSODA 通信的机制。

于 2013-06-25T19:12:45.397 回答