Dijkstra’s Algorithm and Uniform Cost Search (UCS)

Unlike Depth-first Search (DFS) and Breadth-first Search (BFS), Dijkstra’s algorithm and UCS has path cost to be considered. Dijkstra’s algorithm is an algorithm that finds the shortest path from one node to every other node in the graph while UCS finds the shortest path between 2 nodes.

This video by John Levine is very vivid in illustrating the process of UCS. Once we understand how UCS works, Dijkstra’s algorithm is just an algorithm that finds the shortest path to every point instead of a single point.

For example, give the below graph, the codes for Dijkstra algo and UCS algo are

import collections
def generateDirectedGraph(edges):
    graph = collections.defaultdict(dict)
    for u, v, dist in edges:
        graph[u][v] = dist
    return graph
  
weighted_edges = [['a', 'b', 6], ['a', 'c', 3], ['b', 'c', 1], ['c', 'b', 4], ['b', 'd', 2], ['c', 'd', 8], ['c', 'e', 2], ['d', 'e', 9], ['e', 'd', 7]]
directed_weighted_graph = generateDirectedGraph(weighted_edges)
directed_weighted_graph

def dijkstra(graph, src):
    # The only criterium of adding a node to queue is if its distance has changed at the current step.
    queue = [src]
    minDistances = {v: float("inf") for v in graph}
    minDistances[src] = 0
    predecessor = {}

    while queue:
        currentNode = queue.pop(0)
        for neighbor in graph[currentNode]:
            # get potential newDist from start to neighbor
            newDist = minDistances[currentNode] + graph[currentNode][neighbor]
            
            # if the newDist is shorter to reach neighbor updated to newDist
            if newDist < minDistances[neighbor]:
                minDistances[neighbor] = min(newDist, minDistances[neighbor])
                queue.append(neighbor)
                predecessor[neighbor] = currentNode

    return minDistances, predecessor

shortest_path_cost, predecessor = dijkstra(directed_weighted_graph, 'a')
print("shortest_path_cost from node a to every nodes in graph:", shortest_path_cost, "\npredecessor dictionary:", predecessor)

# Unifrom Cost Search - shortest path between Source and Destination (Greedy)
def UCS(graph, src, dest):
    minDistances, predecessor = dijkstra(graph, src)
    
    path = []
    currentNode = dest
    while currentNode != src:
        if currentNode not in predecessor:
            print("Path not reachable")
            break
        else:
            path.insert(0, currentNode)
            currentNode = predecessor[currentNode]
    path.insert(0, src)
    
    if dest in minDistances and minDistances[dest] != float("inf"):
        print('Shortest distance is ' + str(minDistances[dest]))
        print('And the path is ' + str(path))
        
UCS(directed_weighted_graph, 'a', 'd')

the algo logic is like below, first the lazy Dijkstra's

Need to revisit this link by WilliamFiset for a full view of graph theory.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.