test_biconnected.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. import pytest
  2. import networkx as nx
  3. from networkx import NetworkXNotImplemented
  4. def assert_components_edges_equal(x, y):
  5. sx = {frozenset(frozenset(e) for e in c) for c in x}
  6. sy = {frozenset(frozenset(e) for e in c) for c in y}
  7. assert sx == sy
  8. def assert_components_equal(x, y):
  9. sx = {frozenset(c) for c in x}
  10. sy = {frozenset(c) for c in y}
  11. assert sx == sy
  12. def test_barbell():
  13. G = nx.barbell_graph(8, 4)
  14. nx.add_path(G, [7, 20, 21, 22])
  15. nx.add_cycle(G, [22, 23, 24, 25])
  16. pts = set(nx.articulation_points(G))
  17. assert pts == {7, 8, 9, 10, 11, 12, 20, 21, 22}
  18. answer = [
  19. {12, 13, 14, 15, 16, 17, 18, 19},
  20. {0, 1, 2, 3, 4, 5, 6, 7},
  21. {22, 23, 24, 25},
  22. {11, 12},
  23. {10, 11},
  24. {9, 10},
  25. {8, 9},
  26. {7, 8},
  27. {21, 22},
  28. {20, 21},
  29. {7, 20},
  30. ]
  31. assert_components_equal(list(nx.biconnected_components(G)), answer)
  32. G.add_edge(2, 17)
  33. pts = set(nx.articulation_points(G))
  34. assert pts == {7, 20, 21, 22}
  35. def test_articulation_points_repetitions():
  36. G = nx.Graph()
  37. G.add_edges_from([(0, 1), (1, 2), (1, 3)])
  38. assert list(nx.articulation_points(G)) == [1]
  39. def test_articulation_points_cycle():
  40. G = nx.cycle_graph(3)
  41. nx.add_cycle(G, [1, 3, 4])
  42. pts = set(nx.articulation_points(G))
  43. assert pts == {1}
  44. def test_is_biconnected():
  45. G = nx.cycle_graph(3)
  46. assert nx.is_biconnected(G)
  47. nx.add_cycle(G, [1, 3, 4])
  48. assert not nx.is_biconnected(G)
  49. def test_empty_is_biconnected():
  50. G = nx.empty_graph(5)
  51. assert not nx.is_biconnected(G)
  52. G.add_edge(0, 1)
  53. assert not nx.is_biconnected(G)
  54. def test_biconnected_components_cycle():
  55. G = nx.cycle_graph(3)
  56. nx.add_cycle(G, [1, 3, 4])
  57. answer = [{0, 1, 2}, {1, 3, 4}]
  58. assert_components_equal(list(nx.biconnected_components(G)), answer)
  59. def test_biconnected_components1():
  60. # graph example from
  61. # https://web.archive.org/web/20121229123447/http://www.ibluemojo.com/school/articul_algorithm.html
  62. edges = [
  63. (0, 1),
  64. (0, 5),
  65. (0, 6),
  66. (0, 14),
  67. (1, 5),
  68. (1, 6),
  69. (1, 14),
  70. (2, 4),
  71. (2, 10),
  72. (3, 4),
  73. (3, 15),
  74. (4, 6),
  75. (4, 7),
  76. (4, 10),
  77. (5, 14),
  78. (6, 14),
  79. (7, 9),
  80. (8, 9),
  81. (8, 12),
  82. (8, 13),
  83. (10, 15),
  84. (11, 12),
  85. (11, 13),
  86. (12, 13),
  87. ]
  88. G = nx.Graph(edges)
  89. pts = set(nx.articulation_points(G))
  90. assert pts == {4, 6, 7, 8, 9}
  91. comps = list(nx.biconnected_component_edges(G))
  92. answer = [
  93. [(3, 4), (15, 3), (10, 15), (10, 4), (2, 10), (4, 2)],
  94. [(13, 12), (13, 8), (11, 13), (12, 11), (8, 12)],
  95. [(9, 8)],
  96. [(7, 9)],
  97. [(4, 7)],
  98. [(6, 4)],
  99. [(14, 0), (5, 1), (5, 0), (14, 5), (14, 1), (6, 14), (6, 0), (1, 6), (0, 1)],
  100. ]
  101. assert_components_edges_equal(comps, answer)
  102. def test_biconnected_components2():
  103. G = nx.Graph()
  104. nx.add_cycle(G, "ABC")
  105. nx.add_cycle(G, "CDE")
  106. nx.add_cycle(G, "FIJHG")
  107. nx.add_cycle(G, "GIJ")
  108. G.add_edge("E", "G")
  109. comps = list(nx.biconnected_component_edges(G))
  110. answer = [
  111. [
  112. tuple("GF"),
  113. tuple("FI"),
  114. tuple("IG"),
  115. tuple("IJ"),
  116. tuple("JG"),
  117. tuple("JH"),
  118. tuple("HG"),
  119. ],
  120. [tuple("EG")],
  121. [tuple("CD"), tuple("DE"), tuple("CE")],
  122. [tuple("AB"), tuple("BC"), tuple("AC")],
  123. ]
  124. assert_components_edges_equal(comps, answer)
  125. def test_biconnected_davis():
  126. D = nx.davis_southern_women_graph()
  127. bcc = list(nx.biconnected_components(D))[0]
  128. assert set(D) == bcc # All nodes in a giant bicomponent
  129. # So no articulation points
  130. assert len(list(nx.articulation_points(D))) == 0
  131. def test_biconnected_karate():
  132. K = nx.karate_club_graph()
  133. answer = [
  134. {
  135. 0,
  136. 1,
  137. 2,
  138. 3,
  139. 7,
  140. 8,
  141. 9,
  142. 12,
  143. 13,
  144. 14,
  145. 15,
  146. 17,
  147. 18,
  148. 19,
  149. 20,
  150. 21,
  151. 22,
  152. 23,
  153. 24,
  154. 25,
  155. 26,
  156. 27,
  157. 28,
  158. 29,
  159. 30,
  160. 31,
  161. 32,
  162. 33,
  163. },
  164. {0, 4, 5, 6, 10, 16},
  165. {0, 11},
  166. ]
  167. bcc = list(nx.biconnected_components(K))
  168. assert_components_equal(bcc, answer)
  169. assert set(nx.articulation_points(K)) == {0}
  170. def test_biconnected_eppstein():
  171. # tests from http://www.ics.uci.edu/~eppstein/PADS/Biconnectivity.py
  172. G1 = nx.Graph(
  173. {
  174. 0: [1, 2, 5],
  175. 1: [0, 5],
  176. 2: [0, 3, 4],
  177. 3: [2, 4, 5, 6],
  178. 4: [2, 3, 5, 6],
  179. 5: [0, 1, 3, 4],
  180. 6: [3, 4],
  181. }
  182. )
  183. G2 = nx.Graph(
  184. {
  185. 0: [2, 5],
  186. 1: [3, 8],
  187. 2: [0, 3, 5],
  188. 3: [1, 2, 6, 8],
  189. 4: [7],
  190. 5: [0, 2],
  191. 6: [3, 8],
  192. 7: [4],
  193. 8: [1, 3, 6],
  194. }
  195. )
  196. assert nx.is_biconnected(G1)
  197. assert not nx.is_biconnected(G2)
  198. answer_G2 = [{1, 3, 6, 8}, {0, 2, 5}, {2, 3}, {4, 7}]
  199. bcc = list(nx.biconnected_components(G2))
  200. assert_components_equal(bcc, answer_G2)
  201. def test_null_graph():
  202. G = nx.Graph()
  203. assert not nx.is_biconnected(G)
  204. assert list(nx.biconnected_components(G)) == []
  205. assert list(nx.biconnected_component_edges(G)) == []
  206. assert list(nx.articulation_points(G)) == []
  207. def test_connected_raise():
  208. DG = nx.DiGraph()
  209. with pytest.raises(NetworkXNotImplemented):
  210. next(nx.biconnected_components(DG))
  211. with pytest.raises(NetworkXNotImplemented):
  212. next(nx.biconnected_component_edges(DG))
  213. with pytest.raises(NetworkXNotImplemented):
  214. next(nx.articulation_points(DG))
  215. pytest.raises(NetworkXNotImplemented, nx.is_biconnected, DG)