Le modèle SIR

Serge-Étienne Parent

Qu'est-ce qu'un modèle SIR?

Le modèle SIR suppose que la population totale, inline_formula not implemented est composée de personnes pouvant être classées comme susceptibles d'être infectées (inline_formula not implemented), infectées (inline_formula not implemented) ou ne pouvant plus être infectées (inline_formula not implemented, pour retirées). Les inline_formula not implemented sont autant les personnes immunisées après avoir été contaminées... que les personnes décédées.

formula not implemented

Les personnes susceptibles peuvent migrer vers la catégorie des infectées, et les personnes infectées peuvent migrer vers la catégorie des retirées (figure 1).

Figure 1. Migration entre les compartiments inline_formula not implemented, inline_formula not implemented et inline_formula not implemented.

Nous cherchons comment évolueront des effectifs initiaux dans chaque contenants selon les flux qui les relient. Puisque nous désirons modéliser la variation dans le temps, nous sommes confrontés à un problème d'équation différentielle (modéliser la variation) ordinaire (en fonction d'une seule variable, le temps).

Variation sur inline_formula not implemented

Les personnes susceptibles cesseront de l'être lorsqu'elles migrront vers le stade d'infection. On les retirera du bilan proportionnellement à inline_formula not implemented et à inline_formula not implemented à un taux de contamination inline_formula not implemented.

formula not implemented

Si inline_formula not implemented et inline_formula not implemented sont chacun exprimés en effectifs (disons en inline_formula not implemented), et que la dérivée inline_formula not implemented doit être exprimée en inline_formula not implemented, le paramètre inline_formula not implemented devra être un taux en terme de inline_formula not implemented. Plus inline_formula not implemented est élevé, plus l'infection se dispersera rapidement.

Variation sur inline_formula not implemented

L'effectif inline_formula not implemented accumulera ce qui sort de l'effectif inline_formula not implemented (inline_formula not implemented). De plus, l'effectif inline_formula not implemented diminuera avec la rémission (ou la mortalité) assciée à un taux inline_formula not implemented.

formula not implemented

Le taux inline_formula not implemented sera exprimé en inline_formula not implemented. Son inverse est le nombre de jours nécessaires pour une rémission (ou un décès).

Variation sur inline_formula not implemented

Enfin, les inline_formula not implemented accumuleront ce qui sort de l'état d'infection.

formula not implemented

Si l'on prend la somme des variations,

formula not implemented

Le modèle ne suggérant aucune variation, la population totale est prise comme constante.

Quatre questions

À partir de ces équations, on peut se poser trois questions.

  1. Où se trouve la fameuse "croissance exponentielle" dans ce système d'équations?

  2. Où se trouve le fameux "paramètre inline_formula not implemented", qui indique la capacité de propagation d'une épidémie?

  3. Comment résoudre ces équations?

  4. Comment "aplatir la courbe"?

La croissance exponentielle

Mais où est la fameuse "croissance exponentielle" de l'infection dans ces équations? Elle se trouve dans le déplacement des cas susceptibles à infectés, inline_formula not implemented, où inline_formula not implemented est ici ne nombre de personnes infectées cumulées étant donnée que l'on retire la partie inline_formula not implemented. L'exponentielle se trouve dans la tendance de inline_formula not implemented, et non dans celle de inline_formula not implemented.

formula not implementedformula not implementedformula not implemented

Bien que inline_formula not implemented ne soit pas indépendant de inline_formula not implemented, prenons-la pour une constante pour simplifier. Sortir inline_formula not implemented de l'intégrale implique que le nombre de personnes susceptibles d'être infectées reste constant. Mais dans les faits, il y a une migration de l'effectif de inline_formula not implemented vers inline_formula not implemented, puis de inline_formula not implemented vers inline_formula not implemented, faisant de la croissance exponentielle une approximation de la tendance observée en début d'épidémie.

formula not implementedformula not implemented

Si on part le chrono à 0, inline_formula not implemented, qu'on l'arrête à un temps quelconque inline_formula not implemented, et qu'on pose inline_formula not implemented,

formula not implemented

En faisant l'exponentielle de part et d'autre de l'équation et en isolant inline_formula not implemented, on retrouve notre fonction exponentielle.

formula not implemented

Le paramètre inline_formula not implemented

Le paramètre inline_formula not implemented décrit la virulence d'une épidémie. Pour comprendre comment il est obtenu, faisons un petit détour.

À l'équilibre, le nombre de personnes qui sont retirées de l'infection est égale au nombre de personnes infectées, i.e. inline_formula not implemented. Mais si l'infection se propage, on aura inline_formula not implemented. Dans ce cas, on aura aussi

formula not implemented

Donc

formula not implementedformula not implementedformula not implementedformula not implemented

On utilise la variable inline_formula not implemented pour déterminer une constante de propagation. Ce n'est pas le même inline_formula not implemented que celui su modèle SIR, mais une convention pour nommer cette variable.

formula not implemented

Au début de l'épidémie, inline_formula not implemented. On obtient ainsi le fameux inline_formula not implemented.

formula not implemented

Un inline_formula not implemented est plus élevé que 1 indique une situation à risque d'épidémie.

Pour comparaison, une étude récente estime le inline_formula not implemented de la COVID-19 à entre 3.8 et 8.9 (ce qui est particulièrement élevé par rapport à ce qui a été publié ailleurs, me dit-on) et celui de la grippe saisonnière entre 1.2 et 1.4.

Enfin, si l'on divise inline_formula not implemented par inline_formula not implemented, on obtient le nombre de personnes qui seront infectées par une personne porteuse de l'infection.

Résoudre le système

Le modèle SIR avec Insight Maker

La figure 1 est une capture d'écran tirée de Insight Maker, un logiciel en ligne qui permet de modéliser des systèmes d'équations différentielles ordinaires (aussi appelés des systèmes dynamiques) sans trop demander de compétences en programmation. L'approche consiste à placer des stocks, des flux et des variables sur un canevas. Les stocks sont nos trois catégories inline_formula not implemented, inline_formula not implemented et inline_formula not implemented. Les flux connectent les stocks. Le flux connectant inline_formula not implemented et inline_formula not implemented est égal à [Taux infection]*[Susceptibles]*[Infectes] et celui connectant inline_formula not implemented à inline_formula not implemented est égal à [Taux de guerison]*[Infectes]. Les bulles oranges sont les variables qui affectent les flux, desquelles on peut calculer le inline_formula not implemented. Le schéma de calcul est présenté à la figure 2.

Figure 2. Simulation avec Insight Maker, https://insightmaker.com/insight/192683/SIR

Le modèle SIR

Insight Maker est un très bon outil pour appréhender un problème. Mais si on décide d'aller plus lion, on aura avantage à utiliser un langage de programmation. Je propose deux versions, en R et en Python.

Cette version effectue la démarche en R. Pour poursuivre en Python, c'est par ici.

Voyons maintenant comment implémenter cela en langage R. Nous aurons préalablement besoin des modules tidyverse pour les opérations génériques et deSolve pour la résolution de systèmes d'équations différentielles.

install.packages("deSolve")
32.9s
library("tidyverse")
library("deSolve")
0.4s

Pour modéliser notre système d'équation différentielles ordinaires, nous devons définir notre problème dans une fonction comprenant

  • N, un vecteur comprenant le nombre de personnes susceptibles (S), infectées (I) et rétablies (R).

  • t, la variable par rapport à laquelle dériver

  • p, un vecteur contenant les paramètres alpha et beta et

  • les équations différentielles définies précédemment.

Pour que la fonction de différenciation utilisées plus loin fonctionne, elle doit prendre une variable t pour le temps et p pour les paramètres. Puis elle doit retourner les différenciations dans une liste.

SIR_model <- function(t, N, p) {
  S <- N[1]
  I <- N[2]
  R <- N[3]
  
  alpha <- p[1]
  beta <- p[2]
  
  dS_dt <- -alpha * S * I
  dI_dt <- alpha * S * I - I * beta
  dR_dt <- I * beta
  return(list(c(dS_dt, dI_dt, dR_dt)))
}
1.2s

Établissons certains paramètres inspirés de la COVID-19 au Québec. Il s'agit d'un cas fictif, et non pas d'une simulation crédible ayant des vertus prédictives.

time <- seq(0, 150, by = 0.1)
N0 <- c(S = 7.5, I = 0.005, R = 0) # en millions
p <- c(alpha = 0.04, # taux d'infection en 1/(Mpers jour)
       beta = 0.07 # taux de récupération en 1/jour
)
0.2s

Ces paramètres nous permettent d'emblée de calculer le inline_formula not implemented.

N0[1] * p[1] / p[2]
0.3s

La fonction ode agglomère les paramètres et la fonction pour solutionner le système.

solution <- ode(y = N0, times = time, SIR_model, p)
0.3s

Sur graphique,

data.frame(solution) %>% 
  pivot_longer(cols = -time) %>% 
  ggplot(aes(x = time, y = value)) +
  #facet_wrap(~name, ncol = 1, scales = "free") +
  geom_line(aes(colour = name))
1.1s

~3 millions de personnes infectées en ~40 jours. 👽 Rappel: c'est un cas fictif 👽!!!

Aplatir la courbe

Le paramètre inline_formula not implemented est fixe étant donné que nous n'avons pas de remède pour guérir de la COVID-19 plus rapidement. Le nombre de personnes susceptibles pourrait être diminué avec un vaccin, qui n'existe toujours pas. Nous avons toutefois le pouvoir de modifier inline_formula not implemented avec des mesures de distanciation physique. Voyons la courbe d'infectio pour différentes valeurs de inline_formula not implemented.

alpha_v <- seq(0, 0.1, by = 0.01)
solution_l <- list()
for (i in seq_along(alpha_v)) {
  p <- c(alpha = alpha_v[i], beta = 0.1)
  solution_l[[i]] <- data.frame(ode(y = N0, times = time, SIR_model, p)) %>% 
    pivot_longer(cols = -time) %>% 
    mutate(alpha = alpha_v[i])
}
solution <- do.call(rbind.data.frame, solution_l)
0.9s
solution %>% 
  filter(name == "I") %>% 
  ggplot(aes(x = time, y = value)) +
  geom_line(aes(group = alpha, colour = alpha), size = 1) +
  labs(x = "Temps (jour)", y = "Effectif infecté (million de personnes)")
1.0s

En diminuant inline_formula not implemented, on applatit la courbe. D'où les mesures importantes prises au Québec depuis début mars.

Allez plus loin

On pourra par la suite ajouter d'autres compartiments, stratifier les compartiments, ajouter un flux pour un taux possible de réinfection, ajuster les paramètre sur les donées existantes, créer des modèles régionaux aux paramètres différenciés, simuler des courbes selon les incertitudes que l'on a sur les paramètres, et l'on aurait un beau petit modèle épidémiologique plus représentatif de la réalité que cet exemple fictif.

Runtimes (1)