SIR 模型错误 - 找不到错误,需要帮助定位潜在的偏差源?
SIR model error - can't find bug, need help in locating potential source of deviation?
这个问题会很有趣。我试图复制一个 paper 的结果,该结果与自由移动代理系统中的疾病 t运行 任务有关(听起来是 NetLogo 的完美工作)。我根据论文中给出的细节在 NetLogo 中很容易地编写了一个简单的 SIR 模型,确保我的模型参数与列出的参数匹配,并让仿真 运行。一切 运行 都很完美,直到我检查了实验结果与预测值的匹配程度(根据论文的结果)。他们离开了,而且差距相当大。我以为代码某处有错误,所以我检查了所有内容,结果发现 什么都没有。然后我确保事件的顺序是正确的(因为移动、感染和恢复的顺序很重要),并且这些也与论文相符。我仔细考虑了这个问题,直到最后我打开 R,在 RStudio 中编写完全相同的程序,让它 运行,才发现结果与预测完全吻合! R 代码与我 期望 NetLogo 代码做的事情相同,所以我认为 NetLogo 的幕后发生了一些事情,或者我在某处产生了误解偏差的...请注意,由于论文中的结果是平均场近似值,因此您必须 运行 程序几次才能接近理论结果。
我不确定哪里出错了,因为我的 R 代码确认预测值是正确的,所以我得出结论,我的 NetLogo 代码中 某处 不正确.我对 NetLogo 不太熟悉,如果有人能帮助我找到以下代码中可能发生偏差的位置,我将不胜感激。实验平均值往往低于预测值,表明感染发生的速度比预期的要快,但在我看到的所有变化中,none 解决了这个问题(例如,感染不会一次发生一个每只传染性龟)。任何 suggestions/help 将不胜感激。
我的代码的精简版如下所示。这应该 运行 在带有标准 setup/go 按钮的常规界面中。结果存储在可以绘制的列表中,任何好奇的人都可以通过 Plot 对象看到模拟过程中的偏差。提前谢谢你。
;; Simple SIR model
globals [
;; variables for storing predictions
predS
predE
predI
predR
oldPredS
oldPredE
oldPredI
oldPredR
;; list to store experimental values
Slist
;; list to store predicted values
predSList
;; model variables
length-of-patch ;; length of habitat (a square of area length-of-patch^2)
infection-radius ;; the distance from an infectious individual a susceptible agent has to be within
;; in order to risk getting infected
total-pop ;; total population in the model
force-of-infection ;; probability of infection if within infection-radius distance
I0 ;; initial infected
recovery-rate ;; probability of recovery
]
turtles-own [
infected-status ;; 0 susceptible, 1 infected, 2 recovered
]
to setup
ca ;; clear
;; define the variables
set length-of-patch 31.62278 ;; the square root of 1000 (so the density is 1)
set infection-radius 1
set total-pop 1000
set force-of-infection 0.1
set I0 10
set recovery-rate 0.05
;; setup simulation
setup-patches
setup-agents
reset-ticks
;; initialize lists as empty
set Slist []
set predSList []
end
to go
;; update experimental values (density of susceptible individuals)
set Slist lput ((count turtles with [infected-status = 0]) / (length-of-patch ^ 2)) Slist
if (ticks = 0) ;; if ticks == 0, make sure initial value is the same as experimental
[
;; update predicted values with densities of agents
set predS ((count turtles with [infected-status = 0]) / (length-of-patch ^ 2))
set predI ((count turtles with [infected-status = 1]) / (length-of-patch ^ 2))
set predR 0
;; placeholder variables for iterative process
set oldPredS predS
set oldPredI predI
set oldPredR predR
;; store predicted S population in corresponding list
set predSList lput (predS) predSList
]
if (ticks > 0) ;; if ticks > 0, then update predicted values according to paper results
[
;; update predicted values
set predI (oldPredI + oldPredS * (1 - (1 - force-of-infection * oldPredI) ^ (pi * (infection-radius ^ 2))) - recovery-rate * oldPredI)
set predR (oldPredR + recovery-rate * oldPredI)
set predS ((total-pop / (length-of-patch ^ 2)) - predI - predR)
;; placeholder variables
set oldPredS predS
set oldPredI predI
set oldPredR predR
;; store values in corresponding list
set predSList lput (oldPredS) predSList
]
;; perform movement, infection, and recovery, in that order
move-agents
infect-agents
recover-agents
if (count turtles with [infected-status = 1] = 0) [
;; if no one else is infected, stop
stop
]
tick
end
to setup-patches
;; resize the world to make it fit comfortably in the interface
resize-world 0 length-of-patch 0 length-of-patch
set-patch-size 400 / (length-of-patch)
end
to setup-agents
;; create susceptible agents
crt (total-pop - I0) [
set infected-status 0
setxy random-pxcor random-pycor
set color 55 ;; green
set size 2
]
;; create I0 infected agents
crt I0 [
set infected-status 1
setxy random-pxcor random-pycor
set color 15 ;; red
set size 2
]
end
to move-agents ;; move all the agents
ask turtles [
setxy random-pxcor random-pycor
]
end
to infect-agents
;; iterate over infected turtles
ask turtles with [infected-status = 1] [
;; check neighborhood around infected turtle for susceptible turtles...
let numNeighbors count (turtles with [infected-status = 0] in-radius infection-radius)
if (numNeighbors > 0) [ ;; there are susceptibles around, so we perform infection
ask (turtles with [infected-status = 0] in-radius infection-radius) [
let %draw (random-float 1)
if (%draw <= force-of-infection) [ ;; probability of infection
;; infect one of the neighbors
set infected-status 1
set color 15 ;; red
]
]
] ;; end of if numneighbors > 0
]
end
to recover-agents
ask turtles with [infected-status = 1] [
let %draw (random-float 1)
if (%draw <= recovery-rate) [ ;; an agent recovered
set infected-status 2
set color 105
]
]
end
我能看到的一个问题是您有:setxy random-pxcor random-pycor
但您想要:setxy random-xcor random-ycor
基本上,您是将所有海龟放在补丁的中心,因此它们彼此重叠,而不是将它们随机分布在 space 中。该定位改变了海龟之间可能距离的分布。
我还将海龟的数量更改为 10241089,并将大小更改为 sqrt 1024(而不是 1000)以使密度匹配正确。
两者都减少了不匹配,但不清楚它们是否解决了问题,因为我没有进行大量运行。
更新
需要更多的维度匹配。更改代码以便有 1089 个代理,将 pred 计算的长度设置为 33,并将世界大小调整为最大值 32 似乎使曲线更近。这认识到补丁坐标 0 到 32 实际上描述了长度为 33 的大小,因为 NetLogo 坐标将从 -0.5 和 运行 32.5 开始,如 @Jasper
所述
这个问题会很有趣。我试图复制一个 paper 的结果,该结果与自由移动代理系统中的疾病 t运行 任务有关(听起来是 NetLogo 的完美工作)。我根据论文中给出的细节在 NetLogo 中很容易地编写了一个简单的 SIR 模型,确保我的模型参数与列出的参数匹配,并让仿真 运行。一切 运行 都很完美,直到我检查了实验结果与预测值的匹配程度(根据论文的结果)。他们离开了,而且差距相当大。我以为代码某处有错误,所以我检查了所有内容,结果发现 什么都没有。然后我确保事件的顺序是正确的(因为移动、感染和恢复的顺序很重要),并且这些也与论文相符。我仔细考虑了这个问题,直到最后我打开 R,在 RStudio 中编写完全相同的程序,让它 运行,才发现结果与预测完全吻合! R 代码与我 期望 NetLogo 代码做的事情相同,所以我认为 NetLogo 的幕后发生了一些事情,或者我在某处产生了误解偏差的...请注意,由于论文中的结果是平均场近似值,因此您必须 运行 程序几次才能接近理论结果。
我不确定哪里出错了,因为我的 R 代码确认预测值是正确的,所以我得出结论,我的 NetLogo 代码中 某处 不正确.我对 NetLogo 不太熟悉,如果有人能帮助我找到以下代码中可能发生偏差的位置,我将不胜感激。实验平均值往往低于预测值,表明感染发生的速度比预期的要快,但在我看到的所有变化中,none 解决了这个问题(例如,感染不会一次发生一个每只传染性龟)。任何 suggestions/help 将不胜感激。
我的代码的精简版如下所示。这应该 运行 在带有标准 setup/go 按钮的常规界面中。结果存储在可以绘制的列表中,任何好奇的人都可以通过 Plot 对象看到模拟过程中的偏差。提前谢谢你。
;; Simple SIR model
globals [
;; variables for storing predictions
predS
predE
predI
predR
oldPredS
oldPredE
oldPredI
oldPredR
;; list to store experimental values
Slist
;; list to store predicted values
predSList
;; model variables
length-of-patch ;; length of habitat (a square of area length-of-patch^2)
infection-radius ;; the distance from an infectious individual a susceptible agent has to be within
;; in order to risk getting infected
total-pop ;; total population in the model
force-of-infection ;; probability of infection if within infection-radius distance
I0 ;; initial infected
recovery-rate ;; probability of recovery
]
turtles-own [
infected-status ;; 0 susceptible, 1 infected, 2 recovered
]
to setup
ca ;; clear
;; define the variables
set length-of-patch 31.62278 ;; the square root of 1000 (so the density is 1)
set infection-radius 1
set total-pop 1000
set force-of-infection 0.1
set I0 10
set recovery-rate 0.05
;; setup simulation
setup-patches
setup-agents
reset-ticks
;; initialize lists as empty
set Slist []
set predSList []
end
to go
;; update experimental values (density of susceptible individuals)
set Slist lput ((count turtles with [infected-status = 0]) / (length-of-patch ^ 2)) Slist
if (ticks = 0) ;; if ticks == 0, make sure initial value is the same as experimental
[
;; update predicted values with densities of agents
set predS ((count turtles with [infected-status = 0]) / (length-of-patch ^ 2))
set predI ((count turtles with [infected-status = 1]) / (length-of-patch ^ 2))
set predR 0
;; placeholder variables for iterative process
set oldPredS predS
set oldPredI predI
set oldPredR predR
;; store predicted S population in corresponding list
set predSList lput (predS) predSList
]
if (ticks > 0) ;; if ticks > 0, then update predicted values according to paper results
[
;; update predicted values
set predI (oldPredI + oldPredS * (1 - (1 - force-of-infection * oldPredI) ^ (pi * (infection-radius ^ 2))) - recovery-rate * oldPredI)
set predR (oldPredR + recovery-rate * oldPredI)
set predS ((total-pop / (length-of-patch ^ 2)) - predI - predR)
;; placeholder variables
set oldPredS predS
set oldPredI predI
set oldPredR predR
;; store values in corresponding list
set predSList lput (oldPredS) predSList
]
;; perform movement, infection, and recovery, in that order
move-agents
infect-agents
recover-agents
if (count turtles with [infected-status = 1] = 0) [
;; if no one else is infected, stop
stop
]
tick
end
to setup-patches
;; resize the world to make it fit comfortably in the interface
resize-world 0 length-of-patch 0 length-of-patch
set-patch-size 400 / (length-of-patch)
end
to setup-agents
;; create susceptible agents
crt (total-pop - I0) [
set infected-status 0
setxy random-pxcor random-pycor
set color 55 ;; green
set size 2
]
;; create I0 infected agents
crt I0 [
set infected-status 1
setxy random-pxcor random-pycor
set color 15 ;; red
set size 2
]
end
to move-agents ;; move all the agents
ask turtles [
setxy random-pxcor random-pycor
]
end
to infect-agents
;; iterate over infected turtles
ask turtles with [infected-status = 1] [
;; check neighborhood around infected turtle for susceptible turtles...
let numNeighbors count (turtles with [infected-status = 0] in-radius infection-radius)
if (numNeighbors > 0) [ ;; there are susceptibles around, so we perform infection
ask (turtles with [infected-status = 0] in-radius infection-radius) [
let %draw (random-float 1)
if (%draw <= force-of-infection) [ ;; probability of infection
;; infect one of the neighbors
set infected-status 1
set color 15 ;; red
]
]
] ;; end of if numneighbors > 0
]
end
to recover-agents
ask turtles with [infected-status = 1] [
let %draw (random-float 1)
if (%draw <= recovery-rate) [ ;; an agent recovered
set infected-status 2
set color 105
]
]
end
我能看到的一个问题是您有:setxy random-pxcor random-pycor
但您想要:setxy random-xcor random-ycor
基本上,您是将所有海龟放在补丁的中心,因此它们彼此重叠,而不是将它们随机分布在 space 中。该定位改变了海龟之间可能距离的分布。
我还将海龟的数量更改为 10241089,并将大小更改为 sqrt 1024(而不是 1000)以使密度匹配正确。
两者都减少了不匹配,但不清楚它们是否解决了问题,因为我没有进行大量运行。
更新
需要更多的维度匹配。更改代码以便有 1089 个代理,将 pred 计算的长度设置为 33,并将世界大小调整为最大值 32 似乎使曲线更近。这认识到补丁坐标 0 到 32 实际上描述了长度为 33 的大小,因为 NetLogo 坐标将从 -0.5 和 运行 32.5 开始,如 @Jasper
所述