移除移动代理路径中的循环
Remove cycles in the path of moving agents
我有一个 link 节点的列表,该列表由 walker
代理人在 link 上的动议期间收集。
当他到达目的地时,他必须保存他的路径但没有循环。
消除循环的方法是从源link开始逐个位置迭代扫描link:对于i-th
位置的link,从目标 link 开始扫描路径,直到遇到 link 的第一次出现,例如,在位置 j
(它始终保持 i <= j
因为扫描过程停止最迟在 i
位置)。如果我们有j > i
,从位置i+1
到位置j
的links的子路径对应一个循环,可以消除。
我一直在尝试编写一个递归 to-report
代码,它以初始列表作为参数但没有成功。我的测试代码给出了循环而不是没有循环的路径是这样的:
to-report no-cycles [ lista ]
ifelse empty? lista [
report lista ] [
let x1 (first lista)
let rest (butfirst lista)
let rev-rest (reverse rest)
let rev-rest1 (first rev-rest)
ifelse x1 != rev-rest1 [
report no-cycles (butlast rest)
] [
report lista ]
]
end
我不知道这是不是一个好方法。
非常感谢您的帮助
我无法弄清楚如何使您的编码方法准确工作,但您的一般概念是有道理的。下面的代码是一个 to-report
,它接受一个列表并向后遍历它,将当前项目之前的所有项目与当前项目进行比较。如果有匹配项,它会跳转到该项目的最早实例。请注意,我正在使用 link 和数字列表对此进行测试,因此它应该删除任何类型列表中的重复项目。但是,它会 return 一个列表,因此如果您输入 link 的列表,它将 而不是 return 一个代理集 - 如果您想要link 做一些你必须使用 foreach "your-list"
而不是 ask
的事情。如果您只需要列表,下面的代码至少可以帮助您入门。
to-report no-cycles [ input_list ]
ifelse empty? input_list [
report input_list
]
[
let final_list []
let temp_list reverse input_list
let n 0
while [ n < length temp_list] [
let x n
let cur item n temp_list
while [ x < length temp_list ] [
if (item x temp_list) = cur [
set n x
]
set x x + 1
]
set final_list fput (item n temp_list) final_list
set n n + 1
]
report final_list
]
end
编辑如下
获得 link 列表后,您可以使用 foreach
遍历列表并执行您喜欢的操作。例如,如果您希望列表中的每个 link 都将一个变量增加 1,则可以使用下面的代码块。
to-report modify-links-in-list [ input_list_of_links ]
;;; input must be a list of links, not an agentset
foreach input_list_of_links [
[x] ->
ask x [
set example_var example_var + 1
]
]
report input_list_of_links
end
这将修改 link 本身的变量,因此请检查您希望更改的 link 之一,以监控它是否正常工作。希望这就是您所追求的!
我有一个 link 节点的列表,该列表由 walker
代理人在 link 上的动议期间收集。
当他到达目的地时,他必须保存他的路径但没有循环。
消除循环的方法是从源link开始逐个位置迭代扫描link:对于i-th
位置的link,从目标 link 开始扫描路径,直到遇到 link 的第一次出现,例如,在位置 j
(它始终保持 i <= j
因为扫描过程停止最迟在 i
位置)。如果我们有j > i
,从位置i+1
到位置j
的links的子路径对应一个循环,可以消除。
我一直在尝试编写一个递归 to-report
代码,它以初始列表作为参数但没有成功。我的测试代码给出了循环而不是没有循环的路径是这样的:
to-report no-cycles [ lista ]
ifelse empty? lista [
report lista ] [
let x1 (first lista)
let rest (butfirst lista)
let rev-rest (reverse rest)
let rev-rest1 (first rev-rest)
ifelse x1 != rev-rest1 [
report no-cycles (butlast rest)
] [
report lista ]
]
end
我不知道这是不是一个好方法。
非常感谢您的帮助
我无法弄清楚如何使您的编码方法准确工作,但您的一般概念是有道理的。下面的代码是一个 to-report
,它接受一个列表并向后遍历它,将当前项目之前的所有项目与当前项目进行比较。如果有匹配项,它会跳转到该项目的最早实例。请注意,我正在使用 link 和数字列表对此进行测试,因此它应该删除任何类型列表中的重复项目。但是,它会 return 一个列表,因此如果您输入 link 的列表,它将 而不是 return 一个代理集 - 如果您想要link 做一些你必须使用 foreach "your-list"
而不是 ask
的事情。如果您只需要列表,下面的代码至少可以帮助您入门。
to-report no-cycles [ input_list ]
ifelse empty? input_list [
report input_list
]
[
let final_list []
let temp_list reverse input_list
let n 0
while [ n < length temp_list] [
let x n
let cur item n temp_list
while [ x < length temp_list ] [
if (item x temp_list) = cur [
set n x
]
set x x + 1
]
set final_list fput (item n temp_list) final_list
set n n + 1
]
report final_list
]
end
编辑如下
获得 link 列表后,您可以使用 foreach
遍历列表并执行您喜欢的操作。例如,如果您希望列表中的每个 link 都将一个变量增加 1,则可以使用下面的代码块。
to-report modify-links-in-list [ input_list_of_links ]
;;; input must be a list of links, not an agentset
foreach input_list_of_links [
[x] ->
ask x [
set example_var example_var + 1
]
]
report input_list_of_links
end
这将修改 link 本身的变量,因此请检查您希望更改的 link 之一,以监控它是否正常工作。希望这就是您所追求的!