代表其他海龟记忆的海龟变量
Turtle variable representing memory of other turtles
我有一个模型,其中海龟以离散的增量导航节点图(也存储为海龟)和链接(使用 move-to
过程)。我想创建一个基于海龟的变量,让海龟记住它们访问图中特定节点的次数。
例如
- 海龟
move-to
一个节点
- 在所需结构中查找该节点的存在
- 如果它存在
set #visits #visits + 1
与该节点关联
- 如果不将其包含在结构中并且
set #visits 1
我想我的选择与列表或表格有关 - 但我不确定其中哪一个最有效。关于表,我不认为键可以是乌龟——也许是从它的 who 派生的字符串——但这感觉可能效率低下。
可能相关的两点:
有些图会有大量节点(~5000),而且通常有些海龟永远不会访问所有节点,因此在-上增长结构可能是明智的the-fly 以节省内存。
也可以有比较多的代理(~2500)
任何建议,一如既往,非常感谢。
表是更有效的方式,也更容易编码,尽管使用代理作为键不起作用(令我惊讶的是)。也就是说,您可以只使用 who
个数字作为键。
它看起来像:
extensions [ table ]
turtles-own [ node-visits ]
...
to move-to-node [ node ]
move-to node
let key [ who ] of node
let visits ifelse-value (table:has-key? node-visits key) [ table:get node-visits key ] [ 0 ]
table:put node-visits key (visits + 1)
end
tables 在内存使用和查找速度方面都是高效的。您可以使用列表来做到这一点,并提高内存使用效率(如果您使用键值对) 或 查找速度(如果您使用 who
数字作为索引或其他东西)但不是两者,除非你基本上用列表编写自己的散列 table 实现。
现在,除此之外,您通常应该担心这些性能问题,直到您:
- 现在遇到性能问题
- 知道这些是性能问题的根源(通过使用计时器或
profiler
扩展进行分析)
我建议 table 扩展的真正原因是因为它最容易实现。
我意识到我迟到了,Bryan 的回答非常好,但另一种解决方案是使用单独的链接来记录对节点的访问次数:
breed [ nodes node ]
undirected-link-breed [ edges edge ] ; node <---> node
breed [ agents an-agent ]
directed-link-breed [ visits visit ] ; agent ----> node
visits-own [ num-visits ]
to setup
clear-all
create-nodes 10 [ create-edges-with n-of (1 + random 2) other nodes ]
create-agents 10 [ move-to one-of nodes ]
end
to go
ask agents [
let destination one-of [ edge-neighbors ] of one-of nodes-here
move-to destination
if out-visit-to destination = nobody [ create-visit-to destination ]
ask out-visit-to destination [ set num-visits num-visits + 1 ]
]
end
它可能不如使用 table 扩展那么快,但它的优点是允许来自双方的查询:你问代理它访问了哪些节点多少次,但你可以还询问一个节点它被哪些代理人访问了多少次。
我有一个模型,其中海龟以离散的增量导航节点图(也存储为海龟)和链接(使用 move-to
过程)。我想创建一个基于海龟的变量,让海龟记住它们访问图中特定节点的次数。
例如
- 海龟
move-to
一个节点 - 在所需结构中查找该节点的存在
- 如果它存在
set #visits #visits + 1
与该节点关联 - 如果不将其包含在结构中并且
set #visits 1
我想我的选择与列表或表格有关 - 但我不确定其中哪一个最有效。关于表,我不认为键可以是乌龟——也许是从它的 who 派生的字符串——但这感觉可能效率低下。
可能相关的两点:
有些图会有大量节点(~5000),而且通常有些海龟永远不会访问所有节点,因此在-上增长结构可能是明智的the-fly 以节省内存。
也可以有比较多的代理(~2500)
任何建议,一如既往,非常感谢。
表是更有效的方式,也更容易编码,尽管使用代理作为键不起作用(令我惊讶的是)。也就是说,您可以只使用 who
个数字作为键。
它看起来像:
extensions [ table ]
turtles-own [ node-visits ]
...
to move-to-node [ node ]
move-to node
let key [ who ] of node
let visits ifelse-value (table:has-key? node-visits key) [ table:get node-visits key ] [ 0 ]
table:put node-visits key (visits + 1)
end
tables 在内存使用和查找速度方面都是高效的。您可以使用列表来做到这一点,并提高内存使用效率(如果您使用键值对) 或 查找速度(如果您使用 who
数字作为索引或其他东西)但不是两者,除非你基本上用列表编写自己的散列 table 实现。
现在,除此之外,您通常应该担心这些性能问题,直到您:
- 现在遇到性能问题
- 知道这些是性能问题的根源(通过使用计时器或
profiler
扩展进行分析)
我建议 table 扩展的真正原因是因为它最容易实现。
我意识到我迟到了,Bryan 的回答非常好,但另一种解决方案是使用单独的链接来记录对节点的访问次数:
breed [ nodes node ]
undirected-link-breed [ edges edge ] ; node <---> node
breed [ agents an-agent ]
directed-link-breed [ visits visit ] ; agent ----> node
visits-own [ num-visits ]
to setup
clear-all
create-nodes 10 [ create-edges-with n-of (1 + random 2) other nodes ]
create-agents 10 [ move-to one-of nodes ]
end
to go
ask agents [
let destination one-of [ edge-neighbors ] of one-of nodes-here
move-to destination
if out-visit-to destination = nobody [ create-visit-to destination ]
ask out-visit-to destination [ set num-visits num-visits + 1 ]
]
end
它可能不如使用 table 扩展那么快,但它的优点是允许来自双方的查询:你问代理它访问了哪些节点多少次,但你可以还询问一个节点它被哪些代理人访问了多少次。