我正在尝试实现一个处理非负ODE系统的算法。我需要像MATLAB中的ode45这样的东西来定义必须为非负的状态。
我已经在3年前讨论过了,但是没有真正的解决方案。 deSolve仍然不是要走的路。我发现一些看起来很有前途的python代码。也许这在R中也是可能的。最后,我必须定义一个函数包装器,如python中的functools。它的作用非常简单。这是python包装器的代码:
def wrap(f):
@wraps(f)
def wrapper(t, y, *args, **kwargs):
low = y < 0
y = np.maximum(y, np.ones(np.shape(y))*0)
result = f(t, y, *args, **kwargs)
result[too_low] = np.maximum(result[low], np.ones(low.sum())*0)
return result
return wrapper
return wrap
我的意思是在python中这很简单。包装程序将在
调用的集成的每个步骤中使用solver = scipy.integrate.odeint(f, y0)
solution = solver.solve()
R中是否可能相同?我知道也有一个functools包和functools函数。但是我不知道这是否真的有效。我可以在deSolve中使用事件吗?
我现在已经在这个项目上工作了5年,但我没有想法。我使用了MATLAB,C ++和Python接口,但是所有这些都很慢,我在R中需要它。非常感谢您的帮助!
答案 0 :(得分:1)
出于充分的理由,deSolve不支持自动非负约束。过去,我们曾多次提出这样的问题,但事实证明,在所有这些情况下,负值的原因都是模型规范不完整。典型的情况是某些内容是从空池中导出的。由于不必要的负值通常表示模型规格不足,因此我们(目前)不考虑在将来添加“非负”约束。
示例:在以下等式中,通过模型设计,X可以变为负数:
dX / dt = -k
以下内容不能:
dX / dt = -k * X
如果您需要“在大多数情况下”线性减少,并且在X变为零之前不久将其减少为零,则可以使用Monod类型的防护措施(或类似方法):
dX / dt = -k * X /(k2 + X)
k2的选择相对不严格。与求解器的数值精度相比,它应该足够小而不影响整体性能,并且不要太小。
另一种避免负值的方法是在对数转换的空间中工作。以下是一些相关线程:
https://stat.ethz.ch/pipermail/r-sig-dynamic-models/2010q2/000028.html
https://stat.ethz.ch/pipermail/r-sig-dynamic-models/2013q3/000222.html
https://stat.ethz.ch/pipermail/r-sig-dynamic-models/2016/000437.html
此外,当然也可以在R中编写自己的包装器。
希望有帮助