10- 网络上病毒传播的SIR模型 用Links建模网络动力学
该系列笔记基于集智乐园的《Netlogo多主体建模入门》课程,感谢张江老师与各位志愿者的辛勤付出。
首先,我们需要知道SIR模型是什么。
经典的SIR模型:
感染者有α 的概率感染健康者,
感染者有β的概率治疗成功,恢复之后就不会再被感染(neilogo的模型中是:痊愈后有一定的概率会获得病毒抗性)。
将人群分成三种状态:
S: 易感态、疑似态(Susceptibility)
I: 感染态(Infection)
R: 恢复态(Recovery)
三种状态彼此之间可以以一定的概率彼此之间相互转换
感染态可以沿着网络进行传播。
实现思路:
预备的代码知识:
Link对象
属性:
代表link两端的节点,end1代表起点,end2代表终点。
ask turtle 0
[
create-links-with other turtles
ask link-neighbors [ set color red ] ;; turtles 1 and 2 turn red
]
link有关的函数:
用法:
create-links-from turtleset
创建其他 turtles 与 当前 turtle的连边(从其他 turtles指向当前 turtle)
ask turtle 0 [ create-links-to other turtles ]
创建当前 turtle 到 其他 turtles的连边
指定已经和当前 turtle 创建连边的 邻居
这是个回调函数,会返回两个turtle之间的连边(有向的,或者无向的都行)。如果有多条,就返回随机的一条边。如果没有,就显示nobody。
ask turtle 1 [ show in-link-from turtle 0 ] ;; shows link 0 1
ask turtle 0 [ show in-link-from turtle 1 ] ;; shows nobody
self与myself的区别
layout-spring
用法:
layout-spring turtle-set link-set spring-constant spring-length repulsion-constant
五个变量的意思分别是:turtles集合对象、link 集合对象、弹簧系数(常量)、弹簧的自然长度、斥力系数(两个节点存在除了弹簧外的另一种斥力,这是1个单位距离处的2个节点将彼此施加的力。)
示例:
layout-spring turtles links 0.3 (world-width / (sqrt number-of-nodes)) 1
然后我们可以直接使用模型库中的 Virus on a Network
模型解读:
我调了多组参数进行了大量实验,观察到 :感染者的人数总会经历一个从逐渐增多,到逐渐下降的 “山形函数”。
这是 Uri Wilensky 在 2008 写的模型之一。
以下是我个人读懂这位老兄的模型代码后写的一些注解,供大家参考。
turtles-own
[
infected? ;; 布尔值,如果为真,则是被感染状态
resistant? ;; 如果为真,获得病毒抗性,无法被感染
virus-check-timer ;; 距离上一次治疗过去了多少时间步,大于virus-check-frequency的时候,此人会去接受治疗,于是置0。
;; 为0的时候,该个体会变成易感状态
]
to setup
clear-all
setup-nodes ;; 调用初始化节点 的函数
setup-spatially-clustered-network ;; 调用 初始化网络 的函数
ask n-of initial-outbreak-size turtles
[ become-infected ] ;; 初始化指定数量的感染者
ask links [ set color white ] ;; 初始化连边为白色
reset-ticks
end
to setup-nodes ;;初始化节点
set-default-shape turtles "circle"
create-turtles number-of-nodes
[
; 为了生成的节点不会分布在 视窗 的边缘
setxy (random-xcor * 0.95) (random-ycor * 0.95)
become-susceptible ;; 全部节点都是易感的
set virus-check-timer 0
]
end
to setup-spatially-clustered-network ;; 初始化网络
let num-links (average-node-degree * number-of-nodes) / 2 ;;新建一个全局变量:连边数
while [count links < num-links ]
[
ask one-of turtles
[
;; 选择 在不和该turtle为邻居的其他节点中,距离该turtle最近的节点,赋值给choice
let choice (min-one-of (other turtles with [not link-neighbor? myself])
[distance myself])
;; 只要存在符合的节点,就创建连边
if choice != nobody [ create-link-with choice ]
]
]
;; 这里用到layout-spring,就是那个把连边当作弹簧的可视化方法
repeat 10
[
layout-spring turtles links 0.3 (world-width / (sqrt number-of-nodes)) 1
]
end
to go
if all? turtles [not infected?] ;; 如果全部的状态为未被感染,那就停止运行
[ stop ]
ask turtles
[
set virus-check-timer virus-check-timer + 1 ;;每次go,都给 “距离上一次病毒检查过去了多少时间步” 记一次时
if virus-check-timer >= virus-check-frequency ;; 定期做检查
[ set virus-check-timer 0 ] ;; 置0
]
;;调用函数,实现感染者传播病毒
spread-virus
;; 调用函数,实现健康者定期做治疗
do-virus-checks
tick
end
to become-infected ;; 个体被感染
set infected? true
set resistant? false
set color red
end
to become-susceptible ;; 个体变成易感的
set infected? false
set resistant? false
set color blue
end
to become-resistant ;; 个体被获得病毒抗性
set infected? false
set resistant? true
set color gray
ask my-links [ set color gray - 2 ] ;; 让无效节点的连边颜色变灰
end
to spread-virus ;; 感染者传播病毒
ask turtles with [infected?]
[ ask link-neighbors with [not resistant?]
[ if random-float 100 < virus-spread-chance
[ become-infected ] ] ]
end
to do-virus-checks ;; 健康者定期做治疗
ask turtles with [infected? and virus-check-timer = 0]
[
if random 100 < recovery-chance ;; 有一定概率治愈
[
ifelse random 100 < gain-resistance-chance
[ become-resistant ] ;;在治愈的基础上,有一定概率能获得病毒抗性
[ become-susceptible ] ;;不够幸运,未能获得病毒抗性的人,重新变成易感的
]
]
end
; Copyright 2008 Uri Wilensky.
; See Info tab for full copyright and license.
后话:
大家如果遇到不会的函数,一定要多从词典中找相关的一些介绍。
模型的不足之处
然而交通网络的出现与发展让更多人能够跨距离地接触
现实情况中,少数的节点拥有极其多的连接,而大多数节点只有很少量的连接。
改进:
将网络修改成 无标度网络
可以尝试引入 Preferential Attachment 模型的一些代码。
--------------------------------------