fork download
  1. from collections import deque
  2. import random
  3.  
  4.  
  5. def is_topsorted(V,E,sequence):
  6. sequence = list(sequence)
  7. #from wikipedia definition of top-sort
  8. #for every edge uv, u comes before v in the ordering
  9. for u,v in E:
  10. ui = sequence.index(u)
  11. vi = sequence.index(v)
  12. if not (ui < vi):
  13. return False
  14. return True
  15.  
  16. #the collection_type should behave like a set:
  17. # it must have add(), pop() and __len__() as members.
  18. def topsort(V,E,collection_type):
  19. #out edges
  20. INS = {}
  21.  
  22. #in edges
  23. OUTS = {}
  24. for v in V:
  25. INS[v] = set()
  26. OUTS[v] = set()
  27.  
  28. #for each edge u,v,
  29. for u,v in E:
  30. #record the out-edge from u
  31. OUTS[u].add(v)
  32. #record the in-edge to v
  33. INS[v].add(u)
  34.  
  35. #1. Store all vertices with indegree 0 in a queue
  36. #We will start
  37. topvertices = collection_type()
  38.  
  39. for v,in_vertices in INS.iteritems():
  40. if len(in_vertices) == 0:
  41. topvertices.add(v)
  42.  
  43. result = []
  44.  
  45. #4. Perform steps 2 and 3 while the queue is not empty.
  46. while len(topvertices) != 0:
  47. #2. get a vertex U and place it in the sorted sequence (array or another queue).
  48. u = topvertices.pop()
  49. result.append(u)
  50.  
  51. #3. For all edges (U,V) update the indegree of V,
  52. # and put V in the queue if the updated indegree is 0.
  53.  
  54. for v in OUTS[u]:
  55. INS[v].remove(u)
  56. if len(INS[v]) == 0:
  57. topvertices.add(v)
  58.  
  59. return result
  60.  
  61. class stack_collection:
  62. def __init__(self):
  63. self.data = list()
  64. def add(self,v):
  65. self.data.append(v)
  66. def pop(self):
  67. return self.data.pop()
  68. def __len__(self):
  69. return len(self.data)
  70.  
  71. class queue_collection:
  72. def __init__(self):
  73. self.data = deque()
  74. def add(self,v):
  75. self.data.append(v)
  76. def pop(self):
  77. return self.data.popleft()
  78. def __len__(self):
  79. return len(self.data)
  80.  
  81. class random_orderd_collection:
  82. def __init__(self):
  83. self.data = []
  84. def add(self,v):
  85. self.data.append(v)
  86. def pop(self):
  87. result = random.choice(self.data)
  88. self.data.remove(result)
  89. return result
  90. def __len__(self):
  91. return len(self.data)
  92.  
  93. """
  94. Poor man's graph generator.
  95. Requires networkx.
  96.  
  97. Don't make the edge_count too high compared with the vertex count,
  98. otherwise it will run for a long time or forever.
  99. """
  100. def nx_generate_random_dag(vertex_count,edge_count):
  101. import networkx as nx
  102.  
  103. V = range(1,vertex_count+1)
  104. random.shuffle(V)
  105.  
  106. G = nx.DiGraph()
  107. G.add_nodes_from(V)
  108.  
  109. while nx.number_of_edges(G) < edge_count:
  110.  
  111. u = random.choice(V)
  112. v = random.choice(V)
  113. if u == v:
  114. continue
  115.  
  116. for tries in range(2):
  117. G.add_edge(u,v)
  118. if not nx.is_directed_acyclic_graph(G):
  119. G.remove_edge(u,v)
  120. u,v = v,u
  121. V = G.nodes()
  122. E = G.edges()
  123.  
  124. assert len(E) == edge_count
  125. assert len(V) == vertex_count
  126. return V,E
  127.  
  128.  
  129.  
  130.  
  131. def main():
  132.  
  133. graphs = []
  134.  
  135. V = [1,2,3,4,5]
  136. E = [(1,2),(1,5),(1,4),(2,4),(2,5),(3,4),(3,5)]
  137.  
  138. graphs.append((V,E))
  139.  
  140. """
  141. Uncomment this section if you have networkx.
  142. This will generate 3 random graphs.
  143. """
  144. """
  145. for i in range(3):
  146. G = nx_generate_random_dag(30,120)
  147. V,E = G
  148. print 'random E:',E
  149. graphs.append(G)
  150. """
  151.  
  152.  
  153. #This graph was generated using nx_generate_random_dag() from above
  154. V = range(1,31)
  155. E = [(1, 10), (1, 11), (1, 14), (1, 17), (1, 18), (1, 21), (1, 23),
  156. (1, 30), (2, 4), (2, 12), (2, 15), (2, 17), (2, 18), (2, 19),
  157. (2, 25), (3, 22), (4, 5), (4, 8), (4, 22), (4, 23), (4, 26),
  158. (5, 27), (5, 23), (6, 24), (6, 28), (6, 27), (6, 20), (6, 29),
  159. (7, 3), (7, 19), (7, 13), (8, 24), (8, 10), (8, 3), (8, 12),
  160. (9, 4), (9, 8), (9, 10), (9, 14), (9, 19), (9, 27), (9, 28),
  161. (9, 29), (10, 18), (10, 5), (10, 23), (11, 27), (11, 5),
  162. (12, 10), (13, 9), (13, 26), (13, 3), (13, 12), (13, 6), (14, 24),
  163. (14, 28), (14, 18), (14, 20), (15, 3), (15, 12), (15, 17), (15, 19),
  164. (15, 25), (15, 27), (16, 4), (16, 5), (16, 8), (16, 18), (16, 20), (16, 23),
  165. (16, 26), (16, 28), (17, 4), (17, 5), (17, 8), (17, 12), (17, 22), (17, 28),
  166. (18, 11), (18, 3), (19, 10), (19, 18), (19, 5), (19, 22), (20, 5), (20, 29),
  167. (21, 25), (21, 12), (21, 30), (21, 17), (22, 11), (24, 3), (24, 10),
  168. (24, 11), (24, 28), (25, 10), (25, 17), (25, 23), (25, 27), (26, 3),
  169. (26, 18), (26, 19), (28, 26), (28, 11), (28, 23), (29, 2), (29, 4),
  170. (29, 11), (29, 15), (29, 17), (29, 22), (29, 23), (30, 3), (30, 7),
  171. (30, 17), (30, 20), (30, 25), (30, 26), (30, 28), (30, 29)]
  172.  
  173. graphs.append((V,E))
  174.  
  175. #add other graphs here for testing
  176.  
  177.  
  178. for G in graphs:
  179. V,E = G
  180.  
  181. #sets in python are unordered but in practice their hashes usually order integers.
  182. top_set = topsort(V,E,set)
  183.  
  184. top_stack = topsort(V,E,stack_collection)
  185.  
  186. top_queue = topsort(V,E,queue_collection)
  187.  
  188. random_results = []
  189. for i in range(0,10):
  190. random_results.append(topsort(V,E,random_orderd_collection))
  191.  
  192. print
  193. print 'V: ', V
  194. print 'E: ', E
  195. print 'top_set ({0}): {1}'.format(is_topsorted(V,E,top_set),top_set)
  196. print 'top_stack ({0}): {1}'.format(is_topsorted(V,E,top_stack),top_stack)
  197. print 'top_queue ({0}): {1}'.format(is_topsorted(V,E,top_queue),top_queue)
  198.  
  199. for random_result in random_results:
  200. print 'random_result ({0}): {1}'.format(is_topsorted(V,E,random_result),random_result)
  201. assert is_topsorted(V,E,random_result)
  202.  
  203. assert is_topsorted(V,E,top_set)
  204. assert is_topsorted(V,E,top_stack)
  205. assert is_topsorted(V,E,top_queue)
  206.  
  207.  
  208.  
  209. main()
  210.  
  211.  
  212.  
Success #stdin #stdout 0.12s 11112KB
stdin
Standard input is empty
stdout
V:  [1, 2, 3, 4, 5]
E:  [(1, 2), (1, 5), (1, 4), (2, 4), (2, 5), (3, 4), (3, 5)]
top_set (True): [1, 2, 3, 4, 5]
top_stack (True): [3, 1, 2, 5, 4]
top_queue (True): [1, 3, 2, 4, 5]
random_result (True): [1, 2, 3, 5, 4]
random_result (True): [1, 2, 3, 5, 4]
random_result (True): [1, 3, 2, 4, 5]
random_result (True): [3, 1, 2, 4, 5]
random_result (True): [1, 2, 3, 5, 4]
random_result (True): [3, 1, 2, 4, 5]
random_result (True): [1, 2, 3, 4, 5]
random_result (True): [1, 2, 3, 5, 4]
random_result (True): [1, 2, 3, 5, 4]
random_result (True): [1, 2, 3, 5, 4]

V:  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
E:  [(1, 10), (1, 11), (1, 14), (1, 17), (1, 18), (1, 21), (1, 23), (1, 30), (2, 4), (2, 12), (2, 15), (2, 17), (2, 18), (2, 19), (2, 25), (3, 22), (4, 5), (4, 8), (4, 22), (4, 23), (4, 26), (5, 27), (5, 23), (6, 24), (6, 28), (6, 27), (6, 20), (6, 29), (7, 3), (7, 19), (7, 13), (8, 24), (8, 10), (8, 3), (8, 12), (9, 4), (9, 8), (9, 10), (9, 14), (9, 19), (9, 27), (9, 28), (9, 29), (10, 18), (10, 5), (10, 23), (11, 27), (11, 5), (12, 10), (13, 9), (13, 26), (13, 3), (13, 12), (13, 6), (14, 24), (14, 28), (14, 18), (14, 20), (15, 3), (15, 12), (15, 17), (15, 19), (15, 25), (15, 27), (16, 4), (16, 5), (16, 8), (16, 18), (16, 20), (16, 23), (16, 26), (16, 28), (17, 4), (17, 5), (17, 8), (17, 12), (17, 22), (17, 28), (18, 11), (18, 3), (19, 10), (19, 18), (19, 5), (19, 22), (20, 5), (20, 29), (21, 25), (21, 12), (21, 30), (21, 17), (22, 11), (24, 3), (24, 10), (24, 11), (24, 28), (25, 10), (25, 17), (25, 23), (25, 27), (26, 3), (26, 18), (26, 19), (28, 26), (28, 11), (28, 23), (29, 2), (29, 4), (29, 11), (29, 15), (29, 17), (29, 22), (29, 23), (30, 3), (30, 7), (30, 17), (30, 20), (30, 25), (30, 26), (30, 28), (30, 29)]
top_set (True): [16, 1, 21, 30, 7, 13, 6, 9, 14, 20, 29, 2, 15, 25, 17, 4, 8, 24, 28, 26, 19, 12, 10, 18, 3, 22, 11, 5, 23, 27]
top_stack (True): [16, 1, 21, 30, 7, 13, 6, 9, 14, 20, 29, 2, 15, 25, 17, 4, 8, 12, 24, 28, 26, 19, 10, 18, 3, 22, 11, 5, 23, 27]
top_queue (True): [1, 16, 21, 30, 7, 13, 9, 6, 14, 20, 29, 2, 15, 25, 17, 4, 8, 24, 12, 28, 26, 19, 10, 18, 3, 22, 11, 5, 27, 23]
random_result (True): [1, 21, 30, 16, 7, 13, 9, 14, 6, 20, 29, 2, 15, 25, 17, 4, 8, 12, 24, 28, 26, 19, 10, 18, 3, 22, 11, 5, 23, 27]
random_result (True): [1, 16, 21, 30, 7, 13, 9, 6, 14, 20, 29, 2, 15, 25, 17, 4, 8, 12, 24, 28, 26, 19, 10, 18, 3, 22, 11, 5, 27, 23]
random_result (True): [1, 16, 21, 30, 7, 13, 6, 9, 14, 20, 29, 2, 15, 25, 17, 4, 8, 12, 24, 28, 26, 19, 10, 18, 3, 22, 11, 5, 27, 23]
random_result (True): [16, 1, 21, 30, 7, 13, 9, 14, 6, 20, 29, 2, 15, 25, 17, 4, 8, 24, 12, 28, 26, 19, 10, 18, 3, 22, 11, 5, 23, 27]
random_result (True): [1, 21, 16, 30, 7, 13, 9, 14, 6, 20, 29, 2, 15, 25, 17, 4, 8, 12, 24, 28, 26, 19, 10, 18, 3, 22, 11, 5, 23, 27]
random_result (True): [16, 1, 21, 30, 7, 13, 6, 9, 14, 20, 29, 2, 15, 25, 17, 4, 8, 24, 12, 28, 26, 19, 10, 18, 3, 22, 11, 5, 23, 27]
random_result (True): [1, 21, 30, 7, 16, 13, 6, 9, 14, 20, 29, 2, 15, 25, 17, 4, 8, 24, 12, 28, 26, 19, 10, 18, 3, 22, 11, 5, 23, 27]
random_result (True): [1, 21, 16, 30, 7, 13, 9, 6, 14, 20, 29, 2, 15, 25, 17, 4, 8, 12, 24, 28, 26, 19, 10, 18, 3, 22, 11, 5, 23, 27]
random_result (True): [1, 21, 16, 30, 7, 13, 9, 6, 14, 20, 29, 2, 15, 25, 17, 4, 8, 12, 24, 28, 26, 19, 10, 18, 3, 22, 11, 5, 23, 27]
random_result (True): [16, 1, 21, 30, 7, 13, 9, 6, 14, 20, 29, 2, 15, 25, 17, 4, 8, 12, 24, 28, 26, 19, 10, 18, 3, 22, 11, 5, 23, 27]