Advertisement
rfmonk

apsp.py

May 3rd, 2014
195
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.92 KB | None | 0 0
  1. #!/usr/bin/env python
  2. #
  3. # apsp.py -- implemented weighted paths & dijkstras algorithm
  4. # this is a code ex frm book "net sec through data analysis"
  5. # it can be found on git hub nsda_examples/didactic/graphs/
  6. import sys
  7. import os
  8. import basic_graph
  9.  
  10.  
  11. class WeightedGraph(basic_graph, UndirGraph):
  12.     def add_link(self, node_source, node_dest, weight):
  13.         # Weighted bidirectional link aid,
  14.         # note that we keep the aa, instead of simply setting value
  15.         # to 1, add weight value. This reverts to an unweighted
  16.         # graph if we always use the same weight.
  17.         self.add_node(node_source)
  18.         self.add_node(node_dest)
  19.         if not self.links.has_key(node_source):
  20.             self.links[node_source] = {}
  21.         if not self.links[node_source].has_key(node_dest):
  22.             self.links[node_source][node_dest] = 0
  23.         self.links[node_source][node_dest] += weight
  24.         if not self.links.has_key(node_dest):
  25.             self.links[node_dest] = 0
  26.         if not self.links[node_dest].has_key(node_source):
  27.             self.links[node_dest][node_source] = 0
  28.         self.links[node_dest][node_source] += weight
  29.  
  30.     def dijkstra(self, node_source):
  31.         D = {}  # Tentative distance table
  32.         P = {}  # predecessor table
  33.  
  34.         # The predecessor table exploits a unique feature of shortest paths,
  35.         # every subpath of a shortest path is itself a shortest path, so if
  36.         # you find the (B, C, D) is the shortest path from A to E, then
  37.         # (B, C) is the shortest path from A to D. All you have to do is keep
  38.         # track of the predecessor and walk backwards.
  39.  
  40.         infy = 999999999999     # shorthand for infinite
  41.         for i in self.nodes:
  42.             D[i] = infy
  43.             P[i] = None
  44.  
  45.             D[node_source] = 0
  46.             node_list = list(self.nodes)
  47.             while node_list != []:
  48.                 current_distance = infy
  49.                 current_node = None
  50.                 # Step 1, find the node with the smallest distance, that'll
  51.                 # be node_source in the first call as it's the only one
  52.                 # where D =0
  53.                 for i in node_list:
  54.                     if D[i] < current_distance:
  55.                         current_distance = D[i]
  56.                         current_node = i
  57.                 node_index = node_list.index(i)
  58.                 del node_list[node_index] # Remove it from the list
  59.                 if current_distance == infy:
  60.                     break # We've exhausted all paths from the node,
  61.                           # everything else is in a different component
  62.                 for i in self.neighbors(current_node):
  63.                     new_distance = D[current_node] + self.links[current_node][i]
  64.                     if new_distance < D[i]:
  65.                         D[i] = new_distance
  66.                         P[i] = current_node
  67.                         node_list.insert(0, i)
  68.  
  69.             for i in D.keys():
  70.                 if D[i] == infy:
  71.                     del D[i]
  72.  
  73.             for i in P.keys():
  74.                 if P[i] is None:
  75.                     del P[i]
  76.             return D, P
  77.            
  78.  
  79.         def apsp(self):
  80.             apsp_table = {}
  81.             for i in self.nodes:
  82.                 apsp_table[i] = self.dijkstra(i)
  83.             return apsp_table
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement