test_misc.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. import random
  2. from copy import copy
  3. import pytest
  4. import networkx as nx
  5. from networkx.utils import (
  6. PythonRandomInterface,
  7. arbitrary_element,
  8. create_py_random_state,
  9. create_random_state,
  10. dict_to_numpy_array,
  11. discrete_sequence,
  12. flatten,
  13. groups,
  14. make_list_of_ints,
  15. pairwise,
  16. powerlaw_sequence,
  17. )
  18. from networkx.utils.misc import _dict_to_numpy_array1, _dict_to_numpy_array2
  19. nested_depth = (
  20. 1,
  21. 2,
  22. (3, 4, ((5, 6, (7,), (8, (9, 10), 11), (12, 13, (14, 15)), 16), 17), 18, 19),
  23. 20,
  24. )
  25. nested_set = {
  26. (1, 2, 3, 4),
  27. (5, 6, 7, 8, 9),
  28. (10, 11, (12, 13, 14), (15, 16, 17, 18)),
  29. 19,
  30. 20,
  31. }
  32. nested_mixed = [
  33. 1,
  34. (2, 3, {4, (5, 6), 7}, [8, 9]),
  35. {10: "foo", 11: "bar", (12, 13): "baz"},
  36. {(14, 15): "qwe", 16: "asd"},
  37. (17, (18, "19"), 20),
  38. ]
  39. @pytest.mark.parametrize("result", [None, [], ["existing"], ["existing1", "existing2"]])
  40. @pytest.mark.parametrize("nested", [nested_depth, nested_mixed, nested_set])
  41. def test_flatten(nested, result):
  42. if result is None:
  43. val = flatten(nested, result)
  44. assert len(val) == 20
  45. else:
  46. _result = copy(result) # because pytest passes parameters as is
  47. nexisting = len(_result)
  48. val = flatten(nested, _result)
  49. assert len(val) == len(_result) == 20 + nexisting
  50. assert issubclass(type(val), tuple)
  51. def test_make_list_of_ints():
  52. mylist = [1, 2, 3.0, 42, -2]
  53. assert make_list_of_ints(mylist) is mylist
  54. assert make_list_of_ints(mylist) == mylist
  55. assert type(make_list_of_ints(mylist)[2]) is int
  56. pytest.raises(nx.NetworkXError, make_list_of_ints, [1, 2, 3, "kermit"])
  57. pytest.raises(nx.NetworkXError, make_list_of_ints, [1, 2, 3.1])
  58. def test_random_number_distribution():
  59. # smoke test only
  60. z = powerlaw_sequence(20, exponent=2.5)
  61. z = discrete_sequence(20, distribution=[0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3])
  62. class TestNumpyArray:
  63. @classmethod
  64. def setup_class(cls):
  65. global np
  66. np = pytest.importorskip("numpy")
  67. def test_numpy_to_list_of_ints(self):
  68. a = np.array([1, 2, 3], dtype=np.int64)
  69. b = np.array([1.0, 2, 3])
  70. c = np.array([1.1, 2, 3])
  71. assert type(make_list_of_ints(a)) == list
  72. assert make_list_of_ints(b) == list(b)
  73. B = make_list_of_ints(b)
  74. assert type(B[0]) == int
  75. pytest.raises(nx.NetworkXError, make_list_of_ints, c)
  76. def test__dict_to_numpy_array1(self):
  77. d = {"a": 1, "b": 2}
  78. a = _dict_to_numpy_array1(d, mapping={"a": 0, "b": 1})
  79. np.testing.assert_allclose(a, np.array([1, 2]))
  80. a = _dict_to_numpy_array1(d, mapping={"b": 0, "a": 1})
  81. np.testing.assert_allclose(a, np.array([2, 1]))
  82. a = _dict_to_numpy_array1(d)
  83. np.testing.assert_allclose(a.sum(), 3)
  84. def test__dict_to_numpy_array2(self):
  85. d = {"a": {"a": 1, "b": 2}, "b": {"a": 10, "b": 20}}
  86. mapping = {"a": 1, "b": 0}
  87. a = _dict_to_numpy_array2(d, mapping=mapping)
  88. np.testing.assert_allclose(a, np.array([[20, 10], [2, 1]]))
  89. a = _dict_to_numpy_array2(d)
  90. np.testing.assert_allclose(a.sum(), 33)
  91. def test_dict_to_numpy_array_a(self):
  92. d = {"a": {"a": 1, "b": 2}, "b": {"a": 10, "b": 20}}
  93. mapping = {"a": 0, "b": 1}
  94. a = dict_to_numpy_array(d, mapping=mapping)
  95. np.testing.assert_allclose(a, np.array([[1, 2], [10, 20]]))
  96. mapping = {"a": 1, "b": 0}
  97. a = dict_to_numpy_array(d, mapping=mapping)
  98. np.testing.assert_allclose(a, np.array([[20, 10], [2, 1]]))
  99. a = _dict_to_numpy_array2(d)
  100. np.testing.assert_allclose(a.sum(), 33)
  101. def test_dict_to_numpy_array_b(self):
  102. d = {"a": 1, "b": 2}
  103. mapping = {"a": 0, "b": 1}
  104. a = dict_to_numpy_array(d, mapping=mapping)
  105. np.testing.assert_allclose(a, np.array([1, 2]))
  106. a = _dict_to_numpy_array1(d)
  107. np.testing.assert_allclose(a.sum(), 3)
  108. def test_pairwise():
  109. nodes = range(4)
  110. node_pairs = [(0, 1), (1, 2), (2, 3)]
  111. node_pairs_cycle = node_pairs + [(3, 0)]
  112. assert list(pairwise(nodes)) == node_pairs
  113. assert list(pairwise(iter(nodes))) == node_pairs
  114. assert list(pairwise(nodes, cyclic=True)) == node_pairs_cycle
  115. empty_iter = iter(())
  116. assert list(pairwise(empty_iter)) == []
  117. empty_iter = iter(())
  118. assert list(pairwise(empty_iter, cyclic=True)) == []
  119. def test_groups():
  120. many_to_one = dict(zip("abcde", [0, 0, 1, 1, 2]))
  121. actual = groups(many_to_one)
  122. expected = {0: {"a", "b"}, 1: {"c", "d"}, 2: {"e"}}
  123. assert actual == expected
  124. assert {} == groups({})
  125. def test_create_random_state():
  126. np = pytest.importorskip("numpy")
  127. rs = np.random.RandomState
  128. assert isinstance(create_random_state(1), rs)
  129. assert isinstance(create_random_state(None), rs)
  130. assert isinstance(create_random_state(np.random), rs)
  131. assert isinstance(create_random_state(rs(1)), rs)
  132. # Support for numpy.random.Generator
  133. rng = np.random.default_rng()
  134. assert isinstance(create_random_state(rng), np.random.Generator)
  135. pytest.raises(ValueError, create_random_state, "a")
  136. assert np.all(rs(1).rand(10) == create_random_state(1).rand(10))
  137. def test_create_py_random_state():
  138. pyrs = random.Random
  139. assert isinstance(create_py_random_state(1), pyrs)
  140. assert isinstance(create_py_random_state(None), pyrs)
  141. assert isinstance(create_py_random_state(pyrs(1)), pyrs)
  142. pytest.raises(ValueError, create_py_random_state, "a")
  143. np = pytest.importorskip("numpy")
  144. rs = np.random.RandomState
  145. rng = np.random.default_rng(1000)
  146. rng_explicit = np.random.Generator(np.random.SFC64())
  147. nprs = PythonRandomInterface
  148. assert isinstance(create_py_random_state(np.random), nprs)
  149. assert isinstance(create_py_random_state(rs(1)), nprs)
  150. assert isinstance(create_py_random_state(rng), nprs)
  151. assert isinstance(create_py_random_state(rng_explicit), nprs)
  152. # test default rng input
  153. assert isinstance(PythonRandomInterface(), nprs)
  154. def test_PythonRandomInterface_RandomState():
  155. np = pytest.importorskip("numpy")
  156. rs = np.random.RandomState
  157. rng = PythonRandomInterface(rs(42))
  158. rs42 = rs(42)
  159. # make sure these functions are same as expected outcome
  160. assert rng.randrange(3, 5) == rs42.randint(3, 5)
  161. assert rng.choice([1, 2, 3]) == rs42.choice([1, 2, 3])
  162. assert rng.gauss(0, 1) == rs42.normal(0, 1)
  163. assert rng.expovariate(1.5) == rs42.exponential(1 / 1.5)
  164. assert np.all(rng.shuffle([1, 2, 3]) == rs42.shuffle([1, 2, 3]))
  165. assert np.all(
  166. rng.sample([1, 2, 3], 2) == rs42.choice([1, 2, 3], (2,), replace=False)
  167. )
  168. assert np.all(
  169. [rng.randint(3, 5) for _ in range(100)]
  170. == [rs42.randint(3, 6) for _ in range(100)]
  171. )
  172. assert rng.random() == rs42.random_sample()
  173. def test_PythonRandomInterface_Generator():
  174. np = pytest.importorskip("numpy")
  175. rng = np.random.default_rng(42)
  176. pri = PythonRandomInterface(np.random.default_rng(42))
  177. # make sure these functions are same as expected outcome
  178. assert pri.randrange(3, 5) == rng.integers(3, 5)
  179. assert pri.choice([1, 2, 3]) == rng.choice([1, 2, 3])
  180. assert pri.gauss(0, 1) == rng.normal(0, 1)
  181. assert pri.expovariate(1.5) == rng.exponential(1 / 1.5)
  182. assert np.all(pri.shuffle([1, 2, 3]) == rng.shuffle([1, 2, 3]))
  183. assert np.all(
  184. pri.sample([1, 2, 3], 2) == rng.choice([1, 2, 3], (2,), replace=False)
  185. )
  186. assert np.all(
  187. [pri.randint(3, 5) for _ in range(100)]
  188. == [rng.integers(3, 6) for _ in range(100)]
  189. )
  190. assert pri.random() == rng.random()
  191. @pytest.mark.parametrize(
  192. ("iterable_type", "expected"), ((list, 1), (tuple, 1), (str, "["), (set, 1))
  193. )
  194. def test_arbitrary_element(iterable_type, expected):
  195. iterable = iterable_type([1, 2, 3])
  196. assert arbitrary_element(iterable) == expected
  197. @pytest.mark.parametrize(
  198. "iterator", ((i for i in range(3)), iter([1, 2, 3])) # generator
  199. )
  200. def test_arbitrary_element_raises(iterator):
  201. """Value error is raised when input is an iterator."""
  202. with pytest.raises(ValueError, match="from an iterator"):
  203. arbitrary_element(iterator)