diff --git a/graphs/graphs_floyd_warshall.py b/graphs/graphs_floyd_warshall.py index aaed9ac5df8b..6a210692ae5b 100644 --- a/graphs/graphs_floyd_warshall.py +++ b/graphs/graphs_floyd_warshall.py @@ -1,62 +1,112 @@ # floyd_warshall.py """ -The problem is to find the shortest distance between all pairs of vertices in a -weighted directed graph that can have negative edge weights. +The problem is to find and return the shortest distance between all pairs of vertices +in a weighted directed graph that can have negative edge weights. """ -def _print_dist(dist, v): - print("\nThe shortest path matrix using Floyd Warshall algorithm\n") - for i in range(v): - for j in range(v): - if dist[i][j] != float("inf"): - print(int(dist[i][j]), end="\t") - else: - print("INF", end="\t") - print() +def floyd_warshall(graph: list[list[float]], vertex: int) -> tuple: + # 1. For all edges from v to n, distance[i][j] = weight(edge(i, j)). + + # 2. distance[i][j] = min(distance[i][j], distance[i][k] + distance[k][j]). + # 3. Step 2 is true for each pair of vertices.Repeat for k vertex in the graph. + + # 4. Whenever distance[i][j] is given a new minimum value, + # next vertex[i][j] = next vertex[i][k]. -def floyd_warshall(graph, v): """ :param graph: 2D array calculated from weight[edge[i, j]] - :type graph: List[List[float]] + :param v: number of vertices - :type v: int + :return: shortest distance between all vertex pairs + distance[u][v] will contain the shortest distance from vertex u to v. - 1. For all edges from v to n, distance[i][j] = weight(edge(i, j)). - 3. The algorithm then performs distance[i][j] = min(distance[i][j], distance[i][k] + - distance[k][j]) for each possible pair i, j of vertices. - 4. The above is repeated for each vertex k in the graph. - 5. Whenever distance[i][j] is given a new minimum value, next vertex[i][j] is - updated to the next vertex[i][k]. + # doctests: + + >>> graph = [[0, 3, float('inf')], [2, 0, float('inf')],[float('inf'), 7, 0]] + >>> floyd_warshall(graph, 3)[0] + [[0, 3, inf], [2, 0, inf], [9, 7, 0]] + + >>> graph = [[0, 1, 4],[float('inf'), 0, 2],[float('inf'), float('inf'), 0]] + >>> floyd_warshall(graph, 3)[0] + [[0, 1, 3], [inf, 0, 2], [inf, inf, 0]] + + >>> graph = [[0, 0, 0],[0, 0, 0],[0, 0, 0]] + >>> floyd_warshall(graph, 3)[0] + [[0, 0, 0], [0, 0, 0], [0, 0, 0]] + + #Graph with all edge weights = infinity + + >>> graph = [[float('inf'), float('inf'), float('inf')], + ... [float('inf'), float('inf'), float('inf')], + ... [float('inf'), float('inf'), float('inf')]] + >>> floyd_warshall(graph, 3)[0] + [[inf, inf, inf], [inf, inf, inf], [inf, inf, inf]] + + + #Handling negetive weighted graph: + + >>> graph = [[0, -2, float('inf')],[float('inf'), 0, 3],[4, float('inf'), 0]] + >>> floyd_warshall(graph, 3)[0] + [[0, -2, 1], [7, 0, 3], [4, 2, 0]] + + + #Handling negetive weighted cycle: + + >>> graph = [[0, -1, float('inf')],[float('inf'), 0, -2],[-3, float('inf'), 0]] + >>> floyd_warshall(graph, 3)[0] + [[-6, -7, -9], [-5, -6, -8], [-9, -10, -12]] + + + #Number of vertex in function argument should match number of vertex in graph: + + >>> graph = [[0, -1, float('inf')],[float('inf'), 0, -2]] + >>> floyd_warshall(graph, 3)[0] + Traceback (most recent call last): + ... + IndexError: list index out of range + + + #Graph data type should be a 2D list: + + >>> graph = "strings not allowed" + >>> floyd_warshall(graph, 3)[0] + Traceback (most recent call last): + ... + IndexError: string index out of range """ - dist = [[float("inf") for _ in range(v)] for _ in range(v)] + dist = [[float("inf") for _ in range(vertex)] for _ in range(vertex)] - for i in range(v): - for j in range(v): + for i in range(vertex): + for j in range(vertex): dist[i][j] = graph[i][j] - # check vertex k against all other vertices (i, j) - for k in range(v): + + for k in range(vertex): # looping through rows of graph array - for i in range(v): + + for i in range(vertex): # looping through columns of graph array - for j in range(v): + + for j in range(vertex): if ( dist[i][k] != float("inf") and dist[k][j] != float("inf") and dist[i][k] + dist[k][j] < dist[i][j] ): dist[i][j] = dist[i][k] + dist[k][j] - - _print_dist(dist, v) - return dist, v + return dist, vertex if __name__ == "__main__": + import doctest + + doctest.testmod() + v = int(input("Enter number of vertices: ")) e = int(input("Enter number of edges: "))