gpt4 book ai didi

python - 实现双向 A* 最短路径算法

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:25:40 25 4
gpt4 key购买 nike

我正在实现对称双向 A* 最短路径算法,如 [Goldberg and Harrelson,2005] 中所述.这只是为了理解算法,因此我使用了最基本的版本,没有任何优化步骤。

我的问题是双向算法似乎扫描的边数几乎是测试图上单向 A* 搜索中扫描边数的两倍。

示例: 使用 A*(左)和双向 A*(右)的道路网络上的 s-t 查询。向前和向后搜索扫描的节点分别用红色和绿色着色。启发式函数只是到 t 或 s 的欧氏距离。计算出的路径(蓝色)在两个图中都是正确的。

A* search example

我可能对算法逻辑理解不正确。这是我如何将单向 A* 调​​整为双向(来自引用资料)

  • 在向前搜索和向后搜索之间交替。维护变量 mu作为 s-t 路径长度的当前最佳估计。
  • 在正向搜索中,如果w在边缘(v,w)已被反向搜索扫描,不更新 w 的标签。
  • 每次向前搜索扫描(v,w)如果w已被反向搜索扫描,更新mu如果dist(s,v) + len(v,w)+dist(w,t)<= mu
  • 停止条件:前向搜索即将扫描一个顶点时vdist(s,v) + potential_backward(v) >= mu
  • (类似的规则适用于向后搜索)

如果有人能指出我的实现中的缺陷,或者对双向 A* 算法进行更详细的解释,我将不胜感激。

Python 代码:

""" 
bidirectional_a_star: bidirectional A* search

g: input graph (networkx object)
s, t: source and destination nodes
pi_forward, pi_backward: forward and backward potential function values
wt_attr: attribute name to be used as edge weight
"""

def bidirectional_a_star(g,s,t,pi_forward, pi_backward, wt_attr='weight' ):
# initialization
gRev = g.reverse() # reverse graph
ds = { v:float('inf') for v in g } # best distances from s or t
dt = ds.copy()
ds[s]=0
dt[t]=0
parents = {} # predecessors in forward/backward search
parentt = {}
pqueues =[(ds[s]+pi_forward[s],s)] # priority queues for forward/backward search
pqueuet = [(dt[t]+pi_backward[t],t)]

mu = float('inf') # best s-t distance

scanned_forward=set() # set of scanned vertices in forward/backward search
scanned_backward=set()

while (len(pqueues)>0 and len(pqueuet)>0):
# forward search
(priority_s,vs) = heappop(pqueues) # vs: first node in forward queue

if (priority_s >= mu): # stop condition
break

for w in g.neighbors(vs): # scan outgoing edges from vs
newDist = ds[vs] + g.edge[vs][w][wt_attr]

if (ds[w] > newDist and w not in scanned_backward):
ds[w] = newDist # update w's label
parents[w] = vs
heappush(pqueues, (ds[w]+pi_forward[w] , w) )

if ( (w in scanned_backward) and (newDist + dt[w]<mu)):
mu = newDist+dt[w]

scanned_forward.add(vs) # mark vs as "scanned"

# backward search
(priority_t,vt) = heappop(pqueuet) # vt: first node in backward queue

if (priority_t>= mu ):
break

for w in gRev.neighbors(vt):
newDist = dt[vt] + gRev.edge[vt][w][wt_attr]

if (dt[w] >= newDist and w not in scanned_forward):
if (dt[w] ==newDist and parentt[vt] < w):
continue
else:
dt[w] = newDist
parentt[w] = vt
heappush(pqueuet,(dt[w]+pi_backward[w],w))
if ( w in scanned_forward and newDist + ds[w]<= mu):
mu = newDist+dt[w]

scanned_backward.add(vt)

# compute s-t distance and shortest path
scanned = scanned_s.intersection(scanned_t)
minPathLen = min( [ ds[v]+dt[v] for v in scanned ] ) # find s-t distance
minPath = reconstructPath(ds,dt,parents,parentt,scanned) # join s-v and v-t path

return (minPathLen, minPath)

更新

正在关注 Janne's comment , 我创建了一个 demo测试几个例子的搜索。实现得到改进,扫描的节点更少。

示例:(有向)网格图上从红点到绿点的最短路径。中间的图突出显示了 A* 扫描的节点;右图显示了前向搜索扫描的节点(橙色)和反向搜索扫描的节点(蓝色) toy example

但是,在道路网络中,正向搜索和反向搜索扫描到的节点的并集仍然多于单向搜索扫描到的节点数。也许这取决于输入图?

最佳答案

嘿,你的问题是,你没有设置正确的停止条件,停止条件是什么时候(向前和向后搜索满足),

关于python - 实现双向 A* 最短路径算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32624035/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com