Simulation Python du modèle épidémique (modèle Kermack-McKendrick)

Épidémie

Citation: https://kotobank.jp/word/%E3%82%A8%E3%83%94%E3%83%87%E3%83%9F%E3%83%83%E3%82%AF-683127

> Épidémie En médecine et en santé publique, les personnes atteintes d'une certaine maladie font des prédictions normales dans une zone ou un groupe donné.
> Dépassement d'un montant important. Une maladie infectieuse telle que la grippe est répandue dans une zone spécifique.
> L'état dans lequel cela se produit simultanément dans diverses parties du monde est appelé pandémie.

Modèle Kermack-McKendrick

http://mathworld.wolfram.com/Kermack-McKendrickModel.html

Un modèle qui représente l'évolution du nombre de personnes infectées par des maladies infectieuses dans une population fermée. Ci-après, il est représenté par une équation différentielle simultanée.

\begin{eqnarray}
\frac{dx(x)}{dt}&=&-kx(t)y(t)\\
\frac{dy(t)}{dt}&=&kx(t)y(t)-ly(t)\\
\frac{dz(t)}{dt}&=&ly(t)
\end{eqnarray}

$ x (t) ≥ 0 $: nombre de personnes en bonne santé, $ y (t) ≥ 0 $: nombre de personnes malades, $ z (t) ≥ 0 $: nombre de personnes rétablies, $ k ≥ 0 $ : Taux d'infection, $ l ≥ 0 $: Taux de guérison

En tant qu'interprétation ・ Ensemble 1: Le taux de variation du nombre de personnes en bonne santé $ x $ est proportionnel au nombre de personnes en bonne santé x au nombre de personnes malades. Le coefficient de proportionnalité est de $ -k $. Puisque $ k, x, y ≥ 0 $, le nombre de personnes en bonne santé n'augmentera pas. Si le nombre de personnes malades devient 0, le nombre de personnes en bonne santé sera maintenu constant. · Type 2: Le taux de changement du nombre de malades $ y $ est déterminé par le taux de changement du nombre de personnes en bonne santé et la contribution du nombre de malades. Plus le taux de variation du nombre de personnes en bonne santé est élevé ou plus le nombre de personnes malades est élevé, plus le taux de variation du nombre de personnes malades est faible. Si le signe $ kx (t) -l $ est positif, le nombre de malades augmentera, et s'il est négatif, il diminuera. ・ Type 3: Le taux de variation du nombre de personnes qui ont récupéré $ z $ est proportionnel au nombre de personnes malades. La constante de proportionnalité est $ l $. Plus il y a de malades, plus le nombre de personnes qui guérissent augmentera rapidement.

Un point fixe

\begin{eqnarray}
\frac{dx(x)}{dt}&=&-kx(t)y(t)=0…①\\
\frac{dy(t)}{dt}&=&kx(t)y(t)-ly(t)=0…②\\
\frac{dz(t)}{dt}&=&ly(t)=0…③
\end{eqnarray}

Le point qui devient.

À partir de ② $ x $ = $ \ frac {l} {k} $ De ① et ③ $ y = 0 $

Quantité de stockage

\begin{eqnarray}
\frac{dx(x)}{dy(t)}&=&\frac{-kx(t)y(t)}{kx(t)y(t)-ly(t)}\\
&=&\frac{-kx(t)}{kx(t)-l}\\
(\frac{l}{k}\frac{1}{x}-1)dx(t)&=&dy(t)\\
\int{(\frac{l}{k}\frac{1}{x}-1)dx(t)}&=&\int{dy(t)}\\
\frac{l}{k}logx(t)-x(t)&=&y(t)+E
\end{eqnarray}

$ \ Frac {l} {k} logx (t) -x (t) -y (t) $ est la quantité de stockage (elle prend une valeur constante même si l'heure change).

Simulation par calcul numérique

Méthode de calcul

http://qiita.com/popondeli/items/391810fd727cefb190e7 La méthode de Rungecutta décrite dans est étendue et utilisée pour les équations différentielles simultanées.

·Code source

import numpy as np
import matplotlib.pyplot as plt
import math

k = 1.0
l = 1.0

DELTA_T = 0.001
MAX_T = 100.0

def dx(x, y, z, t):
    return -k * x * y
    
def dy(x, y, z, t):
    return k * x * y - l * y
    
def dz(x, y, z, t):
    return l * y
    
def calc_conceved_quantity(x, y, z, t):
    return (l/k)*math.log(x) - x - y
    
def runge_kutta(init_x, init_y, init_z, init_t):
    x, y, z, t = init_x, init_y, init_z, init_t
    history = [[x, y, z, t, calc_conceved_quantity(x, y, z, t)]]
    cnt = 0
    while t < MAX_T:
        cnt += 1
        k1_x = DELTA_T*dx(x, y, z, t)
        k1_y = DELTA_T*dy(x, y, z, t)
        k1_z = DELTA_T*dz(x, y, z, t)
        
        k2_x = DELTA_T*dx(x + k1_x/2, y + k1_y/2, z + k1_z/2, t + DELTA_T/2)
        k2_y = DELTA_T*dy(x + k1_x/2, y + k1_y/2, z + k1_z/2, t + DELTA_T/2)
        k2_z = DELTA_T*dz(x + k1_x/2, y + k1_y/2, z + k1_z/2, t + DELTA_T/2)
        
        k3_x = DELTA_T*dx(x + k2_x/2, y + k2_y/2, z + k2_z/2, t + DELTA_T/2)
        k3_y = DELTA_T*dy(x + k2_x/2, y + k2_y/2, z + k2_z/2, t + DELTA_T/2)
        k3_z = DELTA_T*dz(x + k2_x/2, y + k2_y/2, z + k2_z/2, t + DELTA_T/2)
        
        k4_x = DELTA_T*dx(x + k3_x, y + k3_y, z + k3_z, t + DELTA_T)
        k4_y = DELTA_T*dy(x + k3_x, y + k3_y, z + k3_z, t + DELTA_T)
        k4_z = DELTA_T*dz(x + k3_x, y + k3_y, z + k3_z, t + DELTA_T)
        
        x += (k1_x + 2*k2_x + 2*k3_x + k4_x)/6
        y += (k1_y + 2*k2_y + 2*k3_y + k4_y)/6
        z += (k1_z + 2*k2_z + 2*k3_z + k4_z)/6
        t += DELTA_T
        x = max(0, x)
        y = max(0, y)
        z = max(0, z)
        if cnt % 100 == 0:
            history.append([x, y, z, t, calc_conceved_quantity(x, y, z, t)])
    return history
    
if __name__ == '__main__':
    #Calcul numérique par la méthode Rungekutta
    history = np.array(runge_kutta(init_x = 1, init_y = 0.1, init_z = 0, init_t = 0))
    
    x_min, x_max = min(history[:,0]), max(history[:,0])
    y_min, y_max = min(history[:,1]), max(history[:,1])
    z_min, z_max = min(history[:,2]), max(history[:,2])
    t_min, t_max = 0, MAX_T
    
    #Tracer le diagramme de phase x vs y
    plt.subplot(4, 1, 1)
    plt.title("x vs y")
    plt.xlim(x_min, x_max)
    plt.ylim(y_min, y_max)
    plt.scatter(history[:,0], history[:,1])
    
    # x(Nombre de personnes en bonne santé)Tracez le changement d'heure de
    plt.subplot(4, 1, 2)
    plt.title("t vs x")
    plt.xlim(t_min, t_max)
    plt.ylim(0, x_max)
    plt.scatter(history[:,3], history[:,0])
    
    # y(Nombre de malades)Tracez le changement d'heure de
    plt.subplot(4, 1, 3)
    plt.title("t vs y")
    plt.xlim(t_min, t_max)
    plt.ylim(0, y_max)
    plt.scatter(history[:,3], history[:,1])
    
    #Tracer la quantité de stockage au fil du temps
    plt.subplot(4, 1, 4)
    plt.title(u"t vs conserved quantity")
    plt.xlim(t_min, t_max)
    plt.scatter(history[:,3], history[:,4])
    plt.show()

$ k $ et $ l $ valent 1,0.

figure_1-1.png

Résultats dus aux différences de valeurs initiales x et y

Diagramme de phase X vs y lorsque la simulation est répétée 100 fois avec les valeurs initiales de $ x et y $ étant donné une valeur aléatoire de 0 à 1.

Code source

import numpy as np
import matplotlib.pyplot as plt
import math
import random

k = 1.0
l = 1.0

DELTA_T = 0.001
MAX_T = 100.0

def dx(x, y, z, t):
    return -k * x * y
    
def dy(x, y, z, t):
    return k * x * y - l * y
    
def dz(x, y, z, t):
    return l * y
    
def calc_conceved_quantity(x, y, z, t):
    return (l/k)*math.log(x) - x - y
    
def runge_kutta(init_x, init_y, init_z, init_t):
    x, y, z, t = init_x, init_y, init_z, init_t
    history = [[x, y, z, t, calc_conceved_quantity(x, y, z, t)]]
    cnt = 0
    while t < MAX_T:
        cnt += 1
        k1_x = DELTA_T*dx(x, y, z, t)
        k1_y = DELTA_T*dy(x, y, z, t)
        k1_z = DELTA_T*dz(x, y, z, t)
        
        k2_x = DELTA_T*dx(x + k1_x/2, y + k1_y/2, z + k1_z/2, t + DELTA_T/2)
        k2_y = DELTA_T*dy(x + k1_x/2, y + k1_y/2, z + k1_z/2, t + DELTA_T/2)
        k2_z = DELTA_T*dz(x + k1_x/2, y + k1_y/2, z + k1_z/2, t + DELTA_T/2)
        
        k3_x = DELTA_T*dx(x + k2_x/2, y + k2_y/2, z + k2_z/2, t + DELTA_T/2)
        k3_y = DELTA_T*dy(x + k2_x/2, y + k2_y/2, z + k2_z/2, t + DELTA_T/2)
        k3_z = DELTA_T*dz(x + k2_x/2, y + k2_y/2, z + k2_z/2, t + DELTA_T/2)
        
        k4_x = DELTA_T*dx(x + k3_x, y + k3_y, z + k3_z, t + DELTA_T)
        k4_y = DELTA_T*dy(x + k3_x, y + k3_y, z + k3_z, t + DELTA_T)
        k4_z = DELTA_T*dz(x + k3_x, y + k3_y, z + k3_z, t + DELTA_T)
        
        x += (k1_x + 2*k2_x + 2*k3_x + k4_x)/6
        y += (k1_y + 2*k2_y + 2*k3_y + k4_y)/6
        z += (k1_z + 2*k2_z + 2*k3_z + k4_z)/6
        t += DELTA_T
        x = max(0, x)
        y = max(0, y)
        z = max(0, z)
        if cnt % 100 == 0:
            history.append([x, y, z, t, calc_conceved_quantity(x, y, z, t)])
    return history
    
if __name__ == '__main__':

    for i in range(0, 100):
        init_x = random.random()
        init_y = random.random()
    
        #Calcul numérique par la méthode Rungekutta
        history = np.array(runge_kutta(init_x, init_y, init_z = 0, init_t = 0))
        
        x_min, x_max = min(history[:,0]), max(history[:,0])
        y_min, y_max = min(history[:,1]), max(history[:,1])
        z_min, z_max = min(history[:,2]), max(history[:,2])
        t_min, t_max = 0, MAX_T
        
        #Tracer le diagramme de phase x vs y
        plt.title("x vs y")
        plt.xlim(0, 1)
        plt.ylim(0, 1)
        plt.scatter(history[:,0], history[:,1])
    plt.show()

figure_1-2.png

En dessinant une courbe, elle tombe à $ y = 0 $ (= nombre de personnes infectées 0).

Résultats dus aux différences de paramètres k et l (taux d'infection, taux de récupération)

Taux de récupération plus élevé

l = 3.0k = 1.0

figure_1-3_l-3.png

La chute à $ y = 0 $ devient raide

Augmentation du taux d'infection

l = 1.0k = 5.0

figure_1-4_k-5.png

Une fois infecté, le nombre de personnes infectées augmente et diminue à 0

Recommended Posts

Simulation Python du modèle épidémique (modèle Kermack-McKendrick)
Simulation GUI du nouveau virus corona (modèle SEIR)
Spécifier le modèle d'éclairage du matériau SCN dans Pythonista
Le sens de soi
Comptez le nombre de paramètres dans le modèle d'apprentissage en profondeur
le zen de Python
L'histoire de sys.path.append ()
La vengeance des types: la vengeance des types
Essayez d'évaluer les performances du modèle d'apprentissage automatique / de régression
J'ai essayé de refactoriser le modèle CNN de TensorFlow en utilisant TF-Slim
Implémenter le modèle mathématique «modèle SIR» des maladies infectieuses avec Open Modelica
L'histoire du champ de modèle Django disparaissant de la classe
J'ai fait une fonction pour vérifier le modèle de DCGAN
Analysez le modèle thématique pour devenir romancier avec GensimPy3
Aligner la version de chromedriver_binary
Grattage du résultat de "Schedule-kun"
10. Compter le nombre de lignes
Vers la retraite de Python2
Avantages d'affiner le modèle de Django
Obtenez le nombre de chiffres
Expliquez le code de Tensorflow_in_ROS
Réutiliser les résultats du clustering
GoPiGo3 du vieil homme
Calculez le nombre de changements
Changer le thème de Jupyter
La popularité des langages de programmation
Changer le style de matplotlib
Calibrer le modèle avec PyCaret
Visualisez la trajectoire de Hayabusa 2
À propos des composants de Luigi
Composants liés du graphique
Filtrer la sortie de tracemalloc
À propos des fonctionnalités de Python
Simulation du contenu du portefeuille
Le pouvoir des pandas: Python
[Pytorch] Je souhaite attribuer manuellement les paramètres d'entraînement du modèle
Traduit l'explication du modèle supérieur du concours de détection des ondes cérébrales de Kaggle
[Django] Corrige le pluriel du nom du modèle sur l'écran de gestion
Essayez de modéliser le rendement cumulatif du roulement dans le trading à terme
[Français] scikit-learn 0.18 Guide de l'utilisateur 3.3. Évaluation du modèle: quantifier la qualité de la prédiction
Évaluer les performances d'un modèle de régression simple à l'aide de la validation d'intersection LeaveOneOut
[Introduction au modèle SIR] Considérez le résultat de l'ajustement de Diamond Princess ♬
Évaluer la précision du modèle d'apprentissage par test croisé de scikit learn