我试着对这个问题进行A星搜索。紧接着是框架的Joseph Kern实现和给定的算法伪代码here:def AStar(start, goal, neighbor_nodes, distance, cost_estimate):
def reconstruct_path(came_from, current_node):
path = []
while current_node is not None:
path.append(current_node)
current_node = came_from[current_node]
return list(reversed(path))
g_score = {start: 0}
f_score = {start: g_score[start] + cost_estimate(start, goal)}
openset = {start}
closedset = set()
came_from = {start: None}
while openset:
current = min(openset, key=lambda x: f_score[x])
if current == goal:
return reconstruct_path(came_from, goal)
openset.remove(current)
closedset.add(current)
for neighbor in neighbor_nodes(current):
if neighbor in closedset:
continue
if neighbor not in openset:
openset.add(neighbor)
tentative_g_score = g_score[current] + distance(current, neighbor)
if tentative_g_score >= g_score.get(neighbor, float('inf')):
continue
came_from[neighbor] = current
g_score[neighbor] = tentative_g_score
f_score[neighbor] = tentative_g_score + cost_estimate(neighbor, goal)
return []
由于A-Star是一种启发式搜索算法,你需要想出一个函数来估计剩余成本(这里是:距离),直到达到目标。除非你对次优方案感到满意,否则不应高估成本。这里的保守选择是manhattan (or taxicab) distance,因为这表示所用Von Neumann邻域网格上两点之间的直线距离。(在这种情况下,这绝对不会高估成本。)
然而,这将大大低估手边给定迷宫的实际成本。因此,我将另外两个距离度量平方欧几里德距离和曼哈顿距离乘以4进行比较。然而,这些可能高估了实际成本,因此可能产生次优结果。
代码如下:import sys
from PIL import Image
def is_blocked(p):
x,y = p
pixel = path_pixels[x,y]
if any(c < 225 for c in pixel):
return True
def von_neumann_neighbors(p):
x, y = p
neighbors = [(x-1, y), (x, y-1), (x+1, y), (x, y+1)]
return [p for p in neighbors if not is_blocked(p)]
def manhattan(p1, p2):
return abs(p1[0]-p2[0]) + abs(p1[1]-p2[1])
def squared_euclidean(p1, p2):
return (p1[0]-p2[0])**2 + (p1[1]-p2[1])**2
start = (400, 984)
goal = (398, 25)
# invoke: python mazesolver.py [.jpg|.png|etc.]
path_img = Image.open(sys.argv[1])
path_pixels = path_img.load()
distance = manhattan
heuristic = manhattan
path = AStar(start, goal, von_neumann_neighbors, distance, heuristic)
for position in path:
x,y = position
path_pixels[x,y] = (255,0,0) # red
path_img.save(sys.argv[2])
这里有一些图片用于结果的可视化(受Joseph Kern发布的图片的启发)。动画在main while循环的10000次迭代后显示一个新帧。
广度优先搜索:
A星曼哈顿距离:
A星平方欧氏距离:
A星曼哈顿距离乘以4:
结果表明,对于所使用的启发式方法,迷宫的探索区域有很大的不同。因此,平方欧几里德距离甚至会产生与其他度量不同的(次优)路径。
关于A-Star算法在终止前的运行时间方面的性能,请注意,与只需要评估每个候选位置的“目标性”的广度优先搜索(BFS)相比,对距离和成本函数的许多评估相加。这些额外的功能评估(A-Star)的成本是否超过要检查的节点(BFS)的成本,特别是性能是否对应用程序来说是一个问题,这是个人的看法,当然不能得到普遍的回答。
与穷举搜索(例如,BFS)相比,通常可以说关于知情搜索算法(例如A-Star)是否是更好的选择的事情如下。随着迷宫维数的增加,即搜索树的分枝因子的增加,穷举搜索(穷举搜索)的缺点呈指数增长。随着复杂性的增加,这样做变得越来越不可行,在某个时候,无论结果路径是(近似)最优还是非最优,您都会对任何结果路径感到非常满意。