praca_magisterska/algorithms/dijkstra.py

112 lines
3.7 KiB
Python
Raw Normal View History

import heapq as heap
# function which takes graph, vertex set, start and goal, uses djikstra algorithm to establish shortest paths from start
# every other vertex in graph and returns shortest path between start and goal
def dijkstra_algorithm(graph, start, goal, is_directed=False):
# dictionary which will store for every vertex it's distance to start
dist = dict()
# dictionary which keeps if vertex was already popped from queue
visited = dict()
# dictionary which keeps for every vertex which other vertex is previous on the shortest path from start
prev = dict()
# list which is used to keep priority queue with vertexes to be explored by the algorithm
queue = []
# dictionary for keeping neighbors of vertexes.
point_set = dict()
for arc in graph.keys():
point_set[arc[0]] = []
point_set[arc[1]] = []
# creating dictionary which for every vertex keeps all it's neighbors
for arc in graph.keys():
point_set[arc[0]].append(arc[1])
if not is_directed:
point_set[arc[1]].append(arc[0])
# initialization of needed lists
for vertex in point_set:
# setting distance of every vertex from the starting vertex to infinity
dist[vertex] = float('inf')
# setting previous vertex in currently found shortest path for every vertex to None
prev[vertex] = None
# setting flag for every vertex keeping track if it was already visited my the algorithm
visited[vertex] = False
# pushing start vertex to priority queue
heap.heappush(queue, (0, start))
# setting distance to start for start vertex to 0
dist[start] = 0
# setting start vertex not to be added to priority queue again
visited[start] = True
# main loop
while len(queue) > 0:
# getting first vertex from the priority queue and saving it in current variable
current = heap.heappop(queue)
# iterating trough all neighbors of the current vertex
for neighbor in point_set[current[1]]:
# initializing potential distance to be replaced with the current neighbors
new_dist = 0
#
if not is_directed:
if neighbor > current[1]:
new_dist = dist[current[1]] + graph[(neighbor, current[1])]
else:
new_dist = dist[current[1]] + graph[(current[1], neighbor)]
else:
new_dist = dist[current[1]] + graph[(current[1], neighbor)]
if new_dist < dist[neighbor]:
dist[neighbor] = new_dist
for k in range(len(queue)):
if queue[k][1] == neighbor:
queue[k] = (new_dist, neighbor)
heap.heapify(queue)
prev[neighbor] = current[1]
if not visited[neighbor]:
visited[neighbor] = True
heap.heappush(queue, (new_dist, neighbor))
temp = goal
shortest_path = [goal]
while prev[temp] is not None:
shortest_path.append(prev[temp])
temp = prev[temp]
shortest_path.reverse()
return shortest_path, dist[goal]
if __name__ == "__main__":
g = {
(2, 1): 3,
(3, 2): 2,
(5, 3): 1,
(9, 5): 5,
(10, 9): 4,
(9, 4): 3,
(4, 1): 4,
(7, 1): 6,
(3, 1): 4,
(6, 2): 3,
(8, 6): 8,
(8, 3): 2,
(9, 1): 8
}
g2 = {
(4, 1): 6,
(1, 3): 4,
(1, 2): 2,
(2, 4): 5,
(3, 4): 1,
(5, 3): 1
}
print(dijkstra_algorithm(g, 7, 10))
2022-01-18 13:38:48 +01:00
print(dijkstra_algorithm(g2, 1, 4, is_directed=True))
print(dijkstra_algorithm(g2, 1, 5, is_directed=True))