test_sparse6.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. from io import BytesIO
  2. import pytest
  3. import networkx as nx
  4. from networkx.utils import edges_equal, nodes_equal
  5. class TestSparseGraph6:
  6. def test_from_sparse6_bytes(self):
  7. data = b":Q___eDcdFcDeFcE`GaJ`IaHbKNbLM"
  8. G = nx.from_sparse6_bytes(data)
  9. assert nodes_equal(
  10. sorted(G.nodes()),
  11. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
  12. )
  13. assert edges_equal(
  14. G.edges(),
  15. [
  16. (0, 1),
  17. (0, 2),
  18. (0, 3),
  19. (1, 12),
  20. (1, 14),
  21. (2, 13),
  22. (2, 15),
  23. (3, 16),
  24. (3, 17),
  25. (4, 7),
  26. (4, 9),
  27. (4, 11),
  28. (5, 6),
  29. (5, 8),
  30. (5, 9),
  31. (6, 10),
  32. (6, 11),
  33. (7, 8),
  34. (7, 10),
  35. (8, 12),
  36. (9, 15),
  37. (10, 14),
  38. (11, 13),
  39. (12, 16),
  40. (13, 17),
  41. (14, 17),
  42. (15, 16),
  43. ],
  44. )
  45. def test_from_bytes_multigraph_graph(self):
  46. graph_data = b":An"
  47. G = nx.from_sparse6_bytes(graph_data)
  48. assert isinstance(G, nx.Graph)
  49. multigraph_data = b":Ab"
  50. M = nx.from_sparse6_bytes(multigraph_data)
  51. assert isinstance(M, nx.MultiGraph)
  52. def test_read_sparse6(self):
  53. data = b":Q___eDcdFcDeFcE`GaJ`IaHbKNbLM"
  54. G = nx.from_sparse6_bytes(data)
  55. fh = BytesIO(data)
  56. Gin = nx.read_sparse6(fh)
  57. assert nodes_equal(G.nodes(), Gin.nodes())
  58. assert edges_equal(G.edges(), Gin.edges())
  59. def test_read_many_graph6(self):
  60. # Read many graphs into list
  61. data = b":Q___eDcdFcDeFcE`GaJ`IaHbKNbLM\n:Q___dCfDEdcEgcbEGbFIaJ`JaHN`IM"
  62. fh = BytesIO(data)
  63. glist = nx.read_sparse6(fh)
  64. assert len(glist) == 2
  65. for G in glist:
  66. assert nodes_equal(
  67. G.nodes(),
  68. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
  69. )
  70. class TestWriteSparse6:
  71. """Unit tests for writing graphs in the sparse6 format.
  72. Most of the test cases were checked against the sparse6 encoder in Sage.
  73. """
  74. def test_null_graph(self):
  75. G = nx.null_graph()
  76. result = BytesIO()
  77. nx.write_sparse6(G, result)
  78. assert result.getvalue() == b">>sparse6<<:?\n"
  79. def test_trivial_graph(self):
  80. G = nx.trivial_graph()
  81. result = BytesIO()
  82. nx.write_sparse6(G, result)
  83. assert result.getvalue() == b">>sparse6<<:@\n"
  84. def test_empty_graph(self):
  85. G = nx.empty_graph(5)
  86. result = BytesIO()
  87. nx.write_sparse6(G, result)
  88. assert result.getvalue() == b">>sparse6<<:D\n"
  89. def test_large_empty_graph(self):
  90. G = nx.empty_graph(68)
  91. result = BytesIO()
  92. nx.write_sparse6(G, result)
  93. assert result.getvalue() == b">>sparse6<<:~?@C\n"
  94. def test_very_large_empty_graph(self):
  95. G = nx.empty_graph(258049)
  96. result = BytesIO()
  97. nx.write_sparse6(G, result)
  98. assert result.getvalue() == b">>sparse6<<:~~???~?@\n"
  99. def test_complete_graph(self):
  100. G = nx.complete_graph(4)
  101. result = BytesIO()
  102. nx.write_sparse6(G, result)
  103. assert result.getvalue() == b">>sparse6<<:CcKI\n"
  104. def test_no_header(self):
  105. G = nx.complete_graph(4)
  106. result = BytesIO()
  107. nx.write_sparse6(G, result, header=False)
  108. assert result.getvalue() == b":CcKI\n"
  109. def test_padding(self):
  110. codes = (b":Cdv", b":DaYn", b":EaYnN", b":FaYnL", b":GaYnLz")
  111. for n, code in enumerate(codes, start=4):
  112. G = nx.path_graph(n)
  113. result = BytesIO()
  114. nx.write_sparse6(G, result, header=False)
  115. assert result.getvalue() == code + b"\n"
  116. def test_complete_bipartite(self):
  117. G = nx.complete_bipartite_graph(6, 9)
  118. result = BytesIO()
  119. nx.write_sparse6(G, result)
  120. # Compared with sage
  121. expected = b">>sparse6<<:Nk" + b"?G`cJ" * 9 + b"\n"
  122. assert result.getvalue() == expected
  123. def test_read_write_inverse(self):
  124. for i in list(range(13)) + [31, 47, 62, 63, 64, 72]:
  125. m = min(2 * i, i * i // 2)
  126. g = nx.random_graphs.gnm_random_graph(i, m, seed=i)
  127. gstr = BytesIO()
  128. nx.write_sparse6(g, gstr, header=False)
  129. # Strip the trailing newline.
  130. gstr = gstr.getvalue().rstrip()
  131. g2 = nx.from_sparse6_bytes(gstr)
  132. assert g2.order() == g.order()
  133. assert edges_equal(g2.edges(), g.edges())
  134. def test_no_directed_graphs(self):
  135. with pytest.raises(nx.NetworkXNotImplemented):
  136. nx.write_sparse6(nx.DiGraph(), BytesIO())
  137. def test_write_path(self, tmp_path):
  138. # Get a valid temporary file name
  139. fullfilename = str(tmp_path / "test.s6")
  140. # file should be closed now, so write_sparse6 can open it
  141. nx.write_sparse6(nx.null_graph(), fullfilename)
  142. with open(fullfilename, mode="rb") as fh:
  143. assert fh.read() == b">>sparse6<<:?\n"