数学建模社区-数学中国

标题: Python实现简单的SI传播模型 [打印本页]

作者: 杨利霞    时间: 2020-4-18 16:16
标题: Python实现简单的SI传播模型
Python实现简单的SI传播模型% c' [: Z/ ?+ f$ t8 t5 x4 z+ o7 O
#SI疾病传播模型的原理
' w% r- y8 D# y9 I9 ^3 ]- {在经典的传染病模型中,种群(Population)内N个个体的状态可分为如下几类8 Y. @  {# u) A3 L

7 B  ]3 w2 s7 S5 E% F3 i8 H易感状态(Susceptible)。一个个体在感染前是处于易感状态的,即该个体有可能被邻居个体感染。
: ~- N6 j5 h5 s) X0 D易感状态I(Infected)。一个感染上某种病毒的个体就称为是处于感染状态。,即该个体还会以一定概率感染其邻居个体。
! B5 R- U4 F; b) `移除状态(Remove,Refractory或者Recovered)。也成为免疫状态或恢复状态,当一个个体经历过一个完整的感染周期后,该个体就不再被感染,因此就可以不再考虑改革提。
, v  A3 C, R; E, R: \% ?( }SI传播模型是最简单的疾病传播模型,模型中的所有个体都只可能处于两个状态中的一个
% v& P: y( _+ B4 R即易感(S)状态或感染(I)状态。SI模型中的个体一旦被感染后就永远处于感染状态。8 s8 v4 P: N  {7 R' N2 [
在给定时刻t,令S(t)与I(t)分别代表该时刻处于易感和感染状态的个体数目,显然有- j) s" B# z  G/ O) g  q; X
S(t)+I(t)恒等于N,这里,N是个体总数。随着时间t的增长,易感个体与感染个体的接触6 _. J$ K! q% q$ W; \6 M
会导致感染个体数量的增加。加入由于个体之间的接触而导致疾病传播的概率为β,疾病仅在
. t1 a1 H" I7 r感染个体和易感个体之间进行接触时才会以概率β将疾病传染给易感个体。在时刻t,易感个体的比例为S(t)/N,感染个体的数量为I(t),一次,易感个体的数量将以如下变化率减少' A+ r3 a) ^' h- P* Z
ds/dt = -β*S(t)I(t)/N$ o, G# u8 D: r( X  d$ f0 ]
同时,感染个体的数量会以与易感个体相反的变化率增加,: i1 D% X7 M) q
ds/dt = βS(t)*I(t)/N
6 f9 Y' T7 X) {, B3 T分别将时刻t处于易感状态和感染状态的个体所占比例记为,; ?0 P& }% K- u$ Y9 e7 c+ M6 [
s(t)=S(t)/N4 |7 r2 c) n5 [0 O7 a4 R
i(t)=I(t)/N
1 x- W+ ?1 L$ ?1 p6 M显然有,
# ^! c1 A' Z) c+ D$ q- L: B( ^' Cs(t)+i(t)恒等于1,此时之前的公式可以记做
, S6 j( R0 f' I9 Q, |; H6 T& Vds/dt=-βsi
# M( D5 Y' P; `di/dt=βsi
3 S8 S% T1 c! @! e" Q& d8 G
# q7 _0 g0 x1 ?, }9 Tdi/dt=βi(1-i)
5 I+ W4 H& |; P( r8 h上式也成为Logistic增长方程式(Logistic growth equation),
5 a$ Q2 ?' y% N6 r% U方程的解和图像如图1 Z' h1 q, L- ?5 V2 V' P4 h
1.jpg ' s8 m, r6 H$ I& X( P; b
代码和相关文件以及环境链接:链接:https://pan.baidu.com/s/1JSfHuTPaglFimeEBLdSDyQ
' e& ^4 g1 P6 b- z: z7 x% W提取码:z448
  i" D5 U# W% Q) d9 I; z, p+ p+ R( t8 R) f1 |  b; E& W! n/ o

: ]$ {- J  w3 }'''
0 Y& K3 a0 a7 i7 `实验环境Python2.7.13,igraph包,cairo包,numpy包
) s" Y* o/ @: b; P'''4 w! k5 c- `5 o' Y
# -*- coding:utf8 -*/ l# ~6 ]3 B, H3 V  f; F# U5 D
from igraph import *
$ o2 U' F1 T4 Q- E, _6 I5 g5 mimport numpy as numpy
( X! ]! Q! h* |2 Y4 Ufrom  numpy import *( Q, U5 _1 o) x1 \) Q* A
import random
: H& D3 e& l& s
" F8 Q7 x$ u9 k- g1 S) E$ A* `! f4 V. u" mdef len_arr(infected_array,nodes_num):#获取感染数组长度
7 A; A  i4 K( j# ~2 v( h+ B    len_value=0#初始化长度
) W9 `: V0 \+ x; P4 @# Y    len_value=nodes_num-infected_array.count(-1)#被感染数量是结点总数减去未感染节点数(未感染的结点被标记为-1)
  J& k  Y* u: O    return len_value
! i- |  ^; m( P1 X: ?0 |- Y
0 J' [/ ]7 ~- q: Q! cg=Graph.Read_GML("C:\python27\e1.gml")#将本地保存的网络数据读入变量g(生成图)
3 B5 y9 S; W! msummary(g)
2 V) j, w8 d4 O0 P5 f5 Knodes_num=g.vcount()#统计图中的结点个数
# e$ k" z& o( m; R3 o! bnet_mat=g.get_adjacency(type=GET_ADJACENCY_BOTH)#将网络数据转换为邻接矩阵存储在变量net_mat
) ^# ?4 F( b& f$ Dg.vs["color"]=["white"]#给图的顶点序列颜色赋值白色
- S1 q1 |0 o# Za=[arange(nodes_num)+1]*3#声明一个N行3列的数组a! w% x1 l9 O! k4 E3 K. W, F" c/ R
nodes_state=matrix(a).T#nodes_state通过转置a矩阵创建,用于存放每个节点的状态信息以及其被感染的时间(这个是理解算法的重中之重!!!)8 q5 T7 ^+ P8 A- `+ [1 Y
                                                    #第一列是节点编号,第二列是节点状态,感染状态用-2表示,第三列是节点感染的时间% o2 t! @8 K3 _- `( Y' @' D. D* {
print(nodes_state)' }6 M- c! |* E
infected_array=[-1]*34#用于存放本轮被感染的结点, 这些结点将参与下一次感染   34代表网络节点数
* H$ _" Y9 ]$ G3 p& v/ R+ eprint(infected_array)" @# ~: m1 c5 x; Z7 e

3 u! Q( ~, H5 i9 |; m( q& x$ winfe_rate=1#传播率(感染率) 1代表邻接点100%被感染
" _+ C% ]; J. m- ]2 k3 D( j8 c8 F* jset_time=2#传播次数(感染次数) 2次! i8 e9 a: F8 v) U0 w
source_seed=1#感染源位置
4 J7 j3 N9 r$ W5 x3 xnodes_state[0:nodes_num,2]=-1#给所有节点初始化感染时间为-1! L  ?& J& a) j+ y* V8 ?
nodes_state[source_seed-1,1]=-2#设置第一个感染源感染状态 -2代表感染状态
: R7 p$ p4 @2 T" f* @" X$ X* hnodes_state[source_seed-1,2]=1#设置第一个感染源的感染时间为1
5 `% p( ^; B/ n9 Pg.vs[source_seed-1]["color"]="red"#将感染的顶点颜色标红2 t) q" o% N- V0 ^# {
infected_array[0]=source_seed#将感染源的位置存入被感染节点列表
2 o& T9 F4 X, {7 mplot(g)#绘制
4 o) h; [- V: r6 {1 c* A+ j- S# {0 E3 h2 T
stop=False#感染过程结束的标记% b( x: }# h5 l% o) \% `
temp_time=0#第几次感染) y2 C# o) C" p
temp_len=0#本轮的感染源数量初始化
' w  q+ r  o( z4 z, J- K& B6 Z2 w4 h" G4 m
while not stop:
% n) D! x3 [8 a5 F9 j7 p0 D8 t; D    i=0#记录让每个感染源都传播一次$ W0 |) f* E! y, G
    if len_arr(infected_array,nodes_num)>0 and len_arr(infected_array,nodes_num)<=nodes_num:#感染可以进行
. f. V; a- e+ ?* x        temp_len=len_arr(infected_array,nodes_num)#获取本轮的感染源数量% G0 r, u4 M3 l$ k
        while i<temp_len:9 S) l& ^: r7 e' K5 \
            temp_time=nodes_state[infected_array-1,2]#获取每一个节点的感染时间4 p* Y- l; J( Z! S
            nei_count=0#下一轮可以被感染到的节点数量6 T: d  N' @" U/ n2 L
            #生成下一轮可能被感染的节点的集合nei_arr
8 v' l3 P  ~+ w1 ?; z2 \            for j in range(nodes_num):#遍历节点
, w( R  b- ?' S1 J                if net_mat[infected_array-1,j]==1 and nodes_state[j,1]!=-2:#是邻接节点而且未被感染
% c& ]! V" H- p- u/ ?; m. {                    nei_count=nei_count+1#下一轮可以被感染到的节点数量++) R) m4 z6 |3 I. @2 J# s* X/ m* f
            nei_arr=[-1]*nei_count#用于临时存放本轮被感染的结点, 这些结点将参与下一次感染3 Q/ e! ~2 t* Y6 A$ @& t
            t=0
/ d, e% {  ~( D' Y4 V. M' n0 }" \4 u& R            for j in range(nodes_num):$ [- S, g% h+ Z" x5 a5 z. _
                if net_mat[infected_array-1,j]==1 and nodes_state[j,1]!=-2:
9 W# t: N" t& @5 Q                    nei_arr[t]=j+15 L, j+ J' t/ j2 K2 f
                    t=t+1
; E- o8 G% e  N2 w' D  }            ran_infe_arr=random.sample(range(nei_count),int(nei_count*infe_rate))#随机生成会被感染的节点的数组  W- ]  g- V+ x, N/ s% X
                                        #random.simple(arg1,num) 从arg1集合中随机取num个数据生成一个对象2 B6 t, r. u) O
            if len(ran_infe_arr)>0:#存在需要被感染的节点9 _. A7 b3 \; X! u* K
                t=0#让ran_infe_arr内每个感染源都被感染
( n( J5 n6 A8 J3 o! f                while t<len(ran_infe_arr):#对刚才生成的会被感染的数组内的节点进行感染9 R8 @1 Z: [$ Y( B& e+ i* O5 t
                    nodes_state[nei_arr[ran_infe_arr[t]]-1,1]=-2#标记为感染状态9 R5 _# D( r7 ?! {  P' l
                    nodes_state[nei_arr[ran_infe_arr[t]]-1,2]=temp_time+1#记录感染时间3 L$ d% ^1 i/ N
                    infected_array[len_arr(infected_array,nodes_num)]=nei_arr[ran_infe_arr[t]]#将此次感染节点放入总的感染节点数组中7 P, B3 r! n+ J  b9 j: x# ]: V
                    g.vs[nei_arr[ran_infe_arr[t]]-1]["color"]="pink"#将此次感染的节点集的所有节点颜色置为粉色* K" X- n! z' d' F
                    plot(g)#绘制
: b: |. W! i" N3 @% h: P  U$ _                    t=t+1
& B/ Z0 l- T5 u            i=i+13 `2 R6 t3 P5 v4 A. x" g
    if temp_time>set_time-1:#当执行感染的次数等于设置的次数结束感染4 _2 z# h2 B/ z0 D
        stop=True ' X5 L) v7 t. ~0 g* P9 v, D3 `+ V' M

) |# b  w) r! U/ J/ K# ?7 u4 |3 n% u! _; u; ]5 d6 g. S! N3 _$ s
视频演示bilibili传送门
# B/ Y3 y5 F/ M6 N效果图- G" I+ _% W* ^% m9 v" t5 Z! @

! P* {" Y* H2 I/ A
; }  \( Q/ v4 b: A2 _. n4 ~; F 2.jpg . ?2 [  c- S$ Z6 t' _6 z8 D
  j  E3 |) G; q, {- }
3.png ! W! t! {4 |* Y5 E- c7 I0 K9 t9 ?9 ~

% m' M0 e7 g* k3 N 4.jpg ; z0 t! y' q( C6 V5 f1 p

9 ^( u$ X$ K, C' C# g 5.png
! e+ G% X- ~8 |' U6 `" P. s, L" S$ g  V& n, e4 h
6.png
8 X4 g4 l2 Y+ s* }/ }$ N; m7 F' F
7.png ————————————————. R! l0 g' z* Z( c4 w/ ]1 b
版权声明:本文为CSDN博主「eck_燃」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。) |) p- p4 e, i- {5 S- U
原文链接:https://blog.csdn.net/wdays83892469/article/details/80878862
9 [* [+ P: i- B6 g1 V. X, ~
5 {0 W2 m8 v8 d& S5 u- y/ A2 I, {! Q/ b. W# |0 T% J% ?8 F* t

作者: 尔雅    时间: 2020-4-18 17:50
发表回复棒!- f  U5 l5 B6 ^3 B9 z





欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5