-
Notifications
You must be signed in to change notification settings - Fork 0
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.
- What is the SIR Model?
- Mathematical Background
- Parameters Explained
- Basic Reproduction Number (R₀)
- Code Examples
- Visualizing Results
- Advanced Usage
- Common Pitfalls
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 |
Susceptible (S) → Infected (I) → Recovered (R)
↓ ↓ ↓
Healthy Sick/Fatal Immune
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
Total population remains constant:
S(t) + I(t) + R(t) = N = constant
| 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)
| 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)
R₀ is the most important metric in epidemiology:
R₀ = β / γ
| R₀ Value | Meaning |
|---|---|
| R₀ < 1 | Disease will die out naturally |
| R₀ = 1 | Disease becomes endemic (stable) |
| R₀ > 1 | Disease will spread (epidemic) |
| Disease | R₀ |
|---|---|
| Seasonal flu | 1.3 |
| COVID-19 (original) | 2.5 - 3.0 |
| SARS | 3.0 |
| Measles | 12 - 18 |
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())beta = 0.5
gamma = 0.2
R0 = beta / gamma
print(f"R₀ = {R0:.2f}") # Output: R₀ = 2.50peak_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)}")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)}")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()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()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()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()| Population | Issue |
|---|---|
| < 100 | Stochastic effects dominate, results not reliable |
| 100 - 1000 | Acceptable for demonstrations |
| > 1000 | Good for realistic simulations |
| 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) |
# 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)| Concept | Summary |
|---|---|
| SIR | Susceptible → Infected → Recovered |
| R₀ | β/γ - predicts outbreak severity |
| Peak | Maximum infected - healthcare capacity planning |
| Final size | Total infected - epidemic impact |
- SEIR Model Tutorial - Add exposed compartment
- Parameter Optimization - Fit to real data
- CLI Reference - Command line options