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 ] ]
]
]
我的模型中有大约 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 ] ]
]
]