【问题标题】:Supply argument to reporter向记者提供论据
【发布时间】:2021-12-20 10:58:42
【问题描述】:

以下可能是 Netlogo 的基本编程问题。 我想写一些通用的记者,我可以为他们应该报告的内容提供论据。假设以下程序:

turtles-own [
  houses
  cars
]

to setup
  clear-all
  create-turtles 10
  reset-ticks
end

to go
  ask turtles [
    set houses houses + random 2
    set cars cars + random 5
  ]
  
  tick
end

我可以这样写一个关于房屋均值的记者:

to-report mean-houses
  report mean [ houses ] of turtles
end

但我想要一个通用的报告器,我也可以用它来报告汽车的平均值,如下所示:

to-report means [ param ]
  report mean [ param ] of turtles
end

但是这并没有按预期工作:

setup
repeat 15 [go]
show means houses

> ERROR: You can't use HOUSES in an observer context, because HOUSES is turtle-only.*

在这种情况下,如何让 Netlogo 评估 param 在海龟的上下文中?我熟悉如何在 R 中执行此操作(例如,通过 tidy evaluation 使用 {{ x }} 或早期的引用机制进行掩码),但不熟悉如何将其转换为 Netlogo。

【问题讨论】:

  • 我无法重现您的问题。通过使用完全相同的代码,在命令中心以观察者身份运行 mean-houses 不会给我任何错误,并报告海龟中 houses 的平均数量:observer> setup observer> repeat 15 [go] observer> show mean-houses observer: 8.8
  • @Matteo 很抱歉不清楚:setup -> repeat 15 [go] -> show means houses。然后扩展:show means cars。目标:避免重复代码。
  • 对不起,我认为是我误解了你的问题。老实说,我不确定有没有办法解决这个问题,或者至少我想不出一个办法。我会继续思考,但我也会问:让观察者运行这样一个过程是否有真正的优势,而观察者仍然需要指定感兴趣的变量?换句话说,与mean [houses] of turtles 相比,拥有means [houses] 是否有真正的优势? ...除非这个使用 mean 的例子只是为了一个最小的例子,而你实际上在做的事情涉及更长的计算
  • 这个例子主要是为了简单起见(但我也有这个确切的用例)。在我的真实模型中,我计算了三个不同数量的基尼系数——复制代码三次似乎非常冗长。
  • 有道理。其实有一个变通方法,看答案

标签: netlogo


【解决方案1】:

由于错误状态,您正试图将仅乌龟变量(房屋)传递给在观察者上下文中使用的过程,该过程不起作用,因为 Netlogo 将在实际运行之前尝试将变量传递给过程过程。

相反,您可以使用以下代码。在此示例中,您首先使用“of”-原语将房屋/汽车变量提取为列表。只有这样你才能将它们传递给由观察者运行的“手段”程序。

to-report means [ param ]
  report mean param 
end
show means [houses] of turtles
show means [cars] of turtles

【讨论】:

  • 一个好的答案将始终包括解释为什么这会解决问题,以便 OP 和任何未来的读者可以从中学习。
  • @Tyler2P 谢谢你的评论。我已更新我的答案以包含此更改背后的原因。可能还是有点乱,因为我还不习惯行话。
  • 是的。这是将值列表从代理集传递给在该列表上起作用的报告者的正确和最简单的答案。其他任何事情都只会增加复杂性。我在回答中对此进行了探索。
【解决方案2】:

NetLogo 方式

<reporter> [ <expression> ] of <agentset>

注意:我在下面使用“代理”,因为这个答案适用于任何 NetLogo 代理,无论是海龟、海龟品种、补丁还是链接。

NetLogo 不是将代理变量(或表达式)传递给过程,然后以某种方式使代理生成一个列表,然后对列表进行操作,NetLogo 可以很容易地首先从每个代理单独评估的表达式中生成列表代理集,因此您可以将该列表传递给某个记者。语法(如您所知)是:

;; return list of <expression>
;; calculated by each member of agentset
[ expression ] of agentset

所以,如果这是你的记者:

to-report gini [ samples ] 
  ;; samples will be sorted here, don't pre-sort!
  ;; best guess -- please correct if wrong
  ;; source:
  ;; https://en.wikipedia.org/wiki/Gini_coefficient#Calculation
  let n length samples 
  let indexes (range 1 (n + 1))
  let s1 2 * sum (map  [[i y] -> i * y] indexes sort samples)
  let s2 n * sum samples
  let G (s1 / s2) - ((n + 1) / n) 
  report G 
end

然后您可以像这样计算各种度量的基尼系数:

print gini [ measure-1 ] of turtles
print gini [ measure-2 ] of turtles
print gini [ measure-3 ] of turtles

这是有道理的,因为 gini 是一个接受一组样本的函数。这让您可以轻松地使用其他亚群或品种或其他任何东西。

“缩写”语法

我将带你“沿着花园小径走”,所以如果你喜欢目前所看到的,你可以在这里停下来。如果您想轻笑,请继续阅读。

也许上面的内容对你来说太冗长了,你真的,真的,想摆脱“乌龟”? (即使您以后可能希望将通用函数更通用地应用于子群体?)

嗯,你可以。我们可以使用“匿名记者”来编写它:

print gini [-> houses ]

然后 gini 可能看起来像这样:

to-report gini [ sample-expression ]
  let samples sort [ run-result sample-expression ] of turtles
  ;;; ... the rest of your gini function here
  report G
end

好的,但是您已经在函数中嵌入了“of turtles”。但是,如果稍后您想针对某些子种群评估此函数,或者可能使用补丁而不是海龟,该怎么办?

您也可以通过将代理集作为输入来解决此问题。

to-report gini [ anon-reporter source ]
  let samples [ run-result anon-reporter ] of source
  ;; etc
end

然后写:

print gini [-> measure-1 ] turtles
print gini [-> measure-2 ] turtles
print gini [-> measure-3 ] turtles

呃,有点尴尬。让我们添加一点语法糖:

to-report of_ [ agents ] report agents end

现在我们可以写了:

print gini [-> measure-1 ] of_ turtles
print gini [-> measure-2 ] of_ turtles
print gini [-> measure-3 ] of_ turtles

哦,亲爱的。这看起来很熟悉,不是吗?但比我们开始时更冗长。

所以现在我们回到:

print gini [ measure-1 ] of turtles

【讨论】:

  • 非常感谢您提供工作示例。您计算 gini 的实现实际上比我使用的要快得多,所以这非常有帮助。
  • 拜托,我认为这个功能是错误的。编辑似乎更正确。来源:: en.wikipedia.org/wiki/Gini_coefficient#Calculation
【解决方案3】:

您可以使用runresult,前提是您乐于将过程的参数作为字符串传递:

to-report means [varname]
  report mean [runresult varname] of turtles
end

在指挥中心试一试:

observer> setup
observer> repeat 15 [go]
observer> show means "houses"
observer: 7.4

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-28
    • 2017-01-08
    • 2016-10-20
    • 1970-01-01
    • 1970-01-01
    • 2020-08-07
    • 2021-12-24
    • 1970-01-01
    相关资源
    最近更新 更多