0

Ok, so I've implemented Djakstra's shortest path algorithm in Python and it is working properly (the distances are calculated correctly), but I want it to return the new optimized graph also. Here's my work:

nodes = ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I')
graph = {'A': {'B': 4, 'H': 8},
         'B': {'A': 4, 'C': 8, 'H': 11},
         'C': {'B': 8, 'D': 7, 'I': 2, 'F': 4},
         'D': {'C': 7, 'E': 9, 'F': 14},
         'E': {'D': 9, 'F': 10},
         'F': {'E': 10, 'D': 14, 'C': 4, 'G': 2},
         'G': {'F': 2, 'H': 1, 'I': 6},
         'H': {'A': 8, 'B': 11, 'I': 7, 'G': 1},
         'I': {'C': 2, 'H': 7, 'G':6}}



inf = 5000 #truncating inf as 5000
sptset = {} #shortest path tree set (SPT)
main = {} #main dict with nodes and their distances
source = 'A'

#initialization of source (starting point)
for node in nodes:
    main[node] = inf
main[source] = 0
sptset[source] = 0
temp_set = {source: 0}
path = {source: None}

current = None


while len(sptset)<len(nodes):
    path[min(temp_set, key=temp_set.get)] = current
    #keeping track of the path
    current = min(temp_set, key=temp_set.get)
    #choosing the next node to check as the minimum of the mainset 
    #(IF node IS NOT in stpset)
    sptset[current] = main.get(current)
    #adding the current node to stpset

    for neighbor in graph[current].keys():
        #for every adjacent node of the current
        alt = main.get(current) + graph[current].get(neighbor)
        #calculate the distance of current node(from the mainset) + wight to neighbor(from graph)
        if alt < main.get(neighbor):
        #if that sum is less than the distance of neighbor (from the mainset), then update it in mainset
            main[neighbor] = alt


    temp_set = {}
    for key in main.keys():
        if key not in sptset.keys():
            temp_set[key] = main.get(key)
    #this dictionary is being used to reconstruct the mainset WITHOUT the nodes already in stpset
    #(this is done so that the algorithm can be reiterated and a new current node can be chosen)


print path
print sptset

Now after the path gets printed, you can clearly that's just the algorithm path's, not the true path of the nodes. How can I figure out the true path of the nodes based on the distances I just calculated ?

z0r
  • 8,185
  • 4
  • 64
  • 83
Damian Radinoiu
  • 97
  • 2
  • 10

2 Answers2

0

You need to update the parent whenever you update the minimum distance. So instead of having path[min(temp_set, key=temp_set.get)] = current at the top of the main loop do the parent update under the same if block as distance:

if alt < main.get(neighbor):
#if that sum is less than the distance of neighbor (from the mainset), then update it in mainset
    path[neighbor] = current
    main[neighbor] = alt
niemmi
  • 17,113
  • 7
  • 35
  • 42
0

You don't need to store the path for each node: that information is already available in main. For a graph with low connectivity it's fine to scan over main to reconstruct any path as needed:

def parent_node(node):
    neighbors = graph[node]
    if len(neighbors) == 0:
        return None
    best_neighbor = min(neighbors, key=lambda neighbor: main[neighbor])
    if main[best_neighbor] >= main[node]:
        return None
    return best_neighbor

def shortest_path(node):
    path = []
    while node:
        path.append(node)
        node = parent_node(node)
    path.reverse()
    return path

farthest_node = max(graph, key=lambda node: main[node])
print shortest_path(farthest_node)
z0r
  • 8,185
  • 4
  • 64
  • 83