|
| 1 | +""" |
| 2 | +Dijktra's shortest path algorithm. Finds the path and distance from source to target. |
| 3 | +To add an edge between vertex a and b with distance dist: |
| 4 | + graph[a].append((b, dist)) and graph[b].append((a, dist)). |
| 5 | +""" |
| 6 | + |
| 7 | + |
| 8 | +import heapq |
| 9 | + |
| 10 | + |
| 11 | +def dijkstra(graph, source, target): |
| 12 | + """ |
| 13 | + Finds the shortest path and shortest distance from source to target |
| 14 | +
|
| 15 | + :param graph: Dictionary linking the vertices using list of tuples |
| 16 | + :param source: The vertex to start the path. |
| 17 | + :param target: The vertex to end the path. |
| 18 | + :return: shortest path and distance from source to target |
| 19 | + """ |
| 20 | + INF = float('Inf') |
| 21 | + predecessors = {x: x for x in graph} |
| 22 | + distances = {x: INF for x in graph} |
| 23 | + distances[source] = 0 |
| 24 | + temp = [] |
| 25 | + heapq.heappush(temp, [source, distances[source]]) |
| 26 | + |
| 27 | + while temp: |
| 28 | + u = heapq.heappop(temp) |
| 29 | + u_dist = u[1] |
| 30 | + u_idx = u[0] |
| 31 | + if u_dist == distances[u_idx]: |
| 32 | + for v in graph[u_idx]: |
| 33 | + v_idx = v[0] |
| 34 | + u2v = v[1] |
| 35 | + if distances[u_idx] + u2v < distances[v_idx]: |
| 36 | + distances[v_idx] = distances[u_idx] + u2v |
| 37 | + heapq.heappush(temp, [v_idx, distances[v_idx]]) |
| 38 | + predecessors[v_idx] = u_idx |
| 39 | + |
| 40 | + if distances[target] == INF: |
| 41 | + return None, None |
| 42 | + else: |
| 43 | + path = [] |
| 44 | + vertex = target |
| 45 | + while True: |
| 46 | + path.append(str(vertex)) |
| 47 | + if vertex == predecessors[vertex]: |
| 48 | + break |
| 49 | + vertex = predecessors[vertex] |
| 50 | + return path[::-1], distances[target] |
| 51 | + |
| 52 | + |
| 53 | +def main(): |
| 54 | + """ |
| 55 | + driver function to test the dijkstra's algorithm |
| 56 | + """ |
| 57 | + graph = {'s': [('a', 2), ('b', 1)], |
| 58 | + 'a': [('s', 3), ('b', 4), ('c', 8)], |
| 59 | + 'b': [('s', 4), ('a', 2), ('d', 2)], |
| 60 | + 'c': [('a', 2), ('d', 7), ('t', 4)], |
| 61 | + 'd': [('b', 1), ('c', 11), ('t', 5)], |
| 62 | + 't': [('c', 3), ('d', 5)] |
| 63 | + } |
| 64 | + source = 'a' |
| 65 | + target = 't' |
| 66 | + path, cost = dijkstra(graph, source, target) |
| 67 | + print('The path from ' + source + ' to ' + target + ' :') |
| 68 | + if path is None or cost is None: |
| 69 | + print('does not exist') |
| 70 | + else: |
| 71 | + print(str(path) + ' with cost: ' + str(cost)) |
| 72 | + |
| 73 | + |
| 74 | +if __name__ == "__main__": |
| 75 | + main() |
0 commit comments