test_bfs.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. from functools import partial
  2. import pytest
  3. import networkx as nx
  4. class TestBFS:
  5. @classmethod
  6. def setup_class(cls):
  7. # simple graph
  8. G = nx.Graph()
  9. G.add_edges_from([(0, 1), (1, 2), (1, 3), (2, 4), (3, 4)])
  10. cls.G = G
  11. def test_successor(self):
  12. assert dict(nx.bfs_successors(self.G, source=0)) == {0: [1], 1: [2, 3], 2: [4]}
  13. def test_predecessor(self):
  14. assert dict(nx.bfs_predecessors(self.G, source=0)) == {1: 0, 2: 1, 3: 1, 4: 2}
  15. def test_bfs_tree(self):
  16. T = nx.bfs_tree(self.G, source=0)
  17. assert sorted(T.nodes()) == sorted(self.G.nodes())
  18. assert sorted(T.edges()) == [(0, 1), (1, 2), (1, 3), (2, 4)]
  19. def test_bfs_edges(self):
  20. edges = nx.bfs_edges(self.G, source=0)
  21. assert list(edges) == [(0, 1), (1, 2), (1, 3), (2, 4)]
  22. def test_bfs_edges_reverse(self):
  23. D = nx.DiGraph()
  24. D.add_edges_from([(0, 1), (1, 2), (1, 3), (2, 4), (3, 4)])
  25. edges = nx.bfs_edges(D, source=4, reverse=True)
  26. assert list(edges) == [(4, 2), (4, 3), (2, 1), (1, 0)]
  27. def test_bfs_edges_sorting(self):
  28. D = nx.DiGraph()
  29. D.add_edges_from([(0, 1), (0, 2), (1, 4), (1, 3), (2, 5)])
  30. sort_desc = partial(sorted, reverse=True)
  31. edges_asc = nx.bfs_edges(D, source=0, sort_neighbors=sorted)
  32. edges_desc = nx.bfs_edges(D, source=0, sort_neighbors=sort_desc)
  33. assert list(edges_asc) == [(0, 1), (0, 2), (1, 3), (1, 4), (2, 5)]
  34. assert list(edges_desc) == [(0, 2), (0, 1), (2, 5), (1, 4), (1, 3)]
  35. def test_bfs_tree_isolates(self):
  36. G = nx.Graph()
  37. G.add_node(1)
  38. G.add_node(2)
  39. T = nx.bfs_tree(G, source=1)
  40. assert sorted(T.nodes()) == [1]
  41. assert sorted(T.edges()) == []
  42. def test_bfs_layers(self):
  43. expected = {
  44. 0: [0],
  45. 1: [1],
  46. 2: [2, 3],
  47. 3: [4],
  48. }
  49. assert dict(enumerate(nx.bfs_layers(self.G, sources=[0]))) == expected
  50. assert dict(enumerate(nx.bfs_layers(self.G, sources=0))) == expected
  51. def test_bfs_layers_missing_source(self):
  52. with pytest.raises(nx.NetworkXError):
  53. next(nx.bfs_layers(self.G, sources="abc"))
  54. with pytest.raises(nx.NetworkXError):
  55. next(nx.bfs_layers(self.G, sources=["abc"]))
  56. def test_descendants_at_distance(self):
  57. for distance, descendants in enumerate([{0}, {1}, {2, 3}, {4}]):
  58. assert nx.descendants_at_distance(self.G, 0, distance) == descendants
  59. def test_descendants_at_distance_missing_source(self):
  60. with pytest.raises(nx.NetworkXError):
  61. nx.descendants_at_distance(self.G, "abc", 0)
  62. class TestBreadthLimitedSearch:
  63. @classmethod
  64. def setup_class(cls):
  65. # a tree
  66. G = nx.Graph()
  67. nx.add_path(G, [0, 1, 2, 3, 4, 5, 6])
  68. nx.add_path(G, [2, 7, 8, 9, 10])
  69. cls.G = G
  70. # a disconnected graph
  71. D = nx.Graph()
  72. D.add_edges_from([(0, 1), (2, 3)])
  73. nx.add_path(D, [2, 7, 8, 9, 10])
  74. cls.D = D
  75. def test_limited_bfs_successor(self):
  76. assert dict(nx.bfs_successors(self.G, source=1, depth_limit=3)) == {
  77. 1: [0, 2],
  78. 2: [3, 7],
  79. 3: [4],
  80. 7: [8],
  81. }
  82. result = {
  83. n: sorted(s) for n, s in nx.bfs_successors(self.D, source=7, depth_limit=2)
  84. }
  85. assert result == {8: [9], 2: [3], 7: [2, 8]}
  86. def test_limited_bfs_predecessor(self):
  87. assert dict(nx.bfs_predecessors(self.G, source=1, depth_limit=3)) == {
  88. 0: 1,
  89. 2: 1,
  90. 3: 2,
  91. 4: 3,
  92. 7: 2,
  93. 8: 7,
  94. }
  95. assert dict(nx.bfs_predecessors(self.D, source=7, depth_limit=2)) == {
  96. 2: 7,
  97. 3: 2,
  98. 8: 7,
  99. 9: 8,
  100. }
  101. def test_limited_bfs_tree(self):
  102. T = nx.bfs_tree(self.G, source=3, depth_limit=1)
  103. assert sorted(T.edges()) == [(3, 2), (3, 4)]
  104. def test_limited_bfs_edges(self):
  105. edges = nx.bfs_edges(self.G, source=9, depth_limit=4)
  106. assert list(edges) == [(9, 8), (9, 10), (8, 7), (7, 2), (2, 1), (2, 3)]
  107. def test_limited_bfs_layers(self):
  108. assert dict(enumerate(nx.bfs_layers(self.G, sources=[0]))) == {
  109. 0: [0],
  110. 1: [1],
  111. 2: [2],
  112. 3: [3, 7],
  113. 4: [4, 8],
  114. 5: [5, 9],
  115. 6: [6, 10],
  116. }
  117. assert dict(enumerate(nx.bfs_layers(self.D, sources=2))) == {
  118. 0: [2],
  119. 1: [3, 7],
  120. 2: [8],
  121. 3: [9],
  122. 4: [10],
  123. }
  124. def test_limited_descendants_at_distance(self):
  125. for distance, descendants in enumerate(
  126. [{0}, {1}, {2}, {3, 7}, {4, 8}, {5, 9}, {6, 10}]
  127. ):
  128. assert nx.descendants_at_distance(self.G, 0, distance) == descendants
  129. for distance, descendants in enumerate([{2}, {3, 7}, {8}, {9}, {10}]):
  130. assert nx.descendants_at_distance(self.D, 2, distance) == descendants