SIR information dissemination model

SIR model and python reproduction

SIR model

The SIR model is a classic model in the infectious disease model. It can be used in the simulation prediction of the infectious disease process, and can also be used to abstractly express the information dissemination process in the social network. This article describes the latter.
The SIR model divides the nodes in the social network into three categories: SSClass S , susceptible, refers to nodes that have not received information and do not have the ability to spread;IIType I , infected person, refers to a node that receives information and has the ability to spread;RRClass R , immunizer, refers to the node that exits the propagation process after receiving information.
The propagation mechanism of the SIR model is shown in the figure below:

where,β ββ represents the infection rate, that is, timettt time unit timeIIInfected individuals and SSnewly added to class I nodesThe number of S -type nodes is proportional, and the proportional coefficient isβ βb ;c cγ represents the immunity rate (recovery rate), that is, the timettRRper unit time at tThe newly added immune individuals and RR of R nodesThe number of R nodes is proportional, and the proportional coefficient isγ γc .

SIR mathematical model

propagation dynamics equation

We express the above propagation model as a kinetic equation. Here set the total number of nodes to NNN , the initial numbers of the other three types of nodes areS , I , RS, I, RSIR N = S + I + R N=S+I+R N=S+I+R。则有下列方程
{ d S d t = − β S I N , d I d t = β S I N − γ I , d R d t = γ I \begin{cases} \quad \dfrac{dS}{dt}=-βS\dfrac{I}{N},\\ \quad \dfrac{dI}{dt}=βS\dfrac{I}{N}-γI,\\ \quad \dfrac{dR}{dt}=γI \end{cases} dtdS=βSNI,dtd I=βSNIc I ,dtdR=c I
Among them, IN \dfrac{I}{N}NIstands for SSS TypeIIClass I contact rate.

Python implementation

from scipy.integrate import odeint
import numpy as np
import matplotlib.pyplot as plt


def sir_model(input_v, t):
    s, i, r = input_v
    n = s + i + r
    ds_dt = - beta * s * (i / n)
    di_dt = beta * s * (i / n) - gamma * i
    dr_dt = gamma * i
    return [ds_dt, di_dt, dr_dt]


if __name__ == '__main__':
    # 模型输入值
    N = 10000  # 设定总节点数量
    S0 = 9980  # S类节点数量
    I0 = 18  # I类节点数量
    R0 = N - S0 - I0  # R类节点数量
    input_value = (S0, I0, R0)
    beta = 0.5  # 设定感染率
    gamma = 0.1  # 设定免疫率
    # 设定步长 即传播次数
    times = np.linspace(0, 60, 60)
    # 求解微分方程
    result = odeint(sir_model, input_value, t=times)
    # 画图
    plt.plot(result[:, 0], '-ro', label='S')
    plt.plot(result[:, 1], '-b^', label='I')
    plt.plot(result[:, 2], '-gs', label='R')
    plt.legend(loc=0)
    plt.xlabel('times')
    plt.ylabel('number')
    plt.show()

The implementation result is shown in the figure below.

Simulating the information dissemination process of SIR model in social network

Since there is no data set here, we can only use the Networkx library in python. Here we use the BA scale-free network model (personally think it is closer to the real social network).

import networkx as nx
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import random
# 确保 中文 和 -
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False


def update_node_status(G, node, beta, gamma):
    """
    更改节点状态
    :param G: 输入图
    :param node: 节点序数
    :param beta: 感染率
    :param gamma: 免疫率
    """
    # 如果当前节点状态为 感染者(I) 有概率gamma变为 免疫者(R)
    if G.nodes[node]['status'] == 'I':
        p = random.random()
        if p < gamma:
            G.nodes[node]['status'] = 'R'
    # 如果当前节点状态为 易感染者(S) 有概率beta变为 感染者(I)
    if G.nodes[node]['status'] == 'S':
        for adj_node in G[node]:
            if G.nodes[adj_node]['status'] == 'I':
                p = random.random()
                if p < beta:
                    G.nodes[node]['status'] = 'I'
                    break


def update_network_data(G, beta, gamma):
    """
    更改图数据
    :param G: 输入图
    :param beta: 感染率
    :param gamma: 免疫率
    """
    for node in G:
        update_node_status(G, node, beta, gamma)


def initial_network_data(G, i_num, r_num):
    """
    初始化图数据
    :param G: 输入图
    :param i_num: 感染者数量
    :param r_num: 免疫者数量
    """
    # 感染节点集
    i_set = set(random.sample(G.nodes, i_num))
    # 免疫节点集
    r_set = set(random.sample(G.nodes, r_num))
    # 两个集合不能重复
    while r_set & i_set:
        r_set = set(random.sample(G.nodes, r_num))
    # 初始化节点状态
    for node in G:
        if node in i_set:
            G.nodes[node]['status'] = 'I'
        elif node in r_set:
            G.nodes[node]['status'] = 'R'
        else:
            G.nodes[node]['status'] = 'S'


def count_node(G):
    """
    计算当前图内各个节点的数目
    :param G: 输入图
    :return: 各个节点数目
    """
    s_num, i_num, r_num = 0, 0, 0
    for node in G:
        if G.nodes[node]['status'] == 'S':
            s_num += 1
        elif G.nodes[node]['status'] == 'I':
            i_num += 1
        else:
            r_num += 1
    return s_num, i_num, r_num


def draw_network(G):
    """
    输出初始网络节点分布
    :param G: 输入图
    """
    # 设置图大小
    fig, ax = plt.subplots(figsize=(12, 8))
    ax.set_title("易感染者-感染者-免疫者节点初始分布")
    pos = nx.spring_layout(G, scale=1)
    nx.draw(G, pos=pos, with_labels=True, font_color='white', edge_color='grey',
            node_color=[color_dict[ba.nodes[node]['status']] for node in G])


def draw_node_trend(G, beta, gamma):
    """
    输出各类节点趋势
    :param G: 输入图
    :param beta: 感染率
    :param gamma: 免疫率
    """
    # 设定传播步长
    t_list = np.linspace(1, 24, 24)
    # 开始模拟传播
    for t in range(len(t_list)):
        # 计算并存储当前各个节点数目
        node_list.append(count_node(G))
        update_network_data(G, beta, gamma)
    # 整理数据
    df = pd.DataFrame(data=node_list, index=t_list, columns=['S', 'I', 'R'])
    # 显示数据曲线
    df.plot(figsize=(8, 6), color=[color_dict.get(x) for x in df.columns])
    plt.ylabel('nodes(节点数)')
    plt.xlabel('days(天数)')
    plt.title('易感染者-感染者-免疫者节点趋势')
    plt.savefig('SIR_model')
    plt.show()


def update_graph(i, G, ax, pos, beta, gamma):
    """
    动态更新节点
    :param i: 输入帧
    :param ax: 输入图参数
    :param G: 输入图
    :param beta: 感染率
    :param gamma: 免疫率
    """
    i = int(i)
    ax.set_title("第" + str(i + 1) + "天 易感染者-感染者-免疫者节点分布")
    ax.axis('off')
    plt.box(False)
    if i == 1:
        # 第一天  初始节点分布  直接画出
        nx.draw(G, with_labels=True, font_color='white', edge_color='grey',
                node_color=[color_dict[ba.nodes[node]['status']] for node in G], pos=pos)
    else:
        # 以后变化 需要演变节点
        update_network_data(G, beta, gamma)
        nx.draw_networkx_nodes(G, with_labels=True, font_color='white', edge_color='grey',
                               node_color=[color_dict[ba.nodes[node]['status']] for node in G], pos=pos)


def draw_network_trend(G, beta, gamma, days):
    """
    输出网络动态变化视频
    :param G: 输入图
    :param beta: 感染率
    :param gamma: 免疫率
    :param days: 需要的时间(迭代次数)
    """
    fig, ax = plt.subplots(figsize=(12, 8))
    pos = nx.spring_layout(G, scale=1)
    ani = animation.FuncAnimation(fig, update_graph, frames=days,
                                  fargs=(G, ax, pos, beta, gamma), interval=300)
    writer = animation.FFMpegWriter()
    ani.save('network_trend.mp4', writer=writer)


if __name__ == '__main__':
    # 总人数
    N = 10000
    # 易感染者人数
    s = 9980
    # 感染者人数
    i = 18
    # 免疫者人数
    r = N - s - i
    # 各个节点数目列表
    node_list = []
    # 节点颜色
    color_dict = {
    
    'S': 'blue', 'I': 'red', 'R': 'green'}
    # 创建BA无标度网络
    ba = nx.barabasi_albert_graph(N, 3, seed=1)
    # 初始化网络节点
    initial_network_data(ba, i, r)
    # 输出节点趋势图
    draw_node_trend(ba, 0.4, 0.1)
    # 初始节点分布图
    # 输出初始节点网络图
    # draw_network(ba)
    # 输出网络动态变化图
    # draw_network_trend(ba, 0.2, 0.15, 50)

The result obtained by the above code is shown in the figure below.

Here, if there is a data set, you can modify this code, input the edge set and node set in the data set into the blank graph in Networkx, and the rest can not be changed, or you can simulate the propagation process of the SIR model in the real social network.
From the SIR model we can see that β βb andc cγ will affect the information dissemination process to a great extent. If using a real data set, also pay attention to the differentβ βb andc cγ value, there will be different results. At the same time, by making good use of the real data set, we can find the approximate true valueβ βb andc cgamma value.
In addition, in the last few lines of the above main program code, I added functions to generate the initial network distribution map and dynamically realize the node changes in the social network. The dynamic implementation part requires a ffmpeg software to generate.

Guess you like

Origin blog.csdn.net/weixin_44177875/article/details/106608800