Skip to content

SIR Model Tutorial

milad edited this page May 10, 2026 · 2 revisions

Complete guide to understanding and using the SIR (Susceptible-Infected-Recovered) epidemic model.


📋 Table of Contents


🧠 What is the SIR Model?

The SIR model is a classic compartmental model in epidemiology that divides a population into three groups:

Compartment Symbol Description
Susceptible S Healthy individuals who can catch the disease
Infected I Sick individuals who can transmit the disease
Recovered R Individuals who recovered and are immune

Flow Diagram

Susceptible (S)  →  Infected (I)  →  Recovered (R)
     ↓                  ↓                  ↓
   Healthy           Sick/Fatal         Immune

📐 Mathematical Background

Differential Equations

The SIR model is described by three differential equations:

dS/dt = -β × S × I / N
dI/dt =  β × S × I / N - γ × I
dR/dt =  γ × I

Where:

  • N = Total population (S + I + R)
  • β (beta) = Infection rate
  • γ (gamma) = Recovery rate

Conservation Law

Total population remains constant:

S(t) + I(t) + R(t) = N = constant

📊 Parameters Explained

Infection Rate (β)

Value Meaning
0.0 - 0.3 Low transmission (e.g., Ebola with strict quarantine)
0.3 - 0.6 Moderate transmission (e.g., seasonal flu)
0.6 - 1.0 High transmission (e.g., COVID-19 without measures)

Example:

  • β = 0.5 means each infected person infects 0.5 susceptible per day (on average)

Recovery Rate (γ)

Value Meaning Average Illness Duration
0.1 Slow recovery 10 days
0.2 Moderate recovery 5 days
0.5 Fast recovery 2 days
1.0 Very fast 1 day

Formula: Recovery rate = 1 / (average illness duration in days)


🔢 Basic Reproduction Number (R₀)

R₀ is the most important metric in epidemiology:

R₀ = β / γ

Interpreting R₀

R₀ Value Meaning
R₀ < 1 Disease will die out naturally
R₀ = 1 Disease becomes endemic (stable)
R₀ > 1 Disease will spread (epidemic)

Real-World Examples

Disease R₀
Seasonal flu 1.3
COVID-19 (original) 2.5 - 3.0
SARS 3.0
Measles 12 - 18

💻 Code Examples

Basic SIR Simulation

from sir_simulator.core_models.sir_model import run_sir_simulation

# Parameters
beta = 0.5    # Infection rate
gamma = 0.2   # Recovery rate
S0 = 990      # Initial susceptible
I0 = 10       # Initial infected
R0 = 0        # Initial recovered
t_max = 100   # 100 days

# Run simulation
df = run_sir_simulation(beta, gamma, S0, I0, R0, t_max)

print(df.tail())

Calculate R₀

beta = 0.5
gamma = 0.2
R0 = beta / gamma
print(f"R₀ = {R0:.2f}")  # Output: R₀ = 2.50

Find Peak Infection

peak_infected = df['Infected'].max()
peak_day = df[df['Infected'] == peak_infected]['time'].values[0]

print(f"Peak infected: {int(peak_infected)} on day {int(peak_day)}")

Calculate Final Epidemic Size

final_susceptible = df['Susceptible'].iloc[-1]
final_recovered = df['Recovered'].iloc[-1]
total_cases = S0 + I0 - final_susceptible

print(f"Total infected during outbreak: {int(total_cases)}")
print(f"Final recovered: {int(final_recovered)}")

📊 Visualizing Results

Basic Plot with Matplotlib

import matplotlib.pyplot as plt

df = run_sir_simulation(0.5, 0.2, 990, 10, 0, 100)

plt.figure(figsize=(10, 6))
plt.plot(df['time'], df['Susceptible'], label='Susceptible', color='blue')
plt.plot(df['time'], df['Infected'], label='Infected', color='red')
plt.plot(df['time'], df['Recovered'], label='Recovered', color='green')
plt.xlabel('Time (days)')
plt.ylabel('Population')
plt.title('SIR Epidemic Model')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

Highlight Peak Infection

import matplotlib.pyplot as plt

df = run_sir_simulation(0.5, 0.2, 990, 10, 0, 100)

peak_idx = df['Infected'].idxmax()
peak_infected = df.loc[peak_idx]

plt.figure(figsize=(10, 6))
plt.plot(df['time'], df['Infected'], label='Infected', color='red')
plt.scatter(peak_infected['time'], peak_infected['Infected'], 
            color='black', s=100, zorder=5, label='Peak Infection')
plt.xlabel('Time (days)')
plt.ylabel('Infected')
plt.title('SIR Model - Peak Infection')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

🎯 Advanced Usage

Compare Different β Values

import matplotlib.pyplot as plt

beta_values = [0.3, 0.5, 0.7, 0.9]
colors = ['blue', 'green', 'orange', 'red']

plt.figure(figsize=(10, 6))

for beta, color in zip(beta_values, colors):
    df = run_sir_simulation(beta, 0.2, 990, 10, 0, 100)
    plt.plot(df['time'], df['Infected'], label=f'β={beta}', color=color)

plt.xlabel('Time (days)')
plt.ylabel('Infected Population')
plt.title('SIR Model - Effect of Infection Rate (β)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

Compare Different γ Values

import matplotlib.pyplot as plt

gamma_values = [0.1, 0.2, 0.3, 0.4]
colors = ['blue', 'green', 'orange', 'red']

plt.figure(figsize=(10, 6))

for gamma, color in zip(gamma_values, colors):
    df = run_sir_simulation(0.5, gamma, 990, 10, 0, 100)
    plt.plot(df['time'], df['Infected'], label=f'γ={gamma}', color=color)

plt.xlabel('Time (days)')
plt.ylabel('Infected Population')
plt.title('SIR Model - Effect of Recovery Rate (γ)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

⚠️ Common Pitfalls

1. Population Too Small

Population Issue
< 100 Stochastic effects dominate, results not reliable
100 - 1000 Acceptable for demonstrations
> 1000 Good for realistic simulations

2. Parameters Not Realistic

Range Validity
β > 1 Too high (can't infect >100% of contacts)
γ > 1 Too high (recovery quicker than 1 day)
R₀ > 20 Unrealistic (no real disease has R₀ > 20)

3. Simulation Time Too Short

# Too short - outbreak not complete
df = run_sir_simulation(0.5, 0.2, 990, 10, 0, t_max=30)

# Proper - wait for outbreak to finish
df = run_sir_simulation(0.5, 0.2, 990, 10, 0, t_max=200)

📚 Key Takeaways

Concept Summary
SIR Susceptible → Infected → Recovered
R₀ β/γ - predicts outbreak severity
Peak Maximum infected - healthcare capacity planning
Final size Total infected - epidemic impact

🔗 Next Steps


⬆ Back to Home

Clone this wiki locally