while-loop - Netlogo 计算所有接触的海龟类型
问题描述
在 Netlogo 中,我有一个全部接触的海龟网格,我想计算形成每个绿海龟集群(在其他颜色中)的绿海龟的数量(下面代码中的 MHC = 3)。也许我做错了,但这似乎非常非常困难。
我尝试过设计为从单个绿色单元(未连接到任何先前的绿色集群)开始的 while 循环,并将一个数字分配给它的 turtles-own 变量block
。然后每个绿色邻居in-radius 1
收到相同的号码,依此类推,直到每个接触的绿色单元格收到相同的号码。然后下一个集群将收到一个新号码并重新开始。但是,除非这只是一个糟糕的包围问题,否则它似乎真的不起作用。这是功能代码(它只是创建颜色变化的海龟网格):
turtles-own[MHC block]
globals[prWound]
to set-up
clear-all
reset-ticks
ask patches [sprout 1 [set color magenta]]
ask turtles [set MHC 2]
set prWound 0.0001
end
to rules
ask turtles with [MHC = 0][set color red]
ask turtles with [MHC = 1][set color green]
ask turtles with [MHC = 2][set color magenta]
ask turtles with [MHC = 3][set color blue]
ask turtles with [MHC = 4][set color orange]
ask turtles [if random 100 < 1 [set MHC (random 5)] ;vary MHC betwen 0-4,
set block 0
if random-float 1 < prWound [ask turtles in-radius 4 [die] die]
if any? patches in-radius 1 with [not any? turtles-here] and random 100 < 50 [if random 100 < 2.5
[set MHC (random 5)] hatch 1 [move-to one-of patches in-radius 1 with [not any? turtles-here]
]
tick
end
to go
rules
end
这是我尝试添加block
无法使用的值的部分(在勾号之前添加):
ask turtles with [MHC = 1][
if block = 0 [set block (max([block] of turtles) + 1) ]
while [any? [turtles with [MHC = 1 and block = 0] in-radius 1] of turtles with [block = [block] of myself]]
[if any? [turtles with [MHC = 1 and block = 0] in-radius 1] of turtles with [block = [block] of myself]
[set block ([block] of myself)]]
]
我认为半径内可能至少是问题之一——我不确定它是否可以这样使用。
解决方案
更新:更简单的方法
我将最初的回复保留在下面不变,但是请注意可以采取更简单的方法:
to count-blocks
set block-now 0
ask turtles [set block 0]
while [any? turtles with [condition]] [
set block-now block-now + 1
ask one-of turtles with [condition] [
join-and-search
]
]
end
to join-and-search
set block block-now
if any? (turtles-on neighbors) with [condition] [
ask (turtles-on neighbors) with [condition] [
join-and-search
]
]
end
to-report condition
ifelse (color = green and block = 0)
[report TRUE]
[report FALSE]
end
需要注意的是,虽然while
在这种情况下只使用了一次,但to join-and-search
实际上是通过调用自身创建了一个循环,执行的递归调用只if any? (turtles on neighbor) with [condition]
存在;这使得candidate?
这里不需要该段落(即成为候选人,招募候选人,停止成为候选人)。
我认为在这种情况下只需要一个警告:我不知道让过程自己调用是否是最佳实践。一方面,这听起来像是值得标记的东西;另一方面,在我看来,这join-and-search
不会比任何其他以奇怪条件构建的循环更成问题。
初步答复
在尝试解决这个问题时,我自己发现了一些我没有考虑过的事情in-radius
,而且肯定存在部分问题。
然而,在公开之前,让我说我不确定这in-radius
件事是否是你尝试的所有错误:当我发现它时,我已经采取了我的方法来解决这个问题。
然而,一般来说,有一条建议:保持代码尽可能整洁和可读(包括缩进)——发现问题所在变得容易得多。
也就是说,我的方法的主要元素:
- 两个
while
循环:第一个循环检查整个模拟中是否有任何符合条件的海龟将启动一个新的block
;第二个(嵌套在第一个中)检查是否还有任何海龟要分配给当前block
正在评估的海龟。 - 一个
candidate?
turtles-own
变量,构成第二个while
循环的条件。当被分配到一个块时,每个海龟也会搜索它的邻居。如果有任何海龟应该添加到当前块中,那么这些海龟将candidate? = TRUE
重新开始内部循环。 - 此外,我在许多具有相关名称的过程中拆分了相对较少的命令。这使得代码更具可读性但也更具可扩展性:当您要扩展模型的变量、代理集、条件等时,将代码行添加到分配的部分并检查特定部分是否正在处理它会更容易自己的。
to-report condition
全局变量的block-now
存在主要是为了可读性。- 到目前为止,此代码每次都会重新计算块数
go
(并且块可能会在一次迭代go
和另一次迭代之间改变数量)。肯定有可能使该方法适应您希望在go
迭代中保留块数的情况。
globals [
prWound
block-now
]
turtles-own [
MHC
block
candidate?
]
to setup
clear-all
reset-ticks
ask patches [sprout 1 [set color magenta]]
ask turtles [set MHC 2]
set prWound 0.0001
end
to go
rules
count-blocks
tick
end
to rules
ask turtles with [MHC = 0][set color red]
ask turtles with [MHC = 1][set color green]
ask turtles with [MHC = 2][set color magenta]
ask turtles with [MHC = 3][set color blue]
ask turtles with [MHC = 4][set color orange]
ask turtles [
if random 100 < 1 [set MHC (random 5)]
set block 0
if random-float 1 < prWound [ask turtles in-radius 4 [die] die]
if any? patches in-radius 1 with [not any? turtles-here] and random 100 < 50 [
if random 100 < 2.5 [
set MHC random 5
]
hatch 1 [move-to one-of patches in-radius 1 with [not any? turtles-here]]
]
]
end
to count-blocks
set block-now 0
ask turtles [
set block 0
]
while [any? turtles with [condition]] [start-count-round]
end
to start-count-round
set block-now (block-now + 1)
ask turtles [
set candidate? FALSE
]
ask one-of turtles with [condition] [set candidate? TRUE]
while [any? turtles with [candidate?]] [
ask turtles with [candidate?] [
join
search
conclude
]
]
end
to join
set block block-now
end
to search
let target (turtles-on neighbors) with [condition and not candidate?]
ask target [set candidate? TRUE]
end
to conclude
set candidate? FALSE
end
to-report condition
ifelse (color = green and block = 0)
[report TRUE]
[report FALSE]
end
前
后
怎么样in-radius
?
虽然看起来很直观,海龟寻找turtles in-radius 1
会发现海龟站在任何直接相邻的斑块上,但事实并非如此:输入数字in-radius
实际上是一个距离- 即不是需要跨越的斑块数量.
就距离而言,站在水平或垂直相邻的斑块上的海龟距离为 1。相反,站在对角相邻的斑块上的乌龟距离为 1.4:
observer> clear-all
observer> ask patch 0 0 [sprout 1]
observer> ask patch 0 1 [sprout 1]
observer> ask patch 1 1 [sprout 1]
observer> ask turtle 0 [show distance turtle 1]
(turtle 0): 1
observer> ask turtle 0 [show distance turtle 2]
(turtle 0): 1.4142135623730951
这就是为什么在我替换let target turtles in-radius 1 with [condition and not candidate?]
为let target (turtles-on neighbors) with [condition and not candidate?]
.
请注意,您in-radius
在共享的第一块代码中使用了两次。虽然在一种情况下是 just patches in-radius 1
,您可以用 替换neighbors
,但在另一种情况下是turtles in-radius 4
。在后一种情况下,您可能需要考虑该距离的影响。
关于代码的最后说明
只是为了确保:你确定事情的顺序to rules
是你想要的吗?对于现在的情况,海龟会改变它们的MHC
值,但只会在随后的一轮中改变颜色go
(但到那时,它们会MHC
再次改变)。