Proyecto Unidad 2: Simulación epidemiológica
Al final del proyecto, tu programa debe de tener un comportamiento como el siguiente:
$ python SimulacionEpidemiologica.py
¿Cuántas personas hay en la simulación?: 9
¿Cuántos contagiados iniciales hay?: 3
¿Cuál es el valor de beta?: 0.4
¿Cuál es el valor de gamma?: 0.15
Día 0 array([[1, 0, 0], [0, 0, 1], [0, 0, 1]]) Día 1 array([[2, 0, 0], [1, 1, 2], [0, 0, 1]]) Día 2 array([[2, 1, 0], [2, 1, 2], [1, 0, 2]]) Día 3 array([[2, 2, 0], [2, 2, 2], [1, 1, 2]]) Día 4 array([[2, 2, 0], [2, 2, 2], [2, 2, 2]]) Final de la simulación en día 4. 1 Suceptibles. 8 Removidos.
Código Inicial
Descarga los archivos necesarios para comenzar este proyecto.
Descargar archivosInspiración
Los procesos epidemiológicos siguen un patrón de comportamiento, en el cual las personas pueden entrar en uno de varios posibles estados. El modelo que describe este comportamiento en su forma más básica se conoce como modelo SIR.
Este modelo matemático considera tres posibles estados en los que pueden encontrarse los individuos ante un proceso infeccioso. Estos tres estados corresponden con:
- S (susceptible): En este estado se encuentran los individuos que no han sido contagiados con el patógeno y por tanto están susceptibles a contagiarse.
- I (infectado): Este es el estado en el que se encuentran aquellos que están infectados por el patógeno, y que además presentan la capacidad de contagiar a los individuos en estado susceptible. Los individuos en este estado son los principales agentes infecciosos en la mayoría de las ocasiones, ya que son ellos los que transmiten la enfermedad entre los individuos de la población.
- R (removido o recuperado): Aquí se encuentran los individuos que ya padecieron la enfermedad, y que por un cierto conjunto de circunstancias (e.g. muerte, recuperación, inmunidad, vacuna, etc.) ya no tienen la capacidad de infectarse, y por tanto dejan de contribuir al proceso infeccioso.
Estos tres estado base son los que regulan el proceso infeccioso en una población de individuos cuando se presenta un patógeno. Tómese en cuenta que esta es una clara simplificación del fenómeno epidemiológico, ya que es el modelo básico.
El modelo se puede visualizar gráficamente de la forma siguiente:

Dicha visualización se puede interpretar como un grafo dirigido, o como una secuencia de pasos. Nótese que en esta figura están presentes los tres estados antes mencionados S, I y R, cada uno como un nodo. Las aristas que los conectan tienen dirección, de forma que de un estado únicamente se puede pasar al siguiente y no de forma inversa (e.g. de infectado únicamente se puede pasar a removido, no de forma inversa). Igualmente se puede notar que se agregan dos parámetros antes no mencionados β (beta) y γ (gamma), los cuales indican el peso de la arista, o interpretados de otra forma indican a qué tasa o probabilidad se pasa de un estado a otro. Estos dos valores, al ser probabilidades están acotados al rango [0, 1].
Del grafo podemos interpretar entonces que:
- β es la probabilidado o tasa de que un susceptible pase al estado infectado.
- γ hace refencia a la probabilidad o tasa a la que un infectado muere o se recupera.
Supongamos que tenemos una población finita de nueve individuos, los cuales por simplicidad vamos a representar en el espacio de forma cuadrada como sigue:
S | S | S |
S | S | S |
S | S | S |
Al principio todos son scueptibles a contagiarse. Para que un proceso infeccioso con el modelo SIR modifique el estado de la población es necesario contar con al menos un individuo en estado infectado, de otra forma no habría manera de contagiarse.
Supongamos ahora que uno de estos nueve individuos se infecta, ahora nuestra población queda de la siguiente forma:
S | S | I |
S | S | S |
S | S | S |
en esta ocasión tenemos un caso inicial, por lo que la simulación puede comenzar. Suopongamos por simplicidad que los pasos de la simulación van a ser diarios (i.e. un paso = un día). El cuadro de arriba hace referencia al día 0, donde comienza nuestra simulación.
El siguiente paso sería simular el día 1. Para lograrlo debemos de actualizar los estados de cada uno de nuestros individuos según el modelo, del cual podemos inferir las siguientes reglas básicas:
- Si un susceptible entra en contacto con un infectado, tiene una probabilidad β de contagiarse depués de la interacción.
- Un infectado, por el simple hecho de estarlo, tiene una probabilidad γ de pasar al estado de removido.
Volviendo a nuestra simulación, para el individuo de la esquina superior izquierda actualizaríamos su estado según sus vecinos. Podemos ver que ninguno de los individuos que lo rodean está infectado, de forma que no hay posibilidad de que tenga contacto con uno. Esto conlleva que no haya forma de cambiar su estado por lo que continúa como susceptible para el siguiente paso de simulación.
S | S | I |
S | S | S |
S | S | S |
Avanzamos una casilla hacia la derecha en la fila, volvemos a encontrar que el individuo se encuentra en el estado de susceptible. Sin embargo, en esta ocasión uno de los individuos a sus costados está infectado, por tanto tiene una interacción y probabilidad de contagiarse.
S | S | I |
S | S | S |
S | S | S |
Para determinar si se infecta o no, se debe de lanzar una moneda cargada. Este enunciado quiere decir que, si lanzamos una moneda solo hay dos posibilidades: águila o sol, pero con la particularidad de que hay una probabilidad β que caiga sol (o 1 por ejemplo) y una probabilidad 1 - β de que caiga águila (o 0). Dependiendo del valor que caiga es la decisión que se toma, en este caso si cae sol el individuo susceptible se contagia, mientras que si cae águila el individuo susceptible sigue siendo susceptible (no se infectó).
Supongamos para nuestra simulación que la moneda cargada cayó en sol, por lo que el individuo sí se contagia. De forma que ahora nuestros individuos quedan de la siguiente forma:
S | I | I |
S | S | S |
S | S | S |
Ahora tenemos un nuevo infectado, por lo que el patógeno se está propagando a través de nuestra población simulada, igual que en la vida real.
De forma similar ahora pasamos a evaluar el estado de nuestro siguiente individuo, notamos que en este caso ya estaba infectado.
S | S | I |
S | S | S |
S | S | S |
Probablemente una de las primeras cosas que vas a notar es que el segundo individuo de la primera fila, que en nuestro paso anterior habíamos determinado como infectado, ya no lo está. No, no es un error de dedo, esto es porque, a pesar de que ya fue determinado como infectado, al principio del día o paso de nuestra simulación estaba como susceptible, por lo que todas las interacciones de ese día con los demás fueron como susceptible, ¿o a poco creías que el patógeno iba a decidir empezar a contagiar por la esquina superior izquierda y avanzar así como lo hicimos nosotros?
Por tanto va a ser muy importante que guardes temporalmente la nueva distribución de los estados en la población para el nuevo paso de simulación, así como no perder los estados iniciales en cada uno antes de la actualización.
Habiendo mencionado eso, retomemos el proceso de actualización del individuo infectado. Para hacerlo se sigue un procedimiento similar al antes mencionado de la moneda cargada pero ahora con probabilidad γ de que el individuo modifique su estado a removido y 1 - γ la probabilidad de que permanezca infectado. Supongamos que el ejercicio de la moneda cargada apuntó a que el individuo sí pasa al estado de removido. Por lo que la población en el siguiente paso de simulación quedaría de la siguiente manera:
S | I | R |
S | S | S |
S | S | S |
Una vez que se haga este proceso para cada uno de los individuos de la población, se abrá terminado el paso de simuñación y se podrá pasar al siguiente. para nuestro ejemplo supongamos que después del primer paso de simulación quedó como sigue:
S | I | R |
S | S | I |
S | S | S |
Supongamos que hacemos otro paso de simulación. Ahora nuestra población podría tener la siguiente distribución:
S | R | R |
S | I | I |
S | S | I |
Y así sucesivamente:
I | R | R |
I | I | R |
S | S | R |
¿En qué momento el modelo llega a un estado estable? Esto sucede cuando ya no hay infectados en la población, de forma que ya no pueda haber transmisiones del patógeno entre los individuos. Por tanto solo existen dos escenarios finales posibles, ¿los puedes deducir?
Proyecto
En este proyecto desarrollarás un código que lleve a cabo simulaciones con el modelo SIR como la descrita anteriormente.
Tu programa le pedirá cuatro parámetros al usuario: el tamaño de la población, el número de infectados iniciales, el valor de β como el de γ.
Una vez que haya ingresado los datos, tu código deberá de distribuir el número de casos inciales indicado a lo largo de la población y llevar a cabo la simulaciuón del proceso infeccioso hasta que haya llegado a su estado estable.
Probablemente sea más ilustrativo el fenómeno si despliegas en cada paso de simulación el estado de cada individuo en la población. Al final de la simulación deberás de informar al usuario en cuántos días o simulaciones se llegó al estado estable, así como el número de susceptibles y removidos quedaron en la población al término de la misma.
Ayudas
En la carpeta comprimida (.zip) que descargaste al principio de esta página encontrarás los códigos para comenzar con el proyecto. Esta carpeta tiene dos scripts que te ayudarán a realizarlo.
Ayudas.py
Contiene la función ObtenerNumeroEntero(pregunta)
que pide al usuario un número entero imrpimiendo en pantalla el parámetro opcional
pregunta
. Regresa el número entero ingresado por el usuario.
Tiene la definición de la función ObtenerNumeroFlotante(pregunta, min, max)
que pide un número decimal al usuario imrpimiendo pregunta
que es un parámetro opcional. Cuanta con otros dos parámetros opcionales: min
y max
. Si no se especifica ninguno de ellos el número
ingresado por el usuario puede estar en el rango (-∞, ∞), mientras que si se especifica el valor min
el
rango para el número ingresado por el ususario sería [min
, ∞), de forma comtraria si se especifica max
el rango sería (-∞, max
] y por último, si ambos se especifican el rango de los posibles valores quedan acotados por
[min
, max
]. El valor regresado por la función es un número de punto flotante o decimal ingresado por el usuario en el
rango especificado.
SimulacionEpidemiologica.py
Este será tu código principal. En él se importan las funciones ObtenerNumeroEntero
y ObtenerNumeroFlotante
antes descritas,
del código Ayudas.py
. Además de que importa la librería de numpy
como np
.
Este código cuenta también con tres asignaciones de las variables dimension
que será el número de personas que el usuario espera que haya en la simulación.
iniciales
que será el número de infectados iniciales en la simulación, también ingresado por el usuario. Igualmente pide al usuario que indique el valor
de los parámetros β y γ los cuales se asignan a las variables beta
y gamma
respectivamente. Ambos parámetros están delimitados por el rango [0, 1] usando los parámetros min
y max
de ObtenerNumeroFlotante
.
En este proyecto daremos forma cuadrada a la distribución de personas, por lo que se tomará la raíz cuadrada de dimension
y se crea una tupla
dimensiones = (dimension, dimension)
. Esta tupla será la que indique las dimensiones del cuadrado. Para hacerlo se utiliza la función zeros
de numpy
que creará un arreglo con las dimensiones especificadas, en nuestro caso por dimensiones
, mientras que
inicializa todos sus elementos en cero. Este arreglo se asigna a la variable personas
.
Posteriormente se llama la función CasosIniciales
que su intención es distribuir el número de casos iniciales a lo largo de la población. Hemos incluiido
la definición inicial de la función, dejándote como tarea la implementación.
Por último se encuentra un ciclo while
el cual tiene como propósito llevar a cabo un paso de simulación hasta que se tope con el estado estable antes mencionado,
donde ya no haya infectados en la población. En cada una de sus iteraciones el ciclo llama a la función PasoSimulacion
la cual ya hemos definido para tí, pero que
te dejamos la tarea de implementarla.
Podrás observar que el arreglo personas
es un arreglo de valores numéricos. Esto nos será de ayuda para la implementación, ya que generalmente es más sencillo trabajar
con números, en lugar de caracteres o cadenas de caracteres (strings). Por tanto para este proyecto, y en particular para la implementación del arreglo personas
utilizaremos el siguiente mapeo entre el estado de la persona y el número que tendrá asignado su correspondiente elemento:
- El estado susceptible S, tendrá asignado el valor 0.
- El estado infectado I, tendrá asignado el valor 1.
- El estado removido R, tendrá asignado el valor 2.
Por tanto esta tabla:
S | R |
I | I |
R | S |
Y esta otra:
0 | 2 |
1 | 1 |
2 | 0 |
son equivalentes. Siguiendo esta equivalencia es como funciona el ciclo while
que está escrito en el código.
Especificación
Para lograr este proyecto deberás de completar las funciones CasosIniciales
y PasoSimulacion
definidas en SimulacionEpidemiologica.py
de forma que puedan llevar llevar a cabo lo siguiente:
- La función
CasosIniciales
deberá asignar el estado de infectado al número de elementos marcado por la variableiniciales
, que recibe como argumento. La forma de distribuirlos te la dejamos a libertad, pero te recomendamos probar con varias para apreciar la importancia que tienen en el fenómeno. - Completar la función
PasoSimulacion
de forma que cuando se llame sea capaz de actualizar todos los elementos en el arreglopersonas
según el caso en que se encuentre cada elemento y las reglas indicadas por el modelo SIR.
Nota: para la simulación considera únicamente los individuos que se encuentran a distancia uno del elemento a actualizar. Esto quiere decir que únicamente si está inmediatamente después ya sea de forma vertical, horizontal o diagonal podrá afectar al individuo a actualizar. Algo como lo siguiente:
1 | 2 | 0 | 0 |
1 | 0 | 0 | 0 |
2 | 0 | 0 | 0 |
2 | 0 | 0 | 0 |
donde el elemento a actualizar es el de color verde, y aquellos que se toman en cuenta para actualizar su estado son los marcados en gris. Toma en cuenta que, por cada infectado enntre estos individuos se debe de lanzar la moneda cargada para decidir si infectan o no al individuo en verde; de forma que para este caso se debe de lanzar una primera moneda, si con esta no se infecta el individuo, entonces se lleva a cabo la segunda. Si en ninguna de las dos sale infectado, el individuo seguirá como susceptible para el siguiente paso de simulación, de lo contario entrará al estado infectado.
Walkthrough
Resultados esperados
Tu programa deberá de llevar a cabo una simulación del modelo SIR en una población indicada por los parámetros indicados por el usuario: población, número de casos iniciales, valor de los parámetros β y γ. Deberá de imprimir el estado de la población en cada día de simulación, y al llegar al final deberá de reportar el número de días que duró la simulación, así como el número de susceptibles y removidos al final del proceso infeccioso. Deberá de mostrar un comportamiento similar al siguiente:
$ python SimulacionEpidemiologica.py
¿Cuántas personas hay en la simulación?: 4
¿Cuántos contagiados iniciales hay?: 1
¿Cuál es el valor de beta?: 0.3
¿Cuál es el valor de gamma?: 0.5
Día 0 array([[0, 1], [0, 0]]) Día 1 array([[1, 2], [0, 0]]) Día 2 array([[1, 2], [0, 0]]) Día 3 array([[2, 2], [0, 0]]) Final de la simulación en día 3. 2 Suceptibles. 2 Removidos.
Una vez que tu programa sea capaz de simular un modelo SIR para emular un proceso infeccioso, habrás culminado con éxito tu segundo proyecto.
Solución al proyecto
Archivos con la solución al proyecto SimulacionEpidemiologica.
Descargar archivos