NetLogo 调试

NetLogo Debugging

交互式的 NetLogo 使调试变得容易,但我还没有找到任何可用于设置断点和单步执行代码的工具。 如果存在,请指导我。或者我可以使用当前可用的设置实现相同的效果。

我不知道是否存在这样的工具。对于调试,我使用有意义的打印语句。首先,我创建一个开关作为全局参数来设置调试模式的开启和关闭,然后我向每个方法添加一条语句,打印哪个方法更新哪个变量以及它们被调用的顺序(如果调试模式打开)。

我还使用探查器扩展,它显示每种方法被调用了多少次,以及哪个是最耗时或最不耗时的。

另一种可能性是在任何现代浏览器中进行调试if/when NetLogo Web 生成source maps。这样就可以在NetLogo代码中设置断点,然后在NetLogo代码上使用Chrome或者FireFox或者IE11的开发者工具

NetLogo 就是将代码放在一个位置。当我 运行 在 2D 或 3D 中进行模拟时,我通常知道我的整个系统在时间点 X 将产生什么。所以当我测试时,我通常对我的代理进行颜色编码,"turtles",围绕我正在跟踪的变量(如蛋白质信号的数量等)

它可以很简单,比如当您想知道的变量超过阈值时将它们设为红色,或者当低于阈值时将它们设为蓝色。或者您可以添加另一种颜色,也许是绿色,以便您跟踪感兴趣的海龟何时落入 "optimal" 范围内。

当前不存在。尽管如此,您仍然可以使用上面的备选方案之一,或者您可以查看 user-message (https://ccl.northwestern.edu/netlogo/docs/dictionary.html#user-message),这将弹出一个对话框。这也将阻止在那一步的执行,虽然没有为您提供跳转到下一行的机制,但对我来说,这个解决方案被证明是最好的。

我已经将user-messageinspect一起用作NetLogo的调试工具。 a video demo 介绍了如何使用它们来确定错误原因。

  • 使用inspect的原因是当我们不确定到底哪里出错时检查对象的所有属性
  • 使用user-message打印一些指令,输出一些结果并停止程序

在我发现打印语句之前,我发现 Netlogo 有点难以调试。

我主要关注导致问题的模块,并在 critical 块中添加打印语句以检查变量的状态。我发现这是一种有效的调试方法。

我真希望文档更全面,有更多代码示例。也许一些好心人会把它作为一个项目。

注意:请注意,这种方法不仅仅是一种复杂的方法,它可以实现与使用 random-seed 完全相同的好处。使用 random-seed 是一种 事前 重现 运行 的方法。但是,对于罕见的错误,手动更改 random-seed(可能几百次)是不切实际的,直到您偶然遇到出现错误的 运行。相反,这种方法使您能够在错误发生后重现错误,通过重现罕见的 运行 ex-post 可能会节省大量时间。

如果有人觉得它有用并想节省设置时间,请随时从 Modeling Commons 下载 this blueprint



不是 NetLogo 的功能,而是我最近想出的权宜之计。

有些错误可能很少发生(例如,每隔几百 运行 秒)。如果是这种情况,即使只是重现错误也会变得很耗时。

为了避免这个问题,可以采用如下安排(注意代码块只有很少几行代码,绝大部分只是注释)。

globals [
 current-seed
]

to setup
  clear-all
  reset-ticks

  manage-randomness
end

to manage-randomness
; This procedure checks if the user wants to use a new seed given by the 'new-seed' primitive, or if
; they want to use a custom-defined seed. In the latter case, the custom-defined seed is retrieved
; from the 'custom-seed' global variable, which is set in the Interface in the input box. Such variable
; can be defined either manually by the user, or through the 'save-current-seed-as-custom' button (see
; the 'save-current-seed-as-custom' procedure below).
; In either case, this selection is mediated by the 'current-seed' global variable. This is because
; having a global variable storing the value that will be passed to the 'random-seed' primitive is the
; only way to [1] have such value displayed in the Interface, and [2] re-use such value in case the
; user wants to perform 'save-current-seed-as-custom'.

  ifelse (use-custom-seed?)
   [set current-seed custom-seed]
   [set current-seed new-seed]

  random-seed current-seed
end


to save-current-seed-as-custom
; This procedure lets the user store the seed that was used in the current run (and stored in the
; 'random-seed' global variable; see comment in 'manage-randomness') as 'custom-seed', which will
; allow such value to be re-used after turning on the 'use-custom-seed?' switch in the Interface.

  set custom-seed current-seed
end

这样就可以在发生罕见错误的地方重现相同的 运行,只需将 运行 的种子保存为自定义种子并打开开关即可。

为了让事情更有用,可以将相同的逻辑应用于滴答:准确跳转到发生罕见错误的同一点(可能在 运行 开始后数千滴答),可以结合之前关于种子的安排和以下关于刻度的安排:

to go
; The first if-statement allows the user to bring the run to a custom-defined ticks value.
; The custom-defined ticks value is retrieved from the 'custom-ticks' global variable,
; which is set in the Interface in the input box. Such variable can be defined either
; manually by the user, or through the 'save-current-ticks-as-custom' button (see the
; 'save-current-ticks-as-custom' procedure above).

  if (use-custom-ticks?) AND (ticks = custom-ticks) [stop]

  ; Insert here the normal 'go' procedure.

  tick
end


to save-current-ticks-as-custom
; This procedure lets the user store the current 'ticks' value as 'custom-ticks'. This will allow
; the user, after switching on the 'use-custom-ticks?' switch, to bring the simulation to the
; exact same ticks as when the 'save-current-ticks-as-custom' button was used. If used in combination
; with the 'save-current-seed-as-custom' button and 'use-custom-seed?' switch, this allows the user
; to surely and quickly jump to the exact same situation as when a previous simulation was interrupted.

  set custom-ticks ticks
end

这不仅可以快速跳转到发生罕见错误的地方,而且如果需要,还可以手动将 custom-ticks 值更改为更早的几个滴答,以便能够在错误发生之前观察事情是如何建立的。有些东西,很少有错误,否则会变得非常耗时。