test_sparse6.py 5.3 KB

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