A*搜索算法(A Star Search Algorithm)
-
A*算法主要用于在二维平面上寻找两个点之间的最短路径。在从起始点到目标点的过程中有很多个状态空间,DFS和BFS没有任何启发策略所以穷举所有的状 态空间,不适合仅需对局部进行搜索的应用。启发式搜索的关键在于:当前节点在选择下一步节点的时候,可以通过一个启发函数进行选择,选择到达终点代价最小 的节点作为下一步节点。A*的启发函数构造为:
f(n)=g(n)+h(n)
f(n)是可选的下一个节点的代 价,g(n)表示从start点到n点的代价,h(n)表示从n点到end点的代价;但是h(n)是无法预知的,(如果将BFS看作一种A*的话,其 h(n)恒定为0,g(n)表示到起始点的层数)所以A*算法将当n点到end点的直线距离作为h(n)的估值,显然只能无限接近实际最优解。
-
A*算法维护两张表OPEN和CLOSED,OPEN保存所有可探测但是还没有访问的节点,CLOSED保存素有已经访问的节点;启发函数就当前在 OPEN表中的节点进行排序,按照代价从低到高排列,每次选择代价最小的节点进行访问;当前访问的节点会根据簿记信息更新代价信息,并且将其直接连接的子 节点访问OPEN表中,最后将当前节点放入CLOSED表;A*算法开始于将start点放入OPEN表,结束于找到end点,或者OPEN表为 空,CLOSED表已经包含所有可访问节点。
-
程序实现中g(n)表示在抽象的状态空间中start点到n点的深度,h(n)表示在实际地图中n点所在地图位置到end点地图位置的直线距离,伪代码如下:
1 function A*(start,goal) 2 closedset := the empty set 3 // closedset存储已经访问过的节点 4 openset := {start} 5 //openset存储已经探测到但还未访问的节点,初始化时放入start点 6 came_from := the empty map 7 //came_from存储最短路径 8 9 g_score[start] := 0 10 //g_score[u]存储当前当u点到start点的最小代价 11 h_score[start] := heuristic_cost_estimate(start, goal) 12 //h_score[u]存储当前u点到goal点的最小代价 13 f_score[start] := g_score[start] + h_score[start] 14 //f_score[u]存储当前u点在整个状态空间中的代价 15 16 while openset is not empty 17 current := the node in openset having the lowest f_score[] value 18 //从当前openset中选取具有最小f_score的节点current 19 if current = goal 20 return reconstruct_path(came_from, came_from[goal]) 21 //判定如果是goal点,则结束 22 remove current from openset 23 add current to closedset 24 //判定如果不是goal点,则将current点从openset中移到closedset 25 for each neighbor in neighbor_nodes(current) 26 //遍历current直接相连的节点neighbor 27 //如果neighbor已经处理过一次(在closedset中),则跳过 28 if neighbor in closedset 29 continue 30 tentative_g_score := g_score[current] + dist_between(current,neighbor) 31 //利用当前current点的g_score重新计算neighbor的g_score 32 if neighbor not in openset 33 //如果neighbor是新探测到的节点(没有在openset中),创建新节点 34 add neighbor to openset 35 h_score[neighbor] := heuristic_cost_estimate(neighbor, goal) 36 tentative_is_better := true 37 else if tentative_g_score < g_score[neighbor] 38 //如果neighbor已经探测到,并且当前g_socre[current]有更小的代价 39 tentative_is_better := true 40 else 41 tentative_is_better := false 42 //更新neighbor的代价 43 if tentative_is_better = true 44 came_from[neighbor] := current 45 g_score[neighbor] := tentative_g_score 46 f_score[neighbor] := g_score[neighbor] + h_score[neighbor] 47 48 return failure 49 50 function reconstruct_path(came_from, current_node) 51 if came_from[current_node] is set 52 p := reconstruct_path(came_from, came_from[current_node]) 53 return (p + current_node) 54 else 55 return current_node