1. 程式人生 > 其它 >數模-微分方程(SIR模型)

數模-微分方程(SIR模型)

SIR模型


程式碼

fun1.m

function dx=fun1(t,x)   % 大家可以修改裡面的引數,來看結果的變化
    beta = 0.1;  % 易感染者與已感染者接觸且被傳染的強度
    gamma = 0.02;  % 康復率
    dx = zeros(3,1);  % x(1)表示S  x(2)表示I  x(3)表示R
    C = x(1)+x(2);  % 傳染病系統中的有效人群,也就是課件中的N' = S+I
    dx(1) = - beta*x(1)*x(2)/C;  
    dx(2) = beta*x(1)*x(2)/C - gamma*x(2);
    dx(3) = gamma*x(2); 
end

code.m

%% 最簡單的SIR模型
clc;clear
N = 1000;  % 總人數
i0 = 1; % 初始時刻患者(已感染者)的人數
[t,x]=ode45('fun1',[1:500],[N-i0 i0 0]);   % 記得給康復者R一個初始值
x = round(x);  % 對x進行四捨五入(人數為整數)
figure(1)
% x的第一列是易感染者S的數量,x的第二列是患者I的數量,x的第三列是康復者R的數量
plot(t,x(:,1),'r-',t,x(:,2),'b-',t,x(:,3),'g-','Linewidth',1.5)  
legend('易感染者S','患者I','康復者R')

結果

分別取康復率為0.01,0.02一直到0.05,把患病人數I的結果放到一個圖形上(相對於上面的模型)

程式碼

fun2.m

function dx=fun2(t,x)   % 大家可以修改裡面的引數,來看結果的變化
    global GAMMA % 定義康復率為全域性變數
    beta = 0.1;  % 易感染者與已感染者接觸且被傳染的強度
    dx = zeros(3,1);  % x(1)表示S  x(2)表示I  x(3)表示R
    C = x(1)+x(2);  % 傳染病系統中的有效人群,也就是課件中的N' = S+I
    dx(1) = - beta*x(1)*x(2)/C;  
    dx(2) = beta*x(1)*x(2)/C - GAMMA*x(2);
    dx(3) = GAMMA*x(2);
end

code.m

%% 分別取康復率為0.01,0.02一直到0.05,把患病人數I的結果放到一個圖形上
clc;clear
global GAMMA % 定義康復率為全域性變數(我習慣用大寫字母來定義)
N = 1000;  % 總人數
i0 = 1; % 初始時刻患者(已感染者)的人數
% https://ww2.mathworks.cn/help/matlab/ref/colormap.html
c = jet(5);  % jet是matlab自帶的顏色圖陣列,等會畫圖我們要用不同顏色區分
% 每行一個0-1之間三元素 RGB 向量。第一列紅色強度。第二列綠色強度。第三列藍色強度。
for i = 1:5
    GAMMA = 0.01*i;   % 在迴圈中來改變康復率GAMMA的值
    [t,x]=ode45('fun2',[1:500],[N-i0 i0 0]);   % 記得給康復者R一個初始值
    x = round(x);  % 對x進行四捨五入(人數為整數)
    % x的第一列是易感染者S的數量,x的第二列是患者I的數量,x的第三列是康復者R的數量
    figure(2)
    % 這裡我們就只繪製患病人數I的圖形了
    plot(t, x(:,2), '-', 'color', c(i,:),'DisplayName',num2str(GAMMA),'Linewidth',1.5)    
    % 'color' 後面的c(i,:)是前面生成的一個RGB向量,可以用來指定這個曲線的顏色
    % 'DisplayName' 後面需要加上當前圖例對應的文字
    hold on
end
legend show    % 要加上這句話,否則圖例不會顯示
% 等價於直接使用命令: legend('0.01','0.02','0.03','0.04','0.05')

結果

不定義全域性變數,我們可以用另外一種方法(這種方法的通用性更強)

由於我們引數多加了一個GAMMA,所以我們要改為函式控制代碼的方式

程式碼

newfun2.m

% % 不定義全域性變數的寫法
function dx=newfun2(t,x,GAMMA)   % 把GAMMA當成引數傳入進來
    beta = 0.1;  % 易感染者與已感染者接觸且被傳染的強度
    dx = zeros(3,1);  % x(1)表示S  x(2)表示I  x(3)表示R
    C = x(1)+x(2);  % 傳染病系統中的有效人群,也就是課件中的N' = S+I
    dx(1) = - beta*x(1)*x(2)/C;  
    dx(2) = beta*x(1)*x(2)/C - GAMMA*x(2);
    dx(3) = GAMMA*x(2);
end

code.m

% % 不定義全域性變數,我們可以用另外一種方法(這種方法的通用性更強)
clc;clear
N = 1000;  % 總人數
i0 = 1; % 初始時刻患者(已感染者)的人數
c = jet(5);  
for i = 1:5
    GAMMA = 0.01*i;   % 在迴圈中來改變康復率GAMMA的值
    [t,x]=ode45(@(t,x) newfun2(t,x,GAMMA),[1:500],[N-i0 i0 0]);  
    x = round(x);  % 對x進行四捨五入(人數為整數)
    % x的第一列是易感染者S的數量,x的第二列是患者I的數量,x的第三列是康復者R的數量
    figure(2)
    % 這裡我們就只繪製患病人數I的圖形了
    plot(t, x(:,2), '-', 'color', c(i,:),'DisplayName',num2str(GAMMA),'Linewidth',1.5) 
    hold on
end
legend show    % 要加上這句話,否則圖例不會顯示

結果

SIR模型的擴充套件1

程式碼

fun3.m

function dx=fun3(t,x)   % 大家可以修改裡面的引數,來看結果的變化
    beta = 0.1;  % 易感染者與已感染者接觸且被傳染的強度
    gamma = 0.01;  % 康復率
    if t > 100
        gamma = gamma * 10;  % 第100期後研發了疫苗,使得康復率增加為原來的10倍
    end
    dx = zeros(3,1);  % x(1)表示S  x(2)表示I  x(3)表示R
    C = x(1)+x(2);  % 傳染病系統中的有效人群,也就是課件中的N' = S+I
    dx(1) = - beta*x(1)*x(2)/C;  
    dx(2) = beta*x(1)*x(2)/C - gamma*x(2);
    dx(3) = gamma*x(2); 
end

code.m

%% 考慮某種使得康復率gamma增加的因素(例如研發了疫苗、醫療裝置升級等)
% 第100期後研發了疫苗,使得康復率增加為原來的10倍
clc;clear
N = 1000;  % 總人數
i0 = 1; % 初始時刻患者(已感染者)的人數
[t,x]=ode45('fun3',[1:200],[N-i0 i0 0]);   % 記得給康復者R一個初始值
x = round(x);  % 對x進行四捨五入(人數為整數)
figure(3)
% x的第一列是易感染者S的數量,x的第二列是患者I的數量,x的第三列是康復者R的數量
plot(t,x(:,1),'r-',t,x(:,2),'b-',t,x(:,3),'g-','Linewidth',1.5) 
legend('易感染者S','患者I','康復者R')

結果

SIR模型的擴充套件2

程式碼

fun4.m

function dx=fun4(t,x)   % 大家可以修改裡面的引數,來看結果的變化
    beta = 0.1;  % 易感染者與已感染者接觸且被傳染的強度
    gamma = 0.02;  % 康復率
    d = 0.005; % 因病的死亡率
    dx = zeros(4,1);  % x(1)表示S  x(2)表示I  x(3)表示R  x(4)表示ID
    C = x(1)+x(2);  % 傳染病系統中的有效人群,也就是課件中的N' = S+I
    dx(1) = - beta*x(1)*x(2)/C;  
    dx(2) = beta*x(1)*x(2)/C - gamma*x(2) -d*x(2);
    dx(3) = gamma*x(2);
    dx(4) = d*x(2);
end

code.m

%% 考慮疾病的死亡率的SIR模型
clc;clear
N = 1000;  % 總人數
i0 = 1; % 初始時刻患者(已感染者)的人數
[t,x]=ode45('fun4',[1:400],[N-i0 i0 0 0]);   % 記得給患病死亡人數ID一個初始值
x = round(x);  % 對x進行四捨五入(人數為整數)
figure(4)
% x的第一列是易感染者S的數量,x的第二列是患者I的數量
% x的第三列是康復者R的數量, x的第四列是患病死亡人數ID的數量
plot(t,x(:,1),'r-',t,x(:,2),'b-',t,x(:,3),'g-',t,x(:,4),'k-','Linewidth',1.5)   
legend('易感染者S','患者I','康復者R','患病死亡人數ID')

結果