【问题标题】:The path does not reach the end node in my A* algorithm在我的 A* 算法中路径没有到达末端节点
【发布时间】:2023-03-15 07:54:02
【问题描述】:

How to speed up least-cost path model at large spatial extents 开始,我尝试在 Netlogo 中编写 A* 算法,以在大空间范围内增加我的最低成本路径模型。这是我的代码:

to findPath [ID-start-node ID-end-node]

 let currentNodesInList [ ]
 let current-node node ID-start-node
 let end-node node ID-end-node
 ask current-node [ set color red]
 ask end-node [ set color red]

 set currentNodesInList lput current-node currentNodesInList

 while [not member? end-node currentNodesInList] [

 ask current-node [ 

 foreach sort nodes-on neighbors [ 

  ask ? [set f-value [link-cost] of link ([who] of current-node) ([who] of ?) + distance end-node] ]  

  let next-current-node min-one-of [nodes-on neighbors] of current-node [f-value]
  ask link ([who] of current-node) ([who] of next-current-node) [set color red]
  set current-node next-current-node

  set currentNodesInList lput current-node currentNodesInList] ]
end

当 ID-start-node 和 ID-end-node 在景观中接近时,代码似乎可以工作。但是,当 ID-start-node 和 ID-end-node 之间的距离较大时,路径不会到达 ID-end-node(见下图;但有时,代码可以工作)。

图中ID-start-node和ID-end-node用红色开始表示,路径用红色绘制。

非常感谢您的帮助。

【问题讨论】:

  • 只是一个小的编码提示:几乎没有必要或最好使用 who 号码来查找内容。几乎每次你使用 who 号码来做某事时,都有更好的方法。所以例如link ([who] of current-node) ([who] of ?)可以缩短为[link-with current-node] of ?
  • 至于您的实际问题,我试过了,但仅通过查看您的代码我无法发现错误。除了应用标准调试技术之外,不确定还有什么建议,例如将打印语句添加到您的代码中,以便它告诉您更多关于它在做什么。然后尝试找出最开始出错的地方。
  • 非常感谢赛斯。我认为路径没有到达结束节点,因为路径会返回(每次都向后退一步)。所以我不确定 f.value [link-cost] of link ([who] of current-node) ([who] of ?) + distance end-node 的计算是否正确? f.value 是否等于 A* 算法中起始节点与其邻居节点之间的链接成本 + 起始节点和结束节点之间的距离?非常感谢您的帮助。
  • 这听起来像是一个很好的问题,您可以使用 NetLogo 本身进行调查。您可以通过在代码中添加 showprint 语句并查看数字是否符合您的意图来提出问题。

标签: a-star netlogo


【解决方案1】:

您可能想在 NetLogo 用户社区中查看此模型:

http://ccl.northwestern.edu/netlogo/models/community/Astardemo1

它实现了一个简单的过程(查找路径),将源补丁和目标补丁作为参数并返回补丁列表(这是从源补丁到目标补丁的最短路径之一) A-star 最短路径查找算法。

您也可以尝试关闭世界环绕。

【讨论】:

  • 那个好像不存在了。
【解决方案2】:

A* 必须有一种方法来备份尝试旧路径,如果它遇到死胡同,或者看起来效率低下的事情。您的实现只是继续沿着一条路径前进。虽然您的方式绝对是实现寻路的最自然的方式,而且更简单,但这可能就是您遇到问题的原因。

这是我想出的一个实现。它直接使用补丁而不是链接,这实际上看起来对你来说会更好。只需给它一个补丁任务,报告跨越该补丁以及源和目标补丁的成本。我对此不太满意:真正的 A* 使用堆来跟踪它认为每条可能的路径应该有多好。我不得不用一个列表来模拟堆,所以它不会像真正的 A* 那样快。如果其他人看到改进,请随时编辑我的答案或在 cmets 中提出建议!无论如何,这里是:

to-report find-path [ get-cost source destination ]
  let paths (list (list source))
  let estimated-costs (list [distance destination ] of source)
  let path first paths

  let visited patch-set source
  let encountered patch-set source

  while [ source != destination ] [
    let estimated-cost min estimated-costs
    let path-index position estimated-cost estimated-costs
    set path item path-index paths
    set source last path
    let path-cost estimated-cost - [ distance destination ] of source
    let source-cost [ runresult get-cost ] of source

    set paths remove-item path-index paths
    set estimated-costs remove-item path-index estimated-costs

    set visited (patch-set source visited)

    ask [ neighbors with [ not member? self visited ] ] of source [
      let patch-cost runresult get-cost
      let step-cost distance source * (patch-cost + source-cost) / 2
      let est-cost path-cost + step-cost + distance destination

      let add? true

      if member? self encountered [
        let other-path false
        foreach paths [
          if last ? = self [
            set other-path ?
          ]
        ]
        if other-path != false [
          let other-path-index position other-path paths
          let other-path-cost item other-path-index estimated-costs
          ifelse other-path-cost < est-cost [
            set add? false
          ] [
            set paths remove-item other-path-index paths
            set estimated-costs remove-item other-path-index estimated-costs
          ]
        ]
      ]

      if add? [
        set estimated-costs fput est-cost estimated-costs
        set paths fput (lput self path) paths

        set encountered (patch-set self encountered)
      ]
    ]    
  ]
  report path
end

如果cost 是一个包含穿越该补丁的成本的补丁变量,那么您可以这样称呼它:find-path task [ cost ] source-patch target-patch。希望这会有所帮助!

【讨论】:

  • 非常感谢 Megh 和 Bryan 的回复。感谢您的帮助,我编写了一个似乎可行的 A* 算法。我的代码计算位于多边形边缘的所有补丁之间的路径(以提高模拟速度)并在所有这些补丁中绘制成本最低的路径。但是,我很失望,因为我发现我的代码太慢了(例如,在上图中绘制路径需要 2 分钟)。是否有另一种解决方案来减少要测试的补丁数量?我要发布一个新问题吗?当然,我可以给出我的代码。感谢您的帮助。
猜你喜欢
  • 2019-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多