I'm trying to write an algorithm which will reconstruct the shortest path/s (multiple paths tied for the shortest if there are any) between all pairs of vertices in the Floyd-Warshall algorithm. I took some hints from the question here: https://stackoverflow.com/a/11371588/7447425
Based on this, I've modified the Floyd-Warshall algorithm:
from math import inf
def floyd_warshall(n, edge):
rn = range(n)
dist = [[inf] * n for i in rn]
next = [[-1] * n for i in rn]
for i in rn:
for j in rn:
next[i][j]=[-1]
for i in rn:
dist[i][i] = 0
for u, v, w in edge:
dist[u][v] = w
next[u][v]=[v]
for k in rn:
for i in rn:
for j in rn:
sum_ik_kj = dist[i][k] + dist[k][j]
if dist[i][j] > sum_ik_kj:
dist[i][j] = sum_ik_kj
next[i][j]=nxt[i][k]
elif(sum_ik_kj==dist[i][j] and dist[i][j]!=inf and k!=j and k!=i):
next[i][j].extend(next[i][k])
return next
The graph is in the form of edge-list for e.g.,:
edge = [[0,2,2],[2,3,2],[3,1,1],[1,0,4],[1,2,3],[0,3,4],[3,0,5]]
# Here n is the value of the highest numbered-vertex. In the above graph, n=4
n=4
next=floyd_warshall(n,edge)
Everything seems to be working well till this point.
For the path-reconstruction,
for i in range(n):
for j in range(n):
if(i!=j):
allPaths=[]
allPaths=getpath(i,j,next,allPaths)
print(allPaths)
def getpath(i,j,nxt,allPaths):
for k in next[i][j]:
if(k==-1):
allPaths.extend([i,j])
elif(k==j):
allPaths.append(j)
else:
paths_I_K=getpath(i,k,next,allPaths)
paths_K_J=getpath(k,j,next,allPaths)
for i_k in paths_I_K:
for k_j in paths_K_J:
i_k.pop()
allPaths.append(i_k+k_j)
return allPaths
But this isn't working. So, can anyone kindly rectify the getpath function (or write a more efficient one) so that I can get all the shortest paths (paths tied for shortest paths) between every pair of vertices?
For the graph above, I've got
next=
[[[-1], [3, 2], [2], [3, 2]],
[[0], [-1], [2], [2]],
[[3], [3], [-1], [3]],
[[0, 1], [1], [1], [-1]]]
which is accurate, but path reconstruction through this is becoming quite a hassle.