🌐 AI搜索 & 代理 主页
Skip to content

Commit 683e767

Browse files
committed
Add Astar implementation
1 parent 0a5a145 commit 683e767

File tree

2 files changed

+115
-1
lines changed

2 files changed

+115
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
- `bfs.py`
3030
- 04_dijkstra
3131
- `dijkstra.py`
32-
- a*
32+
- 05_astar
33+
-astar.py
3334
- mst_boruvka
3435
- mst_kruskal
3536
- mst_prim
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
from collections import deque
2+
3+
class Graph:
4+
# example of adjacency list (or rather map)
5+
# adjacency_list = {
6+
# 'A': [('B', 1), ('C', 3), ('D', 7)],
7+
# 'B': [('D', 5)],
8+
# 'C': [('D', 12)]
9+
# }
10+
11+
def __init__(self, adjacency_list):
12+
self.adjacency_list = adjacency_list
13+
14+
def get_neighbors(self, v):
15+
return self.adjacency_list[v]
16+
17+
# heuristic function with equal values for all nodes
18+
def h(self, n):
19+
H = {
20+
'A': 1,
21+
'B': 1,
22+
'C': 1,
23+
'D': 1
24+
}
25+
26+
return H[n]
27+
28+
def a_star_algorithm(self, start_node, stop_node):
29+
# open_list is a list of nodes which have been visited, but who's neighbors
30+
# haven't all been inspected, starts off with the start node
31+
# closed_list is a list of nodes which have been visited
32+
# and who's neighbors have been inspected
33+
open_list = set([start_node])
34+
closed_list = set([])
35+
36+
# g contains current distances from start_node to all other nodes
37+
# the default value (if it's not found in the map) is +infinity
38+
g = {}
39+
40+
g[start_node] = 0
41+
42+
# parents contains an adjacency map of all nodes
43+
parents = {}
44+
parents[start_node] = start_node
45+
46+
while len(open_list) > 0:
47+
n = None
48+
49+
# find a node with the lowest value of f() - evaluation function
50+
for v in open_list:
51+
if n == None or g[v] + self.h(v) < g[n] + self.h(n):
52+
n = v;
53+
54+
if n == None:
55+
print('Path does not exist!')
56+
return None
57+
58+
# if the current node is the stop_node
59+
# then we begin reconstructin the path from it to the start_node
60+
if n == stop_node:
61+
reconst_path = []
62+
63+
while parents[n] != n:
64+
reconst_path.append(n)
65+
n = parents[n]
66+
67+
reconst_path.append(start_node)
68+
69+
reconst_path.reverse()
70+
71+
print('Path found: {}'.format(reconst_path))
72+
return reconst_path
73+
74+
# for all neighbors of the current node do
75+
for (m, weight) in self.get_neighbors(n):
76+
# if the current node isn't in both open_list and closed_list
77+
# add it to open_list and note n as it's parent
78+
if m not in open_list and m not in closed_list:
79+
open_list.add(m)
80+
parents[m] = n
81+
g[m] = g[n] + weight
82+
83+
# otherwise, check if it's quicker to first visit n, then m
84+
# and if it is, update parent data and g data
85+
# and if the node was in the closed_list, move it to open_list
86+
else:
87+
if g[m] > g[n] + weight:
88+
g[m] = g[n] + weight
89+
parents[m] = n
90+
91+
if m in closed_list:
92+
closed_list.remove(m)
93+
open_list.add(m)
94+
95+
# remove n from the open_list, and add it to closed_list
96+
# because all of his neighbors were inspected
97+
open_list.remove(n)
98+
closed_list.add(n)
99+
100+
print('Path does not exist!')
101+
return None
102+
103+
def main():
104+
adjacency_list = {
105+
'A': [('B', 1), ('C', 3), ('D', 7)],
106+
'B': [('D', 5)],
107+
'C': [('D', 12)]
108+
}
109+
graph1 = Graph(adjacency_list)
110+
graph1.a_star_algorithm('A', 'D')
111+
112+
if __name__=="__main__":
113+
main()

0 commit comments

Comments
 (0)