Seltsam SciPy ODE Integration Fehler
Ich bin die Implementierung eines sehr einfachen Susceptible-Infected-Recovered-model mit einem stabilen Bevölkerung für ein idle-Seite des Projekts - in der Regel eine ziemlich einfache Aufgabe. Aber ich bin mit in solver-Fehler mit entweder PysCeS oder SciPy, die beide verwenden, lsoda als Ihre zugrunde liegende solver. Dies geschieht nur für bestimmte Werte der parameter, und ich bin ratlos, warum. Der code, den ich verwende ist wie folgt:
import numpy as np
from pylab import *
import scipy.integrate as spi
#Parameter Values
S0 = 99.
I0 = 1.
R0 = 0.
PopIn= (S0, I0, R0)
beta= 0.50
gamma=1/10.
mu = 1/25550.
t_end = 15000.
t_start = 1.
t_step = 1.
t_interval = np.arange(t_start, t_end, t_step)
#Solving the differential equation. Solves over t for initial conditions PopIn
def eq_system(PopIn,t):
'''Defining SIR System of Equations'''
#Creating an array of equations
Eqs= np.zeros((3))
Eqs[0]= -beta * (PopIn[0]*PopIn[1]/(PopIn[0]+PopIn[1]+PopIn[2])) - mu*PopIn[0] + mu*(PopIn[0]+PopIn[1]+PopIn[2])
Eqs[1]= (beta * (PopIn[0]*PopIn[1]/(PopIn[0]+PopIn[1]+PopIn[2])) - gamma*PopIn[1] - mu*PopIn[1])
Eqs[2]= gamma*PopIn[1] - mu*PopIn[2]
return Eqs
SIR = spi.odeint(eq_system, PopIn, t_interval)
Diese erzeugt die folgende Fehlermeldung:
lsoda-- at current t (=r1), mxstep (=i1) steps
taken on this call before reaching tout
In above message, I1 = 500
In above message, R1 = 0.7818108252072E+04
Excess work done on this call (perhaps wrong Dfun type).
Run with full_output = 1 to get quantitative information.
Normalerweise, wenn ich ein problem auftreten, so, es ist etwas unheilbar falsch mit der Gleichung system, das ich eingerichtet, aber ich kann nicht sehen, nichts falsch mit ihm. Komischerweise, funktioniert es auch, wenn Sie sich ändern mu etwas wie 1/15550
. Im Falle dass es war etwas falsch mit dem system, ich auch implementiert das Modell in R wie folgt:
require(deSolve)
sir.model <- function (t, x, params) {
S <- x[1]
I <- x[2]
R <- x[3]
with (
as.list(params),
{
dS <- -beta*S*I/(S+I+R) - mu*S + mu*(S+I+R)
dI <- beta*S*I/(S+I+R) - gamma*I - mu*I
dR <- gamma*I - mu*R
res <- c(dS,dI,dR)
list(res)
}
)
}
times <- seq(0,15000,by=1)
params <- c(
beta <- 0.50,
gamma <- 1/10,
mu <- 1/25550
)
xstart <- c(S = 99, I = 1, R= 0)
out <- as.data.frame(lsoda(xstart,times,sir.model,params))
Diese auch verwendet lsoda, aber scheint zu gehen reibungslos über die Bühne. Kann jemand sehen, was falsch läuft in der Python-code?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich denke, dass für die Parameter, die Sie gewählt haben, Sie laufen in Probleme mit Steifigkeit - aufgrund der numerischen Instabilität der solver die Schrittweite ist immer wieder in immer sehr klein, in Regionen, in denen die Steigung der Lösung, die Kurve ist tatsächlich ziemlich flach. Die Fortran-solver
lsoda
, die eingehüllt ist vonscipy.integrate.odeint
versucht zu wechseln, adaptiv zwischen Methoden geeignet, um zu 'steif' und 'nicht-steife Systeme, aber in diesem Fall scheint es zu sein, andernfalls wechseln Sie zu steif Methoden.Sehr grob können Sie einfach Massiv erhöhen der maximal zulässigen Schritte, und der solver wird es am Ende:
Eine bessere option ist die Verwendung der Objekt-orientierten ODE-solver
scipy.integrate.ode
, die können Sie explizit wählen, ob steif oder nicht steif Methoden:Ausgabe:
Den infizierten Bevölkerung
PopIn[1]
zerfällt zu null. Scheinbar (normal) numerische Ungenauigkeit führt zuPopIn[1]
immer negativ (ca. -3.549 e-12) in der Nähe von t=322.9. Dann schließlich die Lösung bläst in der Nähe von t=7818.093, mitPopIn[0]
gehen in Richtung +unendlich und -PopIn[1]
gehen in Richtung -unendlich.Edit: ich entfernte meinen früheren Vorschlag für einen "quick fix". Es war ein fragwürdiger hack.