test_cuts.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. """Unit tests for the :mod:`networkx.algorithms.cuts` module."""
  2. import networkx as nx
  3. class TestCutSize:
  4. """Unit tests for the :func:`~networkx.cut_size` function."""
  5. def test_symmetric(self):
  6. """Tests that the cut size is symmetric."""
  7. G = nx.barbell_graph(3, 0)
  8. S = {0, 1, 4}
  9. T = {2, 3, 5}
  10. assert nx.cut_size(G, S, T) == 4
  11. assert nx.cut_size(G, T, S) == 4
  12. def test_single_edge(self):
  13. """Tests for a cut of a single edge."""
  14. G = nx.barbell_graph(3, 0)
  15. S = {0, 1, 2}
  16. T = {3, 4, 5}
  17. assert nx.cut_size(G, S, T) == 1
  18. assert nx.cut_size(G, T, S) == 1
  19. def test_directed(self):
  20. """Tests that each directed edge is counted once in the cut."""
  21. G = nx.barbell_graph(3, 0).to_directed()
  22. S = {0, 1, 2}
  23. T = {3, 4, 5}
  24. assert nx.cut_size(G, S, T) == 2
  25. assert nx.cut_size(G, T, S) == 2
  26. def test_directed_symmetric(self):
  27. """Tests that a cut in a directed graph is symmetric."""
  28. G = nx.barbell_graph(3, 0).to_directed()
  29. S = {0, 1, 4}
  30. T = {2, 3, 5}
  31. assert nx.cut_size(G, S, T) == 8
  32. assert nx.cut_size(G, T, S) == 8
  33. def test_multigraph(self):
  34. """Tests that parallel edges are each counted for a cut."""
  35. G = nx.MultiGraph(["ab", "ab"])
  36. assert nx.cut_size(G, {"a"}, {"b"}) == 2
  37. class TestVolume:
  38. """Unit tests for the :func:`~networkx.volume` function."""
  39. def test_graph(self):
  40. G = nx.cycle_graph(4)
  41. assert nx.volume(G, {0, 1}) == 4
  42. def test_digraph(self):
  43. G = nx.DiGraph([(0, 1), (1, 2), (2, 3), (3, 0)])
  44. assert nx.volume(G, {0, 1}) == 2
  45. def test_multigraph(self):
  46. edges = list(nx.cycle_graph(4).edges())
  47. G = nx.MultiGraph(edges * 2)
  48. assert nx.volume(G, {0, 1}) == 8
  49. def test_multidigraph(self):
  50. edges = [(0, 1), (1, 2), (2, 3), (3, 0)]
  51. G = nx.MultiDiGraph(edges * 2)
  52. assert nx.volume(G, {0, 1}) == 4
  53. def test_barbell(self):
  54. G = nx.barbell_graph(3, 0)
  55. assert nx.volume(G, {0, 1, 2}) == 7
  56. assert nx.volume(G, {3, 4, 5}) == 7
  57. class TestNormalizedCutSize:
  58. """Unit tests for the :func:`~networkx.normalized_cut_size` function."""
  59. def test_graph(self):
  60. G = nx.path_graph(4)
  61. S = {1, 2}
  62. T = set(G) - S
  63. size = nx.normalized_cut_size(G, S, T)
  64. # The cut looks like this: o-{-o--o-}-o
  65. expected = 2 * ((1 / 4) + (1 / 2))
  66. assert expected == size
  67. # Test with no input T
  68. assert expected == nx.normalized_cut_size(G, S)
  69. def test_directed(self):
  70. G = nx.DiGraph([(0, 1), (1, 2), (2, 3)])
  71. S = {1, 2}
  72. T = set(G) - S
  73. size = nx.normalized_cut_size(G, S, T)
  74. # The cut looks like this: o-{->o-->o-}->o
  75. expected = 2 * ((1 / 2) + (1 / 1))
  76. assert expected == size
  77. # Test with no input T
  78. assert expected == nx.normalized_cut_size(G, S)
  79. class TestConductance:
  80. """Unit tests for the :func:`~networkx.conductance` function."""
  81. def test_graph(self):
  82. G = nx.barbell_graph(5, 0)
  83. # Consider the singleton sets containing the "bridge" nodes.
  84. # There is only one cut edge, and each set has volume five.
  85. S = {4}
  86. T = {5}
  87. conductance = nx.conductance(G, S, T)
  88. expected = 1 / 5
  89. assert expected == conductance
  90. # Test with no input T
  91. G2 = nx.barbell_graph(3, 0)
  92. # There is only one cut edge, and each set has volume seven.
  93. S2 = {0, 1, 2}
  94. assert nx.conductance(G2, S2) == 1 / 7
  95. class TestEdgeExpansion:
  96. """Unit tests for the :func:`~networkx.edge_expansion` function."""
  97. def test_graph(self):
  98. G = nx.barbell_graph(5, 0)
  99. S = set(range(5))
  100. T = set(G) - S
  101. expansion = nx.edge_expansion(G, S, T)
  102. expected = 1 / 5
  103. assert expected == expansion
  104. # Test with no input T
  105. assert expected == nx.edge_expansion(G, S)
  106. class TestNodeExpansion:
  107. """Unit tests for the :func:`~networkx.node_expansion` function."""
  108. def test_graph(self):
  109. G = nx.path_graph(8)
  110. S = {3, 4, 5}
  111. expansion = nx.node_expansion(G, S)
  112. # The neighborhood of S has cardinality five, and S has
  113. # cardinality three.
  114. expected = 5 / 3
  115. assert expected == expansion
  116. class TestBoundaryExpansion:
  117. """Unit tests for the :func:`~networkx.boundary_expansion` function."""
  118. def test_graph(self):
  119. G = nx.complete_graph(10)
  120. S = set(range(4))
  121. expansion = nx.boundary_expansion(G, S)
  122. # The node boundary of S has cardinality six, and S has
  123. # cardinality three.
  124. expected = 6 / 4
  125. assert expected == expansion
  126. class TestMixingExpansion:
  127. """Unit tests for the :func:`~networkx.mixing_expansion` function."""
  128. def test_graph(self):
  129. G = nx.barbell_graph(5, 0)
  130. S = set(range(5))
  131. T = set(G) - S
  132. expansion = nx.mixing_expansion(G, S, T)
  133. # There is one cut edge, and the total number of edges in the
  134. # graph is twice the total number of edges in a clique of size
  135. # five, plus one more for the bridge.
  136. expected = 1 / (2 * (5 * 4 + 1))
  137. assert expected == expansion