NetLogo疏散模拟问题:乘客行为异常与Setup按钮报错排查
NetLogo疏散模拟问题修复方案
一、Setup按钮报错修复
报错原因
choose-exit过程中构建PP列表的语法错误:(patch-set [neighbors4] of lucky-exit with [accessible?])错误地将筛选逻辑嵌套在patch-set内部,导致NetLogo将单个patch识别为agentset输入,触发类型不匹配错误。
修复方法
将PP列表的构建改为直接对出口的4邻域patch集进行筛选,正确代码如下:
; 修正PP列表构建逻辑 let pp-list neighbors4 of lucky-exit with [accessible?]
二、乘客智能移动修复(解决徘徊、越界问题)
问题根源
- 每次
go循环都会重新调用choose-exit,导致乘客频繁更换目标,方向反复变化出现徘徊; move过程未判断patch-ahead是否存在(边界外情况),导致越界;- 到达LPP后未继续朝向出口,而是重新计算目标,导致停滞。
修复方法
- 调整
go逻辑,仅当乘客未到达目标区域时才重新计算目标:
to go type "----------------------------[GO.tick]\n" ask passengers [ if panic? and not safe? [ ; 仅未到达出口或其邻域时重新选择目标 if not (patch-here = target-exit or member? patch-here neighbors4 of target-exit) [ set target-exit choose-exit patch-here ] face target-exit ] move ] tick end
- 完善
move过程,增加边界与可达性判断:
to move if panic? and not safe? [ let next-patch patch-ahead 1 ; 确保下一个patch存在、可达且无其他乘客 if next-patch != nobody and [accessible?] of next-patch and not any? other passengers-here [ move-to next-patch ; 到达出口标记为安全 if member? patch-here exits-list [ set safe? true set color green ; 用颜色直观标记安全状态 ] ] ] end
- 调整
choose-exit逻辑,让LPP作为临时目标,出口作为长期目标:
to-report choose-exit [current-position] ; ... 保留原有计算最近出口、权重选择出口的逻辑 ... ; 计算出口的PP集合(4邻域可达patch) let pp-list neighbors4 of lucky-exit with [accessible?] let M count pp-list ; PP为空时直接选择出口作为目标 let lpp ifelse-value (M > 0) [one-of pp-list] [lucky-exit] face lpp set my-exits-list lput lucky-exit my-exits-list ; 返回出口作为长期目标,确保乘客最终朝向出口移动 report lucky-exit end
三、完善PP/LPP机制实现
核心实现逻辑
- PP定义:出口的4邻域中
accessible? = true的patch,确保仅包含可达区域; - LPP选择:使用
one-of pp-list实现均等概率选择(每个PP被选中概率为1/M,M为PP数量); - 边界处理:当PP为空(如出口被阻挡)时,直接将出口设为目标,避免无有效移动方向。
修改后的choose-exit中PP/LPP相关代码:
; 计算出口的PP集合 let pp-list neighbors4 of lucky-exit with [accessible?] let M count pp-list ; 处理PP为空的边界情况 let lpp ifelse-value (M > 0) [one-of pp-list] [lucky-exit] ; 朝向LPP移动 face lpp
完整修复后代码
breed [ passengers passenger] breed [ fire-spots a-fire-spot] breed [ smoke-spots a-smoke-spot] globals [ exit1 ;; pID exit2 ;; pID exits-list ;; [ pID ... ] passenger_count ;; integer exit-probabilities ;; [probability ...] ] passengers-own [ in-seat? ;; boolean safe? ;; boolean dead? ;; boolean panic? ;; boolean current-heading ;; turtleHDG target-exit ;; pID my-exits-list ;; [ pID ... ] item? ;; boolean ] patches-own [ accessible? ;; boolean fire? ;; boolean ] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; FUNZIONI SETUP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to setup __clear-all-and-reset-ticks type "----------------------------[SETUP]\n" initialize-globals initialize-train initialize-exits initialize-passengers ; initialize-fire reset-ticks end to initialize-globals set exit1 patch 64 -13 set exit2 patch 13 -54 set exits-list ( list exit1 exit2 ) set exit-probabilities (list 0.5 0.5) end to initialize-train import-pcolors "images/ambiente.png" ask patches [ if pcolor = 86.6 [set pcolor cyan] if pcolor = 0 [set pcolor black] if pcolor = 64.3 [set pcolor green] if pcolor = 9.9 [set pcolor white] set fire? false set accessible? false ; 默认所有patch不可达 ] ask patches with [pcolor = white] [ set accessible? true ; 白色patch标记为可达 ] end to initialize-exits set exit1 patch 64 -13 set exit2 patch 13 -54 set exits-list (list exit1 exit2) end to initialize-passengers create-passengers passenger-count [ set shape "person business" set size 2 set color yellow set in-seat? false set safe? false set dead? false set panic? true set current-heading 0 set my-exits-list [] set target-exit nobody ; 随机放置在可达patch上 let target one-of patches with [accessible?] move-to target set target-exit choose-exit patch-here update-exit-probabilities self ] end to-report choose-exit [current-position] let possible-exits [] let shortest-distance 10000 let nearest-exit nobody foreach exits-list [ exitUnderTest -> let exit-distance distance exitUnderTest if exit-distance < shortest-distance [ set shortest-distance exit-distance set nearest-exit exitUnderTest set possible-exits [] ] if exit-distance = shortest-distance [ set possible-exits lput exitUnderTest possible-exits ; 直接存储patch对象,减少转换错误 ] ] if length possible-exits = 0 [ print "No exits found." report nobody ] ; 按权重选择出口 let lucky-exit one-of weighted-n-of 1 possible-exits exit-probabilities set target-exit lucky-exit ; 计算PP集合并选择LPP let pp-list neighbors4 of lucky-exit with [accessible?] let M count pp-list let lpp ifelse-value (M > 0) [one-of pp-list] [lucky-exit] face lpp set my-exits-list lput lucky-exit my-exits-list report lucky-exit ; 返回出口作为长期目标 end to update-exit-probabilities [passenger1] let kie 1.5 ; 修正参数引用错误:使用传入的passenger1而非未定义的passenger let initial-exit [target-exit] of passenger1 let initial-exit-index position initial-exit exits-list if initial-exit-index = false [ print "Error: Exit not found in exits-list" stop ] let initial-exit-probability item initial-exit-index exit-probabilities let pie kie * initial-exit-probability if pie > 1 [ set pie 1 ] let delta-pi pie - initial-exit-probability let updated-exit-probabilities [] foreach exit-probabilities [p -> let index position p exit-probabilities if index = initial-exit-index [ set updated-exit-probabilities lput pie updated-exit-probabilities ] [ let pje p - (p / (1 - initial-exit-probability)) * delta-pi ; 确保概率不小于0 if pje < 0 [ set pje 0 ] set updated-exit-probabilities lput pje updated-exit-probabilities ] ] set exit-probabilities updated-exit-probabilities end ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; FUNZIONI GO ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to go type "----------------------------[GO.tick]\n" ask passengers [ if panic? and not safe? [ ; 仅未到达出口或其邻域时重新选择目标 if not (patch-here = target-exit or member? patch-here neighbors4 of target-exit) [ set target-exit choose-exit patch-here ] face target-exit ] move ] tick end to move if panic? and not safe? [ let next-patch patch-ahead 1 ; 确保下一个patch存在、可达且无其他乘客 if next-patch != nobody and [accessible?] of next-patch and not any? other passengers-here [ move-to next-patch ; 到达出口标记为安全 if member? patch-here exits-list [ set safe? true set color green ] ] ] end
额外修复点
- 修正
update-exit-probabilities中的参数引用错误,避免变量未定义; - 在
choose-exit中直接存储patch对象而非坐标列表,减少转换错误; - 增加概率下限判断,避免
exit-probabilities出现负值。
内容的提问来源于stack exchange,提问作者accismns
相关产品推荐
相关产品推荐

