1
1
# floyd_warshall.py
2
2
"""
3
- The problem is to find and return the shortest distance between all pairs of vertices
3
+ The problem is to find and return the shortest distance between all pairs of vertices
4
4
in a weighted directed graph that can have negative edge weights.
5
5
6
6
https://docs.python.org/3/library/doctest.html
7
7
8
8
"""
9
9
10
- def floyd_warshall (graph :list [list [float ]], vertex :int ) -> tuple :
11
- #1. For all edges from v to n, distance[i][j] = weight(edge(i, j)).
12
-
13
- #2. distance[i][j] = min(distance[i][j], distance[i][k] + distance[k][j]).
14
-
15
- #3. Step 2 is true for each pair of vertices.Repeat for k vertex in the graph.
16
-
17
- #4. Whenever distance[i][j] is given a new minimum value,
10
+
11
+ def floyd_warshall (graph : list [list [float ]], vertex : int ) -> tuple :
12
+ # 1. For all edges from v to n, distance[i][j] = weight(edge(i, j)).
13
+
14
+ # 2. distance[i][j] = min(distance[i][j], distance[i][k] + distance[k][j]).
15
+
16
+ # 3. Step 2 is true for each pair of vertices.Repeat for k vertex in the graph.
17
+
18
+ # 4. Whenever distance[i][j] is given a new minimum value,
18
19
# next vertex[i][j] = next vertex[i][k].
19
-
20
+
20
21
"""
21
22
:param graph: 2D array calculated from weight[edge[i, j]]
22
-
23
+
23
24
:param v: number of vertices
24
-
25
+
25
26
:return: shortest distance between all vertex pairs
26
-
27
+
27
28
distance[u][v] will contain the shortest distance from vertex u to v.
28
-
29
+
29
30
# doctests:
30
-
31
+
31
32
>>> graph = [[0, 3, float('inf')], [2, 0, float('inf')],[float('inf'), 7, 0]]
32
33
>>> floyd_warshall(graph, 3)[0]
33
34
[[0, 3, inf], [2, 0, inf], [9, 7, 0]]
34
-
35
+
35
36
>>> graph = [[0, 1, 4],[float('inf'), 0, 2],[float('inf'), float('inf'), 0]]
36
37
>>> floyd_warshall(graph, 3)[0]
37
38
[[0, 1, 3], [inf, 0, 2], [inf, inf, 0]]
38
-
39
+
39
40
>>> graph = [[0, 0, 0],[0, 0, 0],[0, 0, 0]]
40
41
>>> floyd_warshall(graph, 3)[0]
41
42
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
42
-
43
+
43
44
#Graph with all edge weights = infinity
44
-
45
+
45
46
>>> graph = [[float('inf'), float('inf'), float('inf')],
46
47
... [float('inf'), float('inf'), float('inf')],
47
48
... [float('inf'), float('inf'), float('inf')]]
48
49
>>> floyd_warshall(graph, 3)[0]
49
50
[[inf, inf, inf], [inf, inf, inf], [inf, inf, inf]]
50
-
51
-
51
+
52
+
52
53
#Handling negetive weighted graph:
53
-
54
+
54
55
>>> graph = [[0, -2, float('inf')],[float('inf'), 0, 3],[4, float('inf'), 0]]
55
56
>>> floyd_warshall(graph, 3)[0]
56
57
[[0, -2, 1], [7, 0, 3], [4, 2, 0]]
57
-
58
-
58
+
59
+
59
60
#Handling negetive weighted cycle:
60
-
61
+
61
62
>>> graph = [[0, -1, float('inf')],[float('inf'), 0, -2],[-3, float('inf'), 0]]
62
63
>>> floyd_warshall(graph, 3)[0]
63
64
[[-6, -7, -9], [-5, -6, -8], [-9, -10, -12]]
64
-
65
-
65
+
66
+
66
67
#Number of vertex in function argument should match number of vertex in graph:
67
-
68
+
68
69
>>> graph = [[0, -1, float('inf')],[float('inf'), 0, -2]]
69
70
>>> floyd_warshall(graph, 3)[0]
70
71
Traceback (most recent call last):
71
72
...
72
73
IndexError: list index out of range
73
-
74
-
74
+
75
+
75
76
#Graph data type should be a 2D list:
76
-
77
+
77
78
>>> graph = "strings not allowed"
78
79
>>> floyd_warshall(graph, 3)[0]
79
80
Traceback (most recent call last):
@@ -87,22 +88,24 @@ def floyd_warshall(graph:list[list[float]], vertex:int) -> tuple:
87
88
for j in range (vertex ):
88
89
dist [i ][j ] = graph [i ][j ]
89
90
# check vertex k against all other vertices (i, j)
90
-
91
+
91
92
for k in range (vertex ):
92
93
# looping through rows of graph array
93
-
94
+
94
95
for i in range (vertex ):
95
96
# looping through columns of graph array
96
-
97
+
97
98
for j in range (vertex ):
98
99
if (
99
100
dist [i ][k ] != float ("inf" )
100
101
and dist [k ][j ] != float ("inf" )
101
102
and dist [i ][k ] + dist [k ][j ] < dist [i ][j ]
102
- ):
103
+ ):
103
104
dist [i ][j ] = dist [i ][k ] + dist [k ][j ]
104
105
return dist , vertex
105
106
106
- if __name__ == "__main__" :
107
+
108
+ if __name__ == "__main__" :
107
109
import doctest
110
+
108
111
doctest .testmod ()
0 commit comments