-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPriorityQueue.py
More file actions
81 lines (68 loc) · 3.25 KB
/
PriorityQueue.py
File metadata and controls
81 lines (68 loc) · 3.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
class PriorityQueue:
def __init__(self, node_count):
# A hash table (dictionary) is used to find nodes (values) which have weights (keys) without excessive iteration
self.unvisited = {0: {(0, 0)}}
def update(self, node, distance):
raise ChildProcessError
def pop(self):
raise ChildProcessError
def get_dist(self, coord):
raise ChildProcessError
class DijkstraQueue(PriorityQueue):
def __init__(self, node_count):
super().__init__(node_count)
self.nodes = {(x // node_count, x % node_count): 9999 for x in range(node_count ** 2)}
self.nodes[(0, 0)] = 0
def update(self, node, distance):
# Updates unvisited table, making new sets if needed and editing them if not
if self.nodes[node] != 9999:
self.unvisited[self.nodes[node]].remove(node)
self.nodes[node] = distance
if distance not in self.unvisited.keys():
self.unvisited[distance] = {node}
else:
self.unvisited[distance].add(node)
def pop(self):
# finds the shortest distance within the unvisited nodes, then pops a random node with that distance
# Allows for O(log|E|) complexity, since only the unvisited edges are cycled through
# And they are further filtered by being grouped by distance
shortest_dist = min(self.unvisited.keys())
# Removes and replaces sets to prevent empty sets clogging the unvisited list
candidates = self.unvisited.pop(shortest_dist)
node = candidates.pop()
if candidates:
self.unvisited[shortest_dist] = candidates
return node
def get_dist(self, coord):
return self.nodes[coord]
class AStarQueue(PriorityQueue):
def __init__(self, node_count):
super().__init__(node_count)
self.nodes = {(x // node_count, x % node_count):
[9999,
abs(x // node_count - node_count) + abs(x % node_count - node_count)]
for x in range(node_count ** 2)}
self.nodes[(0, 0)][0] = 0
def update(self, node, distance):
# Updates unvisited table, making new sets if needed and editing them if not
if self.nodes[node][0] != 9999:
self.unvisited[sum(self.nodes[node])].remove(node)
self.nodes[node][0] = distance
weighting = sum(self.nodes[node])
if weighting not in self.unvisited.keys():
self.unvisited[weighting] = {node}
else:
self.unvisited[weighting].add(node)
def pop(self):
# finds the smallest weight within the unvisited nodes, then pops a random node with that distance
# Allows for O(log|E|) complexity, since only the unvisited edges are cycled through
# And they are further filtered by being grouped by distance
lowest_cost = min(self.unvisited.keys())
# Removes and replaces sets to prevent empty sets clogging the unvisited list
candidates = self.unvisited.pop(lowest_cost)
node = candidates.pop()
if candidates:
self.unvisited[lowest_cost] = candidates
return node
def get_dist(self, coord):
return self.nodes[coord][0]