Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Floyd-Warshall algorithm: get the shortest paths

Assume a graph is represented by a n x n dimension adjacency matrix. I know the how to get the shortest path matrix for all pairs. But I wonder is there a way to trace all the shortest paths? Blow is the python code implementation.

v = len(graph)
for k in range(0,v):
    for i in range(0,v):
        for j in range(0,v):
            if graph[i,j] > graph[i,k] + graph[k,j]:
                graph[i,j] = graph[i,k] + graph[k,j]
like image 587
Joey Lant Avatar asked Apr 16 '17 22:04

Joey Lant


People also ask

Which algorithm is used for finding the shortest paths?

Dijkstra's algorithm (/ˈdaɪkstrəz/ DYKE-strəz) is an algorithm for finding the shortest paths between nodes in a graph, which may represent, for example, road networks.

How does BFS give the shortest path?

We say that BFS is the algorithm to use if we want to find the shortest path in an undirected, unweighted graph. The claim for BFS is that the first time a node is discovered during the traversal, that distance from the source would give us the shortest path.

Can Floyd-Warshall algorithm for all pairs shortest path problem be used on a graph which contains a few negative weighted edges but no negative weight cycle?

Formally the Floyd-Warshall algorithm does not apply to graphs containing negative weight cycle(s). But for all pairs of vertices and for which there doesn't exist a path starting at , visiting a negative cycle, and end at , the algorithm will still work correctly.

Is Floyd-Warshall better than Dijkstra?

Unlike Dijkstra's algorithm, Floyd Warshall can be implemented in a distributed system, making it suitable for data structures such as Graph of Graphs (Used in Maps). Lastly Floyd Warshall works for negative edge but no negative cycle, whereas Dijkstra's algorithm don't work for negative edges.


1 Answers

You have to add to your if statement a new matrix to store path reconstruction data (array p which is predecessor matrix):

    if graph[i,j] > graph[i,k] + graph[k,j]:
        graph[i,j] = graph[i,k] + graph[k,j]
        p[i,j] = p[k,j]

At the beginning the matrix p have to be filled as:

for i in range(0,v):
    for j in range(0,v):
        p[i,j] = i
        if (i != j and graph[i,j] == 0):
             p[i,j] = -30000  # any big negative number to show no arc (F-W does not work with negative weights)

To reconstruct the path between i and j nodes you have to call:

def ConstructPath(p, i, j):
    i,j = int(i), int(j)
    if(i==j):
      print (i,)
    elif(p[i,j] == -30000):
      print (i,'-',j)
    else:
      ConstructPath(p, i, p[i,j]);
      print(j,)

And the test with above function:

import numpy as np

graph = np.array([[0,10,20,30,0,0],[0,0,0,0,0,7],[0,0,0,0,0,5],[0,0,0,0,10,0],[2,0,0,0,0,4],[0,5,7,0,6,0]])

v = len(graph)

# path reconstruction matrix
p = np.zeros(graph.shape)
for i in range(0,v):
    for j in range(0,v):
        p[i,j] = i
        if (i != j and graph[i,j] == 0): 
            p[i,j] = -30000 
            graph[i,j] = 30000 # set zeros to any large number which is bigger then the longest way

for k in range(0,v):
    for i in range(0,v):
        for j in range(0,v):
            if graph[i,j] > graph[i,k] + graph[k,j]:
                graph[i,j] = graph[i,k] + graph[k,j]
                p[i,j] = p[k,j]

# show p matrix
print(p)

# reconstruct the path from 0 to 4
ConstructPath(p,0,4)

Output:

p:

[[ 0.  0.  0.  0.  5.  1.]
 [ 4.  1.  5.  0.  5.  1.]
 [ 4.  5.  2.  0.  5.  2.]
 [ 4.  5.  5.  3.  3.  4.]
 [ 4.  5.  5.  0.  4.  4.]
 [ 4.  5.  5.  0.  5.  5.]]

Path 0-4:

0
1
5
4
like image 183
Serenity Avatar answered Nov 15 '22 12:11

Serenity