路径规划问题:A*算法 以及Python实现

参考:

https://www.geeksforgeeks.org/a-search-algorithm/

https://www.101computing.net/a-star-search-algorithm/

 

一. 概述:

A*算法是一种包含了启发的Djkstra算法,可以用来求带权值的图的最短路径。

A*算法比起Djkstra算法,在寻找最短路径的问题上更加有效率。

算法中,引入了距离作为启发,通过终点和节点的距离计算,选择迭代的点。

通常求距离有以下几种方案:

1. 曼哈顿距离

h = abs (current_cell.x – goal.x) + 
     abs (current_cell.y – goal.y) 

 

2. 对角线距离

 h = max { abs(current_cell.x – goal.x),
           abs(current_cell.y – goal.y) } 

 

3. 欧氏距离

h = sqrt ( (current_cell.x – goal.x)2 + 
            (current_cell.y – goal.y)2 ) 

 

 

二. 示例:

以下示例介绍运用A*算法的详细步骤,假设图如下,求A到Z的最短路径,各节点与Z的距离已经求得,下图中标为橙色

 

第一步:

初始化数据表如下,初始化每个节点到A的最短距离为无穷大

 

第二步:

以A为当前点,求出以A为起点的两条路径,并更新数据表。更新Total Distance为已计算的最短距离 + 与Z的启发距离

 

第三步:

由于C的Total Distance小于b,从c开始计算并更新e和d的距离

 

第四步:

B和D的Total Distance一样,我们从B开始迭代,进一步更新数据表

 

第五步:

 

第六步:

 

第七步:

迭代到Z,获得最小距离。最小路径可以从Z的前一个节点向前追溯,得到路径A-C-D-E。

最后再遍历没有访问的节点F,由于F的Total Distance > 17, 则不可能是最短路径节点。

 

三. Python代码实现:

 1 #!/usr/bin/python3
 2 # -*- coding: utf-8 -*-
 3 # @author: Asp1rant
 4 
 5 
 6 # 存放中间数据的数据结构
 7 class PriorityData:
 8     visited = False
 9     shortest_distance_start = 0
10     heuristic_distance_end = 0
11     total_distance = 0
12     previous_node = ''
13 
14     def __init__(self, heuristic_value):
15         self.heuristic_distance_end = heuristic_value
16         self.shortest_distance_start = 9999
17         self.total_distance = 9999
18 
19 
20 def a_star(graph, heuristic_value, start, end):
21     priority_dic = {}
22     for k in graph.keys():
23         priority_dic[k] = PriorityData(heuristic_value[k])
24     priority_dic[start].shortest_distance_start = 0
25 
26     # 判断终点是否访问
27     def isEndVisited():
28         ret = False
29         if priority_dic[end].visited:
30             distance = priority_dic[end].total_distance
31             ret = True
32         return ret
33 
34     # 更新节点数据表
35     def updateNode(node):
36         neighbors = graph[node]
37         for k in neighbors.keys():
38             neighbor_data = priority_dic[k]
39             if priority_dic[node].shortest_distance_start + neighbors[k] < neighbor_data.shortest_distance_start:
40                 neighbor_data.shortest_distance_start = priority_dic[node].shortest_distance_start + neighbors[k]
41             neighbor_data.total_distance = neighbor_data.shortest_distance_start + neighbor_data.heuristic_distance_end
42             neighbor_data.previous_node = node
43         priority_dic[node].visited = True
44 
45     find_point = start
46     while not isEndVisited():
47         updateNode(find_point)
48         shortest_distance = 9999
49         for k in priority_dic.keys():
50             if not priority_dic[k].visited and priority_dic[k].total_distance < shortest_distance:
51                 find_point = k
52                 shortest_distance = priority_dic[k].total_distance
53 
54     path_node_list = [end]
55     result_distance = priority_dic[end].total_distance
56     previous_node = priority_dic[end].previous_node
57     while previous_node != start:
58         path_node_list.append(previous_node)
59         previous_node = priority_dic[previous_node].previous_node
60     path_node_list.append(start)
61     path = path_node_list[len(path_node_list) - 1]
62     for i in range(len(path_node_list)-2, -1, -1):
63         path += "-"
64         path += path_node_list[i]
65     return (path, result_distance)
66 
67 
68 if __name__ == '__main__':
69     # 用于测试的图
70     graph = {
71                 "A": {"B": 4, "C": 3},
72                 "B": {"E": 12, "F": 5},
73                 "C": {"E": 10, "D": 7},
74                 "D": {"E": 2},
75                 "E": {"Z": 5},
76                 "F": {"Z": 16},
77                 "Z": {}
78             }
79     heuristic_value = {"A": 14, "B": 12, "C": 11, "D": 6, "E": 4, "F": 11, "Z": 0}
80     result = a_star(graph, heuristic_value, "A", "Z")
81     print(result)

结果:

('A-C-D-E-Z', 17)

 

posted @ 2020-10-19 18:32  Asp1rant  阅读(3880)  评论(0编辑  收藏  举报