使用Python实现SEIAR模型,模拟流行病传播过程
SEIAR模型通常适用于预测一些急性传染病的流行趋势,这类疾病具有传染性强,传播途径简单直接,存在隐性感染者,潜伏期短,感染后一段时间具有传染性,病程短,考虑治愈的过程,无免疫保护等特点。 S为易感者,E为暴露者,I为显性感染者,A为隐性感染者,R为康复者。S仓室以单位时间betaS(I+κA)的速率向E仓室流入,E仓室以单位时间betaS(I+κA)的速率向E仓室流入
在一起暴发疫情中,不考虑人口流动和空间分布的影响,疾病传播仅考虑人传人,感染率在疾病流行过程中保持不变,康复者获得暂时性免疫,再次感染者与初始易感者具有相同感染风险等假设的前提下,建立SEIARS模型。
SEIARS模型考虑了无症状感染者(A)和免疫力衰退(Rs)的特点,特别适合模拟以下几类疾病:新型冠状病毒(COVID-19);流感病毒(Influenza);诺如病毒(Norovirus);呼吸道合胞病毒(RSV)。
S为易感者,E为暴露者,I为显性感染者, A为隐性感染者,R为恢复者。
参数 | 含义 |
---|---|
( S ) | 易感者人数:未感染但可能被感染的人群 |
( E ) | 暴露者人数:已被感染但尚未具有传染性的人群 |
( I ) | 感染者人数:具有传染性并能传播疾病的人群 |
( A ) | 无症状感染者人数:无症状但具有一定传染性的人群 |
( R ) | 康复者人数:感染者经过病程后康复的人群 |
( N ) | 总人口数( N = S + E + I + A ),假设人口总数不变 |
( $\beta$ ) | 传播率:每个感染者或无症状感染者在单位时间内感染易感者的概率 |
( $\omega$ ) | 暴露者转化速率:暴露者 ( E ) 转化为感染者的速率 |
( $\omega$') | 暴露者转化速率:暴露者 ( E ) 转化为无症状感染者的速率 |
( p ) | 发病概率:暴露者 ( E ) 转化为感染者 ( I ) 的概率 |
( 1-p ) | 无症状概率:暴露者 ( E ) 转化为无症状感染者 ( A ) 的概率 |
( $\kappa$ ) | 隐形感染者相对患者的传染力的倍数 |
( $\gamma$ ) | 显性感染者变为恢复者的速率,病程倒数 |
( $\gamma$') | 隐性感染者变为恢复者的速率 |
( $\epsilon$) | 恢复者失去免疫力的速率 |
$$
\begin{cases}
dS/dt = -\beta * S * (I + \kappa * A) / N + \epsilon * R \\
dE/dt = \beta * S * (I + \kappa * A) / N - ( p*\omega+ (1-p)*\omega') * E \\
dI/dt = (1-p)*\omega * E - \gamma * I \\
dA/dt = p*\omega * E - \gamma' * A\\
dR/dt = \gamma * I + \gamma' * A - \epsilon * R
\end{cases}
$$
疾病同时存在显性感染者和无症状感染者,康复者获得暂时性免疫,但存在免疫力衰退的情况
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
def seiar_model(y, t, N, beta, kappa, p, omega1 , omega2, gamma1, gamma2, epsilon):
"""
SEIAR model with waning immunity
S: Susceptible
E: Exposed
I: Infectious (symptomatic)
A: Asymptomatic
R: Recovered
"""
S, E, I, A, R = y
# Model equations
dSdt = -beta * S * (I + kappa * A) / N + epsilon * R
dEdt = beta * S * (I + kappa * A) / N - ( p*omega1 + (1-p)*omega2) * E
dIdt = (1-p)*omega1 * E - gamma1 * I
dAdt = p*omega2 * E - gamma2 * A
dRdt = gamma1 * I + gamma2 * A - epsilon * R
return [dSdt, dEdt, dIdt, dAdt, dRdt]
# Model parameters
params = {
'beta': 0.001, # transmission rate
'kappa': 0.5, # relative infectivity of asymptomatic cases
'p': 0.15, # proportion of asymptomatic cases
'omega1': 0.50, # rate of becoming symptomatic
'omega2': 0.80, # rate of becoming asymptomatic
'gamma1': 0.20, # recovery rate for symptomatic
'gamma2': 0.25, # recovery rate for asymptomatic
'epsilon': 0.0027 # immunity waning rate
}
# Simulation settings
N = 10000 # total population
I0 = 10 # initial infectious cases
days = 50 # simulation period
# Calculate initial conditions
E0 = I0 * 2 # initial exposed (assume twice the number of infectious)
A0 = I0 * params['p'] / (1 - params['p']) # initial asymptomatic based on p
R0 = 0 # initial recovered
S0 = N - E0 - I0 - A0 - R0 # initial susceptible
# Initial conditions vector
y0 = [S0, E0, I0, A0, R0]
# Time points
t = np.linspace(0, days, days + 1)
# Solve the differential equations
solution = odeint(seiar_model, y0, t, args=(N,
params['beta'],
params['kappa'],
params['p'],
params['omega1'],
params['omega2'],
params['gamma1'],
params['gamma2'],
params['epsilon']))
# Plot results
plt.figure(figsize=(12, 8))
categories = ['Exposed (E)', 'Infectious (I)', 'Asymptomatic (A)', 'Recovered (R)']
colors = ['#FFC107', '#DC3545', '#28A745', '#17A2B8'] # Harmonious color scheme
for i, (cat, col) in enumerate(zip(categories, colors), start=1):
plt.plot(t, solution[:, i],
label=cat,
color=col,
linewidth=2)
plt.xlabel('Time (days)', fontsize=12)
plt.ylabel('Population', fontsize=12)
plt.title('SEIAR Model Simulation', fontsize=14)
plt.legend(bbox_to_anchor=(1.05, 1),
loc='upper left',
borderaxespad=0.,
fontsize=10)
plt.grid(True, linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()
# Print peak values and their timing
for i, cat in enumerate(categories, start=1):
peak_value = max(solution[:, i])
peak_day = t[np.argmax(solution[:, i])]
print(f"\n{cat}:")
print(f"Peak value: {peak_value:.0f}")
print(f"Peak day: {peak_day:.1f}")
# Calculate and print final sizes
print("\nFinal sizes:")
for i, cat in enumerate(categories, start=1):
final_size = solution[-1, i]
percentage = (final_size / N) * 100
print(f"{cat}: {final_size:.0f} ({percentage:.1f}%)")
#### 4.2 结果
Exposed (E):
Peak value: 20
Peak day: 0.0
Infectious (I):
Peak value: 14
Peak day: 2.0
Asymptomatic (A):
Peak value: 3
Peak day: 2.0
Recovered (R):
Peak value: 25
Peak day: 22.0
Final sizes:
Exposed (E): 0 (0.0%)
Infectious (I): 0 (0.0%)
Asymptomatic (A): 0 (0.0%)
Recovered (R): 23 (0.2%)
模拟为,在总人口数为1万的小区或学校中流感疫情的发生发展,初始感染人口为10人。随着感染的进行,到第3天时,新增感染人数达到顶峰,到第30天时新增感染人数趋于0。
例:传播过程中加入干预措施、改变仓室流向…
注:保证上述描述不变情况下可自行扩展说明书。