我正在实现对称双向A *最短路径算法,如[Goldberg and Harrelson,2005]中所述。这仅用于理解算法,因此我使用了最基本的版本而没有任何优化步骤。
我的问题是双向算法似乎扫描了测试图上单向A *搜索中扫描的边数的近两倍。
示例:使用A *(左)和双向A *(右)在道路网络上进行s-t查询。通过前向和后向搜索扫描的节点分别以红色和绿色着色。启发函数只是到t或s的欧氏距离。计算出的路径(蓝色)在两个图中都是正确的。
我可能错误地理解了算法逻辑。以下是我如何将单向A *调整为双向(来自参考)
mu
保持为s-t路径长度的当前最佳估计值。 w
中的(v,w)
,请不要更新w标签。 (v,w)
和w
时,如果mu
dist(s,v) + len(v,w)+dist(w,t)<= mu
v
dist(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 *扫描的节点;右图显示了前向搜索扫描的节点(橙色)和后向搜索扫描的节点(蓝色)
然而,在道路网络上,前向搜索扫描的节点和后向搜索扫描的节点的联合仍然大于单向搜索扫描的节点数。也许这取决于输入图?
答案 0 :(得分:-2)
嘿,您的问题是,您没有设置正确的条件来停止,停止条件是何时(满足向前和向后搜索),