Simular con autómatas celulares la propagación de una enfermedad

Vamos a ver un ejemplo de uso de los autómatas celulares para que veamos lo fácil que es realizar algunas simulaciones simples con ellos. En este caso vamos a modelar la evolución de una enfermedad en una población. Hay modelos matemáticos muy elaborados sobre enfermedades y que desde luego son más realistas que el que vamos a construir (aunque realmente se puede elaborar tanto como quieras).  La ventaja de los autómatas celulares es que son mucho más visuales lo que permite entender el desarrollo del sistema de forma más intuitiva, además sus mecanismos son más fáciles de entender y modificar que un sistema de ecuaciones diferenciales.

Para modelar nuestro autómata celular vamos a usar terra.js

Cada celda va a simular ser un individuo diferente en contacto con otros individuos (sus celdas vecinas). Un individuo puede estar sano, infectado, recuperado o inmune. Cada estado se corresponde con:

  • Sano: el individuo no ha sido infectado, pero puede contagiarse si cualquiera de sus vecinos está enfermo
  • Enferma: el individuo esta enfermo, durante unos turnos seguirá en ese estado y será contagioso. Pasados esos turnos pasará a estar recuperado
  • Recuperado: tras recuperarse el individuo ni es contagioso ni puede volverse a contagiar
  • Inmune: el individuo es inmune a la infección, no puede estar enfermo (podemos considerarla como vacunada)

Cuando un individuo sano tiene como vecino a uno infectado tiene una probabilidad Pc de contagiarse. Esta probabilidad aumenta con el número de vecinos. La probabilidad de infectarse es 1-(1-Pc)^n siendo n el numero de vecinos infectados. ¿De donde sale esa formula?. Vamos despacito, si tenemos solo un vecino la probabilidad de infectarse es: Pc. Pero si tenemos dos vecinos la probabilidad de infectarse es: la probabilidad de infectarse del vecino A, la probabilidad de infectarse del vecino B y la posibilidad e infectarse de ambos. Resulta más sencillo calcular lo contrario,  la probabilidad de no-contagiarse de ninguno,  que para un vecino es Pnc = 1-Pc. La probabilidad de no infectarse de 2 vecinos es Pnc = (1-Pc)(1-Pc). De tres: Pnc = (1-Pc)(1-Pc)*(1-Pc). De n: Pnc = (1-Pc)^n. Como lo que queremos saber es la probabilidad de infectarse y lo que hemos calculado es la de no infectarse, la de infectarse debe de ser: 1- Pnc => 1-(1-Pc)^n 


var surrounding = neighbors.filter(function (cell) {

  return cell.creature.isIll;

}).length; 

if (Math.random() < 1-Math.pow(1-pc, surrounding)){

  this.isIll = true;

  this.timesIll = illDuration;

}

Si un individuo ya esta enfermo le restamos tiempo de enfermedad cada turno hasta que llegue a 0 que es cuando deja de estar enfermo


this.timesIll--;

if(this.timesIll == 0){

  this.isIll = false;

  this.wasIll = true;

}

Al principio de la simulación los individuos se generan aleatoriamente según las probabilidades indicadas para cada tipo de celda:


var rnd = Math.random();

this.isIll = rnd < startIll;

if(this.isIll){

  this.timesIll = illDuration;

} else {

  this.isInmune = rnd < startIll+startInmune;

}

this.wasIll = false;

}

Ajustando los diversos parámetros se pueden ver distintos comportamientos del sistema.


var pc = 0.2; //probabilida de contagio

var startIll = 0.01; //prob. de estar enfermo al empezar

var startInmune = 0.2; //prob. de ser inmune al empezar

var illDuration = 5; //duración de la enfermedad

El código completo puede verse aquí y una demostración aquí

automata