使用matlab实现SIR简单个体随机模型,模拟流行病传播过程
在SIR简单个体随机模型中,我们有以下假设:
SIR简单个体随机模型的符号定义如下:
个体状态(stage):每个个体的健康状态,通常用整数值表示。数据类型存储为整数数组。其中:
感染持续时间(durationSinceEnteredTheStage):表示每个感染者自进入感染状态以来的时间(天数),用于判断是否康复。数据类型存储为数值数组(n个个体,长度为n)。对于感染者来说,随着时间的推移,durationSinceEnteredTheStage
增加,直到达到设定的康复天数(invGamma
)为止,个体从感染状态转为康复状态。
汇总数据:用来记录每个时间步的群体整体状态。包括:
数据类型均存储为数值数组,长度为模拟的时间步长m。
接触传播是该模型的核心机制。每个易感者个体与感染者的接触是随机的,而每次接触是否会导致感染取决于接触频率 ( c ) 和单次接触感染概率 ( q )。
个体的健康状态随着时间的推移发生转化:
易感到感染:这一过程的转化速率通常由感染者数量( I )和易感者数量( S )共同决定。转化的概率为 $ \lambda = \beta \cdot \frac{I}{N} $,其中 $ \beta $ 是传染率,$ \frac{I}{N} $ 是感染者在总体中的比例。则易感者转为感染者的概率为:
$$P(S \to I) = \beta \cdot \frac{I}{N} \cdot \Delta t$$
感染到康复:感染者转为康复者的速率由康复率 γ 决定。每个时间步长内,感染者有概率 $ \gamma \cdot \Delta t $ 转为康复者( R )。这里的 γ 通常被定义为单位时间内的康复率,即感染者的康复概率。则感染者转为康复者的概率为:
$$P(I \to R) = \gamma \cdot \Delta t$$
输入:个体数 ( N ),每个个体的自然史参数(康复率 γ),接触频率 ( c ),基本再生数 $\ R_0 $
输出:每日新增感染人数,每日现存的处于各自然史状态的个体数
初始化第0天的所有个体的状态(自然史状态x.stage,每个个体进入感染状态后的持续时间x.durationSinceEnteredTheStage);
根据R_0解出个体单次接触感染概率q;
保存当前处于各自然史状态的人数,保存当日新增的病例数;
while 迭代步数未达到最大模拟天数M do
更新所有个体的新感染状态转变(易感到感染);
更新所有个体的新康复状态转变(感染到康复);
保存当前处于各自然史状态的人数,保存当日新增的病例数;
if 当日无新增病例 then
停止迭代并退出循环
end
记录当前时间步的易感者、感染者和康复者数量,计算实时再生数 Rt;
end
绘制易感者、感染者和康复者数量随时间的变化曲线,绘制实时再生数 Rt 变化曲线。
输入:上一时刻所有个体的状态 输出:新感染更新后的所有个体的状态
For each 个体 x do
随机生成个体 x 在 stepSize 这段时间内的密切接触者;
计算个体 x 被感染的概率 Probability = 1 - (1 - q) ^ ((感染者总数 / 总人口数) * (c * Ts));
if 随机数 < Probability 且 stage[i] == 0(易感者) then
更新 x.stage = I;
更新所有感染者的感染持续时间 x.durationSinceEnteredTheStage = x.durationSinceEnteredTheStage + stepSize;
end
end
输入:新感染更新后所有个体的状态 输出:新康复更新后所有个体的状态
For each 个体 x do
if x.stage == 1 且 x.durationSinceEnteredTheStage > invGamma then
x 发展为康复者 R,更新 x.stage = R;
end
end
模拟结果展示了易感者、感染者和康复者在每个时间步长的数量变化,和有效再生数随时间变化的曲线。
随着感染者( I )数量的增加,易感者( S )数量逐渐减少;感染者( I )数量随着疾病的传播逐渐增加,在第24天达到峰值7000后逐渐下降,最终趋于零;康复者( R )的数量逐渐增加,表明感染者( I )逐渐康复并退出传播链。
模拟结果中,基本再生数 ( $R_0 = 3.5$ ),说明每个感染者在完全易感人群中平均能够将疾病传播给3.5个其他个体。随着感染者的增加,易感者逐渐减少,( $R_t$ )逐渐下降至1以下并趋于0,表明疫情正在渐渐平息。
模拟用时3.058秒
m = 60; % days for simulation
n = 1e4; % person
Ts = 1; % day
c = 10; % person per day
q = 0.05; % R0=(c*q)/Gamma
invGamma = 7; % days
% 初始化状态
stage = zeros(n,1); % 0 - susceptible; 1 - infectious; 2 - removed
durationSinceEnteredTheStage = zeros(n,1); % time duration since entered the stage of infectious
stage(1) = 1; % [0, 1, 2] represent [S, I, R] respectively
% 用于记录每个时间步的S, I, R数量以及Reff
S_record = zeros(m,1);
I_record = zeros(m,1);
R_record = zeros(m,1);
Rt_record = zeros(m,1);
% 模拟更新
for i = 1:m
% 传染更新
Probability = 1 - (1-q)^((sum(stage) / n) * (c*Ts));
stage(rand(n,1) < Probability & stage == 0) = 1;
% 状态转变更新
durationSinceEnteredTheStage(stage == 1) = durationSinceEnteredTheStage(stage == 1) + Ts;
stage(stage == 1 & durationSinceEnteredTheStage > invGamma) = 2;
% 记录S, I, R的数量
S_record(i) = sum(stage == 0); % 易感者
I_record(i) = sum(stage == 1); % 感染者
R_record(i) = sum(stage == 2); % 康复者
% 计算实时 Rt
S = S_record(i); % 当前易感者数量
N = n; % 总人口数量
R0 = (c*q)/(1/invGamma); % 计算 R0
Rt_record(i) = R0 * (S / N); % 计算实时 Rt
end
% 绘制S, I, R数量的变化
figure;
hold on;
plot(1:m, S_record, 'g', 'LineWidth', 2); % 绘制易感者曲线,绿色
plot(1:m, I_record, 'r', 'LineWidth', 2); % 绘制感染者曲线,红色
plot(1:m, R_record, 'b', 'LineWidth', 2); % 绘制康复者曲线,蓝色
% 添加标题和标签
title('SIR简单个体随机模型');
xlabel('时间 (天)');
ylabel('人数');
legend('易感者 (S)', '感染者 (I)', '康复者 (R)');
grid on;
% 绘制Rt的变化
figure;
plot(1:m, Rt_record, 'k', 'LineWidth', 2); % 绘制Rt曲线
xlabel('时间 (天)');
ylabel('Rt');
title('实时再生数Rt');
grid on;