使用Python实现SIR模型,模拟流行病传播过程
SIR模型是一种常见的传染病动力学模型,用于模拟疾病在一个固定人群中的传播过程。通过研究易感者、感染者和恢复者人数随时间的变化,可以帮助我们理解疫情传播的规律,并为公共卫生政策提供科学依据。
表 1 SIR 模型参数
参数 | 含义 |
---|---|
S | 易感者人数 |
I | 感染者人数 |
R | 恢复者人数 |
N | 总人口数 (N=S+I+RN=S+I+R) |
β | 传播率,每个感染者在单位时间内感染易感者的概率 |
γ | 康复率,每个感染者在单位时间内康复的概率 |
t | 时间 |
I₀ | 初始感染者人数 |
R₀ | 初始恢复者人数 |
S₀ | 初始易感者人数 |
以下是SIR模型的流程图,展示了易感者、感染者和恢复者之间的转化过程:
图 1 SIR模型流程图
SIR模型由以下三组微分方程描述:
$$
\begin{cases}
\frac{dS}{dt} &= - \beta \cdot \frac{S \cdot I}{N}, \\
\frac{dI}{dt} &= \beta \cdot \frac{S \cdot I}{N} - \gamma \cdot I, \\
\frac{dR}{dt} &= \gamma \cdot I.
\end{cases}
$$
SIR模型适用于以下情况的疾病传播模拟:
在此代码中,我们使用以下条件进行 SIR 模型模拟:
# 导入必要的库
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import solve_ivp
# 设置中文字体(可选,适用于中文环境)
plt.rcParams['font.family'] = ['SimHei'] # 例如 'Microsoft YaHei'
plt.rcParams['axes.unicode_minus'] = False # 防止负号显示问题
# SIR模型微分方程
def sir_ode(t, y, N, beta, gamma):
S, I, R = y
dS = -beta * S * I / N
dI = beta * S * I / N - gamma * I
dR = gamma * I
return [dS, dI, dR]
# 参数设定
N = 21858000 # 总人口数
beta = 1.1 # 传播率
gamma = 0.25 # 康复率
I0 = 170 # 初始感染者人数
R0 = 0 # 初始恢复者人数
S0 = N - I0 - R0 # 初始易感者人数
y0 = [S0, I0, R0]
# 时间范围设置
t_start = 0 # 起始时间
t_end = 160 # 模拟天数
num_points = 160 # 时间点数量
t_eval = np.linspace(t_start, t_end, num_points)
# 求解微分方程
solution = solve_ivp(
sir_ode,
[t_start, t_end],
y0,
args=(N, beta, gamma),
t_eval=t_eval
)
# 检查求解是否成功
if solution.success:
S, I, R = solution.y
else:
raise RuntimeError("微分方程求解失败!")
# 绘制结果
plt.figure(figsize=(12, 6))
plt.plot(solution.t, S, label='易感者 S', color='blue')
plt.plot(solution.t, I, label='感染者 I', color='red')
plt.plot(solution.t, R, label='恢复者 R', color='green')
plt.title(f'SIR 模型模拟结果 (β={beta}, γ={gamma}, N={N}, I0={I0}, R0={R0})')
plt.xlabel('天数')
plt.ylabel('人数')
plt.legend()
plt.grid(True)
plt.show()
运行以上代码后,可以观察到以下趋势:
以下是模拟结果的可视化图表展示:
在保持 SIR 模型的三个仓室(S, I, R)不变的情况下,可以通过以下方式模拟干预措施的效果:
通过降低传播率 β 来模拟隔离措施的实施。例如:
通过将一部分易感者 S 直接转化为恢复者 R,来模拟疫苗接种的效果。例如:
$$ S = S - 0.3 \cdot N,\ R = R + 0.3 \cdot N $$
在保持仓室不变的基础上,可以调整参数或模型逻辑来模拟不同传播特性。例如:
传播率 β 可以是动态变化的,而非一个固定值。例如:
$$
\beta(t) = \begin{cases}
1.1 & t < 30 \
0.8 & 30 \leq t < 60 \
0.5 & t \geq 60
\end{cases}
$$
康复率 γ 可以动态变化。例如:
以下是一些可能的扩展场景:
假设一:强制性防控措施
在疫情初期(例如 t = 20 天),通过强制性隔离大幅降低传播率 β,但未改变康复率 γ。
假设二:部分群体免疫
在疫情发展到一定阶段后,部分人群通过感染或接种疫苗获得免疫(等价于将一部分 S 转移到 R),从而降低后续感染人数。
假设三:周期性传播率变化
在一些季节性流行病(如流感)中,传播率 β 可以呈现周期性变化(例如夏季和冬季的传播率不同)。
通过这些扩展,虽然保持了原有的三个仓室结构,但可以更灵活地模拟实际疫情中的不同动态场景。