路径未到达我的A *算法中的结束节点

时间:2014-05-02 23:58:40

标签: a-star netlogo

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用红色开头表示,路径用红色表示。

enter image description here

非常感谢你的帮助。

2 个答案:

答案 0 :(得分:5)

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

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

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

您也可以尝试关闭世界包装。

答案 1 :(得分:3)

A *必须有一种方法来备份尝试旧路径,如果它遇到了一个deadend,或者看起来效率低下的东西。您的实现只是在一条路上继续前进。虽然你的方式绝对是实现路径查找的最自然的方式,而且更简单,这可能就是你遇到问题的原因。

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

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。希望这有帮助!