移除移动代理路径中的循环

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 之一,以监控它是否正常工作。希望这就是您所追求的!