路徑規划問題: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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM