1. 程式人生 > >簡單的SIR模型傳播--numpy/matplotlib(某師範大學學生的期中大作業)

簡單的SIR模型傳播--numpy/matplotlib(某師範大學學生的期中大作業)

SIR模型是傳染病模型中最經典的模型,其中S表示易感者,I表示感染者,R表示移出者。模型中把傳染病流行範圍內的人群分成三類:S類,易感者(Susceptible),指未得病者,但缺乏免疫能力,與感病者接觸後容易受到感染;I類,感病者(Infective),指染上傳染病的人,它可以傳播給S類成員;R類,移出者(Removal),指被隔離,或因病癒而具有免疫力的人。其中S被附近節點感染的概率為beta,如果S狀態節點有m個I狀態的話,S在下個時間段被感染的概率就是1-(1-beta)^m,如果本身就是I節點,那麼下個階段康復的概率為 u。

然後我們可以用下面程式碼建立ER圖(鄰接矩陣)

def CreateER(N, p):
    mat = np.random.rand(N, N)
    mat = np.where(mat>p, 0, 1)
    for i in range(N):
        mat[i, i] = 0
        mat[i, :] = mat[:, i]
    return mat

接著我們可以通過計算直方圖來進行區間統計,程式碼如下:

def Distribution(mat):
    (a, b) = mat.shape
    Count = np.array([mat[i, :].sum() for i in range(a)])
    hist = np.histogram(Count, bins=1000, range=(0,1000))
    plt.plot(hist[0])
    plt.xlabel('degree')
    plt.ylabel('p(degree)')
    plt.show()
    return hist

最終生成相應的SIR模型

# 對一個mat進行一次SIR的傳播 S 1 -- I 2 -- R 3 普通人--1 感染者--2 恢復者
def SIRSpread(mat, beta, mu, vec):
    nvec = np.array(vec)
    for i in range(vec.size):
        if vec[i] == 1:
            num = 0
            for j in range(vec.size):
                if mat[i,j] == 1 and vec[j] == 2:
                    num = num + 1
            prob = 1 - (1-beta)**num
            rand = random.random()
            if rand < prob:
                nvec[i] = 2
        elif vec[i] == 2:
            rand = random.random()
            if rand < mu:
                nvec[i] = 3
    return nvec
    

# 設定傳播次數,來進行傳播,並返回每個階段S,I,R的數量
def MultiSpread(N, beta, mu, t):
    mat = CreateER(N, 0.01)
    vec = np.array([1 for i in range(N)])

    rNum = random.randint(0, N-1)
    vec[rNum] = 2

    S = []
    I = []
    R = []

    for i in range(t):
        vec = SIRSpread(mat, beta, mu, vec)
        S.append(np.where(np.array(vec)==1, 1, 0).sum())
        I.append(np.where(np.array(vec)==2, 1, 0).sum())
        R.append(np.where(np.array(vec)==3, 1, 0).sum())
    
    return S,I,R

實驗結果如圖所示