Introducción
En esta entrada voy a platicar de una forma en la que se puede plantear un modelo de epidemia básico usando álgebra lineal. Es un modelo bastante simple, sin embargo a partir de él se pueden verificar varias de las lecciones que hemos estado aprendiendo durante la crisis del coronavirus. A grandes rasgos, haremos algunas suposiciones razonables para plantear una epidemia como un modelo de Markov.
Ya que hagamos esto, estudiaremos dos escenarios posibles: en el que la gente sale de sus casas y en el que la gente se queda en sus casas. Para ello usaremos las librerías NumPy y Matplotlib de Python para hacer las cuentas y generar bonitas gráficas como la siguiente:

En particular, veremos que incluso de este modelo simple se notan contrastes importantes en ambos escenarios. En particular, se puede deducir la importancia de #QuédateEnCasa para retrasar el contagio y no saturar los sistemas de salud.
Advertencia: De ninguna forma esta entrada pretende modelar, específicamente, la evolución del coronavirus. Para ello hay expertos trabajando en el tema, y están usando modelos mucho más sofisticados que el que platicaré. Esta entrada es, en todo caso, una introducción al tema y ayuda a explicar, poco a poco, algunos de los argumentos que se usan en modelación matemática de epidemias.
Suposiciones y modelo tipo Markov
Comenzemos a plantear el modelo de epidemia básico. Pensemos en una enfermedad imaginaria, que se llama «Imagivid» y en un territorio imaginario que se llama «Imagilandia», donde la población inicial es de
Vamos a pensar que una persona puede estar en alguno de los siguientes cinco estados:
- Sano
- Síntomas leves
- Síntomas graves
- Recuperado
- Fallecido
Para cada día
Haremos las siguientes suposiciones de cómo se pasa de un estado a otro
- Los únicos fallecidos del periodo de tiempo que tendremos son por Imagivid. Sólo se puede fallecer de ello tras tener síntomas graves. Si alguien tiene síntomas graves, entonces tiene cierta probabilidad
de fallecer al día siguiente, de recuperarse y por lo tanto de quedarse como enfermo grave. - Imagivid se contagia de persona a persona, y de un día a otro una persona tiene probabilidad
de pasar de estar sana a tener síntomas leves. No se puede pasar directamente a tener síntomas graves, recuperarse o morir. De modo que se queda sana de un día a otro con probabilidad - Si una persona tiene síntomas leves, tiene probabilidad
de pasar a tener síntomas graves y de pasar a recuperarse. Por lo tanto, tiene probabilidad de quedarse con síntomas leves. - Una persona que se recupera desarrolla inmunidad a Imagivid, así que se queda en ese estado.
- Una persona que fallece, se queda en ese estado.
En otras palabras, tenemos el siguiente diagrama de cómo se pasa de tener un estado a otro, en donde los números en las flechas muestran la probabilidad de pasar de un estado a otro:

En lenguaje técnico, estamos modelando a la epidemia como un proceso de Markov. Sin embargo, no es necesario entender toda la teoría de procesos de Markov para entender lo que sigue, pues la idea es bastante intuitiva.
Con estos números y suposiciones, podemos entender, en valor esperado, cómo será el vector de población
Este sistema de ecuaciones se puede escribir de una forma mucho más compacta. Si definimos la matriz
De esta forma, si queremos entender qué esperar del día
Un ejemplo concreto en Python
El modelo de epidemia básico que planteamos arriba depende de cinco parámetros:
, la probabilidad de pasar de estar sano a tener síntomas leves, , la probabilidad de pasar de tener síntomas leves a graves, , la probabilidad de pasar de tener síntomas leves a recuperarse, , la probabilidad de pasar de tener síntomas graves a recuperarse y , la probabilidad de pasar de tener síntomas graves, a fallecer.
Hagamos un ejemplo concreto, en el que estos parámetros para Imagivid son los siguientes:
Si ponemos estos valores, la matriz que obtenemos es la siguiente:
Vamos a usar la fórmula que obtuvimos en la sección anterior para entender cómo va evolucionando la epidemia de Imagivid. Para no hacer las cuentas a mano, usaremos Python. Trabajaremos con Python 3 y usaremos Numpy (para las cuentas de matrices) y Matplotlib (para visualizar gráficas). En el siguiente código definimos la población inicial, los parámetros de transición y la matriz de la sección anterior.
import numpy as np
import matplotlib.pyplot as plt
# En cada momento tendremos un vector
# de la distribución de la población
# (sanos, sintomas leves, sintomas graves,
# recuperados, fallecidos)
# Población inicial
x_0=(100000,0,0,0,0)
# Definimos las probabilidades de
# transición
S_L = 0.30
L_G = 0.10
L_R = 0.20
G_R = 0.10
G_F = 0.10
# Definimos la matriz A
A=np.array([[1-S_L,0,0,0,0],[S_L,1-L_G-L_R,0,0,0],[0,L_G,1-G_R-G_F,0,0],[0,L_R,G_R,1,0],[0,0,G_F,0,1]])
Vamos a estudiar la evolución de Imagivid por 60 días. Por ello, vamos a hacer un bucle en Python que calcule cómo son los vectores de población de todos estos 60 días. Para empezar a entender cómo funciona nuestro modelo de epidemia, también pediremos que muestre los valores para los días 1, 2 y 3.
# Encontramos la evolución de la
# epidemia los primeros 60 días
evolution=[x_0]
for j in range(60):
evolution.append(np.matmul(A,evolution[-1]))
# Mostramos lo que pasa los primeros
# 3 días
for j in range(1,4):
print(evolution[j])
Los valores que obtenemos son
Esto nos dice que al primer día hay
Esto son sólo tres días, pero sería bueno poder entender qué sucede en todo el periodo de 60 días. Para ello, vamos a pedir a Python que nos muestre una gráfica de cómo evoluciona la población a través del tiempo. Para ello hacemos lo siguiente
# Hacemos gráfica para mostrar la evolución de todo el tiempo
plt.plot([j[0] for j in evolution], label="Sanos")
plt.plot([j[1] for j in evolution], label="Síntomas leves")
plt.plot([j[2] for j in evolution], label="Síntomas graves")
plt.plot([j[3] for j in evolution], label="Recuperados")
plt.plot([j[4] for j in evolution], label="Fallecidos")
plt.title("Evolución de la población, contagio=0.30")
plt.legend()
plt.show()
Obtenemos la siguiente imagen

La gráfica tiene sentido es de esperarse que, tras cierta cantidad de tiempo, ya sólo haya habitantes recuperados y fallecidos. Notemos que hay un momento el el que la población con síntomas leves es de aproximadamente
¿Qué sucede al final de nuestro periodo de estudio? Si le pedimos a Python que nos de las últimas dos entradas del vector de población al día
#Mostramos recuperados y fallecidos al último día
print(evolution[-1][3])
print(evolution[-1][4])
obtenemos
Disminuir la tasa de infección para retrasar la epidemia
Antes de que sucediera la tragedia, las autoridades de Imagilandia estudiaron el modelo de epidemia que acabamos de mencionar y se dieron cuenta de que tenían que tomar una acción inmediata para mejorar la situación. Decidieron que una cosa muy importante para que la situación mejorara era pedirle a la gente que se quedara en sus casas lo más posible, pues con ello se disminuiría la tasa de contagio. Para ello sacaron la campaña #QuédateEnCasa. Las personas hicieron caso.
Habiendo más personas sanas y enfermas en su propia casa, ahora ni los enfermos pueden contagiar a sanos, ni los sanos estar expuestos a enfermos. Así, una persona sana ahora tiene menor probabilidad de estar enferma al día siguiente. Supongamos que
Vamos a pedirle de nuevo a Python que haga las cuentas para los primeros 60 días bajo las suposiciones de nuestro modelo de epidemia y que nos muestre una gráfica de la evolución de la población.
# Definimos las probabilidades de transición, que son iguales salvo que ahora la tasa de contagio es menor, y por lo tanto S_L es menor
S_L = 0.05
L_G = 0.10
L_R = 0.20
G_R = 0.10
G_F = 0.10
# Definimos la matriz A
A=np.array([[1-S_L,0,0,0,0],[S_L,1-L_G-L_R,0,0,0],[0,L_G,1-G_R-G_F,0,0],[0,L_R,G_R,1,0],[0,0,G_F,0,1]])
evolution2=[x_0]
for j in range(60):
evolution2.append(np.matmul(A,evolution2[-1]))
plt.plot([j[0] for j in evolution2], label="Sanos")
plt.plot([j[1] for j in evolution2], label="Síntomas leves")
plt.plot([j[2] for j in evolution2], label="Síntomas graves")
plt.plot([j[3] for j in evolution2], label="Recuperados")
plt.plot([j[4] for j in evolution2], label="Fallecidos")
plt.title("Evolución de la población, contagio=0.05")
plt.legend()
plt.show()
La gráfica que obtenemos es la siguiente:

Una cosa fantástica en este escenario es que nunca hay muchas personas enfermas simultáneamente. En el peor día, parece haber como
print(evolution2[-1][3])
print(evolution2[-1][4])
obtenemos
print(evolution[30][4])
print(evolution2[30][4])
En el primer escenario, en el que la gente no se queda en casa, al día
Esto parece estar mejor, sin embargo, el tiempo va a seguir pasando, y de todas formas llegaremos al día
La carrera contra el tiempo
Hay muchas razones por las cuales es conveniente retrasar la epidemia de Imagivid en Imagilandia, aunque el modelo sencillo que mostramos arriba muestre qe a los 60 días parecería que habrá la misma cantidad de fallecidos.
Primero, es importante retrasar los contagios pues existe la posibilidad de que los científicos de Imagilandia entiendan mejor a Imagivid y, por ejemplo, desarrollen una vacuna o un tratamiento. ¿Qué sucedería si los científicos encuentran una cura al día
Segundo, también es importante retrasar la epidemia pues permite tener el número de casos simultáneos bajo control. Esto ya lo discutimos un poco arriba, pero pidamos a Python una gráfica más, para poder discutirlo de manera más clara. Supondremos, además, que Imagilandia cuenta con solamente
plt.plot([j[1] for j in evolution2], color="green", linestyle=":", label="Leves, Contagio=0.05")
plt.plot([j[2] for j in evolution2], color="green", label="Severos, Contagio=0.05")
plt.plot([j[1] for j in evolution], color="red", linestyle=":", label="Severos, Contagio=0.30")
plt.plot([j[2] for j in evolution], color="red", label="Severos, Contagio=0.30")
plt.hlines(6000,0,60, color="black", label="Capacidad sistema salud")
plt.title("Enfermos a través del tiempo")
plt.legend()
plt.plot()
Obtenemos la siguiente gráfica:

Cuando la gente sí se queda en sus casas y la tasa de contagio es baja (en verde), siempre hay suficiente espacio en el sistema de salud para tratar a a los enfermos graves.
Cuando la gente no se queda en sus casas y la tasa de contagio es alta (en rojo), notemos que los casos severos sobrepasan al sistema de salud. Aproximadamente entre los días
De esta forma, siguiendo los consejos de quedarse en casa, la población de Imagilandia puede salvar, potencialmente,
Más contenido
Todo el código de Python del modelo lo corrí en una libreta de Jupyter. Puedes ver una versión en PDF de todo el código a continuación.
Si quieres el archivo de Jupyter para jugar con el modelo, puedes obtenerlo en el GitHub del proyecto: https://github.com/leomtz/linear-epidemid.
El modelo de epidemia que presentamos es una aplicación muy sencilla de álgebra lineal. En este blog hemos estado subiendo material de un curso de álgebra lineal que se imparte en la UNAM, y que ahora estamos impartiendo a distancia por la contingencia. A continuación ponemos el enlace a este curso y a otro material que te puede interesar.