是否可以要求代理离开代理集而不依赖于它们在 NetLogo 中的变量?

Is it possible to ask agents to leave an agentset without relying on their variables in NetLogo?

尽管 NetLogo 有一套很好的 primitives allowing for the handy creation of agentsets,但有时我们可能希望代理 'manually' 将自己添加到代理集,作为过程的一部分,它们是 运行 -例如,通过使用 turtle-set.

示例:

globals [
 good-folks
 bad-folks 
]

to setup
  clear-all
  
  set good-folks (turtle-set)
  set bad-folks (turtle-set)
  
  create-turtles 50 [
   ifelse (random 2 < 1)
    [set good-folks (turtle-set good-folks self)]
    [set bad-folks (turtle-set bad-folks self)] 
  ]
end

to go
  ask good-folks [
   do-good-things 
  ]
  
  ask bad-folks [
   do-bad-things 
  ]
end

to do-good-things end
to do-bad-things end

上述方法的优点是可读性更好,可以避免必须创建海龟自己的变量并避免必须求助于 withif 语句 - 如下所示:

turtles-own [
 group 
]

to setup
  clear-all
  
  create-turtles 50 [
   ifelse (random 2 < 1)
    [set group "good folks"]
    [set group "bad folks"]
  ]
end

to go1
  ask turtles with [group = "good folks"] [
   do-good-things 
  ]
  
  ask turtles with [group = "bad folks"] [
   do-bad-things 
  ]
end

; OR

to go2
  ask turtles [
   ifelse (group = "good folks")
    [do-good-things]
    [do-bad-things]
  ]
end

to do-good-things end
to do-bad-things end

特别是,在我看来,后一种方法的扩展不如前一种方法顺利,即更多的组将需要更多的 withs 或 ifs,而不仅仅是能够整齐地引用需要的组。

但是,我不知道有什么方法可以做与 set good-folks (turtle-set good-folks self) 完全相反的事情,即要求乌龟 'manually' 从代理集中删除自己。

; In this case, bad-folks try to recruit some good folks
to do-bad-things
  if (random 3 < 2) [
   ask one-of good-folks [
     set good-folks (turtle-set good-folks - self) ; Leave the good folks <- **How to do this?**
     set bad-folks (turtle-set bad-folks self) ; Join the bad folks
    ] 
  ]
end

我知道这可以通过使用 turtles-own 变量然后将代理集更新为 set <good/bad>-folks turtles with [...] 来实现,但这正是我在这个问题中试图避免的全部事情:可读性较差,更多变量,更多命令等。而且,也许同样重要的是,它看起来与 turtle-set 可以通过与 self 结合使用来增加代理集的用途不一致。如果存在从代理集中减去 self 的方法,它看起来会更容易和更一致 - 它存在吗?

更新

Jasper 的解决方案(即使用品种而不是代理集)只要我想跟踪的组是相互排斥的:代理从一个单一品种切换到另一个单一品种只需要 set breed ...,这将使代理人加入新品种 离开他们以前的品种。但是,如果我想跟踪具有重叠的多个组,这将不起作用:除了 good-folksbad-folks,我可能有 tall-folksshort-folks。代理必须同时属于多个组 - 代理集可以处理而品种不能处理的事情。

也许我遗漏了一些你的要求,但品种不会让你很容易做到这一点吗?您可以 use set breed BREED-NAME to change it,它会自动将海龟从其现有品种中移除(如果有的话)。你甚至可以删掉更多的代码,我认为它看起来更清晰,如果那是你的目标。

breed [ good-folks goodie ]
breed [ bad-folks  baddie ]

to setup
  clear-all
  
  create-turtles 50 [
    ifelse (random 2 < 1) [
      set breed good-folks
    ] [
      set breed bad-folks
    ]
  ]
end

to go
  ask good-folks [
   do-good-things 
  ]
  
  ask bad-folks [
   do-bad-things 
  ]
end

to do-good-things end
  
to do-bad-things
  if (random 3 < 2 and any? good-folks) [
    ask one-of good-folks [
      set breed bad-folks  
    ] 
  ]
end

Jasper 的回复后我的一些思路得到的答案其实很简单,只需要 other:

to do-bad-things
  if (random 3 < 2) [
   ask one-of good-folks [
     set good-folks (turtle-set other good-folks) ; Leave the good folks
     set bad-folks (turtle-set bad-folks self) ; Join the bad folks
    ] 
  ]
end

额外廉价的想法

这也让我觉得如果 NetLogo 有两个原语 joinleave 会很方便,它们的工作方式如下:

to join [agentset]
  (ifelse
    is-turtle? self [
     set agentset (turtle-set agentset self)
    ]
    is-patch? self [
     set agentset (patch-set agentset self)
    ]
    ; else command:
    [set agentset (link-set agentset self)])
end

to leave [agentset]
  (ifelse
    is-turtle? self [
     set agentset (turtle-set other agentset)
    ]
    is-patch? self [
     set agentset (patch-set other agentset)
    ]
    ; else command:
    [set agentset (link-set other agentset)])
end

这样可以做到:

to do-bad-things
  if (random 3 < 2) [
   ask one-of good-folks [
     leave good-folks
     join bad-folks
    ] 
  ]
end

感觉更像是在读书而不是在读代码;虽然我认识到最终对它的需求真的很小。