diff --git a/algorithms/Python/graphs/python-dijkstra.py b/algorithms/Python/graphs/python-dijkstra.py new file mode 100644 index 00000000..888bfad8 --- /dev/null +++ b/algorithms/Python/graphs/python-dijkstra.py @@ -0,0 +1,111 @@ +# A Dijkstra's algorithm implementation in Python +# using adjacency matrix +# Time complexity: O(V+E)*O(logV) + +from math import inf + +wmat = [[0, 2, 0, 0, 0, 1, 0, 0], + [2, 0, 2, 2, 4, 0, 0, 0], + [0, 2, 0, 0, 3, 0, 0, 1], + [0, 2, 0, 0, 4, 3, 0, 0], + [0, 4, 3, 4, 0, 0, 7, 0], + [1, 0, 0, 3, 0, 0, 5, 0], + [0, 0, 0, 0, 7, 5, 0, 6], + [0, 0, 1, 0, 0, 0, 6, 0]] + + +def find_all(wmat, start, end=-1): + """ + Returns a tuple with a distances' list and paths' list of + all remaining vertices with the same indexing. + + (distances, paths) + + For example, distances[x] are the shortest distances from x + vertex which shortest path is paths[x]. x is an element of + {0, 1, ..., n-1} where n is the number of vertices + + Args: + wmat -- weighted graph's adjacency matrix + start -- paths' first vertex + end -- (optional) path's end vertex. Return just the + distance and its path + + Exceptions: + Index out of range, Be careful with start and end vertices + """ + n = len(wmat) + + dist = [inf]*n + dist[start] = wmat[start][start] # 0 + + spVertex = [False]*n + parent = [-1]*n + + path = [{}]*n + + for count in range(n-1): + minix = inf + u = 0 + + for v in range(len(spVertex)): + if spVertex[v] == False and dist[v] <= minix: + minix = dist[v] + u = v + + spVertex[u] = True + for v in range(n): + if not(spVertex[v]) and wmat[u][v] != 0 and dist[u] + wmat[u][v] < dist[v]: + parent[v] = u + dist[v] = dist[u] + wmat[u][v] + + for i in range(n): + j = i + s = [] + while parent[j] != -1: + s.append(j) + j = parent[j] + s.append(start) + path[i] = s[::-1] + + return (dist[end], path[end]) if end >= 0 else (dist, path) + + +def find_shortest_path(wmat, start, end=-1): + """ + Returns paths' list of all remaining vertices. + + Args: + wmat -- weigthted graph's adjacency matrix + start -- paths' first vertex + end -- (optional) path's end vertex. Return just + the path + + Exceptions: + Index out of range, Be careful with start and end vertices. + """ + return find_all(wmat, start, end)[1] + + +def find_shortest_distance(wmat, start, end=-1): + """ + Returns distances' list of all remaining vertices. + + Args: + wmat -- weigthted graph's adjacency matrix + start -- paths' first vertex + end -- (optional) path's end vertex. Return just + the distance + + Exceptions: + Index out of range, Be careful with start and end vertices. + """ + return find_all(wmat, start, end)[0] + +if __name__ == "__main__": + i = 0 + for D, P in zip(*find_all(wmat, 0)): + print("Target: {}, Distance: {}, Path: {}".format(i, D, P)) + i += 1 + print("\nshortest path to last node", find_shortest_path(wmat, 0, 7)) + print("shortest distance to last node", find_shortest_distance(wmat, 0, 7))