aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/networkx/classes/tests/test_digraph.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/networkx/classes/tests/test_digraph.py')
-rw-r--r--.venv/lib/python3.12/site-packages/networkx/classes/tests/test_digraph.py331
1 files changed, 331 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/networkx/classes/tests/test_digraph.py b/.venv/lib/python3.12/site-packages/networkx/classes/tests/test_digraph.py
new file mode 100644
index 00000000..b9972f9a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/networkx/classes/tests/test_digraph.py
@@ -0,0 +1,331 @@
+import pytest
+
+import networkx as nx
+from networkx.utils import nodes_equal
+
+from .test_graph import BaseAttrGraphTester, BaseGraphTester
+from .test_graph import TestEdgeSubgraph as _TestGraphEdgeSubgraph
+from .test_graph import TestGraph as _TestGraph
+
+
+class BaseDiGraphTester(BaseGraphTester):
+ def test_has_successor(self):
+ G = self.K3
+ assert G.has_successor(0, 1)
+ assert not G.has_successor(0, -1)
+
+ def test_successors(self):
+ G = self.K3
+ assert sorted(G.successors(0)) == [1, 2]
+ with pytest.raises(nx.NetworkXError):
+ G.successors(-1)
+
+ def test_has_predecessor(self):
+ G = self.K3
+ assert G.has_predecessor(0, 1)
+ assert not G.has_predecessor(0, -1)
+
+ def test_predecessors(self):
+ G = self.K3
+ assert sorted(G.predecessors(0)) == [1, 2]
+ with pytest.raises(nx.NetworkXError):
+ G.predecessors(-1)
+
+ def test_edges(self):
+ G = self.K3
+ assert sorted(G.edges()) == [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]
+ assert sorted(G.edges(0)) == [(0, 1), (0, 2)]
+ assert sorted(G.edges([0, 1])) == [(0, 1), (0, 2), (1, 0), (1, 2)]
+ with pytest.raises(nx.NetworkXError):
+ G.edges(-1)
+
+ def test_out_edges(self):
+ G = self.K3
+ assert sorted(G.out_edges()) == [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]
+ assert sorted(G.out_edges(0)) == [(0, 1), (0, 2)]
+ with pytest.raises(nx.NetworkXError):
+ G.out_edges(-1)
+
+ def test_out_edges_dir(self):
+ G = self.P3
+ assert sorted(G.out_edges()) == [(0, 1), (1, 2)]
+ assert sorted(G.out_edges(0)) == [(0, 1)]
+ assert sorted(G.out_edges(2)) == []
+
+ def test_out_edges_data(self):
+ G = nx.DiGraph([(0, 1, {"data": 0}), (1, 0, {})])
+ assert sorted(G.out_edges(data=True)) == [(0, 1, {"data": 0}), (1, 0, {})]
+ assert sorted(G.out_edges(0, data=True)) == [(0, 1, {"data": 0})]
+ assert sorted(G.out_edges(data="data")) == [(0, 1, 0), (1, 0, None)]
+ assert sorted(G.out_edges(0, data="data")) == [(0, 1, 0)]
+
+ def test_in_edges_dir(self):
+ G = self.P3
+ assert sorted(G.in_edges()) == [(0, 1), (1, 2)]
+ assert sorted(G.in_edges(0)) == []
+ assert sorted(G.in_edges(2)) == [(1, 2)]
+
+ def test_in_edges_data(self):
+ G = nx.DiGraph([(0, 1, {"data": 0}), (1, 0, {})])
+ assert sorted(G.in_edges(data=True)) == [(0, 1, {"data": 0}), (1, 0, {})]
+ assert sorted(G.in_edges(1, data=True)) == [(0, 1, {"data": 0})]
+ assert sorted(G.in_edges(data="data")) == [(0, 1, 0), (1, 0, None)]
+ assert sorted(G.in_edges(1, data="data")) == [(0, 1, 0)]
+
+ def test_degree(self):
+ G = self.K3
+ assert sorted(G.degree()) == [(0, 4), (1, 4), (2, 4)]
+ assert dict(G.degree()) == {0: 4, 1: 4, 2: 4}
+ assert G.degree(0) == 4
+ assert list(G.degree(iter([0]))) == [(0, 4)] # run through iterator
+
+ def test_in_degree(self):
+ G = self.K3
+ assert sorted(G.in_degree()) == [(0, 2), (1, 2), (2, 2)]
+ assert dict(G.in_degree()) == {0: 2, 1: 2, 2: 2}
+ assert G.in_degree(0) == 2
+ assert list(G.in_degree(iter([0]))) == [(0, 2)] # run through iterator
+
+ def test_out_degree(self):
+ G = self.K3
+ assert sorted(G.out_degree()) == [(0, 2), (1, 2), (2, 2)]
+ assert dict(G.out_degree()) == {0: 2, 1: 2, 2: 2}
+ assert G.out_degree(0) == 2
+ assert list(G.out_degree(iter([0]))) == [(0, 2)]
+
+ def test_size(self):
+ G = self.K3
+ assert G.size() == 6
+ assert G.number_of_edges() == 6
+
+ def test_to_undirected_reciprocal(self):
+ G = self.Graph()
+ G.add_edge(1, 2)
+ assert G.to_undirected().has_edge(1, 2)
+ assert not G.to_undirected(reciprocal=True).has_edge(1, 2)
+ G.add_edge(2, 1)
+ assert G.to_undirected(reciprocal=True).has_edge(1, 2)
+
+ def test_reverse_copy(self):
+ G = nx.DiGraph([(0, 1), (1, 2)])
+ R = G.reverse()
+ assert sorted(R.edges()) == [(1, 0), (2, 1)]
+ R.remove_edge(1, 0)
+ assert sorted(R.edges()) == [(2, 1)]
+ assert sorted(G.edges()) == [(0, 1), (1, 2)]
+
+ def test_reverse_nocopy(self):
+ G = nx.DiGraph([(0, 1), (1, 2)])
+ R = G.reverse(copy=False)
+ assert sorted(R.edges()) == [(1, 0), (2, 1)]
+ with pytest.raises(nx.NetworkXError):
+ R.remove_edge(1, 0)
+
+ def test_reverse_hashable(self):
+ class Foo:
+ pass
+
+ x = Foo()
+ y = Foo()
+ G = nx.DiGraph()
+ G.add_edge(x, y)
+ assert nodes_equal(G.nodes(), G.reverse().nodes())
+ assert [(y, x)] == list(G.reverse().edges())
+
+ def test_di_cache_reset(self):
+ G = self.K3.copy()
+ old_succ = G.succ
+ assert id(G.succ) == id(old_succ)
+ old_adj = G.adj
+ assert id(G.adj) == id(old_adj)
+
+ G._succ = {}
+ assert id(G.succ) != id(old_succ)
+ assert id(G.adj) != id(old_adj)
+
+ old_pred = G.pred
+ assert id(G.pred) == id(old_pred)
+ G._pred = {}
+ assert id(G.pred) != id(old_pred)
+
+ def test_di_attributes_cached(self):
+ G = self.K3.copy()
+ assert id(G.in_edges) == id(G.in_edges)
+ assert id(G.out_edges) == id(G.out_edges)
+ assert id(G.in_degree) == id(G.in_degree)
+ assert id(G.out_degree) == id(G.out_degree)
+ assert id(G.succ) == id(G.succ)
+ assert id(G.pred) == id(G.pred)
+
+
+class BaseAttrDiGraphTester(BaseDiGraphTester, BaseAttrGraphTester):
+ def test_edges_data(self):
+ G = self.K3
+ all_edges = [
+ (0, 1, {}),
+ (0, 2, {}),
+ (1, 0, {}),
+ (1, 2, {}),
+ (2, 0, {}),
+ (2, 1, {}),
+ ]
+ assert sorted(G.edges(data=True)) == all_edges
+ assert sorted(G.edges(0, data=True)) == all_edges[:2]
+ assert sorted(G.edges([0, 1], data=True)) == all_edges[:4]
+ with pytest.raises(nx.NetworkXError):
+ G.edges(-1, True)
+
+ def test_in_degree_weighted(self):
+ G = self.K3.copy()
+ G.add_edge(0, 1, weight=0.3, other=1.2)
+ assert sorted(G.in_degree(weight="weight")) == [(0, 2), (1, 1.3), (2, 2)]
+ assert dict(G.in_degree(weight="weight")) == {0: 2, 1: 1.3, 2: 2}
+ assert G.in_degree(1, weight="weight") == 1.3
+ assert sorted(G.in_degree(weight="other")) == [(0, 2), (1, 2.2), (2, 2)]
+ assert dict(G.in_degree(weight="other")) == {0: 2, 1: 2.2, 2: 2}
+ assert G.in_degree(1, weight="other") == 2.2
+ assert list(G.in_degree(iter([1]), weight="other")) == [(1, 2.2)]
+
+ def test_out_degree_weighted(self):
+ G = self.K3.copy()
+ G.add_edge(0, 1, weight=0.3, other=1.2)
+ assert sorted(G.out_degree(weight="weight")) == [(0, 1.3), (1, 2), (2, 2)]
+ assert dict(G.out_degree(weight="weight")) == {0: 1.3, 1: 2, 2: 2}
+ assert G.out_degree(0, weight="weight") == 1.3
+ assert sorted(G.out_degree(weight="other")) == [(0, 2.2), (1, 2), (2, 2)]
+ assert dict(G.out_degree(weight="other")) == {0: 2.2, 1: 2, 2: 2}
+ assert G.out_degree(0, weight="other") == 2.2
+ assert list(G.out_degree(iter([0]), weight="other")) == [(0, 2.2)]
+
+
+class TestDiGraph(BaseAttrDiGraphTester, _TestGraph):
+ """Tests specific to dict-of-dict-of-dict digraph data structure"""
+
+ def setup_method(self):
+ self.Graph = nx.DiGraph
+ # build dict-of-dict-of-dict K3
+ ed1, ed2, ed3, ed4, ed5, ed6 = ({}, {}, {}, {}, {}, {})
+ self.k3adj = {0: {1: ed1, 2: ed2}, 1: {0: ed3, 2: ed4}, 2: {0: ed5, 1: ed6}}
+ self.k3edges = [(0, 1), (0, 2), (1, 2)]
+ self.k3nodes = [0, 1, 2]
+ self.K3 = self.Graph()
+ self.K3._succ = self.k3adj # K3._adj is synced with K3._succ
+ self.K3._pred = {0: {1: ed3, 2: ed5}, 1: {0: ed1, 2: ed6}, 2: {0: ed2, 1: ed4}}
+ self.K3._node = {}
+ self.K3._node[0] = {}
+ self.K3._node[1] = {}
+ self.K3._node[2] = {}
+
+ ed1, ed2 = ({}, {})
+ self.P3 = self.Graph()
+ self.P3._succ = {0: {1: ed1}, 1: {2: ed2}, 2: {}}
+ self.P3._pred = {0: {}, 1: {0: ed1}, 2: {1: ed2}}
+ # P3._adj is synced with P3._succ
+ self.P3._node = {}
+ self.P3._node[0] = {}
+ self.P3._node[1] = {}
+ self.P3._node[2] = {}
+
+ def test_data_input(self):
+ G = self.Graph({1: [2], 2: [1]}, name="test")
+ assert G.name == "test"
+ assert sorted(G.adj.items()) == [(1, {2: {}}), (2, {1: {}})]
+ assert sorted(G.succ.items()) == [(1, {2: {}}), (2, {1: {}})]
+ assert sorted(G.pred.items()) == [(1, {2: {}}), (2, {1: {}})]
+
+ def test_add_edge(self):
+ G = self.Graph()
+ G.add_edge(0, 1)
+ assert G.adj == {0: {1: {}}, 1: {}}
+ assert G.succ == {0: {1: {}}, 1: {}}
+ assert G.pred == {0: {}, 1: {0: {}}}
+ G = self.Graph()
+ G.add_edge(*(0, 1))
+ assert G.adj == {0: {1: {}}, 1: {}}
+ assert G.succ == {0: {1: {}}, 1: {}}
+ assert G.pred == {0: {}, 1: {0: {}}}
+ with pytest.raises(ValueError, match="None cannot be a node"):
+ G.add_edge(None, 3)
+
+ def test_add_edges_from(self):
+ G = self.Graph()
+ G.add_edges_from([(0, 1), (0, 2, {"data": 3})], data=2)
+ assert G.adj == {0: {1: {"data": 2}, 2: {"data": 3}}, 1: {}, 2: {}}
+ assert G.succ == {0: {1: {"data": 2}, 2: {"data": 3}}, 1: {}, 2: {}}
+ assert G.pred == {0: {}, 1: {0: {"data": 2}}, 2: {0: {"data": 3}}}
+
+ with pytest.raises(nx.NetworkXError):
+ G.add_edges_from([(0,)]) # too few in tuple
+ with pytest.raises(nx.NetworkXError):
+ G.add_edges_from([(0, 1, 2, 3)]) # too many in tuple
+ with pytest.raises(TypeError):
+ G.add_edges_from([0]) # not a tuple
+ with pytest.raises(ValueError, match="None cannot be a node"):
+ G.add_edges_from([(None, 3), (3, 2)])
+
+ def test_remove_edge(self):
+ G = self.K3.copy()
+ G.remove_edge(0, 1)
+ assert G.succ == {0: {2: {}}, 1: {0: {}, 2: {}}, 2: {0: {}, 1: {}}}
+ assert G.pred == {0: {1: {}, 2: {}}, 1: {2: {}}, 2: {0: {}, 1: {}}}
+ with pytest.raises(nx.NetworkXError):
+ G.remove_edge(-1, 0)
+
+ def test_remove_edges_from(self):
+ G = self.K3.copy()
+ G.remove_edges_from([(0, 1)])
+ assert G.succ == {0: {2: {}}, 1: {0: {}, 2: {}}, 2: {0: {}, 1: {}}}
+ assert G.pred == {0: {1: {}, 2: {}}, 1: {2: {}}, 2: {0: {}, 1: {}}}
+ G.remove_edges_from([(0, 0)]) # silent fail
+
+ def test_clear(self):
+ G = self.K3
+ G.graph["name"] = "K3"
+ G.clear()
+ assert list(G.nodes) == []
+ assert G.succ == {}
+ assert G.pred == {}
+ assert G.graph == {}
+
+ def test_clear_edges(self):
+ G = self.K3
+ G.graph["name"] = "K3"
+ nodes = list(G.nodes)
+ G.clear_edges()
+ assert list(G.nodes) == nodes
+ expected = {0: {}, 1: {}, 2: {}}
+ assert G.succ == expected
+ assert G.pred == expected
+ assert list(G.edges) == []
+ assert G.graph["name"] == "K3"
+
+
+class TestEdgeSubgraph(_TestGraphEdgeSubgraph):
+ """Unit tests for the :meth:`DiGraph.edge_subgraph` method."""
+
+ def setup_method(self):
+ # Create a doubly-linked path graph on five nodes.
+ G = nx.DiGraph(nx.path_graph(5))
+ # Add some node, edge, and graph attributes.
+ for i in range(5):
+ G.nodes[i]["name"] = f"node{i}"
+ G.edges[0, 1]["name"] = "edge01"
+ G.edges[3, 4]["name"] = "edge34"
+ G.graph["name"] = "graph"
+ # Get the subgraph induced by the first and last edges.
+ self.G = G
+ self.H = G.edge_subgraph([(0, 1), (3, 4)])
+
+ def test_pred_succ(self):
+ """Test that nodes are added to predecessors and successors.
+
+ For more information, see GitHub issue #2370.
+
+ """
+ G = nx.DiGraph()
+ G.add_edge(0, 1)
+ H = G.edge_subgraph([(0, 1)])
+ assert list(H.predecessors(0)) == []
+ assert list(H.successors(0)) == [1]
+ assert list(H.predecessors(1)) == [0]
+ assert list(H.successors(1)) == []