2019-06-18 10:28:01 +00:00
|
|
|
# floyd_warshall.py
|
|
|
|
"""
|
2024-03-13 06:52:41 +00:00
|
|
|
The problem is to find the shortest distance between all pairs of vertices in a
|
|
|
|
weighted directed graph that can have negative edge weights.
|
2019-06-18 10:28:01 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
def _print_dist(dist, v):
|
2019-10-05 05:14:13 +00:00
|
|
|
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()
|
2018-10-19 12:48:28 +00:00
|
|
|
|
|
|
|
|
2019-06-18 10:28:01 +00:00
|
|
|
def floyd_warshall(graph, v):
|
2019-10-05 05:14:13 +00:00
|
|
|
"""
|
2019-06-18 10:28:01 +00:00
|
|
|
: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)).
|
2020-06-16 08:09:19 +00:00
|
|
|
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.
|
2019-06-18 10:28:01 +00:00
|
|
|
4. The above is repeated for each vertex k in the graph.
|
2020-06-16 08:09:19 +00:00
|
|
|
5. Whenever distance[i][j] is given a new minimum value, next vertex[i][j] is
|
|
|
|
updated to the next vertex[i][k].
|
2024-10-17 07:59:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
>>> num_vertices = 3
|
|
|
|
>>> graph = [
|
|
|
|
... [float('inf'), float('inf'), float('inf')],
|
|
|
|
... [float('inf'), float('inf'), float('inf')],
|
|
|
|
... [float('inf'), float('inf'), float('inf')]
|
|
|
|
... ]
|
2024-10-17 08:51:54 +00:00
|
|
|
|
2024-10-17 07:59:27 +00:00
|
|
|
>>> expected = [
|
|
|
|
... [0, 2, float('inf')],
|
|
|
|
... [1, 0, float('inf')],
|
|
|
|
... [float('inf'), float('inf'), 0]
|
|
|
|
... ]
|
|
|
|
>>> dist, _ = floyd_warshall(graph, num_vertices)
|
2024-10-17 08:57:46 +00:00
|
|
|
<BLANKLINE>
|
2024-10-17 08:26:29 +00:00
|
|
|
The shortest path matrix using Floyd Warshall algorithm
|
2024-10-17 08:57:46 +00:00
|
|
|
<BLANKLINE>
|
2024-10-17 08:26:29 +00:00
|
|
|
0 2 INF
|
|
|
|
1 0 INF
|
|
|
|
INF INF 0
|
2024-10-17 08:42:14 +00:00
|
|
|
>>> dist == expected
|
2024-10-17 07:59:27 +00:00
|
|
|
True
|
2019-06-18 10:28:01 +00:00
|
|
|
"""
|
2019-08-19 13:37:49 +00:00
|
|
|
|
2019-10-05 05:14:13 +00:00
|
|
|
dist = [[float("inf") for _ in range(v)] for _ in range(v)]
|
|
|
|
|
|
|
|
for i in range(v):
|
|
|
|
for j in range(v):
|
|
|
|
dist[i][j] = graph[i][j]
|
|
|
|
|
|
|
|
# check vertex k against all other vertices (i, j)
|
|
|
|
for k in range(v):
|
|
|
|
# looping through rows of graph array
|
|
|
|
for i in range(v):
|
|
|
|
# looping through columns of graph array
|
|
|
|
for j in range(v):
|
|
|
|
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
|
|
|
|
|
|
|
|
# # Expected Output from the vertice, edge and src, dst, weight inputs!!
|
|
|
|
# 0 INF INF
|
|
|
|
# INF 0 2
|
|
|
|
# INF 1 0
|