De nombreux systèmes sont modélisés par des équations différentielles ordinaires. R peut permettre de résoudre certains de ces systèmes et aussi d’estimer leurs paramètres.

On prend ici l’exemple d’un modèle épidémiologique temporel SI.



#edo SIX

library(deSolve) # on utilise deSolve

#on définit le système dans une fonction six ici

six<-function(t,x,parms){
    with( as.list(c(parms,x)),{

    rp<-ap*exp(-bp*t)
    rs<-as*exp(-0.5*(log(t/gs)/bs)^2)
    
    dI<- (rp*X*S+rs*I*S)
    dS<- -(rp*X*S+rs*I*S)

    res<-c(dI,dS)
    list(res)})
}

#on définit les paramètres pour la simulation du système

parms<-c(ap=0.002, bp=0.0084, as=5.9e-7, bs=0.25, gs=1396, X=1, N=1010)

#on crée un vecteur pour le temps
times<-seq(0:3000)

#valeurs initiales des variables (ici tous les individus sont sains au début)

y<- xstart <-(c(I = 0, S = 1010))

#on résout le système avec la fonction lsoda

out<-as.data.frame(lsoda(xstart, times, six, parms))

# toujours regarder le résultat pour détecter les incohérences

plot(out$S~out$time, type="l",col='blue')
plot(out$I~out$time, type="l",col='green',lwd=3)

#on crée un jeu de données en ajoutant un bruit blanc (gaussien)

noisy<-out$I+rnorm(nrow(out),sd=0.15*out$I)

plot(noisy)

#on ajuste le modèle sur ces données par les moindres carrés
# pour cela on utilise la fonction nls, il faut faire attention aux paramètres initiaux

fitnoisy<-nls(noisy~lsoda(xstart,times,six,c(ap=ap, bp=bp, as=as, bs=bs, gs=gs, X=1, N=1010))[,2]
     ,start=list(ap=0.002, bp=0.0084, as=5.9e-7, bs=0.25, gs=1000)
    , control=list(minFactor=1e-20,maxiter=150))

summary(fitnoisy)

# un beau graphique pour visualiser tout ça!

plot(noisy,pch=20,col='grey',main="SIX ode Model Fit",xlab="time",ylab="disease progress")
lines(predict(fitnoisy,times),type='l',col='green',lwd=4.5)


Vous pouvez définir différents systèmes d’équations différentielles en conservant la même structure.
Enfin pour estimer les paramètres il est possible d’utiliser d’autres fonctions et/ou d’autres méthodes (vraisemblance par exemple).
Pour que nls converge il faut donner des valeurs initiales le plus proche possibles des « vraies valeurs ». Je vous conseille donc d’essayer de fitter votre système graphiquement. Si ça ne marche pas vous pouvez utiliser nls2 avec l’algorithme bruteforce…