Netlogo 计算所有接触的类型的海龟

Netlogo calculate all turtles of a type that are touching

在 Netlogo 中,我有一个全部接触的海龟网格,我想计算形成每个绿海龟簇(在其他颜色中)的绿海龟数量(下面代码中的 MHC = 3)。也许我的做法全错了,但似乎很难。

我试过将 while 循环设计为从单个绿色单元格(未连接到任何先前的绿色集群)开始并为其海龟自己的变量分配一个数字 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

之前

Click to see image

之后

Click to see image

in-radius呢?

虽然寻找 turtles in-radius 1 的海龟会发现站在任何直接相邻的斑块上的海龟似乎很直观,但事实并非如此:in-radius [= 的输入数字47=] - 即不是需要交叉的补丁数。

就距离而言,站在水平或垂直相邻块上的海龟的距离为 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。虽然在一种情况下它只是 patches in-radius 1,您可以将其替换为 neighbors,但在另一种情况下它是 turtles in-radius 4。在后一种情况下,您可能需要考虑距离因素的影响。

关于代码的最后说明

只是为了确定一下:您确定 to rules 中的顺序是您想要的吗?对于现在的情况,海龟改变了它们的 MHC 值,但仅在随后的一轮 go 中改变了颜色(但是,到那时,它们将再次改变 MHC)。