NetLogo中变更breed的海龟仍被ask调用的问题求解
解决NetLogo中变更breed的海龟被原breed ask调用的问题
原代码与问题说明
原代码定义了turtles1和turtles2两个breed,在go过程中让turtles1随机将另一只turtles1转为turtles2:
breed [turtles1 turtle1] breed [turtles2 turtle2] to setup clear-all random-seed 1 create-turtles1 5 [set shape "circle" setxy random 30 random 30] reset-ticks end to go ask turtles1[ print "first" print who if any? other turtles1 [ ask one-of other turtles1 [set breed turtles2 set shape "square" print "other" print who] ] ] end
问题在于:ask turtles1 []会收集当前所有turtles1的代理列表并遍历,但在遍历过程中,部分代理的breed被改为turtles2后,这些已变更的代理仍会执行ask块内的代码(比如示例中who=0被改为turtles2后,依然触发后续逻辑导致who=1也被转换)。
解决方案
方案1:提前创建turtles1的快照集合
先将当前所有turtles1存入临时集合,再遍历这个固定的集合。后续breed的变更不会影响遍历对象:
to go let original-turtles1 turtles1 ; 创建初始turtles1的快照集合 ask original-turtles1 [ print "first" print who ; 检查自身是否仍属于turtles1,避免被其他代理提前转换后执行逻辑 if breed = turtles1 [ if any? other turtles1 [ ask one-of other turtles1 [ set breed turtles2 set shape "square" print "other" print who ] ] ] ] end
方案2:在ask块内先检查自身breed
每个turtle1执行逻辑前,先判断自己是否仍属于turtles1,已变更则直接跳过后续操作:
to go ask turtles1 [ if breed != turtles1 [ stop ] ; 已变更breed则退出当前代理的逻辑 print "first" print who if any? other turtles1 [ ask one-of other turtles1 [ set breed turtles2 set shape "square" print "other" print who ] ] ] end
方案3:使用foreach遍历快照集合
NetLogo的foreach基于初始集合遍历,不受后续代理属性变化影响,结合sort可确保遍历顺序稳定:
to go foreach sort turtles1 [ [t] -> ask t [ if breed = turtles1 [ print "first" print who if any? other turtles1 [ ask one-of other turtles1 [ set breed turtles2 set shape "square" print "other" print who ] ] ] ] ] end
以上方案均可有效阻止已变更breed的海龟执行原breed的ask逻辑,其中方案1、3通过固定初始集合避免问题,方案2通过实时检查过滤已变更代理。
内容的提问来源于stack exchange,提问作者Kevin A
相关产品推荐
相关产品推荐

