test_edgedfs.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import pytest
  2. import networkx as nx
  3. from networkx.algorithms import edge_dfs
  4. from networkx.algorithms.traversal.edgedfs import FORWARD, REVERSE
  5. # These tests can fail with hash randomization. The easiest and clearest way
  6. # to write these unit tests is for the edges to be output in an expected total
  7. # order, but we cannot guarantee the order amongst outgoing edges from a node,
  8. # unless each class uses an ordered data structure for neighbors. This is
  9. # painful to do with the current API. The alternative is that the tests are
  10. # written (IMO confusingly) so that there is not a total order over the edges,
  11. # but only a partial order. Due to the small size of the graphs, hopefully
  12. # failures due to hash randomization will not occur. For an example of how
  13. # this can fail, see TestEdgeDFS.test_multigraph.
  14. class TestEdgeDFS:
  15. @classmethod
  16. def setup_class(cls):
  17. cls.nodes = [0, 1, 2, 3]
  18. cls.edges = [(0, 1), (1, 0), (1, 0), (2, 1), (3, 1)]
  19. def test_empty(self):
  20. G = nx.Graph()
  21. edges = list(edge_dfs(G))
  22. assert edges == []
  23. def test_graph(self):
  24. G = nx.Graph(self.edges)
  25. x = list(edge_dfs(G, self.nodes))
  26. x_ = [(0, 1), (1, 2), (1, 3)]
  27. assert x == x_
  28. def test_digraph(self):
  29. G = nx.DiGraph(self.edges)
  30. x = list(edge_dfs(G, self.nodes))
  31. x_ = [(0, 1), (1, 0), (2, 1), (3, 1)]
  32. assert x == x_
  33. def test_digraph_orientation_invalid(self):
  34. G = nx.DiGraph(self.edges)
  35. edge_iterator = edge_dfs(G, self.nodes, orientation="hello")
  36. pytest.raises(nx.NetworkXError, list, edge_iterator)
  37. def test_digraph_orientation_none(self):
  38. G = nx.DiGraph(self.edges)
  39. x = list(edge_dfs(G, self.nodes, orientation=None))
  40. x_ = [(0, 1), (1, 0), (2, 1), (3, 1)]
  41. assert x == x_
  42. def test_digraph_orientation_original(self):
  43. G = nx.DiGraph(self.edges)
  44. x = list(edge_dfs(G, self.nodes, orientation="original"))
  45. x_ = [(0, 1, FORWARD), (1, 0, FORWARD), (2, 1, FORWARD), (3, 1, FORWARD)]
  46. assert x == x_
  47. def test_digraph2(self):
  48. G = nx.DiGraph()
  49. nx.add_path(G, range(4))
  50. x = list(edge_dfs(G, [0]))
  51. x_ = [(0, 1), (1, 2), (2, 3)]
  52. assert x == x_
  53. def test_digraph_rev(self):
  54. G = nx.DiGraph(self.edges)
  55. x = list(edge_dfs(G, self.nodes, orientation="reverse"))
  56. x_ = [(1, 0, REVERSE), (0, 1, REVERSE), (2, 1, REVERSE), (3, 1, REVERSE)]
  57. assert x == x_
  58. def test_digraph_rev2(self):
  59. G = nx.DiGraph()
  60. nx.add_path(G, range(4))
  61. x = list(edge_dfs(G, [3], orientation="reverse"))
  62. x_ = [(2, 3, REVERSE), (1, 2, REVERSE), (0, 1, REVERSE)]
  63. assert x == x_
  64. def test_multigraph(self):
  65. G = nx.MultiGraph(self.edges)
  66. x = list(edge_dfs(G, self.nodes))
  67. x_ = [(0, 1, 0), (1, 0, 1), (0, 1, 2), (1, 2, 0), (1, 3, 0)]
  68. # This is an example of where hash randomization can break.
  69. # There are 3! * 2 alternative outputs, such as:
  70. # [(0, 1, 1), (1, 0, 0), (0, 1, 2), (1, 3, 0), (1, 2, 0)]
  71. # But note, the edges (1,2,0) and (1,3,0) always follow the (0,1,k)
  72. # edges. So the algorithm only guarantees a partial order. A total
  73. # order is guaranteed only if the graph data structures are ordered.
  74. assert x == x_
  75. def test_multidigraph(self):
  76. G = nx.MultiDiGraph(self.edges)
  77. x = list(edge_dfs(G, self.nodes))
  78. x_ = [(0, 1, 0), (1, 0, 0), (1, 0, 1), (2, 1, 0), (3, 1, 0)]
  79. assert x == x_
  80. def test_multidigraph_rev(self):
  81. G = nx.MultiDiGraph(self.edges)
  82. x = list(edge_dfs(G, self.nodes, orientation="reverse"))
  83. x_ = [
  84. (1, 0, 0, REVERSE),
  85. (0, 1, 0, REVERSE),
  86. (1, 0, 1, REVERSE),
  87. (2, 1, 0, REVERSE),
  88. (3, 1, 0, REVERSE),
  89. ]
  90. assert x == x_
  91. def test_digraph_ignore(self):
  92. G = nx.DiGraph(self.edges)
  93. x = list(edge_dfs(G, self.nodes, orientation="ignore"))
  94. x_ = [(0, 1, FORWARD), (1, 0, FORWARD), (2, 1, REVERSE), (3, 1, REVERSE)]
  95. assert x == x_
  96. def test_digraph_ignore2(self):
  97. G = nx.DiGraph()
  98. nx.add_path(G, range(4))
  99. x = list(edge_dfs(G, [0], orientation="ignore"))
  100. x_ = [(0, 1, FORWARD), (1, 2, FORWARD), (2, 3, FORWARD)]
  101. assert x == x_
  102. def test_multidigraph_ignore(self):
  103. G = nx.MultiDiGraph(self.edges)
  104. x = list(edge_dfs(G, self.nodes, orientation="ignore"))
  105. x_ = [
  106. (0, 1, 0, FORWARD),
  107. (1, 0, 0, FORWARD),
  108. (1, 0, 1, REVERSE),
  109. (2, 1, 0, REVERSE),
  110. (3, 1, 0, REVERSE),
  111. ]
  112. assert x == x_