PageRenderTime 49ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/unittests-accessibility.py

http://python-graph.googlecode.com/
Python | 327 lines | 223 code | 70 blank | 34 comment | 49 complexity | aad3f56f139421a7e0bd581ebeec91bf MD5 | raw file
  1. # Copyright (c) Pedro Matiello <pmatiello@gmail.com>
  2. #
  3. # Permission is hereby granted, free of charge, to any person
  4. # obtaining a copy of this software and associated documentation
  5. # files (the "Software"), to deal in the Software without
  6. # restriction, including without limitation the rights to use,
  7. # copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. # copies of the Software, and to permit persons to whom the
  9. # Software is furnished to do so, subject to the following
  10. # conditions:
  11. # The above copyright notice and this permission notice shall be
  12. # included in all copies or substantial portions of the Software.
  13. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  15. # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  17. # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  18. # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. # OTHER DEALINGS IN THE SOFTWARE.
  21. """
  22. Unittests for graph.algorithms.accessibility
  23. """
  24. import unittest
  25. import pygraph
  26. from pygraph.algorithms.searching import depth_first_search
  27. from pygraph.algorithms.accessibility import accessibility
  28. from pygraph.algorithms.accessibility import mutual_accessibility
  29. from pygraph.algorithms.accessibility import connected_components
  30. from pygraph.algorithms.accessibility import cut_nodes
  31. from pygraph.algorithms.accessibility import cut_edges
  32. from pygraph.classes.hypergraph import hypergraph
  33. from copy import deepcopy
  34. from sys import getrecursionlimit
  35. import testlib
  36. def number_of_connected_components(cc):
  37. n = 0
  38. for each in cc:
  39. if cc[each] > n:
  40. n = cc[each]
  41. return n
  42. class test_accessibility(unittest.TestCase):
  43. def setUp(self):
  44. pass
  45. def test_accessibility_in_graph(self):
  46. gr = testlib.new_graph()
  47. gr.add_nodes(['a','b','c'])
  48. gr.add_edge(('a','b'))
  49. gr.add_edge(('a','c'))
  50. ac = accessibility(gr)
  51. for n in gr:
  52. for m in gr:
  53. if (m in ac[n]):
  54. assert m in depth_first_search(gr, n)[0]
  55. assert n in depth_first_search(gr, m)[0]
  56. else:
  57. assert m not in depth_first_search(gr, n)[0]
  58. def test_accessibility_in_digraph(self):
  59. gr = testlib.new_digraph()
  60. gr.add_nodes(['a','b','c'])
  61. gr.add_edge(('a','b'))
  62. gr.add_edge(('a','c'))
  63. ac = accessibility(gr)
  64. for n in gr:
  65. for m in gr:
  66. if (m in ac[n]):
  67. assert m in depth_first_search(gr, n)[0]
  68. else:
  69. assert m not in depth_first_search(gr, n)[0]
  70. def test_accessibility_on_very_deep_graph(self):
  71. gr = pygraph.classes.graph.graph()
  72. gr.add_nodes(range(0,2001))
  73. for i in range(0,2000):
  74. gr.add_edge((i,i+1))
  75. recursionlimit = getrecursionlimit()
  76. accessibility(gr)
  77. assert getrecursionlimit() == recursionlimit
  78. def test_mutual_accessibility_in_graph(self):
  79. gr = testlib.new_graph()
  80. gr.add_nodes(['a','b','c'])
  81. gr.add_edge(('a','b'))
  82. gr.add_edge(('a','c'))
  83. ma = mutual_accessibility(gr)
  84. for n in gr:
  85. for m in gr:
  86. if (m in ma[n]):
  87. assert m in depth_first_search(gr, n)[0]
  88. assert n in depth_first_search(gr, m)[0]
  89. else:
  90. assert m not in depth_first_search(gr, n)[0] or n not in depth_first_search(gr, m)[0]
  91. def test_mutual_accessibility_on_very_deep_graph(self):
  92. gr = pygraph.classes.graph.graph()
  93. gr.add_nodes(range(0,5001))
  94. for i in range(0,5000):
  95. gr.add_edge((i,i+1))
  96. recursionlimit = getrecursionlimit()
  97. mutual_accessibility(gr)
  98. assert getrecursionlimit() == recursionlimit
  99. def test_mutual_accessibility_in_digraph(self):
  100. gr = testlib.new_digraph()
  101. gr.add_nodes(['a','b','c'])
  102. gr.add_edge(('a','b'))
  103. gr.add_edge(('b','a'))
  104. gr.add_edge(('a','c'))
  105. ma = mutual_accessibility(gr)
  106. for n in gr:
  107. for m in gr:
  108. if (m in ma[n]):
  109. assert m in depth_first_search(gr, n)[0]
  110. assert n in depth_first_search(gr, m)[0]
  111. else:
  112. assert m not in depth_first_search(gr, n)[0] or n not in depth_first_search(gr, m)[0]
  113. def test_connected_components_in_graph(self):
  114. gr = testlib.new_graph()
  115. gr.add_nodes(['a','b','c'])
  116. gr.add_edge(('a','b'))
  117. cc = connected_components(gr)
  118. for n in gr:
  119. for m in gr:
  120. if (cc[n] == cc[m]):
  121. assert m in depth_first_search(gr, n)[0]
  122. else:
  123. assert m not in depth_first_search(gr, n)[0]
  124. def test_connected_components_on_very_deep_graph(self):
  125. gr = pygraph.classes.graph.graph()
  126. gr.add_nodes(range(0,5001))
  127. for i in range(0,5000):
  128. gr.add_edge((i,i+1))
  129. recursionlimit = getrecursionlimit()
  130. connected_components(gr)
  131. assert getrecursionlimit() == recursionlimit
  132. def test_cut_nodes_in_graph(self):
  133. gr = testlib.new_graph()
  134. gr.add_nodes(['x','y'])
  135. gr.add_edge(('x','y'))
  136. gr.add_edge(('x',0))
  137. gr_copy = deepcopy(gr)
  138. cn = cut_nodes(gr)
  139. for each in cn:
  140. before = number_of_connected_components(connected_components(gr))
  141. gr.del_node(each)
  142. number_of_connected_components(connected_components(gr)) > before
  143. gr = gr_copy
  144. def test_cut_nodes_on_very_deep_graph(self):
  145. gr = pygraph.classes.graph.graph()
  146. gr.add_nodes(range(0,5001))
  147. for i in range(0,5000):
  148. gr.add_edge((i,i+1))
  149. recursionlimit = getrecursionlimit()
  150. cut_nodes(gr)
  151. assert getrecursionlimit() == recursionlimit
  152. def test_cut_edges_in_graph(self):
  153. gr = testlib.new_graph()
  154. gr.add_nodes(['x','y'])
  155. gr.add_edge(('x','y'))
  156. gr.add_edge(('x',0))
  157. gr_copy = deepcopy(gr)
  158. ce = cut_edges(gr)
  159. for each in ce:
  160. before = number_of_connected_components(connected_components(gr))
  161. gr.del_edge(each)
  162. number_of_connected_components(connected_components(gr)) > before
  163. gr = gr_copy
  164. def test_cut_edges_on_very_deep_graph(self):
  165. gr = pygraph.classes.graph.graph()
  166. gr.add_nodes(range(0,5001))
  167. for i in range(0,5000):
  168. gr.add_edge((i,i+1))
  169. recursionlimit = getrecursionlimit()
  170. cut_edges(gr)
  171. assert getrecursionlimit() == recursionlimit
  172. def test_accessibility_hypergraph(self):
  173. gr = hypergraph()
  174. # Add some nodes / edges
  175. gr.add_nodes(range(8))
  176. gr.add_hyperedges(['a', 'b', 'c'])
  177. # Connect the 9 nodes with three size-3 hyperedges
  178. for node_set in [['a',0,1,2], ['b',2,3,4], ['c',5,6,7]]:
  179. for node in node_set[1:]:
  180. gr.link(node, node_set[0])
  181. access = accessibility(gr)
  182. assert 8 == len(access)
  183. for i in range(5):
  184. assert set(access[i]) == set(range(5))
  185. for i in range(5,8):
  186. assert set(access[i]) == set(range(5,8))
  187. def test_connected_components_hypergraph(self):
  188. gr = hypergraph()
  189. # Add some nodes / edges
  190. gr.add_nodes(range(9))
  191. gr.add_hyperedges(['a', 'b', 'c'])
  192. # Connect the 9 nodes with three size-3 hyperedges
  193. for node_set in [['a',0,1,2], ['b',3,4,5], ['c',6,7,8]]:
  194. for node in node_set[1:]:
  195. gr.link(node, node_set[0])
  196. cc = connected_components(gr)
  197. assert 3 == len(set(cc.values()))
  198. assert cc[0] == cc[1] and cc[1] == cc[2]
  199. assert cc[3] == cc[4] and cc[4] == cc[5]
  200. assert cc[6] == cc[7] and cc[7] == cc[8]
  201. # Do it again with two components and more than one edge for each
  202. gr = hypergraph()
  203. gr.add_nodes(range(9))
  204. gr.add_hyperedges(['a', 'b', 'c', 'd'])
  205. for node_set in [['a',0,1,2], ['b',2,3,4], ['c',5,6,7], ['d',6,7,8]]:
  206. for node in node_set[1:]:
  207. gr.link(node, node_set[0])
  208. cc = connected_components(gr)
  209. assert 2 == len(set(cc.values()))
  210. for i in [0,1,2,3]:
  211. assert cc[i] == cc[i+1]
  212. for i in [5,6,7]:
  213. assert cc[i] == cc[i+1]
  214. assert cc[4] != cc[5]
  215. def test_cut_nodes_in_hypergraph(self):
  216. gr = hypergraph()
  217. # Add some nodes / edges
  218. gr.add_nodes(range(9))
  219. gr.add_hyperedges(['a', 'b', 'c'])
  220. # Connect the 9 nodes with three size-3 hyperedges
  221. for node_set in [['a',0,1,2], ['b',3,4,5], ['c',6,7,8]]:
  222. for node in node_set[1:]:
  223. gr.link(node, node_set[0])
  224. # Connect the groups
  225. gr.add_hyperedges(['l1','l2'])
  226. gr.link(0, 'l1')
  227. gr.link(3, 'l1')
  228. gr.link(5, 'l2')
  229. gr.link(8, 'l2')
  230. cn = cut_nodes(gr);
  231. assert 0 in cn
  232. assert 3 in cn
  233. assert 5 in cn
  234. assert 8 in cn
  235. assert len(cn) == 4
  236. def test_cut_edges_in_hypergraph(self):
  237. gr = hypergraph()
  238. # Add some nodes / edges
  239. gr.add_nodes(range(9))
  240. gr.add_hyperedges(['a1', 'b1', 'c1'])
  241. gr.add_hyperedges(['a2', 'b2', 'c2'])
  242. # Connect the 9 nodes with three size-3 hyperedges
  243. for node_set in [['a1',0,1,2], ['b1',3,4,5], ['c1',6,7,8], ['a2',0,1,2], ['b2',3,4,5], ['c2',6,7,8]]:
  244. for node in node_set[1:]:
  245. gr.link(node, node_set[0])
  246. # Connect the groups
  247. gr.add_hyperedges(['l1','l2'])
  248. gr.link(0, 'l1')
  249. gr.link(3, 'l1')
  250. gr.link(5, 'l2')
  251. gr.link(8, 'l2')
  252. ce = cut_edges(gr)
  253. assert 'l1' in ce
  254. assert 'l2' in ce
  255. assert len(ce) == 2
  256. if __name__ == "__main__":
  257. unittest.main()