NetLogo 创建固定数量链接的高效方式

NetLogo Efficient way to create fixed number of links

我的模型中有大约 5000 个代理人(人)。我想给他们任意数量的朋友,并进行互惠但随机的配对。因此,如果 A 选择 B,那么 B 也会选择 A。我的代码运行良好,但速度相当慢。我以后很可能会想增加朋友的数量和人数。有更快的建议吗?

ask people
[ let new-links friends - count my-links
  if new-links > 0
  [ let candidates other people with [ count my-links < friends ]
    create-links-with n-of min (list new-links count candidates) candidates
    [ hide-link ]
  ]
]

请注意,上面代码中的 friends 是一个全局变量,但我最终的代码可能会概括为将 wanted-number-of-friends 作为 people 的属性。

EDITED 添加了 if new-links > 0 条件,以便在不需要找到候选人时避免嵌套 ask。这提高了速度,但仍然无法真正扩展。

好问题。这实际上很难优化。有问题的行是:

let candidates other people with [ count my-links < friends ]

这很慢,因为它让每个代理都与其他代理进行检查。如果有 5000 个代理,那就是 25,000,000 张支票!不幸的是,如果没有一些奇特的数据结构,就没有真正优化这一特定行的好方法。

幸运的是,有一个解决方案可以很好地概括为在网络中生成任何度数分布(听起来这就是您最终想要的)。不幸的是,该解决方案不能很好地转换为 NetLogo。不过这里是:

  let pairs [] ;; pairs will hold a pairs of turtles to be linked
  while [ pairs = [] ] [ ;; we might mess up creating these pairs (by making self loops), so we might need to try a couple of times
    let half-pairs reduce sentence [ n-values friends [ self ] ] of turtles ;; create a big list where each turtle appears once for each friend it wants to have
    set pairs (map list half-pairs shuffle half-pairs) ;; pair off the items of half-pairs with a randomized version of half-pairs, so we end up with a list like: [[ turtle 0 turtle 5 ] [ turtle 0 turtle 376 ] ... [ turtle 1 turtle 18 ]]
    ;; make sure that no turtle is paired with itself
    if not empty? filter [ first ? = last ? ] pairs [
      set pairs []
    ]
  ]
  ;; now that we have pairs that we know work, create the links
  foreach pairs [
    ask first ? [
      create-link-with last ?
    ]
  ]

这里的friends是全局变量还是turtle变量都没有关系。这花费的时间取决于它需要尝试配对的次数,这是随机的。通过实验,我发现 5000 个代理通常大约需要 3 秒,每个代理的度数为 5。相比之下,在我的机器上使用您原来的方式执行此操作大约需要 60 秒(就其价值而言,这就是我想要的方式建议在使用较少代理时使用)。

经过调试(见),下面的版本比较高效。它为仍然需要链接的海龟构建一个代理集(下面称为 lonely),并在它们获得足够的链接时删除它们。删除单个海龟比每次创建候选集的嵌套过程更有效。

变量 nFriends 是一个全局变量(在原始模型中有一个滑块),它是链接的目标数量,对所有代理都是相同的。

  let lonely turtles with [count my-links < nFriends]
  ask turtles
  [ set lonely other lonely
    let new-links nFriends - count my-links
    if new-links > 0
    [ let chosen n-of min (list new-links count lonely) lonely
      create-links-with chosen [ hide-link ]
      ask chosen [ if count my-links = nFriends [ set lonely other lonely ] ]
    ]
  ]