SEIA模型

使用Python实现SEIA模型,模拟流行病传播过程。


日期

SEIA模型

1 概述

1.1 模型假设

1.2 模型描述

SEIA 模型是一种扩展的流行病动力学模型,用于模拟具有潜伏期(暴露阶段)和无症状传播特征的传染病传播过程。模型通过引入暴露者(E)和无症状感染者(A)的仓室,更贴近现实中传染病的传播动态。

1.3 模型仓室及参数含义

以下是 SEIA 模型的仓室和参数含义(表1):

表1 SEIA模型的仓室和参数含义

参数 含义
S 易感者人数:未感染但可能被感染的人群
E 暴露者人数:已被感染但尚未具有传染性的人群
I 有症状感染者人数:有症状具有传染性并能传播疾病的人群
A 无症状感染者人数:无症状但具有一定传染性的人群
N 总人口数( N = S + E + I + A ),假设人口总数不变
β 传播率:每个感染者或无症状感染者在单位时间内感染易感者的概率
ω 暴露者转化速率:暴露者 ( E ) 转化为感染者或无症状感染者的速率
p 发病概率:暴露者 ( E ) 转化为感染者 ( I ) 的概率
1-p 无症状概率:暴露者 ( E ) 转化为无症状感染者 ( A ) 的概率
t 时间,用于表示疾病传播过程中的动态变化

2 模型流程图及方程

2.1 模型流程图

以下是SEIA 传播动力学模型框架图:

alt text

2.2 模型方程

SEIA 模型常微分方程组如下:

$$ \begin{cases} \frac{dS}{dt} = -\beta S(I + A)/N \\
\frac{dE}{dt} = \beta S(I + A)/N - \omega E \\
\frac{dI}{dt} = p\omega E \\
\frac{dA}{dt} = (1-p)\omega E \end{cases} $$

3 适用疾病流行条件

SEIA 模型适用于以下疾病流行条件,通过 SEIA 模型,可以分析不同疾病传播条件下的人群动态变化,为公共卫生干预提供理论依据:

  1. 具有潜伏期的疾病

    • SEIA 模型中的暴露者(E)仓室描述了潜伏期的存在,因此适用于模拟具有明确潜伏期的传染病,如 COVID-19、SARS 等。
  2. 无症状或低症状传播的疾病

    • 模型中的无症状感染者(A)仓室可以用来描述无症状感染者对疾病传播的影响。适合模拟无症状传播占较大比例的疾病。
  3. 有限人群且人口恒定

    • 模型假设总人口数 ( N ) 恒定,无出生或死亡,因此适合短期内流行病的传播分析,不适用于长时间内的人口动态变化场景。
  4. 均匀传播假设

    • 假设人群接触是随机且均匀分布的,每个个体的感染机会相同。因此,模型适用于未考虑地理位置、社会网络或行为模式等影响的情境。
  5. 传播速率受外界条件影响

    • 模型可以通过调整传播率 (β) 和其他参数,模拟各种外界干预措施对疾病传播的影响(如社交隔离、口罩佩戴、疫苗接种等)。

4 代码(Python)

4.1 条件设定

4.2 代码

以下是用 Python 编写的 SEIA 模型代码,用于模拟疾病传播过程:

SEIA model

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  # 解决负号显示问题

# SEIA模型微分方程
def seia_ode(t, y, N, beta, omega, p):
    S, E, I, A = y  # 易感者、暴露者、有症状感染者和无症状感染者数量
    dS = -beta * S * (I + A) / N  # 易感者的变化
    dE = beta * S * (I + A) / N - omega * E  # 暴露者的变化
    dI = p * omega * E   # 感染者的变化
    dA = (1 - p) * omega * E  # 无症状感染者的变化
    return [dS, dE, dI, dA]

# 绘制图形
def plot_seia(N, beta, omega, p, I0, A0):
    if N <= 0 or I0 < 0 or A0 < 0 or I0 + A0 > N:
        raise ValueError("参数不合理:N 必须大于 0,I0 和 A0 必须非负,且 I0 + A0 不能超过 N。")
    
    # 计算初始的易感者和暴露者数量
    S0 = N - I0 - A0
    E0 = 0
    y0 = [S0, E0, I0, A0]
    
    # 时间点设置
    t_start = 0         # 模拟开始天数
    t_end = 160         # 模拟结束天数
    num_points = 160    # 时间点数量
    t_eval = np.linspace(t_start, t_end, num_points)
    
    # 求解微分方程
    solution = solve_ivp(
        seia_ode,
        [t_start, t_end],
        y0,
        args=(N, beta, omega, p),
        t_eval=t_eval
    )
    
    # 检查求解是否成功
    if not solution.success:
        raise RuntimeError("微分方程求解失败!")

    # 绘制图形
    plt.figure(figsize=(12, 6))
    plt.plot(solution.t, solution.y[0], label='易感者 S', color='blue')
    plt.plot(solution.t, solution.y[1], label='暴露者 E', color='orange')
    plt.plot(solution.t, solution.y[2], label='感染者 I', color='red')
    plt.plot(solution.t, solution.y[3], label='无症状感染者 A', color='purple')
    plt.xlabel('天数')
    plt.ylabel('人数')
    plt.legend()
    plt.grid(True)

    # 使用 plt.figtext() 将标题放置在图形底部
    plt.figtext(0.5, 0.01, f'图3 SEIA 模型模拟结果 (β={beta}, ω={omega}, p={p}, N={N}, I0={I0}, A0={A0})', ha='center', va='bottom')

    plt.show()

  # 定义模型参数
    N = 21858000  # 总人口数
    beta = 0.45   # 传播率
    omega = 0.2   # 暴露转感染速率
    p = 0.5       # 发病概率
    I0 = 170      # 初始感染者数量
    A0 = 0        # 初始无症状感染者数量

  # 调用函数绘制图形
    plot_seia(N, beta, omega, p, I0, A0)

4.3 结果

alt text

SEIA 模型的模拟结果显示了易感者 (S)、暴露者 (E)、有症状感染者 (I) 和无症状感染者 (A) 随时间的变化趋势。结果分析如下: 1.易感者 (S):在开始时,易感者人数接近总人口数,随着时间的推移,易感者人数迅速下降,这表明疾病开始在人群中传播。 2.暴露者 (E):暴露者人数在初期缓慢增加,达到一个峰值后开始下降。这可能是因为暴露者逐渐转化为有症状或无症状感染者。 3.有症状感染者 (I):有症状感染者在暴露者达到峰值后开始增加,并在一段时间后达到自己的峰值,然后逐渐减少。这表明有症状感染者在一段时间内是疾病传播的主要来源。 4.无症状感染者 (A):无症状感染者在有症状感染者开始减少后逐渐增加,达到峰值后保持稳定。这可能是因为无症状感染者在人群中的传播作用相对较小,但他们仍然可以传播疾病。 5.总人口 (N):总人口数是恒定的,由易感者、暴露者、有症状感染者和无症状感染者之和组成。

5 扩展

在传染病传播过程中,公共卫生干预措施(如社交隔离、佩戴口罩、封锁、早期检测或医疗措施的加强等)会显著影响疾病的传播速度。为了在 SEIA 模型中引入这些干预措施,可以通过调整传播率 (β) 随时间的变化来模拟不同的干预效果,也可以通过调整暴露者(E)转化为有症状感染者( I )和无症状感染者( A )的速率或概率来模拟疾病转化动态的变化。

5.1 传播过程中加入干预措施

假设传播率 ( β ) 随时间以某种函数形式变化,例如指数衰减: $$ \beta(t) = \beta_0 \cdot e^{-\lambda t} $$

其中:

另一种可能的调整是分段常数形式: $$ \beta(t) = \begin{cases} \beta_0 & t \leq t_{\text{干预}} \\
\beta_0 \cdot r & t > t_{\text{干预}} \end{cases} $$

其中:

假设暴露者转化为有症状感染者的概率( p )可能随时间变化。可以将 ( p ) 定义为一个动态函数:

$$ p(t) = \begin{cases} p_0 & t \leq t_{\text{干预}} \\
p_0 \cdot k & t > t_{\text{干预}} \end{cases} $$

其中:

通过调整 ( p(t)),可以模拟医疗干预对暴露者发病转化过程的影响。

5.2 模拟代码

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  # 解决负号显示问题

# 定义时间依赖的传播率 beta(t)
def beta(t, beta_0, t_intervention, reduction_ratio, lambda_):
    if t <= t_intervention:
        return beta_0
    else:
        return beta_0 * reduction_ratio * np.exp(-lambda_ * (t - t_intervention))

# 定义时间依赖的发病概率 p(t)
def p(t, p0, t_intervention, adjustment_ratio):
    if t <= t_intervention:
        return p0
    else:
        return p0 * adjustment_ratio

# SEIA模型微分方程
def seia_ode(t, y, N, beta_0, t_intervention, reduction_ratio, lambda_, omega, p0, adjustment_ratio):
    S, E, I, A = y
    beta_t = beta(t, beta_0, t_intervention, reduction_ratio, lambda_)
    p_t = p(t, p0, t_intervention, adjustment_ratio)
    dS = -beta_t * S * (I + A) / N
    dE = beta_t * S * (I + A) / N - omega * E
    dI = p_t * omega * E
    dA = (1 - p_t) * omega * E
    return [dS, dE, dI, dA]

# 绘制图形
def plot_seia(solution, title="SEIA模型模拟结果"):
    plt.figure(figsize=(12, 6))
    plt.plot(solution.t, solution.y[0], label='易感者 S', color='blue')
    plt.plot(solution.t, solution.y[1], label='暴露者 E', color='orange')
    plt.plot(solution.t, solution.y[2], label='有症状感染者 I', color='red')
    plt.plot(solution.t, solution.y[3], label='无症状感染者 A', color='purple')
    plt.axvline(x=t_intervention, color='green', linestyle='--', label=f'干预措施开始 ({t_intervention}天)')
    plt.xlabel('天数')
    plt.ylabel('人数')
    plt.legend()
    plt.grid(True)
    plt.title(title)
    plt.show()

# 模型参数
N = 21858000  # 总人口数
beta_0 = 0.5   # 初始传播率
omega = 0.3    # 暴露转感染速率
p0 = 0.6       # 初始发病概率
I0 = 1000      # 初始感染者数量
A0 = 500       # 初始无症状感染者数量
t_intervention = 30  # 干预措施开始时间(天)
reduction_ratio = 0.5  # 传播率降低的比例
lambda_ = 0.05  # 传播率下降的速度
adjustment_ratio = 0.8  # 发病概率的调整比例

# 初始条件
S0 = N - I0 - A0
E0 = 0
y0 = [S0, E0, I0, A0]

# 时间点设置
t_start = 0
t_end = 160
num_points = 160
t_eval = np.linspace(t_start, t_end, num_points)

# 求解微分方程
solution = solve_ivp(
    seia_ode,
    [t_start, t_end],
    y0,
    args=(N, beta_0, t_intervention, reduction_ratio, lambda_, omega, p0, adjustment_ratio),
    t_eval=t_eval,
    method='RK45'
)

# 检查求解是否成功
if not solution.success:
    raise RuntimeError("微分方程求解失败!")

# 绘制模拟结果
plot_seia(solution, title=f"SEIA模型模拟结果 (β0={beta_0}, ω={omega}, p0={p0}, N={N}, I0={I0}, A0={A0}, t_intervention={t_intervention}, reduction_ratio={reduction_ratio}, adjustment_ratio={adjustment_ratio})")

5.3 影响分析

SEIA模型的模拟结果,展示了在不同时间点上易感者(S)、暴露者(E)、有症状感染者(I)和无症状感染者(A)的数量变化。

alt text

5.4 总结

通过调整 SEIA 模型中的传播率( β )、发病概率( p )等关键参数随时间的动态变化,可以更贴近实际疾病传播的动态过程。无需新增舱室即可模拟公共卫生干预措施对疫情传播的影响,从而为疫情防控和决策提供科学依据。

曾文雯
快乐小狗