传染病SIR模型及蒙特卡洛方法

一、符号说明

以SIR模型为例,这里对SIR重新定义:

  • S:Susceptible 易感人群(数量),与感染者密切接触易受到其感染。
  • I:Infective 感染人群(数量),已患上传染病并有可能传染给易感人群。由于在我国内,感染者一旦出现症状便被隔离,几乎丧失传染的可能性,故被隔离患者归入移除人员,即不再参与传染过程的人员。
  • R:Removed 移除人群(数量),患病后被治愈或死亡人群数量,这部分人不再参与感染和被感染过程。由于国家的隔离政策,被隔离人群也被计算在失去传染能力的移除人群内。
  • N: 人口总数,包括易感人群,感染人群及移除人群。
  • r: 每个患者每天内接触在易感者人数。
  • β: 易感者与感染者接触时的传染率。
  • γ: 感染人群失去传播能力的速率,其中因隔离而丧失传播能力的部分占比应远远大于自行恢复及死亡的部分。

注:(rβ)可以反映出每一个患者的传染能力。反映了疾病的传染强度,其值越大说明感染人群与易感染人群接触时传染的可能性越大。r可以通过统计方法进行计算,而为了追求实际意义,我们后文主要将(rβ)看作一个整体。
.
.


二、基本公式

转换关系的简单示意图如下:
在这里插入图片描述
.
易通过上述转换关系推出经典SIR模型的常微分方程组表达式:
在这里插入图片描述
若取时间t的间隔单位为天,新冠病毒在潜伏期即未隔离时具备着传播能力,而在潜伏期过后因病症爆发而被隔离失去传播能力,又因为新冠病毒的潜伏期约为14天,则不妨取γ=1/14,在已知 γ 数值的情况下我们能较为简单的由其推出其他数据,即(rβ)的数值。

我们为了简化方程,假设人口基数足够大,即在某一较短时间S/N的改变几乎可以忽略不计,举疫情传播早期为例,在疫情刚开始I/N≈0,在短期内S/N≈(N-I)/N≈1,则式(2)可简化为:
在这里插入图片描述
变量分离得:
在这里插入图片描述
易解得:
在这里插入图片描述
.


三、基本数据处理

数据来源:839Studio. Novel-Coronavirus-Updates [DB/OL].GitHub,10:30 May. 8 GMT+8
我们通过将数据处理得到武汉市1月18日至2月1日各类数据,选择这期间的数据的原因是,1月18日接近疫情初期,而2月1日为武汉封城日期。
在这里插入图片描述
数据处理代码:

function Data_Pre_Treatment
warning off
Data=readtable('Updates_NC.csv');
WuhanData=zeros(1,size(Data,2));
WuhanData(1,:)=[];
WuhanTimeData={
    
    };
for i=1:size(Data,1)
    if strcmp('武汉市',Data.x___1{
    
    i})
        WuhanData=[WuhanData;table2array(Data(i,4:6))];
        WuhanTimeData=[WuhanTimeData;table2array(Data(i,1))];
    end
end
TimeMat=zeros(length(WuhanTimeData),2);
for i=1:length(WuhanTimeData)
    DataString=WuhanTimeData{
    
    i};
    YuePoint=regexpi(DataString,'月');
    RiPoint=regexpi(DataString,'日');
    TimeMat(i,:)=[str2double(DataString(1:YuePoint-1)),...
                  str2double(DataString(YuePoint+1:RiPoint-1))];
end
WuhanData=[TimeMat,WuhanData];
indexbegin=find(WuhanData(:,1)==1&WuhanData(:,2)==11);
indexend=find(WuhanData(:,1)==2&WuhanData(:,2)==1);
WuhanData(indexend(end)+1:end,:)=[];
WuhanData(1:indexbegin(1)-1,:)=[];
    function outcome=Data_Merge(foundation,data)
        temp_foundation=unique(foundation,'rows');
        [m,n]=size(temp_foundation);
        outcome=[temp_foundation,zeros(m,size(data,2)-n)];
        for j=1:m
            coe=all(temp_foundation(j,:)==data(:,1:2),2);
            outcome(j,n+1:end)=sum(data(coe,n+1:end),1);
        end
    end
WuhanData=Data_Merge(WuhanData(:,1:2),WuhanData);
[m,n]=size(WuhanData);
for i=m:-1:1
    WuhanData(i,3:5)=sum(WuhanData(1:i,3:5),1);
end
WuhanData(1:4,:)=[];
save WuhanData.mat WuhanData
end

.


四、rβ参数估计及模型简化

利用MATLAB非线性拟合模块确定参数rβ粗略值,编写MATLAB程序如下:

load WuhanData.mat %导入118日至21日武汉各类人群数据
%数据格式:
%======================================
%月份 日期  累计确诊  累计出院 累计死亡
% 1    18      45        15        2
% 1    19      62        19        2
[m,n]=size(WuhanData);
WuhanData(:,3)=WuhanData(:,3)-WuhanData(:,4)-WuhanData(:,5);
%I=e^((-1/14)t)
ft=fittype('n*exp((lmd-1/14).*t)','coefficients',{
    
    'lmd','n'},...
           'independent','t','dependent','I');
cf=fit((1:m)',WuhanData(:,3),ft,'StartPoint',[0 41]);
plot(cf,(1:m)',WuhanData(:,3))
disp(cf)

解得:
General model:
cf(t) = n*exp((lmd-1/14).*t)
Coefficients (with 95% confidence bounds):
lmd = 0.3123 (0.273, 0.3516)
n = 104.5 (52.87, 156.1)
在这里插入图片描述
可以看出(rβ)在疫情爆发初期时,其值约为0.273~0.3516,对于基本传染系数 R 0 R_0 R0可以采取以下式子来估计:
在这里插入图片描述
基本传染系数是指在没有外力介入下,所有人都没有对于疾病的免疫力的情况下,一个人会将疾病传染给其他多少人,若 R 0 R_0 R0<1,传染病会逐渐的消失,而当 R 0 R_0 R0>1时传染并将以指数形式散布,2003年新加坡严重急性呼吸道综合症的 R 0 R_0 R0约为2-3,天花的 R 0 R_0 R0约为5-7,可以看出我们对本次新冠疫情的 R 0 R_0 R0估计值是较高的,明显 R 0 R_0 R0>1且在武汉爆发初期确实是近指数增长,但这并不说明疾病无法被控制,我们还有很多有效地手段可以实施,例如:

  1. 通过自我隔离减少接触易感者人数,即通过降低r来降低 R 0 R_0 R0
  2. 通过改良检测手段及治疗手段,能够对患者进行快速的隔离、治疗,通过增大γ来降低 R 0 R_0 R0
  3. 在公共场合戴口罩,避免肢体接触,勤洗手减少易感者接触感染者时感染率,即通过降低β来降低 R 0 R_0 R0

我们将使用MATLAB进行数值模拟,来向大家展示各个参数对病毒传播的影响。
为了简化模型,忽略地区人数对实验结果造成的影响,仅对模型的本质进行模拟,并将各类人群以比例的方式表示,即将原本以个人为单位的离散化模型变得连续化,我们可假设我们所探究区域的人口总数在短期内基本保持不变,即:

在这里插入图片描述
并令s(t),i(t),r(t)代表各类人群在总数中的占比,即可简化模型:
在这里插入图片描述
即: 在这里插入图片描述
.
.


五、SIR模型MATLAB实现及分析

编写SIR模型代码如下:

[t,sir]=ode15s('SIR',[0 250],[1-1e-6;1e-6;0]);
hold on
plot(t,sir(:,1),'linewidth',1.5)
plot(t,sir(:,2),'linewidth',1.5)
plot(t,sir(:,3),'linewidth',1.5)
[~,peakTpos]=max(sir(:,2));
scatter(t(peakTpos),sir(peakTpos,2),20,'k','filled')
legend('S:易感者比例','I :感染者比例','R:移除者比例','感染者峰值坐标')
title('SIR模型:S(0)=1-10^{-6}   I(0)=10^{-6}   r\beta=0.3123   \gamma=1/14')
xlabel('t:时间(天)')
ylabel('各类人群所占比例')

function newrate=SIR(t,rate)
%rate:
%==================
%[s(t)  i(t)  r(t)]
rb=0.3123;
g=1/14;
newrate=[-rb*rate(1)*rate(2);...
          rb*rate(1)*rate(2)-g*rate(2);...
                             g*rate(2)];
end

若取初始感染者占比为 1 0 − 6 10^{-6} 106,即假设该市有1000万人口,在疫情初始阶段约有10人患病,求解常微分方程数值解结果如下:
在这里插入图片描述
从图中可以看出疫情感染者比例将在经过约62天时到达峰值,且占比约为43.32%,到达峰值后感染者数目逐渐减少且有约1.34% 的人群在疫情过程中未被感染过。超过98%的人群会在此次疫情中被感染,这是一个恐怖的数字,也说明了如不对疫情进行控制,其初始(rβ)
高至可以几乎感染全部人。

我们假设(rβ)中r=5,即每人每天平均接触五个人,我们如果进行自我隔离,将r分别降至2或1,得到结果如下:
在这里插入图片描述
在这里插入图片描述
观察到,当每天接触人数为2时,疫情的爆发大幅度的延后,约238天时到达高峰,且爆发的剧烈程度也有所降低,从高峰期43.32%感染降至约10.83%感染,且在疫情过程中,有约
28.77%的人未曾感染过病毒,足以体现自我隔离的有效性。且如图所示,当每天接触人数降至1时,疫情几乎无法爆发。

假设我们加强了检测力度、拥有了更加先进的对该病毒的检测方法、或对该病毒的医疗有了突破性进展,我们将γ提高至1/7,则的得到如下结果:
在这里插入图片描述
可以看出,增大γ对疫情的爆发时间影响并不大,但却显著的降低了疫情爆发时感染者的比例,同时在疫情结束后有约15.89%的人未被感染,相较于改变γ前1.34%的比例也有了显著的提升。
.
.


六、蒙特卡洛方法的实现及分析

通过各种手段降低β的情形与降低r类似,由于该连续模型下,(rβ)被当作一个整体看待,很难将其分别进行分析,故我们在此引入蒙特卡洛方法:
在一定区域内,将每个人看作独立的个体,用圆点来表示,每隔单位时间每个个体都会向一定方向位移一段距离并且当易感者和感染而未被隔离者相距较近时,易感者可能会向感染而未被隔离者转换,我们使用灰色圆点表示易感者,粉色圆点表示感染而未被隔离者,红色圆点表示移除或被隔离者,红色圆点已不具备传染能力。编写蒙特卡洛方法代码如下:

function MonteCarlo
figure('units','pixels',...
    'position',[350 100 800 500],...
    'Numbertitle','off',...
    'MenuBar','none',...
    'resize','off',...
    'name','MonteCarlo',...
    'color',[0.95 0.95 0.95]);
axes('position',[0 0 1 1]);
axis([0 800 0 500]);
set(gca,'color',[0 0 0.0078]);
set(gca,'xtick',[],'ytick',[],'xcolor','w','ycolor','w')
%==========================================================================
Limit=[0 800 0 500];
beta=0.3;
gama=0.01;
InfectDis=1;
Dis=2;
Num.N=500;
Num.S=Num.N-5;
Num.I=5;
Num.R=0;
Pos.N=rand(Num.N,2).*[Limit(2),Limit(4)];
Pos.S=Pos.N(1:Num.S,:);
Pos.I=Pos.N(Num.S+1:Num.S+Num.R,:);
Pos.R=Pos.N(Num.S+Num.R+1:end,:);

Ncollection=Num.N;
Scollection=Num.S;
Icollection=Num.I;
Rcollection=Num.R;
%==========================================================================
hold on;
DrawSHdl=scatter(Pos.S(:,1),Pos.S(:,2),50,'filled','CData',[0.3,0.3,0.3]);
DrawIHdl=scatter(Pos.I(:,1),Pos.I(:,2),50,'filled','CData',[1,0.5,0.5]);
DrawRHdl=scatter(Pos.R(:,1),Pos.R(:,2),50,'filled','CData',[1,0.1,0.1]);
TxtNHdl=text(10,480,['人口总数:',num2str(Num.N)],'color',[1 1 1],'fontsize',12,'FontWeight','bold');
TxtIHdl=text(10,480-25,['携带者:',num2str(Num.I)],'color',[1 1 1],'fontsize',12,'FontWeight','bold');
TxtRHdl=text(10,480-50,['隔离或具抗性者:',num2str(Num.R)],'color',[1 1 1],'fontsize',12,'FontWeight','bold');
fps = 200;
game = timer('ExecutionMode', 'FixedRate', 'Period',1/fps, 'TimerFcn', @Spread);
set(gcf,'tag','co','CloseRequestFcn',@clo);
start(game)
function clo(~,~)
    stop(game)
    save SIR.mat Ncollection Scollection Icollection Rcollection
    delete(findobj('tag','co'));
    clf
    close
end
    function Spread(~,~)
        Theta=rand(Num.N,1).*2.*pi.*Dis;
        MovDir=[cos(Theta),sin(Theta)];
        Pos.N=Pos.N+MovDir;
        Pos.S=Pos.N(1:Num.S,:);
        Pos.I=Pos.N(Num.S+1:Num.S+Num.I,:);
        Pos.R=Pos.N(Num.S+Num.I+1:end,:);

        DisMat=GetDis(Pos.S,Pos.I);
        S2I=any(DisMat<=InfectDis,2)&rand(Num.S,1)<beta;
        Pos.I=[Pos.I;Pos.S(S2I,:)];
        Pos.S(S2I,:)=[];
        Num.S=size(Pos.S,1);
        Num.I=size(Pos.I,1);

        I2R=rand(Num.I,1)<gama;
        Pos.R=[Pos.R;Pos.I(I2R,:)];
        Pos.I(I2R,:)=[];
        Num.I=size(Pos.I,1);
        Num.R=size(Pos.R,1);

        Pos.N=[Pos.S;Pos.I;Pos.R];

        set(TxtIHdl,'string',['携带者:',num2str(Num.I)]);
        set(TxtRHdl,'string',['隔离或具抗性者:',num2str(Num.R)]);
        set(DrawSHdl,'XData',Pos.S(:,1),'YData',Pos.S(:,2));
        set(DrawIHdl,'XData',Pos.I(:,1),'YData',Pos.I(:,2));
        set(DrawRHdl,'XData',Pos.R(:,1),'YData',Pos.R(:,2));
        Scollection=[Scollection;Num.S];
        Icollection=[Icollection;Num.I];
        Rcollection=[Rcollection;Num.R];
    end
    function dismat=GetDis(pointseta,pointsetb)
        m=size(pointseta,1);
        n=size(pointsetb,1);
        dismat=zeros(m,n);
        for i=1:m
            for j=1:n
                dismat(i,j)=norm(pointseta(i,:)-pointsetb(j,:));
            end
        end
    end
end

由于我们不知道一个人每天进行位移的次数,故我们暂且抛开数值,只研究其变化趋势,同时我们设置单位时间内移除率为0.0001,该数值后期可以通过人工检测而求得,这里不深究,同时设置在单位时间内,易感者和感染者相距足够近感染率为0.3,设置在800x500单位面积内具有500个个体,每隔单位时间个体会向随机方向移动2单位路程,当易感者单位与感染者单位相距1个单位时,易感者有概率受到感染,可以重现感染过程,值得一提的是,最好使用市民手机GPS信号代替粒子随机游走,可以更好的模拟人口流动。

模拟过程:

初始时期具有5个感染者随机分布在图中各处:
初始时期具有5个感染者随机分布在图中各处
部分区域开始大量出现感染者,感染者区域性分布明显:
在这里插入图片描述

携带者量减少,移除者占据人群大部分,携带者与易感者接触可能性降低,传染速度变缓,疫情趋向结束:
在这里插入图片描述
将实验过程中数据搜集并绘制图像:
在这里插入图片描述
注:图中接触可传染补偿应为接触可传染步长

在这里插入图片描述
可以发现其在大尺度上展现出与微分形式相似的结构,而在小尺度上数量变化却是离散的不连续的,另外我们尝试将单位时间内感染者向隔离或移除者转化率升高,则会导致感染者转化过快而无法传播开:
在这里插入图片描述

.
.


七、模型改进

我们可以将模型套用到各种病情当中,但概括性的模型毕竟不能准确描述出各个传染病的特点,就本次新冠病毒而言,传统的SIR模型对于本次新冠肺炎来讲可能并不适用,其原因包括以下几点:

  • 易感人群经过感染后会进入一段长约十四天的潜伏期
  • 疫情在潜伏期仍具有传染能力
  • 感染人群一经发现便被隔离而不具备传染能力
  • 移除人员(包括治愈与死亡)死亡者经过处理失去传播能力,但由于新冠病毒的特殊性,治愈者仍有可能感染

故我们可以对其进行改进,包括增添潜伏者,将其改变为SIQR模型:

  • S:易感者
  • I:感染但未被隔离者
  • Q:被隔离者,不再具备传染能力
  • R:移除者:死亡或具备抵抗能力者
  • r:每个患者每天内接触在易感者人数
  • β:易感者与感染者接触时的传染率
  • γ:感染人群失去传播能力的速率。主要取决于被发现并隔离速率即潜伏期
  • μ:死亡速率及具备抵抗能力转化速率
  • λ:痊愈率(不具备抵抗能力)
    在这里插入图片描述

在这里插入图片描述


八、文章说明

这其实是一篇课程小论文,因为课评分比较水所以当时写的比较随意,如果有不正确的地方希望能的得到指正,疫情都快过去了才发是因为。。。。。我肯定得等结课之后老师打完分再往外发呀对不对。。。。

猜你喜欢

转载自blog.csdn.net/slandarer/article/details/108285577