From 6b8cca5ef7c397febe672abcb9adf17b6aec00e2 Mon Sep 17 00:00:00 2001 From: asmitannu <143717144+asmitannu@users.noreply.github.com> Date: Sun, 15 Dec 2024 17:06:34 +0400 Subject: [PATCH 1/4] Update graphs_floyd_warshall.py Added Python Doctests Added type hints Added explanation to algorithm --- graphs/graphs_floyd_warshall.py | 158 ++++++++++++++++---------------- 1 file changed, 81 insertions(+), 77 deletions(-) diff --git a/graphs/graphs_floyd_warshall.py b/graphs/graphs_floyd_warshall.py index aaed9ac5df8b..f353d95ec10f 100644 --- a/graphs/graphs_floyd_warshall.py +++ b/graphs/graphs_floyd_warshall.py @@ -1,102 +1,106 @@ # floyd_warshall.py """ -The problem is to find the shortest distance between all pairs of vertices in a +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() +https://docs.python.org/3/library/doctest.html +""" -def floyd_warshall(graph, v): +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)). + + #3. distance[i][j] = min(distance[i][j], distance[i][k] +distance[k][j]) for each possible pair i, j of vertices. + + #4. Step 3 repeated for k vertex in the graph. + + #5. Whenever distance[i][j] is given a new minimum value, next vertex[i][j] = next vertex[i][k]. + """ :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 arguement 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 - - -if __name__ == "__main__": - v = int(input("Enter number of vertices: ")) - e = int(input("Enter number of edges: ")) - - graph = [[float("inf") for i in range(v)] for j in range(v)] - - for i in range(v): - graph[i][i] = 0.0 - - # src and dst are indices that must be within the array size graph[e][v] - # failure to follow this will result in an error - for i in range(e): - print("\nEdge ", i + 1) - src = int(input("Enter source:")) - dst = int(input("Enter destination:")) - weight = float(input("Enter weight:")) - graph[src][dst] = weight - - floyd_warshall(graph, v) - - # Example Input - # Enter number of vertices: 3 - # Enter number of edges: 2 - - # # generated graph from vertex and edge inputs - # [[inf, inf, inf], [inf, inf, inf], [inf, inf, inf]] - # [[0.0, inf, inf], [inf, 0.0, inf], [inf, inf, 0.0]] - - # specify source, destination and weight for edge #1 - # Edge 1 - # Enter source:1 - # Enter destination:2 - # Enter weight:2 - - # specify source, destination and weight for edge #2 - # Edge 2 - # Enter source:2 - # Enter destination:1 - # Enter weight:1 + return dist, vertex - # # Expected Output from the vertice, edge and src, dst, weight inputs!! - # 0 INF INF - # INF 0 2 - # INF 1 0 +if __name__== "__main__": + import doctest + doctest.testmod() From 0efe9a4c454d52de968012e46af8b56a9b3b6656 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 15 Dec 2024 13:13:24 +0000 Subject: [PATCH 2/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- graphs/graphs_floyd_warshall.py | 73 +++++++++++++++++---------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/graphs/graphs_floyd_warshall.py b/graphs/graphs_floyd_warshall.py index f353d95ec10f..a5873161fd8a 100644 --- a/graphs/graphs_floyd_warshall.py +++ b/graphs/graphs_floyd_warshall.py @@ -7,70 +7,71 @@ """ -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)). - - #3. distance[i][j] = min(distance[i][j], distance[i][k] +distance[k][j]) for each possible pair i, j of vertices. - - #4. Step 3 repeated for k vertex in the graph. - - #5. Whenever distance[i][j] is given a new minimum value, next vertex[i][j] = next vertex[i][k]. - + +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)). + + # 3. distance[i][j] = min(distance[i][j], distance[i][k] +distance[k][j]) for each possible pair i, j of vertices. + + # 4. Step 3 repeated for k vertex in the graph. + + # 5. Whenever distance[i][j] is given a new minimum value, next vertex[i][j] = next vertex[i][k]. + """ :param graph: 2D array calculated from weight[edge[i, j]] - + :param v: number of vertices - + :return: shortest distance between all vertex pairs - + distance[u][v] will contain the shortest distance from vertex u to v. - + # 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 arguement 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): @@ -84,23 +85,25 @@ def floyd_warshall(graph:list[list[float]], vertex:int) -> tuple: for j in range(vertex): dist[i][j] = graph[i][j] # check vertex k against all other vertices (i, j) - + for k in range(vertex): # looping through rows of graph array - + for i in range(vertex): # looping through columns of graph array - + 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] return dist, vertex -if __name__== "__main__": + +if __name__ == "__main__": import doctest + doctest.testmod() From 79ecb3352b79a9da0f348543c9c17f47a132a817 Mon Sep 17 00:00:00 2001 From: asmitannu <143717144+asmitannu@users.noreply.github.com> Date: Sun, 15 Dec 2024 17:33:58 +0400 Subject: [PATCH 3/4] Update graphs_floyd_warshall.py --- graphs/graphs_floyd_warshall.py | 83 ++++++++++++++++----------------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/graphs/graphs_floyd_warshall.py b/graphs/graphs_floyd_warshall.py index a5873161fd8a..2b1b2cc84263 100644 --- a/graphs/graphs_floyd_warshall.py +++ b/graphs/graphs_floyd_warshall.py @@ -1,77 +1,79 @@ # floyd_warshall.py """ -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. +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. https://docs.python.org/3/library/doctest.html """ - -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)). - - # 3. distance[i][j] = min(distance[i][j], distance[i][k] +distance[k][j]) for each possible pair i, j of vertices. - - # 4. Step 3 repeated for k vertex in the graph. - - # 5. Whenever distance[i][j] is given a new minimum value, next vertex[i][j] = next vertex[i][k]. - +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]. + """ :param graph: 2D array calculated from weight[edge[i, j]] - + :param v: number of vertices - + :return: shortest distance between all vertex pairs - + distance[u][v] will contain the shortest distance from vertex u to v. - + # 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')]] + + >>> 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 arguement 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): @@ -85,25 +87,22 @@ def floyd_warshall(graph: list[list[float]], vertex: int) -> tuple: for j in range(vertex): dist[i][j] = graph[i][j] # check vertex k against all other vertices (i, j) - + for k in range(vertex): # looping through rows of graph array - + for i in range(vertex): # looping through columns of graph array - + 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] - return dist, vertex - -if __name__ == "__main__": +if __name__== "__main__": import doctest - doctest.testmod() From 66045d3d76c099459eb753353f46e13393104e42 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 15 Dec 2024 13:34:20 +0000 Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- graphs/graphs_floyd_warshall.py | 75 +++++++++++++++++---------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/graphs/graphs_floyd_warshall.py b/graphs/graphs_floyd_warshall.py index 2b1b2cc84263..a6693c9a327b 100644 --- a/graphs/graphs_floyd_warshall.py +++ b/graphs/graphs_floyd_warshall.py @@ -1,79 +1,80 @@ # floyd_warshall.py """ -The problem is to find and return the shortest distance between all pairs of vertices +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. https://docs.python.org/3/library/doctest.html """ -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, + +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]. - + """ :param graph: 2D array calculated from weight[edge[i, j]] - + :param v: number of vertices - + :return: shortest distance between all vertex pairs - + distance[u][v] will contain the shortest distance from vertex u to v. - + # 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 arguement 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): @@ -87,22 +88,24 @@ def floyd_warshall(graph:list[list[float]], vertex:int) -> tuple: for j in range(vertex): dist[i][j] = graph[i][j] # check vertex k against all other vertices (i, j) - + for k in range(vertex): # looping through rows of graph array - + for i in range(vertex): # looping through columns of graph array - + 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] return dist, vertex -if __name__== "__main__": + +if __name__ == "__main__": import doctest + doctest.testmod()