sweeneyde

Faster special-case of Dijkstra

Apr 14th, 2020
250
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 1.75 KB | None | 0 0
  1. from collections import deque
  2.  
  3. def shortest_path(graph, source, destination):
  4.     """
  5.    Test/Example of usage:
  6.    
  7.    >>> A, B, C, D = 'ABCD'
  8.    >>> shortest_path({A:{A:0,B:0,C:1,D:2},\
  9.                       B:{A:0,B:0,C:2,D:2},\
  10.                       C:{A:1,B:2,C:0,D:0},\
  11.                       D:{A:2,D:2,C:0,D:0}},\
  12.                       A, D)
  13.    1
  14.    >>> shortest_path({A:{    B:2,       },\
  15.                       B:{A:2,    C:2,   },\
  16.                       C:{    B:2,    D:2},\
  17.                       D:{        C:2,   }},\
  18.                       A, D)
  19.    6
  20.    """
  21.     current_distance = 0
  22.     processed_nodes = set()
  23.    
  24.     # For i in {0,1,2}: qs[i] is a queue of nodes whose
  25.     # minimum distance from source is current_distance+i.
  26.     qs = deque([deque([source]), deque(), deque()])
  27.  
  28.     # while there are reachable, unprocessed nodes...
  29.     while any(qs):
  30.         closest = qs[0]
  31.         while closest:
  32.             # for each node that's current_distance away from source...
  33.             node = closest.popleft()
  34.             if node == destination:
  35.                 return current_distance
  36.             processed_nodes.add(node)
  37.            
  38.             # ... add its unprocessed neighbors to the appropriate queue.
  39.             for neighbor, edge in graph[node].items():
  40.                 if neighbor not in processed_nodes:
  41.                     qs[edge].append(neighbor)
  42.  
  43.         # now that the first queue is empty,
  44.         # start examining the next closest nodes.
  45.         current_distance += 1
  46.         # remove the used-up qs[0] and add a
  47.         # new qs[2] to hold the nodes that are
  48.         # current_distance+2 away.
  49.         qs.append(qs.popleft())
  50.  
  51.                    
  52. import doctest
  53. doctest.testmod()
Advertisement
Add Comment
Please, Sign In to add comment