GiulioRossetti / ndlib

Network Diffusion Library - (for NetworkX and iGraph)
http://ndlib.readthedocs.io/
BSD 2-Clause "Simplified" License
272 stars 80 forks source link

Zombie Epidemiology #210

Closed BradKML closed 2 years ago

BradKML commented 2 years ago

Is your feature request related to a problem? Please describe. It is a possible Halloween special? Unfortunately, this would have to be adapted to be usable in a network setting. I would like to contribute, and guidance is heavily appreciated.

Describe the solution you'd like There is the SZR model, the SIZR model, the Quarantine model, and the Treatment model.

Describe alternatives you've considered https://ndlib.readthedocs.io/en/latest/custom/custom.html#examples

Additional context https://math.uchicago.edu/~shmuel/Modeling/WHEN%20ZOMBIES%20ATTACK!-%20MATHEMATICAL%20MODELLING%20OF%20AN%20OUTBREAK%20OF%20ZOMBIE%20INFECTION.pdf

GiulioRossetti commented 2 years ago

Hi, @BrandonKMLee I think this could be a really nice Halloween special! In principle, you could start from a SIR by adding a transition R->I (where I in our case will become Z): in this way you only need an additional parameter (the "coming back from the dead rate"). The other models should be not too difficult to obtain from that point on. I will surely use the Custom model strategy to implement all of them.

Regarding the adaptation to networked environments: that comes for free! The original formulation (as always) assumes a homogeneous mixing (i.e., a mean-field or complete network), changing the network will automatically filter out missing edges and introduce heterogeneity.

Let me know if you need help!

GiulioRossetti commented 2 years ago

Just a quick implementation of SZR (notice that the "Zombie" compartment is still called "Infected" for library design reasons).

import networkx as nx
import ndlib.models.ModelConfig as mc
import ndlib.models.CompositeModel as gc
import ndlib.models.compartments as cpm
from ndlib.viz.mpl.DiffusionTrend import DiffusionTrend
import matplotlib.pyplot as plt

%matplotlib inline # comment if ran outside a jupyter notebook

# Network generation
g = nx.erdos_renyi_graph(1000, 0.1)

# Composite Model instantiation
model = gc.CompositeModel(g)

# Model statuses
model.add_status("Susceptible")
model.add_status("Infected")
model.add_status("Removed")

# Compartment definition
c1 = cpm.NodeStochastic(0.02, triggering_status="Infected") # Susceptible - Zombie
c2 = cpm.NodeStochastic(0.01) # Susceptible - Removed
c3 = cpm.NodeStochastic(0.015) # Zombie - Removed
c4 = cpm.NodeStochastic(0.01) # Removed - Zombie

# Rule definition
model.add_rule("Susceptible", "Infected", c1)
model.add_rule("Susceptible", "Removed", c2)
model.add_rule("Infected", "Removed", c3)
model.add_rule("Removed", "Infected", c4)

# Model initial status configuration
config = mc.Configuration()
config.add_model_parameter('fraction_infected', 0.1)

# Simulation execution
model.set_initial_status(config)
iterations = model.iteration_bunch(100)
trends = model.build_trends(iterations)

viz = DiffusionTrend(model, trends)
viz.plot()
BradKML commented 2 years ago

FIrst, the SIZR and SIZR-Cure Model

import networkx as nx
import ndlib.models.ModelConfig as mc
import ndlib.models.CompositeModel as gc
import ndlib.models.compartments as cpm
from ndlib.viz.mpl.DiffusionTrend import DiffusionTrend
import matplotlib.pyplot as plt

%matplotlib inline # comment if ran outside a jupyter notebook

# Network generation
g = nx.erdos_renyi_graph(1000, 0.1)

# Composite Model instantiation
model = gc.CompositeModel(g)

# Model statuses
model.add_status("Susceptible")
model.add_status("Infected")
model.add_status("Zombie")
model.add_status("Removed")

# Compartment definition
c_alpha = cpm.NodeStochastic(0.005, , triggering_status="Susceptible")
c_beta = cpm.NodeStochastic(0.0095, triggering_status="Zombie")
c_gamma = cpm.NodeStochastic(0.0001)
c_delta = cpm.NodeStochastic(0.0001)
c_rho = cpm.NodeStochastic(0.005)
c_cure = cpm.NodeStochastic(0.01) # remove if not the cure model

# Rule definition
model.add_rule("Susceptible", "Infected", c_beta)
model.add_rule("Infected", "Zombie", c_rho)
model.add_rule("Zombie", "Removed", c_alpha)
model.add_rule("Removed", "Zombie", c_gamma)
model.add_rule("Susceptible", "Removed", c_delta)
model.add_rule("Infected", "Removed", c_delta)
model.add_rule("Zombie", "Susceptible", c_cure) # remove if not the cure model

# Model initial status configuration
config = mc.Configuration()
config.add_model_parameter('fraction_Zombie', 0.1)

# Simulation execution
model.set_initial_status(config)
iterations = model.iteration_bunch(100)
trends = model.build_trends(iterations)

viz = DiffusionTrend(model, trends)
viz.plot()
BradKML commented 2 years ago

And the SIZRQ model

import networkx as nx
import ndlib.models.ModelConfig as mc
import ndlib.models.CompositeModel as gc
import ndlib.models.compartments as cpm
from ndlib.viz.mpl.DiffusionTrend import DiffusionTrend
import matplotlib.pyplot as plt

%matplotlib inline # comment if ran outside a jupyter notebook

# Network generation
g = nx.erdos_renyi_graph(1000, 0.1)

# Composite Model instantiation
model = gc.CompositeModel(g)

# Model statuses
model.add_status("Susceptible")
model.add_status("Infected")
model.add_status("Zombie")
model.add_status("Removed")
model.add_status("Quarantined")

# Compartment definition
c_alpha = cpm.NodeStochastic(0.005, , triggering_status="Susceptible")
c_beta = cpm.NodeStochastic(0.0095, triggering_status="Zombie")
c_sigma = cpm.NodeStochastic(0.0001)
c_delta = cpm.NodeStochastic(0.0001)
c_rho = cpm.NodeStochastic(0.005)

c_kappa = cpm.NodeStochastic(0.005)
c_sigma = cpm.NodeStochastic(0.005)
c_gamma = cpm.NodeStochastic(0.005)

# Rule definition
model.add_rule("Susceptible", "Infected", c_beta)
model.add_rule("Infected", "Zombie", c_rho)
model.add_rule("Zombie", "Removed", c_alpha)
model.add_rule("Removed", "Zombie", c_sigma)
model.add_rule("Susceptible", "Removed", c_delta)
model.add_rule("Infected", "Removed", c_delta)

model.add_rule("Infected", "Quarantined", c_kappa)
model.add_rule("Zombie", "Quarantined", c_rho)
model.add_rule("Quarantined", "Removed", c_gamma)

# Model initial status configuration
config = mc.Configuration()
config.add_model_parameter('fraction_Zombie', 0.1)

# Simulation execution
model.set_initial_status(config)
iterations = model.iteration_bunch(100)
trends = model.build_trends(iterations)

viz = DiffusionTrend(model, trends)
viz.plot()
GiulioRossetti commented 2 years ago

That's great! I'll make a dedicated page on the documentation website!

Edit 29/10/21

All models have now a dedicated page on the docs: https://ndlib.readthedocs.io/en/latest/custom/compartments/Halloween2021.html

Here's the Twitter link to promote the 2021 Halloween Special: https://twitter.com/GiulioRossetti/status/1454014370715996164

BradKML commented 2 years ago

BTW thanks for the lecture notes in https://github.com/sna-unipi/SNA_lectures_notebooks/blob/main/Chapter%2013%20-%20Epidemics.ipynb and https://github.com/sna-unipi/SNA_lectures_notebooks/blob/main/Chapter%2014%20-%20Opinion%20Dynamics.ipynb