如何在NetLogo中利用O/D矩阵实现智能体跨区域迁移?代码优化问询
关于NetLogo中O/D矩阵优化与智能体跨区域移动的问题
我手头有一个用于人员跨区域移动的O/D矩阵,想用NetLogo的matrix扩展先搭个简易模型,但写出来的代码太冗余了。另外我也想搞清楚,怎么利用这个O/D矩阵把来自"area x"的智能体精准发送到"area y"。
下面是我目前写的NetLogo代码:
extensions [matrix] globals [mat] patches-own [location] turtles-own [residency] to setup ca reset-ticks ask patches [ if pxcor >= 0 and pycor >= 0 [set pcolor black + 0 set location "ne" ] if pxcor < 0 and pycor >= 0 [set pcolor black + 1 set location "nw" ] if pxcor < 0 and pycor < 0 [set pcolor black + 2 set location "sw" ] if pxcor >= 0 and pycor < 0 [set pcolor black + 3 set location "se" ] ] ask n-of 40 patches [ sprout 1 [ set shape "person student" set heading random 360 set residency [location] of patch-here if residency = "nw" [set color yellow + 2] ] ] set-matrix end to set-matrix set mat matrix:from-row-list [[0.5 0.3 0.1 0.1][0.3 0.5 0.1 0.1][0.1 0.1 0.5 0.2][0.1 0.1 0.2 0.5]] print matrix:pretty-print-text mat ; 打印出来的矩阵格式大概是这样: ; nw ne sw se ;nw 0.5 0.3 0.1 0.1 ;ne 0.3 0.5 0.1 0.1 ;sw 0.1 0.1 0.5 0.2 ;se 0.1 0.1 0.2 0.5 end to go ifelse(ticks mod 240 <= 120)[move-out][come-home] tick end to move-out ;; 西北区域居民的移动逻辑(目前只写了一部分) let n-of-nw count turtles with [residency = "nw"] let %nw-nw matrix:get mat 0 0 let %nw-ne matrix:get mat 0 1 let %nw-sw matrix:get mat 0 2 let %nw-se matrix:get mat 0 3 ask n-of (%nw-nw * n-of-nw) turtles with [residency = "nw"] [rt 45 lt 45 set heading random 360 fd 2 face min-one-of patches with [location = "nw"] [distance myself]] ; 后面其他区域的代码还没写完,但能想到会非常重复 end
优化方案与实现思路
1. 消除冗余代码:用列表映射区域与矩阵索引
首先,我们可以把区域名称和对应的矩阵索引做成一个关联列表,这样就不用为每个区域单独写重复的移动逻辑了:
; 新增全局列表,关联区域名和矩阵索引 globals [area-index-map] ; 在setup里初始化这个映射 to setup ; ... 保留原来的setup代码 ... set area-index-map [["nw" 0] ["ne" 1] ["sw" 2] ["se" 3]] set-matrix end
2. 通用的智能体移动函数
接下来写一个通用的移动函数,根据O/D矩阵的概率,自动处理任意区域的智能体分配:
to move-from-area [source-area] ; 获取源区域对应的矩阵行索引 let source-index last first filter [first ? = source-area] area-index-map ; 筛选源区域的所有智能体 let source-turtles turtles with [residency = source-area] let num-source count source-turtles ; 如果该区域没有智能体,直接终止函数 if num-source = 0 [stop] ; 遍历所有目标区域,按概率移动智能体 foreach area-index-map [ let target-area first ? let target-index last ? let move-prob matrix:get mat source-index target-index ; 计算要移动的智能体数量(用round处理小数转整数) let num-to-move round (move-prob * num-source) ; 选择对应数量的智能体,移动到目标区域的随机地块 ask n-of num-to-move source-turtles [ move-to one-of patches with [location = target-area] ; 如果需要更新智能体当前所在区域,可以在这里添加: ; set residency target-area ] ] end
之后在move-out里,只需要一行代码就能处理所有区域:
to move-out ; 对每个区域调用通用移动函数 foreach ["nw" "ne" "sw" "se"] [move-from-area ?] end
3. 精准发送智能体到指定区域
如果需要单独把"area x"的智能体发送到"area y",可以基于上面的逻辑写一个针对性函数:
to move-from-to [source-area target-area] let source-index last first filter [first ? = source-area] area-index-map let target-index last first filter [first ? = target-area] area-index-map let move-prob matrix:get mat source-index target-index let source-turtles turtles with [residency = source-area] let num-to-move round (move-prob * count source-turtles) ask n-of num-to-move source-turtles [ move-to one-of patches with [location = target-area] ] end ; 调用示例:把nw区域的智能体按矩阵概率发送到ne区域 ; move-from-to "nw" "ne"
4. 其他小优化
- 可以把区域颜色也做成映射列表,比如
set area-color-map [["nw" yellow + 2] ["ne" blue] ["sw" green] ["se" red]],在sprout智能体时直接根据residency取对应颜色,避免重复的if判断。 - 处理概率计算的小数问题:如果
move-prob * num-source不是整数,用round或者floor/ceil调整,避免出现非整数的智能体数量。
内容的提问来源于stack exchange,提问作者mrsensible
相关产品推荐
相关产品推荐

