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
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.
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.