我在网上找到了这个算法在python中的实现,并且它可以工作。它搜索从另一点出发到达某一点的最佳路径。这是代码:
from pyamaze import maze,agent,textLabel
from queue import PriorityQueue
def h(cell1,cell2):
x1,y1=cell1
x2,y2=cell2
return abs(x1-x2) + abs(y1-y2)
def aStar(m):
start=(m.rows,m.cols)
g_score={cell:float('inf') for cell in m.grid}
g_score[start]=0
f_score={cell:float('inf') for cell in m.grid}
f_score[start]=h(start,(1,1))
open=PriorityQueue()
open.put((h(start,(1,1)),h(start,(1,1)),start))
aPath={}
while not open.empty():
currCell=open.get()[2]
if currCell==(1,1):
break
for d in 'ESNW':
if m.maze_map[currCell][d]==True:
if d=='E':
childCell=(currCell[0],currCell[1]+1)
if d=='W':
childCell=(currCell[0],currCell[1]-1)
if d=='N':
childCell=(currCell[0]-1,currCell[1])
if d=='S':
childCell=(currCell[0]+1,currCell[1])
temp_g_score=g_score[currCell]+1
temp_f_score=temp_g_score+h(childCell,(1,1))
if temp_f_score < f_score[childCell]:
g_score[childCell]= temp_g_score
f_score[childCell]= temp_f_score
open.put((temp_f_score,h(childCell,(1,1)),childCell))
aPath[childCell]=currCell
fwdPath={}
cell=(1,1)
while cell!=start:
fwdPath[aPath[cell]]=cell
cell=aPath[cell]
return fwdPath
if __name__=='__main__':
m=maze(5,5)
m.CreateMaze()
path=aStar(m)
a=agent(m,footprints=True)
m.tracePath({a:path})
l=textLabel(m,'A Star Path Length',len(path)+1)
m.run()
我对这段代码的疑问是为什么他只使用一个队列?优先级队列是OPEN队列,但是为什么他不使用CLOSED队列呢?因为在许多伪代码中我都找到了两者,并且它通常在条件中使用,例如在这个伪代码中
OPEN = priority queue containing START
CLOSED = empty set
while lowest rank in OPEN is not the GOAL:
current = remove lowest rank item from OPEN
add current to CLOSED
for neighbors of current:
cost = g(current) + movementcost(current, neighbor)
if neighbor in OPEN and cost less than g(neighbor):
remove neighbor from OPEN, because new path is better
if neighbor in CLOSED and cost less than g(neighbor): ⁽²⁾
remove neighbor from CLOSED
if neighbor not in OPEN and neighbor not in CLOSED:
set g(neighbor) to cost
add neighbor to OPEN
set priority queue rank to g(neighbor) + h(neighbor)
set neighbor's parent to current
首先,
CLOSED
不是一个队列,而是一个集合:要么有节点在其中,要么不在其中(没有优先级或其他顺序)。
该集合实际上已被第一个脚本中使用 infinity 所取代。通过用无穷大初始化,表明相应的节点尚未被访问。通过测试 OPEN 或 CLOSED 中的成员资格,在第二个脚本中发现了相同的“未访问”概念。不同之处在于,当当前计算的路径成本小于已知的路径成本时,第二个脚本“取消访问”节点,而第一个脚本直接进行此检查 - 依赖于所有成本都小于无穷大的事实。
所以最终归结为同一件事。