test_degree_seq.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. import pytest
  2. import networkx as nx
  3. class TestConfigurationModel:
  4. """Unit tests for the :func:`~networkx.configuration_model`
  5. function.
  6. """
  7. def test_empty_degree_sequence(self):
  8. """Tests that an empty degree sequence yields the null graph."""
  9. G = nx.configuration_model([])
  10. assert len(G) == 0
  11. def test_degree_zero(self):
  12. """Tests that a degree sequence of all zeros yields the empty
  13. graph.
  14. """
  15. G = nx.configuration_model([0, 0, 0])
  16. assert len(G) == 3
  17. assert G.number_of_edges() == 0
  18. def test_degree_sequence(self):
  19. """Tests that the degree sequence of the generated graph matches
  20. the input degree sequence.
  21. """
  22. deg_seq = [5, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1]
  23. G = nx.configuration_model(deg_seq, seed=12345678)
  24. assert sorted((d for n, d in G.degree()), reverse=True) == [
  25. 5,
  26. 3,
  27. 3,
  28. 3,
  29. 3,
  30. 2,
  31. 2,
  32. 2,
  33. 1,
  34. 1,
  35. 1,
  36. ]
  37. assert sorted((d for n, d in G.degree(range(len(deg_seq)))), reverse=True) == [
  38. 5,
  39. 3,
  40. 3,
  41. 3,
  42. 3,
  43. 2,
  44. 2,
  45. 2,
  46. 1,
  47. 1,
  48. 1,
  49. ]
  50. def test_random_seed(self):
  51. """Tests that each call with the same random seed generates the
  52. same graph.
  53. """
  54. deg_seq = [3] * 12
  55. G1 = nx.configuration_model(deg_seq, seed=1000)
  56. G2 = nx.configuration_model(deg_seq, seed=1000)
  57. assert nx.is_isomorphic(G1, G2)
  58. G1 = nx.configuration_model(deg_seq, seed=10)
  59. G2 = nx.configuration_model(deg_seq, seed=10)
  60. assert nx.is_isomorphic(G1, G2)
  61. def test_directed_disallowed(self):
  62. """Tests that attempting to create a configuration model graph
  63. using a directed graph yields an exception.
  64. """
  65. with pytest.raises(nx.NetworkXNotImplemented):
  66. nx.configuration_model([], create_using=nx.DiGraph())
  67. def test_odd_degree_sum(self):
  68. """Tests that a degree sequence whose sum is odd yields an
  69. exception.
  70. """
  71. with pytest.raises(nx.NetworkXError):
  72. nx.configuration_model([1, 2])
  73. def test_directed_configuration_raise_unequal():
  74. with pytest.raises(nx.NetworkXError):
  75. zin = [5, 3, 3, 3, 3, 2, 2, 2, 1, 1]
  76. zout = [5, 3, 3, 3, 3, 2, 2, 2, 1, 2]
  77. nx.directed_configuration_model(zin, zout)
  78. def test_directed_configuration_model():
  79. G = nx.directed_configuration_model([], [], seed=0)
  80. assert len(G) == 0
  81. def test_simple_directed_configuration_model():
  82. G = nx.directed_configuration_model([1, 1], [1, 1], seed=0)
  83. assert len(G) == 2
  84. def test_expected_degree_graph_empty():
  85. # empty graph has empty degree sequence
  86. deg_seq = []
  87. G = nx.expected_degree_graph(deg_seq)
  88. assert dict(G.degree()) == {}
  89. def test_expected_degree_graph():
  90. # test that fixed seed delivers the same graph
  91. deg_seq = [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
  92. G1 = nx.expected_degree_graph(deg_seq, seed=1000)
  93. assert len(G1) == 12
  94. G2 = nx.expected_degree_graph(deg_seq, seed=1000)
  95. assert nx.is_isomorphic(G1, G2)
  96. G1 = nx.expected_degree_graph(deg_seq, seed=10)
  97. G2 = nx.expected_degree_graph(deg_seq, seed=10)
  98. assert nx.is_isomorphic(G1, G2)
  99. def test_expected_degree_graph_selfloops():
  100. deg_seq = [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
  101. G1 = nx.expected_degree_graph(deg_seq, seed=1000, selfloops=False)
  102. G2 = nx.expected_degree_graph(deg_seq, seed=1000, selfloops=False)
  103. assert nx.is_isomorphic(G1, G2)
  104. assert len(G1) == 12
  105. def test_expected_degree_graph_skew():
  106. deg_seq = [10, 2, 2, 2, 2]
  107. G1 = nx.expected_degree_graph(deg_seq, seed=1000)
  108. G2 = nx.expected_degree_graph(deg_seq, seed=1000)
  109. assert nx.is_isomorphic(G1, G2)
  110. assert len(G1) == 5
  111. def test_havel_hakimi_construction():
  112. G = nx.havel_hakimi_graph([])
  113. assert len(G) == 0
  114. z = [1000, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1]
  115. pytest.raises(nx.NetworkXError, nx.havel_hakimi_graph, z)
  116. z = ["A", 3, 3, 3, 3, 2, 2, 2, 1, 1, 1]
  117. pytest.raises(nx.NetworkXError, nx.havel_hakimi_graph, z)
  118. z = [5, 4, 3, 3, 3, 2, 2, 2]
  119. G = nx.havel_hakimi_graph(z)
  120. G = nx.configuration_model(z)
  121. z = [6, 5, 4, 4, 2, 1, 1, 1]
  122. pytest.raises(nx.NetworkXError, nx.havel_hakimi_graph, z)
  123. z = [10, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2]
  124. G = nx.havel_hakimi_graph(z)
  125. pytest.raises(nx.NetworkXError, nx.havel_hakimi_graph, z, create_using=nx.DiGraph())
  126. def test_directed_havel_hakimi():
  127. # Test range of valid directed degree sequences
  128. n, r = 100, 10
  129. p = 1.0 / r
  130. for i in range(r):
  131. G1 = nx.erdos_renyi_graph(n, p * (i + 1), None, True)
  132. din1 = [d for n, d in G1.in_degree()]
  133. dout1 = [d for n, d in G1.out_degree()]
  134. G2 = nx.directed_havel_hakimi_graph(din1, dout1)
  135. din2 = [d for n, d in G2.in_degree()]
  136. dout2 = [d for n, d in G2.out_degree()]
  137. assert sorted(din1) == sorted(din2)
  138. assert sorted(dout1) == sorted(dout2)
  139. # Test non-graphical sequence
  140. dout = [1000, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1]
  141. din = [103, 102, 102, 102, 102, 102, 102, 102, 102, 102]
  142. pytest.raises(nx.exception.NetworkXError, nx.directed_havel_hakimi_graph, din, dout)
  143. # Test valid sequences
  144. dout = [1, 1, 1, 1, 1, 2, 2, 2, 3, 4]
  145. din = [2, 2, 2, 2, 2, 2, 2, 2, 0, 2]
  146. G2 = nx.directed_havel_hakimi_graph(din, dout)
  147. dout2 = (d for n, d in G2.out_degree())
  148. din2 = (d for n, d in G2.in_degree())
  149. assert sorted(dout) == sorted(dout2)
  150. assert sorted(din) == sorted(din2)
  151. # Test unequal sums
  152. din = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
  153. pytest.raises(nx.exception.NetworkXError, nx.directed_havel_hakimi_graph, din, dout)
  154. # Test for negative values
  155. din = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -2]
  156. pytest.raises(nx.exception.NetworkXError, nx.directed_havel_hakimi_graph, din, dout)
  157. def test_degree_sequence_tree():
  158. z = [1, 1, 1, 1, 1, 2, 2, 2, 3, 4]
  159. G = nx.degree_sequence_tree(z)
  160. assert len(G) == len(z)
  161. assert len(list(G.edges())) == sum(z) / 2
  162. pytest.raises(
  163. nx.NetworkXError, nx.degree_sequence_tree, z, create_using=nx.DiGraph()
  164. )
  165. z = [1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4]
  166. pytest.raises(nx.NetworkXError, nx.degree_sequence_tree, z)
  167. def test_random_degree_sequence_graph():
  168. d = [1, 2, 2, 3]
  169. G = nx.random_degree_sequence_graph(d, seed=42)
  170. assert d == sorted(d for n, d in G.degree())
  171. def test_random_degree_sequence_graph_raise():
  172. z = [1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4]
  173. pytest.raises(nx.NetworkXUnfeasible, nx.random_degree_sequence_graph, z)
  174. def test_random_degree_sequence_large():
  175. G1 = nx.fast_gnp_random_graph(100, 0.1, seed=42)
  176. d1 = (d for n, d in G1.degree())
  177. G2 = nx.random_degree_sequence_graph(d1, seed=42)
  178. d2 = (d for n, d in G2.degree())
  179. assert sorted(d1) == sorted(d2)