NetLogo病毒传播模型开发:多因素感染概率计算与接触时长追踪技术问询
解决NetLogo病毒传播模型中的感染概率计算与接触时长跟踪问题
当然可以实现你想要的功能!针对你遇到的两个核心难点——调用范围内感染者的属性、准确跟踪接触时长,我给你两种实用解决方案,一种是不使用链接的高效方案(更适合追求模型运行速度的场景),另一种是修正后的链接实现思路,你可以根据需求选择。
不使用链接的高效解决方案(推荐)
这种方法不需要创建链接,通过给易感者维护接触记录列表来跟踪时长,同时直接遍历范围内的感染者获取属性,性能更优。
1. 先定义必要的海龟变量
首先给海龟添加所需属性,包括跟踪接触时长的列表:
turtles-own [ susceptible? ; 是否易感 infected? ; 是否感染 age-susceptibility ; 易感者的易感性属性 infectivity ; 感染者的传染性属性 exposure-timers ; 存储接触记录,格式为 [[感染者ID 接触时长] ...] ]
在setup过程中初始化exposure-timers:
to setup ; 其他初始化代码... ask turtles [ set exposure-timers [] ; 根据你的模型设置初始的susceptible?、infected?等属性 ] end
2. 完整的transmit过程实现
这个过程会完成接触时长更新、感染者属性调用、感染概率计算的全流程:
to transmit ; 非易感者直接跳过,减少不必要计算 if not susceptible? [ stop ] ; 获取当前半径2范围内的所有感染者 let nearby-infected turtles in-radius 2 with [infected?] let nearby-infected-ids [who] of nearby-infected ; 步骤1:更新现有接触记录——移除不在范围内的感染者,剩余记录的时长+1 set exposure-timers filter [member? (first ?) nearby-infected-ids] exposure-timers set exposure-timers map [list (first ?) (last ? + 1)] exposure-timers ; 步骤2:添加新进入范围的感染者,初始接触时长设为1 let newly-exposed filter [not member? ? [first] of exposure-timers] nearby-infected-ids foreach newly-exposed [ set exposure-timers lput (list ? 1) exposure-timers ] ; 步骤3:计算总感染风险 let total-risk 0 ; 遍历每个接触的感染者,计算单个感染风险 foreach exposure-timers [ let infected-turtle turtle first ? let infectivity-value [infectivity] of infected-turtle let time-exposed last ? ; 应用你给出的核心公式计算单个风险 let single-risk infectivity-value * time-exposed * age-susceptibility ; 确保单个风险不超过1,避免数值异常 set single-risk min (list single-risk 1) ; 用1 - product(1 - p_i)计算总风险(避免多个风险相加超过1的问题) set total-risk 1 - (1 - total-risk) * (1 - single-risk) ] ; 步骤4:判断是否感染 if random-float 1 < total-risk [ set infected? TRUE set susceptible? FALSE set exposure-timers [] ; 感染后清空接触记录 ] end
注意:多个感染者的总感染概率不能直接相加(会超过1),用1 - product(1 - p_i)可以准确计算出至少被一个感染者感染的概率,更符合病毒传播的实际逻辑。
修正后的链接实现方案
如果你还是想使用链接来跟踪接触时长,下面是修正后的代码,解决了你之前无法删除超出范围链接的问题:
1. 定义链接变量
给链接添加跟踪接触时长的属性:
links-own [ contact-duration ; 记录当前链接对应的接触时长 ]
2. 修正后的transmit过程
to transmit if not susceptible? [ stop ] let nearby-infected turtles in-radius 2 with [infected?] ; 步骤1:删除与不在范围内的感染者的链接 ask link-neighbors with [not member? self nearby-infected] [ ask link-with myself [ die ] ] ; 步骤2:更新现有链接的接触时长 ask link-neighbors with [member? self nearby-infected] [ ask link-with myself [ set contact-duration contact-duration + 1 ] ] ; 步骤3:与新进入范围的感染者创建链接,初始时长设为1 let new-infected filter [not link-with ? exists?] nearby-infected create-links-with new-infected [ set contact-duration 1 ] ; 步骤4:计算总感染风险 let total-risk 0 ask link-neighbors with [infected?] [ let infectivity-value [infectivity] of self let time-exposed [contact-duration] of link-with myself let single-risk infectivity-value * time-exposed * [age-susceptibility] of myself set single-risk min (list single-risk 1) set total-risk 1 - (1 - total-risk) * (1 - single-risk) ] ; 步骤5:判断是否感染 if random-float 1 < total-risk [ set infected? TRUE set susceptible? FALSE ask link-neighbors [ ask link-with myself [ die ] ] ; 感染后删除所有链接 ] end
性能优化提示
如果你模型中的海龟数量较多,想要进一步提升运行速度,可以参考这些小技巧:
- 优先选择不使用链接的方案,链接会增加模型的计算和存储开销,尤其是海龟数量大的时候
- 可以缩小
in-radius的检查范围,或者通过patch来辅助:让海龟记录所在patch,只检查相邻patch内的海龟,减少需要遍历的数量 - 避免在同一个过程中重复计算
nearby-infected,可以将结果缓存到变量中复用
内容的提问来源于stack exchange,提问作者Johanna
相关产品推荐
相关产品推荐

