historical_tests.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. """Original NetworkX graph tests"""
  2. import pytest
  3. import networkx as nx
  4. from networkx import convert_node_labels_to_integers as cnlti
  5. from networkx.utils import edges_equal, nodes_equal
  6. class HistoricalTests:
  7. @classmethod
  8. def setup_class(cls):
  9. cls.null = nx.null_graph()
  10. cls.P1 = cnlti(nx.path_graph(1), first_label=1)
  11. cls.P3 = cnlti(nx.path_graph(3), first_label=1)
  12. cls.P10 = cnlti(nx.path_graph(10), first_label=1)
  13. cls.K1 = cnlti(nx.complete_graph(1), first_label=1)
  14. cls.K3 = cnlti(nx.complete_graph(3), first_label=1)
  15. cls.K4 = cnlti(nx.complete_graph(4), first_label=1)
  16. cls.K5 = cnlti(nx.complete_graph(5), first_label=1)
  17. cls.K10 = cnlti(nx.complete_graph(10), first_label=1)
  18. cls.G = nx.Graph
  19. def test_name(self):
  20. G = self.G(name="test")
  21. assert G.name == "test"
  22. H = self.G()
  23. assert H.name == ""
  24. # Nodes
  25. def test_add_remove_node(self):
  26. G = self.G()
  27. G.add_node("A")
  28. assert G.has_node("A")
  29. G.remove_node("A")
  30. assert not G.has_node("A")
  31. def test_nonhashable_node(self):
  32. # Test if a non-hashable object is in the Graph. A python dict will
  33. # raise a TypeError, but for a Graph class a simple False should be
  34. # returned (see Graph __contains__). If it cannot be a node then it is
  35. # not a node.
  36. G = self.G()
  37. assert not G.has_node(["A"])
  38. assert not G.has_node({"A": 1})
  39. def test_add_nodes_from(self):
  40. G = self.G()
  41. G.add_nodes_from(list("ABCDEFGHIJKL"))
  42. assert G.has_node("L")
  43. G.remove_nodes_from(["H", "I", "J", "K", "L"])
  44. G.add_nodes_from([1, 2, 3, 4])
  45. assert sorted(G.nodes(), key=str) == [
  46. 1,
  47. 2,
  48. 3,
  49. 4,
  50. "A",
  51. "B",
  52. "C",
  53. "D",
  54. "E",
  55. "F",
  56. "G",
  57. ]
  58. # test __iter__
  59. assert sorted(G, key=str) == [1, 2, 3, 4, "A", "B", "C", "D", "E", "F", "G"]
  60. def test_contains(self):
  61. G = self.G()
  62. G.add_node("A")
  63. assert "A" in G
  64. assert [] not in G # never raise a Key or TypeError in this test
  65. assert {1: 1} not in G
  66. def test_add_remove(self):
  67. # Test add_node and remove_node acting for various nbunch
  68. G = self.G()
  69. G.add_node("m")
  70. assert G.has_node("m")
  71. G.add_node("m") # no complaints
  72. pytest.raises(nx.NetworkXError, G.remove_node, "j")
  73. G.remove_node("m")
  74. assert list(G) == []
  75. def test_nbunch_is_list(self):
  76. G = self.G()
  77. G.add_nodes_from(list("ABCD"))
  78. G.add_nodes_from(self.P3) # add nbunch of nodes (nbunch=Graph)
  79. assert sorted(G.nodes(), key=str) == [1, 2, 3, "A", "B", "C", "D"]
  80. G.remove_nodes_from(self.P3) # remove nbunch of nodes (nbunch=Graph)
  81. assert sorted(G.nodes(), key=str) == ["A", "B", "C", "D"]
  82. def test_nbunch_is_set(self):
  83. G = self.G()
  84. nbunch = set("ABCDEFGHIJKL")
  85. G.add_nodes_from(nbunch)
  86. assert G.has_node("L")
  87. def test_nbunch_dict(self):
  88. # nbunch is a dict with nodes as keys
  89. G = self.G()
  90. nbunch = set("ABCDEFGHIJKL")
  91. G.add_nodes_from(nbunch)
  92. nbunch = {"I": "foo", "J": 2, "K": True, "L": "spam"}
  93. G.remove_nodes_from(nbunch)
  94. assert sorted(G.nodes(), key=str), ["A", "B", "C", "D", "E", "F", "G", "H"]
  95. def test_nbunch_iterator(self):
  96. G = self.G()
  97. G.add_nodes_from(["A", "B", "C", "D", "E", "F", "G", "H"])
  98. n_iter = self.P3.nodes()
  99. G.add_nodes_from(n_iter)
  100. assert sorted(G.nodes(), key=str) == [
  101. 1,
  102. 2,
  103. 3,
  104. "A",
  105. "B",
  106. "C",
  107. "D",
  108. "E",
  109. "F",
  110. "G",
  111. "H",
  112. ]
  113. n_iter = self.P3.nodes() # rebuild same iterator
  114. G.remove_nodes_from(n_iter) # remove nbunch of nodes (nbunch=iterator)
  115. assert sorted(G.nodes(), key=str) == ["A", "B", "C", "D", "E", "F", "G", "H"]
  116. def test_nbunch_graph(self):
  117. G = self.G()
  118. G.add_nodes_from(["A", "B", "C", "D", "E", "F", "G", "H"])
  119. nbunch = self.K3
  120. G.add_nodes_from(nbunch)
  121. assert sorted(G.nodes(), key=str), [
  122. 1,
  123. 2,
  124. 3,
  125. "A",
  126. "B",
  127. "C",
  128. "D",
  129. "E",
  130. "F",
  131. "G",
  132. "H",
  133. ]
  134. # Edges
  135. def test_add_edge(self):
  136. G = self.G()
  137. pytest.raises(TypeError, G.add_edge, "A")
  138. G.add_edge("A", "B") # testing add_edge()
  139. G.add_edge("A", "B") # should fail silently
  140. assert G.has_edge("A", "B")
  141. assert not G.has_edge("A", "C")
  142. assert G.has_edge(*("A", "B"))
  143. if G.is_directed():
  144. assert not G.has_edge("B", "A")
  145. else:
  146. # G is undirected, so B->A is an edge
  147. assert G.has_edge("B", "A")
  148. G.add_edge("A", "C") # test directedness
  149. G.add_edge("C", "A")
  150. G.remove_edge("C", "A")
  151. if G.is_directed():
  152. assert G.has_edge("A", "C")
  153. else:
  154. assert not G.has_edge("A", "C")
  155. assert not G.has_edge("C", "A")
  156. def test_self_loop(self):
  157. G = self.G()
  158. G.add_edge("A", "A") # test self loops
  159. assert G.has_edge("A", "A")
  160. G.remove_edge("A", "A")
  161. G.add_edge("X", "X")
  162. assert G.has_node("X")
  163. G.remove_node("X")
  164. G.add_edge("A", "Z") # should add the node silently
  165. assert G.has_node("Z")
  166. def test_add_edges_from(self):
  167. G = self.G()
  168. G.add_edges_from([("B", "C")]) # test add_edges_from()
  169. assert G.has_edge("B", "C")
  170. if G.is_directed():
  171. assert not G.has_edge("C", "B")
  172. else:
  173. assert G.has_edge("C", "B") # undirected
  174. G.add_edges_from([("D", "F"), ("B", "D")])
  175. assert G.has_edge("D", "F")
  176. assert G.has_edge("B", "D")
  177. if G.is_directed():
  178. assert not G.has_edge("D", "B")
  179. else:
  180. assert G.has_edge("D", "B") # undirected
  181. def test_add_edges_from2(self):
  182. G = self.G()
  183. # after failing silently, should add 2nd edge
  184. G.add_edges_from([tuple("IJ"), list("KK"), tuple("JK")])
  185. assert G.has_edge(*("I", "J"))
  186. assert G.has_edge(*("K", "K"))
  187. assert G.has_edge(*("J", "K"))
  188. if G.is_directed():
  189. assert not G.has_edge(*("K", "J"))
  190. else:
  191. assert G.has_edge(*("K", "J"))
  192. def test_add_edges_from3(self):
  193. G = self.G()
  194. G.add_edges_from(zip(list("ACD"), list("CDE")))
  195. assert G.has_edge("D", "E")
  196. assert not G.has_edge("E", "C")
  197. def test_remove_edge(self):
  198. G = self.G()
  199. G.add_nodes_from([1, 2, 3, "A", "B", "C", "D", "E", "F", "G", "H"])
  200. G.add_edges_from(zip(list("MNOP"), list("NOPM")))
  201. assert G.has_edge("O", "P")
  202. assert G.has_edge("P", "M")
  203. G.remove_node("P") # tests remove_node()'s handling of edges.
  204. assert not G.has_edge("P", "M")
  205. pytest.raises(TypeError, G.remove_edge, "M")
  206. G.add_edge("N", "M")
  207. assert G.has_edge("M", "N")
  208. G.remove_edge("M", "N")
  209. assert not G.has_edge("M", "N")
  210. # self loop fails silently
  211. G.remove_edges_from([list("HI"), list("DF"), tuple("KK"), tuple("JK")])
  212. assert not G.has_edge("H", "I")
  213. assert not G.has_edge("J", "K")
  214. G.remove_edges_from([list("IJ"), list("KK"), list("JK")])
  215. assert not G.has_edge("I", "J")
  216. G.remove_nodes_from(set("ZEFHIMNO"))
  217. G.add_edge("J", "K")
  218. def test_edges_nbunch(self):
  219. # Test G.edges(nbunch) with various forms of nbunch
  220. G = self.G()
  221. G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")])
  222. # node not in nbunch should be quietly ignored
  223. pytest.raises(nx.NetworkXError, G.edges, 6)
  224. assert list(G.edges("Z")) == [] # iterable non-node
  225. # nbunch can be an empty list
  226. assert list(G.edges([])) == []
  227. if G.is_directed():
  228. elist = [("A", "B"), ("A", "C"), ("B", "D")]
  229. else:
  230. elist = [("A", "B"), ("A", "C"), ("B", "C"), ("B", "D")]
  231. # nbunch can be a list
  232. assert edges_equal(list(G.edges(["A", "B"])), elist)
  233. # nbunch can be a set
  234. assert edges_equal(G.edges({"A", "B"}), elist)
  235. # nbunch can be a graph
  236. G1 = self.G()
  237. G1.add_nodes_from("AB")
  238. assert edges_equal(G.edges(G1), elist)
  239. # nbunch can be a dict with nodes as keys
  240. ndict = {"A": "thing1", "B": "thing2"}
  241. assert edges_equal(G.edges(ndict), elist)
  242. # nbunch can be a single node
  243. assert edges_equal(list(G.edges("A")), [("A", "B"), ("A", "C")])
  244. assert nodes_equal(sorted(G), ["A", "B", "C", "D"])
  245. # nbunch can be nothing (whole graph)
  246. assert edges_equal(
  247. list(G.edges()),
  248. [("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")],
  249. )
  250. def test_degree(self):
  251. G = self.G()
  252. G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")])
  253. assert G.degree("A") == 2
  254. # degree of single node in iterable container must return dict
  255. assert list(G.degree(["A"])) == [("A", 2)]
  256. assert sorted(d for n, d in G.degree(["A", "B"])) == [2, 3]
  257. assert sorted(d for n, d in G.degree()) == [2, 2, 3, 3]
  258. def test_degree2(self):
  259. H = self.G()
  260. H.add_edges_from([(1, 24), (1, 2)])
  261. assert sorted(d for n, d in H.degree([1, 24])) == [1, 2]
  262. def test_degree_graph(self):
  263. P3 = nx.path_graph(3)
  264. P5 = nx.path_graph(5)
  265. # silently ignore nodes not in P3
  266. assert dict(d for n, d in P3.degree(["A", "B"])) == {}
  267. # nbunch can be a graph
  268. assert sorted(d for n, d in P5.degree(P3)) == [1, 2, 2]
  269. # nbunch can be a graph that's way too big
  270. assert sorted(d for n, d in P3.degree(P5)) == [1, 1, 2]
  271. assert list(P5.degree([])) == []
  272. assert dict(P5.degree([])) == {}
  273. def test_null(self):
  274. null = nx.null_graph()
  275. assert list(null.degree()) == []
  276. assert dict(null.degree()) == {}
  277. def test_order_size(self):
  278. G = self.G()
  279. G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")])
  280. assert G.order() == 4
  281. assert G.size() == 5
  282. assert G.number_of_edges() == 5
  283. assert G.number_of_edges("A", "B") == 1
  284. assert G.number_of_edges("A", "D") == 0
  285. def test_copy(self):
  286. G = self.G()
  287. H = G.copy() # copy
  288. assert H.adj == G.adj
  289. assert H.name == G.name
  290. assert H is not G
  291. def test_subgraph(self):
  292. G = self.G()
  293. G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")])
  294. SG = G.subgraph(["A", "B", "D"])
  295. assert nodes_equal(list(SG), ["A", "B", "D"])
  296. assert edges_equal(list(SG.edges()), [("A", "B"), ("B", "D")])
  297. def test_to_directed(self):
  298. G = self.G()
  299. if not G.is_directed():
  300. G.add_edges_from(
  301. [("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")]
  302. )
  303. DG = G.to_directed()
  304. assert DG is not G # directed copy or copy
  305. assert DG.is_directed()
  306. assert DG.name == G.name
  307. assert DG.adj == G.adj
  308. assert sorted(DG.out_edges(list("AB"))) == [
  309. ("A", "B"),
  310. ("A", "C"),
  311. ("B", "A"),
  312. ("B", "C"),
  313. ("B", "D"),
  314. ]
  315. DG.remove_edge("A", "B")
  316. assert DG.has_edge("B", "A") # this removes B-A but not A-B
  317. assert not DG.has_edge("A", "B")
  318. def test_to_undirected(self):
  319. G = self.G()
  320. if G.is_directed():
  321. G.add_edges_from(
  322. [("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")]
  323. )
  324. UG = G.to_undirected() # to_undirected
  325. assert UG is not G
  326. assert not UG.is_directed()
  327. assert G.is_directed()
  328. assert UG.name == G.name
  329. assert UG.adj != G.adj
  330. assert sorted(UG.edges(list("AB"))) == [
  331. ("A", "B"),
  332. ("A", "C"),
  333. ("B", "C"),
  334. ("B", "D"),
  335. ]
  336. assert sorted(UG.edges(["A", "B"])) == [
  337. ("A", "B"),
  338. ("A", "C"),
  339. ("B", "C"),
  340. ("B", "D"),
  341. ]
  342. UG.remove_edge("A", "B")
  343. assert not UG.has_edge("B", "A")
  344. assert not UG.has_edge("A", "B")
  345. def test_neighbors(self):
  346. G = self.G()
  347. G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")])
  348. G.add_nodes_from("GJK")
  349. assert sorted(G["A"]) == ["B", "C"]
  350. assert sorted(G.neighbors("A")) == ["B", "C"]
  351. assert sorted(G.neighbors("A")) == ["B", "C"]
  352. assert sorted(G.neighbors("G")) == []
  353. pytest.raises(nx.NetworkXError, G.neighbors, "j")
  354. def test_iterators(self):
  355. G = self.G()
  356. G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")])
  357. G.add_nodes_from("GJK")
  358. assert sorted(G.nodes()) == ["A", "B", "C", "D", "G", "J", "K"]
  359. assert edges_equal(
  360. G.edges(), [("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")]
  361. )
  362. assert sorted(v for k, v in G.degree()) == [0, 0, 0, 2, 2, 3, 3]
  363. assert sorted(G.degree(), key=str) == [
  364. ("A", 2),
  365. ("B", 3),
  366. ("C", 3),
  367. ("D", 2),
  368. ("G", 0),
  369. ("J", 0),
  370. ("K", 0),
  371. ]
  372. assert sorted(G.neighbors("A")) == ["B", "C"]
  373. pytest.raises(nx.NetworkXError, G.neighbors, "X")
  374. G.clear()
  375. assert nx.number_of_nodes(G) == 0
  376. assert nx.number_of_edges(G) == 0
  377. def test_null_subgraph(self):
  378. # Subgraph of a null graph is a null graph
  379. nullgraph = nx.null_graph()
  380. G = nx.null_graph()
  381. H = G.subgraph([])
  382. assert nx.is_isomorphic(H, nullgraph)
  383. def test_empty_subgraph(self):
  384. # Subgraph of an empty graph is an empty graph. test 1
  385. nullgraph = nx.null_graph()
  386. E5 = nx.empty_graph(5)
  387. E10 = nx.empty_graph(10)
  388. H = E10.subgraph([])
  389. assert nx.is_isomorphic(H, nullgraph)
  390. H = E10.subgraph([1, 2, 3, 4, 5])
  391. assert nx.is_isomorphic(H, E5)
  392. def test_complete_subgraph(self):
  393. # Subgraph of a complete graph is a complete graph
  394. K1 = nx.complete_graph(1)
  395. K3 = nx.complete_graph(3)
  396. K5 = nx.complete_graph(5)
  397. H = K5.subgraph([1, 2, 3])
  398. assert nx.is_isomorphic(H, K3)
  399. def test_subgraph_nbunch(self):
  400. nullgraph = nx.null_graph()
  401. K1 = nx.complete_graph(1)
  402. K3 = nx.complete_graph(3)
  403. K5 = nx.complete_graph(5)
  404. # Test G.subgraph(nbunch), where nbunch is a single node
  405. H = K5.subgraph(1)
  406. assert nx.is_isomorphic(H, K1)
  407. # Test G.subgraph(nbunch), where nbunch is a set
  408. H = K5.subgraph({1})
  409. assert nx.is_isomorphic(H, K1)
  410. # Test G.subgraph(nbunch), where nbunch is an iterator
  411. H = K5.subgraph(iter(K3))
  412. assert nx.is_isomorphic(H, K3)
  413. # Test G.subgraph(nbunch), where nbunch is another graph
  414. H = K5.subgraph(K3)
  415. assert nx.is_isomorphic(H, K3)
  416. H = K5.subgraph([9])
  417. assert nx.is_isomorphic(H, nullgraph)
  418. def test_node_tuple_issue(self):
  419. H = self.G()
  420. # Test error handling of tuple as a node
  421. pytest.raises(nx.NetworkXError, H.remove_node, (1, 2))
  422. H.remove_nodes_from([(1, 2)]) # no error
  423. pytest.raises(nx.NetworkXError, H.neighbors, (1, 2))