首页 > 解决方案 > 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)]]
  ]

我认为半径内可能至少是问题之一——我不确定它是否可以这样使用。

标签: while-loopnetlogo

解决方案


更新:更简单的方法

我将最初的回复保留在下面不变,但是请注意可以采取更简单的方法:

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再次改变)。


推荐阅读