dsa.dijkstras

Module to access functions for Dijkstra's Algorithm.

 1""" Module to access functions for Dijkstra's Algorithm. """
 2from dsa.heap import MinHeap
 3from dsa.graph import AdjacencyListWeightedGraph
 4
 5def shortest_path(graph: AdjacencyListWeightedGraph, start: str, end: str, debug: bool=False) -> tuple:
 6    """ 
 7    Helper function that returns a weight table and a predecessor table using Dijkstra's Algorithm.
 8
 9    Args:
10        graph (AdjacencyListWeighted Graph): The graph to search.
11        start (str): The starting vertex label.
12        end (str): The ending vertex label.
13        debug (bool): If True, display weight table as it is being built.
14    
15    Raises:
16        KeyError: If start or end vertex is not in the graph.
17        
18    Returns:
19        A tuple of a weight table hashtable and a predecessor predecessorhashtable.
20    """
21    if start not in graph:
22        raise KeyError(f"Start vertex {start} not in graph.")
23    if end not in graph:
24        raise KeyError(f"End vertex {end} not in graph.")
25
26    weight_table = {start: 0}
27    predecessor = {start: start}
28    visited = set()
29    pq = MinHeap()
30
31    pq.insert((0, start))
32    
33    while not pq.is_empty():
34        current_weight, current = pq.pop()
35        if current in visited:
36            continue
37        visited.add(current)
38
39        if current == end:
40            break
41
42        for adjacent, weight in graph[current].items():
43            new_dist = current_weight + weight
44            if new_dist < weight_table.get(adjacent, float('inf')):
45                weight_table[adjacent] = new_dist
46                predecessor[adjacent] = current
47                pq.insert((new_dist, adjacent))
48                if debug:
49                    print(weight_table)
50    
51    return weight_table, predecessor
52
53def find_path(graph: AdjacencyListWeightedGraph, start: str, end: str, debug: bool=False) -> list:
54    """ 
55    Return the shortest path of two vertices using Dijkstra's Algorithm.
56
57    Args:
58        graph (AdjacencyListWeighted Graph): The graph to search.
59        start (str): The starting vertex label.
60        end (str): The ending vertex label.
61        debug (bool): If True, display the weight table.
62    
63    Raises:
64        KeyError: If there is no path from start to end.
65
66    Returns:
67        A list of vertices that form a shortest path.
68    """
69    weight_table, predecessor = shortest_path(graph, start, end, debug)
70
71    # No path or invalid start/end
72    if end not in predecessor:
73        raise KeyError(f"No path from {start} to {end}.")
74
75    path = []
76    current = end
77    path.append(current)
78
79    while current != start:
80        current = predecessor[current]
81        path.append(current)
82
83    path.reverse()
84
85    if debug:
86        print("predecessor table")
87        print(predecessor)
88        print("weight table")
89        print(weight_table)
90        print("shortest path weight", weight_table[end])
91
92    return path
def shortest_path( graph: dsa.graph.AdjacencyListWeightedGraph, start: str, end: str, debug: bool = False) -> tuple:
 6def shortest_path(graph: AdjacencyListWeightedGraph, start: str, end: str, debug: bool=False) -> tuple:
 7    """ 
 8    Helper function that returns a weight table and a predecessor table using Dijkstra's Algorithm.
 9
10    Args:
11        graph (AdjacencyListWeighted Graph): The graph to search.
12        start (str): The starting vertex label.
13        end (str): The ending vertex label.
14        debug (bool): If True, display weight table as it is being built.
15    
16    Raises:
17        KeyError: If start or end vertex is not in the graph.
18        
19    Returns:
20        A tuple of a weight table hashtable and a predecessor predecessorhashtable.
21    """
22    if start not in graph:
23        raise KeyError(f"Start vertex {start} not in graph.")
24    if end not in graph:
25        raise KeyError(f"End vertex {end} not in graph.")
26
27    weight_table = {start: 0}
28    predecessor = {start: start}
29    visited = set()
30    pq = MinHeap()
31
32    pq.insert((0, start))
33    
34    while not pq.is_empty():
35        current_weight, current = pq.pop()
36        if current in visited:
37            continue
38        visited.add(current)
39
40        if current == end:
41            break
42
43        for adjacent, weight in graph[current].items():
44            new_dist = current_weight + weight
45            if new_dist < weight_table.get(adjacent, float('inf')):
46                weight_table[adjacent] = new_dist
47                predecessor[adjacent] = current
48                pq.insert((new_dist, adjacent))
49                if debug:
50                    print(weight_table)
51    
52    return weight_table, predecessor

Helper function that returns a weight table and a predecessor table using Dijkstra's Algorithm.

Args: graph (AdjacencyListWeighted Graph): The graph to search. start (str): The starting vertex label. end (str): The ending vertex label. debug (bool): If True, display weight table as it is being built.

Raises: KeyError: If start or end vertex is not in the graph.

Returns: A tuple of a weight table hashtable and a predecessor predecessorhashtable.

def find_path( graph: dsa.graph.AdjacencyListWeightedGraph, start: str, end: str, debug: bool = False) -> list:
54def find_path(graph: AdjacencyListWeightedGraph, start: str, end: str, debug: bool=False) -> list:
55    """ 
56    Return the shortest path of two vertices using Dijkstra's Algorithm.
57
58    Args:
59        graph (AdjacencyListWeighted Graph): The graph to search.
60        start (str): The starting vertex label.
61        end (str): The ending vertex label.
62        debug (bool): If True, display the weight table.
63    
64    Raises:
65        KeyError: If there is no path from start to end.
66
67    Returns:
68        A list of vertices that form a shortest path.
69    """
70    weight_table, predecessor = shortest_path(graph, start, end, debug)
71
72    # No path or invalid start/end
73    if end not in predecessor:
74        raise KeyError(f"No path from {start} to {end}.")
75
76    path = []
77    current = end
78    path.append(current)
79
80    while current != start:
81        current = predecessor[current]
82        path.append(current)
83
84    path.reverse()
85
86    if debug:
87        print("predecessor table")
88        print(predecessor)
89        print("weight table")
90        print(weight_table)
91        print("shortest path weight", weight_table[end])
92
93    return path

Return the shortest path of two vertices using Dijkstra's Algorithm.

Args: graph (AdjacencyListWeighted Graph): The graph to search. start (str): The starting vertex label. end (str): The ending vertex label. debug (bool): If True, display the weight table.

Raises: KeyError: If there is no path from start to end.

Returns: A list of vertices that form a shortest path.