1

我有一个模型适用于少于 100 个代理(20 * 20 个世界大小),但我现在的模型要求之一是针对不同的代理组测试我的模型,我需要有超过 100 个代理(和 40 * 40 世界大小)。我尝试单独优化每个功能,但恐怕在不破坏模型要求的情况下我可以改变任何东西。

在当前版本中,我使用链接来跟踪代理关系,并且每个代理可以拥有的链接数量没有限制,因此链接数量增长非常快(超过 2000 个链接),需要更新每个链接的每次交互后的关系值。

关于在我的模型中使用链接的更多细节:

  • 代理之间创建/更新链接的价值和频率,如果他们有社交互动

    如果许多代理观察到该代理的异常社交活动,则许多代理会创建或更新其与该代理的链接值和频率(已定义这些活动的不同组,并且将根据活动类型调用不同的操作)

    代理在同一块中时会观察同位代理链接的值,并据此可能有不同类型的社交互动

    一定年龄范围内的代理会根据他们的链接值和其他标准找到一个伴侣。

也许还有一些我现在不记得了,但是链接的值在每个滴答中被多次调用,代理生命周期为 4000,模拟长度为 40000 个滴答,对于 100 个代理,运行需要 10-15 分钟模拟,但对于 200 个代理,只需要 10 分钟即可完成 2000 个滴答声!

由于我在为更多代理测试我的模型时遇到了一个大问题,我正在考虑消除所有链接,并为每对代理及其关系值和关系频率使用一个全局表,但由于使用链接真的很容易,我想我会有难以设定和获得价值。

有谁知道更好的方法来做到这一点?或者使 netlogo 模型可扩展的方法?

更新: 嗨,我一次又一次地检查我确信我的编程风格让我的程序变慢了,我发现 2 例意外询问其中一个非常愚蠢,因为我将链接设置为不可见,这甚至没有必要!!!每当创建链接时,我就可以设置隐藏链接!不用再问了:D

此外,我已经消除了我使用 ask 或 with for out-link neighbors 、 links 和 out-links 的情况。例如,我替换了一个代码,该代码正在检查以查找与调用者代理有共同关系的任何其他代理,我的初始代码非常慢,我用以下代码替换了它,它工作得更快:

Let Agents_I_Met out-link-neighbors 
if any? other agents-here with [any? out-link-neighbors with [member? self Agents_I_Met ]]
          [
Let Other_Agent one-of other agents-here with [any? out-link-neighbors with [member? self Agents_I_Met ]]
Let CommonAgent one-of Agents_I_Met with [member? Other_Agent in-link-neighbors  ]
...

但是仍然有很多情况我需要打电话给其他代理,所以我认为可以让代理询问半径 X 内的其他代理!

最后,现在我的系统在更合理的时间内为 400 个代理和15000-20000个链接运行得更好:)

但我确信仍有改进的地方。感谢赛斯的有用回答:)

4

1 回答 1

2

这不是一个好主意。NetLogo 中的链接实现高效;无论你用什么代替它们,都可能会更慢而不是更快。

您似乎急于认为这是 NetLogo 的错,但可能不是;这个问题几乎可以肯定是你自己的代码中的一个问题,这个问题在你使用的任何编程语言中都会出现。

在大多数 NetLogo 模拟中,运行时间随着代理的数量线性增加,即代理数量增加一倍。从您给出的数字来看,听起来您编写的代码所花费的时间与代理数量的平方成正比。(代理的数量可能呈指数级增长,但人们意外编写需要多项式时间的代码更为常见。)

这可能有两种方式发生:

  • 您正在实施的算法本质上是一种需要多项式时间来计算的算法。
  • 您正在实现的算法可以进行编码,使其在线性时间内执行,但您不小心以需要多项式时间的方式对其进行编码。

你需要问自己,我的代码是什么使它不能在线性时间内运行?

您需要查看代码中遍历模型中所有代理的每个循环,并问自己,这个循环的主体中有什么东西不能在恒定时间内执行吗?

遍历所有代理的原语包括askwith。所以最常见的错误是这样写:

ask turtles [
  ... turtles with [ ... ] ...
]

在不了解代码的其他任何信息的情况下,我可以看一下它并知道它出现的模型将是一个慢模型,因为上面的代码需要多项式时间来执行。每对可能的海龟都会执行这两者with,例如,如果有 100 只海龟,则代码将执行 10,000 步。如果海龟的数量是原来的两倍,那么代码将需要 40,000 步才能执行——海龟数量翻倍会导致运行时间翻四倍,而不仅仅是翻倍。

我们已经在Use undirected links 而不是 Directed links中看到,这种形式的代码是您的模型运行缓慢的原因。

因此,您需要找到模型中嵌套循环的位置,其中两个循环的大小与代理总数成正比。(这两个循环可能不一定是askand with,它们甚至可能不在同一个过程中。)

当你找到一个地方做这件事时,你需要弄清楚你是在做一个本来就需要这么长时间的计算,还是你不小心把它编码成不必要的慢形式。如果是后者,修复它。如果是前者,您需要重新考虑您的要求。

听起来你的要求是错误的。您写道“在当前版本中,我使用链接来跟踪代理关系,并且每个代理可以拥有的链接数量没有限制”。所以链接的数量与海龟的数量成正比,对吧?这意味着您甚至不需要嵌套循环来编写具有多项式运行时的程序;如果你这样做了ask links [ ... ],即使有一次,你也死定了,因为链接的数量已经与海龟数量的平方成正比。

作为如何修复它的示例,您可以考虑在每个海龟可以拥有的关系数量上设置一些固定大小。这将使您的模型再次以线性时间运行成为可能。

但这并不意味着您不应该仔细检查您的代码是否存在意外问题。您可能同时遇到问题,基本和意外缓慢。您可能不小心完成了,ask links [ ... ask turtles ...或者ask turtles [ ... ask links ...在这种情况下,您的运行时间将增加为海龟数量的立方,或者如果您已经完成ask links [ ... ask links ...,则为四次方。

这些建议都不是特别针对 NetLogo。如果在 NetLogo 中编写慢速程序很容易,那只是因为在 NetLogo 中编写各种程序很容易——包括慢速程序。特别是,NetLogo 使编写循环变得非常容易。像这样的一小段代码turtles with [color = red]是一个循环,但它非常短且易于编写,它看起来或感觉不一定像一个循环,因此很容易忽略性能影响。

于 2013-11-10T13:15:48.260 回答