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