Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
restrepo
GitHub Repository: restrepo/ComputationalMethods
Path: blob/master/material/medium_modelling_part_one.ipynb
934 views
Kernel: Python 3 (ipykernel)

Open In Colab

from scipy.integrate import odeint import numpy as np import matplotlib.pyplot as plt %matplotlib inline #!pip install mpld3 import mpld3 mpld3.enable_notebook()

compartmental model.

A compartmental model separates the population into several compartments, for example:

  • Susceptible (can still be infected, “healthy”)

  • Infected

  • Recovered (were already infected, cannot get infected again)

We require the following parameters

  • NN: total population

  • S(t)S(t): number of people susceptible on day t

  • I(t)I(t): number of people infected on day t

  • R(t)R(t): number of people recovered on day t

  • β\beta: expected amount of people an infected person infects per day

  • DD: number of days an infected person has and can spread the disease

  • γ=1/D\gamma=1/D: the proportion of infected recovering per day ( = 1/D)

the basic reproduction number R0R_0, is the total number of people an infected person infects. We just used an intuitive formula: R0=βD.R_0 = \beta \cdot D\,.

Check R0R_0 for Colombia: https://github.com/restrepo/COVID-19/blob/master/covid.ipynb

See Understanding the models that are used to model Coronavirus: Explaining the background and deriving the formulas of the SIR model from scratch. Coding and visualizing the model in Python.

dSdt=βISNdIdt=βISNγIdRdt=γI\begin{align} \frac{d S}{d t}=&-\beta \cdot I \cdot \frac{S}{N} \\ \frac{d I}{d t}=&\beta \cdot I \cdot \frac{S}{N}-\gamma \cdot I \\ \frac{d R}{d t}=&\gamma \cdot I \end{align}

So that (RR include recover or died people) N=S(t)+I(t)+R(t)N=S(t)+I(t)+R(t)

If SIS\gg I and SRS\gg R, then S/N1S/N\approx 1 and only the second equation is relevant and reduce to the exponential growth dI/dt=βIdI/dt=\beta I.

def deriv(U, t, N=1000, β=1, γ=1/4): S, I, R = U dSdt = -β * S * I / N dIdt = β * S * I / N - γ * I dRdt = γ * I return [dSdt, dIdt, dRdt]

We want start with an infected, I0=I(0)=1I_0=I(0)=1 and a R0=R(0)=1.2R_0=R(0)=1.2. Then, by using D=4D=4 β=R0/D=0.3.\beta=R_0/D=0.3\,.

N = 1000 β = 0.3 # infected person infects 0.275 other person per day, such that R_0=1.2 D = 4.0 # infections lasts four days γ = 1.0 / D S0, I0, R0 = 999, 1, 0 # initial conditions: one infected, rest susceptible
t = np.linspace(0, 199, 200) # Grid of time points (in days) U0 = [S0, I0, R0] # Initial conditions vector # Integrate the SIR equations over the time grid, t. ret = odeint(deriv, U0, t, args=(N, β, γ)) S, I, R = ret.T
def plotsir(t, S, I, R,yscale='linear'): f, ax = plt.subplots(1,1,figsize=(10,4)) ax.plot(t, S, 'b', alpha=0.7, linewidth=2, label='Susceptible') ax.plot(t, I, 'y', alpha=0.7, linewidth=2, label='Infected') ax.plot(t, R, 'g', alpha=0.7, linewidth=2, label='Recovered') plt.yscale(yscale) #plt.grid() ax.set_xlabel('Time (days)') ax.yaxis.set_tick_params(length=0) ax.xaxis.set_tick_params(length=0) #ax.grid(b=True, which='major', c='w', lw=2, ls='-') legend = ax.legend() legend.get_frame().set_alpha(0.5) for spine in ('top', 'right', 'bottom', 'left'): ax.spines[spine].set_visible(False) plt.show();
plotsir(t, S, I, R,yscale='log')

Scaling:

Nreal=50E6 sc=Nreal/N sc
50000.0
print(f'N0={int(I0*sc)}') print(f'Nmax={int(I.max()*sc)}')
N0=50000 Nmax=778250
I.max()
26.67215538853332
5E4,5*5E4
(50000.0, 250000.0)