update
This commit is contained in:
0
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__init__.py
vendored
Normal file
0
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__init__.py
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/__init__.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/__init__.cpython-312.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/historical_tests.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/historical_tests.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_coreviews.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_coreviews.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_digraph.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_digraph.cpython-312.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_filters.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_filters.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_function.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_function.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_graph.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_graph.cpython-312.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_graphviews.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_graphviews.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_multidigraph.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_multidigraph.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_multigraph.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_multigraph.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_reportviews.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_reportviews.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_special.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/__pycache__/test_special.cpython-312.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
194
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/dispatch_interface.py
vendored
Normal file
194
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/dispatch_interface.py
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
# This file contains utilities for testing the dispatching feature
|
||||
|
||||
# A full test of all dispatchable algorithms is performed by
|
||||
# modifying the pytest invocation and setting an environment variable
|
||||
# NETWORKX_TEST_BACKEND=nx-loopback pytest
|
||||
# This is comprehensive, but only tests the `test_override_dispatch`
|
||||
# function in networkx.classes.backends.
|
||||
|
||||
# To test the `_dispatchable` function directly, several tests scattered throughout
|
||||
# NetworkX have been augmented to test normal and dispatch mode.
|
||||
# Searching for `dispatch_interface` should locate the specific tests.
|
||||
|
||||
import networkx as nx
|
||||
from networkx import DiGraph, Graph, MultiDiGraph, MultiGraph, PlanarEmbedding
|
||||
from networkx.classes.reportviews import NodeView
|
||||
|
||||
|
||||
class LoopbackGraph(Graph):
|
||||
__networkx_backend__ = "nx-loopback"
|
||||
|
||||
|
||||
class LoopbackDiGraph(DiGraph):
|
||||
__networkx_backend__ = "nx-loopback"
|
||||
|
||||
|
||||
class LoopbackMultiGraph(MultiGraph):
|
||||
__networkx_backend__ = "nx-loopback"
|
||||
|
||||
|
||||
class LoopbackMultiDiGraph(MultiDiGraph):
|
||||
__networkx_backend__ = "nx-loopback"
|
||||
|
||||
|
||||
class LoopbackPlanarEmbedding(PlanarEmbedding):
|
||||
__networkx_backend__ = "nx-loopback"
|
||||
|
||||
|
||||
def convert(graph):
|
||||
if isinstance(graph, PlanarEmbedding):
|
||||
return LoopbackPlanarEmbedding(graph)
|
||||
if isinstance(graph, MultiDiGraph):
|
||||
return LoopbackMultiDiGraph(graph)
|
||||
if isinstance(graph, MultiGraph):
|
||||
return LoopbackMultiGraph(graph)
|
||||
if isinstance(graph, DiGraph):
|
||||
return LoopbackDiGraph(graph)
|
||||
if isinstance(graph, Graph):
|
||||
return LoopbackGraph(graph)
|
||||
raise TypeError(f"Unsupported type of graph: {type(graph)}")
|
||||
|
||||
|
||||
class LoopbackDispatcher:
|
||||
def __getattr__(self, item):
|
||||
try:
|
||||
return nx.utils.backends._registered_algorithms[item].orig_func
|
||||
except KeyError:
|
||||
raise AttributeError(item) from None
|
||||
|
||||
@staticmethod
|
||||
def convert_from_nx(
|
||||
graph,
|
||||
*,
|
||||
edge_attrs=None,
|
||||
node_attrs=None,
|
||||
preserve_edge_attrs=None,
|
||||
preserve_node_attrs=None,
|
||||
preserve_graph_attrs=None,
|
||||
name=None,
|
||||
graph_name=None,
|
||||
):
|
||||
if name in {
|
||||
# Raise if input graph changes
|
||||
"lexicographical_topological_sort",
|
||||
"topological_generations",
|
||||
"topological_sort",
|
||||
# Sensitive tests (iteration order matters)
|
||||
"dfs_labeled_edges",
|
||||
}:
|
||||
return graph
|
||||
if isinstance(graph, NodeView):
|
||||
# Convert to a Graph with only nodes (no edges)
|
||||
new_graph = Graph()
|
||||
new_graph.add_nodes_from(graph.items())
|
||||
graph = new_graph
|
||||
G = LoopbackGraph()
|
||||
elif not isinstance(graph, Graph):
|
||||
raise TypeError(
|
||||
f"Bad type for graph argument {graph_name} in {name}: {type(graph)}"
|
||||
)
|
||||
elif graph.__class__ in {Graph, LoopbackGraph}:
|
||||
G = LoopbackGraph()
|
||||
elif graph.__class__ in {DiGraph, LoopbackDiGraph}:
|
||||
G = LoopbackDiGraph()
|
||||
elif graph.__class__ in {MultiGraph, LoopbackMultiGraph}:
|
||||
G = LoopbackMultiGraph()
|
||||
elif graph.__class__ in {MultiDiGraph, LoopbackMultiDiGraph}:
|
||||
G = LoopbackMultiDiGraph()
|
||||
elif graph.__class__ in {PlanarEmbedding, LoopbackPlanarEmbedding}:
|
||||
G = LoopbackDiGraph() # or LoopbackPlanarEmbedding
|
||||
else:
|
||||
# It would be nice to be able to convert _AntiGraph to a regular Graph
|
||||
# nx.algorithms.approximation.kcomponents._AntiGraph
|
||||
# nx.algorithms.tree.branchings.MultiDiGraph_EdgeKey
|
||||
# nx.classes.tests.test_multidigraph.MultiDiGraphSubClass
|
||||
# nx.classes.tests.test_multigraph.MultiGraphSubClass
|
||||
G = graph.__class__()
|
||||
|
||||
if preserve_graph_attrs:
|
||||
G.graph.update(graph.graph)
|
||||
|
||||
if preserve_node_attrs:
|
||||
G.add_nodes_from(graph.nodes(data=True))
|
||||
elif node_attrs:
|
||||
G.add_nodes_from(
|
||||
(
|
||||
node,
|
||||
{
|
||||
k: datadict.get(k, default)
|
||||
for k, default in node_attrs.items()
|
||||
if default is not None or k in datadict
|
||||
},
|
||||
)
|
||||
for node, datadict in graph.nodes(data=True)
|
||||
)
|
||||
else:
|
||||
G.add_nodes_from(graph)
|
||||
|
||||
if graph.is_multigraph():
|
||||
if preserve_edge_attrs:
|
||||
G.add_edges_from(
|
||||
(u, v, key, datadict)
|
||||
for u, nbrs in graph._adj.items()
|
||||
for v, keydict in nbrs.items()
|
||||
for key, datadict in keydict.items()
|
||||
)
|
||||
elif edge_attrs:
|
||||
G.add_edges_from(
|
||||
(
|
||||
u,
|
||||
v,
|
||||
key,
|
||||
{
|
||||
k: datadict.get(k, default)
|
||||
for k, default in edge_attrs.items()
|
||||
if default is not None or k in datadict
|
||||
},
|
||||
)
|
||||
for u, nbrs in graph._adj.items()
|
||||
for v, keydict in nbrs.items()
|
||||
for key, datadict in keydict.items()
|
||||
)
|
||||
else:
|
||||
G.add_edges_from(
|
||||
(u, v, key, {})
|
||||
for u, nbrs in graph._adj.items()
|
||||
for v, keydict in nbrs.items()
|
||||
for key, datadict in keydict.items()
|
||||
)
|
||||
elif preserve_edge_attrs:
|
||||
G.add_edges_from(graph.edges(data=True))
|
||||
elif edge_attrs:
|
||||
G.add_edges_from(
|
||||
(
|
||||
u,
|
||||
v,
|
||||
{
|
||||
k: datadict.get(k, default)
|
||||
for k, default in edge_attrs.items()
|
||||
if default is not None or k in datadict
|
||||
},
|
||||
)
|
||||
for u, v, datadict in graph.edges(data=True)
|
||||
)
|
||||
else:
|
||||
G.add_edges_from(graph.edges)
|
||||
return G
|
||||
|
||||
@staticmethod
|
||||
def convert_to_nx(obj, *, name=None):
|
||||
return obj
|
||||
|
||||
@staticmethod
|
||||
def on_start_tests(items):
|
||||
# Verify that items can be xfailed
|
||||
for item in items:
|
||||
assert hasattr(item, "add_marker")
|
||||
|
||||
def can_run(self, name, args, kwargs):
|
||||
# It is unnecessary to define this function if algorithms are fully supported.
|
||||
# We include it for illustration purposes.
|
||||
return hasattr(self, name)
|
||||
|
||||
|
||||
dispatcher = LoopbackDispatcher()
|
||||
474
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/historical_tests.py
vendored
Normal file
474
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/historical_tests.py
vendored
Normal file
@@ -0,0 +1,474 @@
|
||||
"""Original NetworkX graph tests"""
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx import convert_node_labels_to_integers as cnlti
|
||||
from networkx.utils import edges_equal, nodes_equal
|
||||
|
||||
|
||||
class HistoricalTests:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.null = nx.null_graph()
|
||||
cls.P1 = cnlti(nx.path_graph(1), first_label=1)
|
||||
cls.P3 = cnlti(nx.path_graph(3), first_label=1)
|
||||
cls.P10 = cnlti(nx.path_graph(10), first_label=1)
|
||||
cls.K1 = cnlti(nx.complete_graph(1), first_label=1)
|
||||
cls.K3 = cnlti(nx.complete_graph(3), first_label=1)
|
||||
cls.K4 = cnlti(nx.complete_graph(4), first_label=1)
|
||||
cls.K5 = cnlti(nx.complete_graph(5), first_label=1)
|
||||
cls.K10 = cnlti(nx.complete_graph(10), first_label=1)
|
||||
cls.G = nx.Graph
|
||||
|
||||
def test_name(self):
|
||||
G = self.G(name="test")
|
||||
assert G.name == "test"
|
||||
H = self.G()
|
||||
assert H.name == ""
|
||||
|
||||
# Nodes
|
||||
|
||||
def test_add_remove_node(self):
|
||||
G = self.G()
|
||||
G.add_node("A")
|
||||
assert G.has_node("A")
|
||||
G.remove_node("A")
|
||||
assert not G.has_node("A")
|
||||
|
||||
def test_nonhashable_node(self):
|
||||
# Test if a non-hashable object is in the Graph. A python dict will
|
||||
# raise a TypeError, but for a Graph class a simple False should be
|
||||
# returned (see Graph __contains__). If it cannot be a node then it is
|
||||
# not a node.
|
||||
G = self.G()
|
||||
assert not G.has_node(["A"])
|
||||
assert not G.has_node({"A": 1})
|
||||
|
||||
def test_add_nodes_from(self):
|
||||
G = self.G()
|
||||
G.add_nodes_from(list("ABCDEFGHIJKL"))
|
||||
assert G.has_node("L")
|
||||
G.remove_nodes_from(["H", "I", "J", "K", "L"])
|
||||
G.add_nodes_from([1, 2, 3, 4])
|
||||
assert sorted(G.nodes(), key=str) == [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"E",
|
||||
"F",
|
||||
"G",
|
||||
]
|
||||
# test __iter__
|
||||
assert sorted(G, key=str) == [1, 2, 3, 4, "A", "B", "C", "D", "E", "F", "G"]
|
||||
|
||||
def test_contains(self):
|
||||
G = self.G()
|
||||
G.add_node("A")
|
||||
assert "A" in G
|
||||
assert [] not in G # never raise a Key or TypeError in this test
|
||||
assert {1: 1} not in G
|
||||
|
||||
def test_add_remove(self):
|
||||
# Test add_node and remove_node acting for various nbunch
|
||||
G = self.G()
|
||||
G.add_node("m")
|
||||
assert G.has_node("m")
|
||||
G.add_node("m") # no complaints
|
||||
pytest.raises(nx.NetworkXError, G.remove_node, "j")
|
||||
G.remove_node("m")
|
||||
assert list(G) == []
|
||||
|
||||
def test_nbunch_is_list(self):
|
||||
G = self.G()
|
||||
G.add_nodes_from(list("ABCD"))
|
||||
G.add_nodes_from(self.P3) # add nbunch of nodes (nbunch=Graph)
|
||||
assert sorted(G.nodes(), key=str) == [1, 2, 3, "A", "B", "C", "D"]
|
||||
G.remove_nodes_from(self.P3) # remove nbunch of nodes (nbunch=Graph)
|
||||
assert sorted(G.nodes(), key=str) == ["A", "B", "C", "D"]
|
||||
|
||||
def test_nbunch_is_set(self):
|
||||
G = self.G()
|
||||
nbunch = set("ABCDEFGHIJKL")
|
||||
G.add_nodes_from(nbunch)
|
||||
assert G.has_node("L")
|
||||
|
||||
def test_nbunch_dict(self):
|
||||
# nbunch is a dict with nodes as keys
|
||||
G = self.G()
|
||||
nbunch = set("ABCDEFGHIJKL")
|
||||
G.add_nodes_from(nbunch)
|
||||
nbunch = {"I": "foo", "J": 2, "K": True, "L": "spam"}
|
||||
G.remove_nodes_from(nbunch)
|
||||
assert sorted(G.nodes(), key=str), ["A", "B", "C", "D", "E", "F", "G", "H"]
|
||||
|
||||
def test_nbunch_iterator(self):
|
||||
G = self.G()
|
||||
G.add_nodes_from(["A", "B", "C", "D", "E", "F", "G", "H"])
|
||||
n_iter = self.P3.nodes()
|
||||
G.add_nodes_from(n_iter)
|
||||
assert sorted(G.nodes(), key=str) == [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"E",
|
||||
"F",
|
||||
"G",
|
||||
"H",
|
||||
]
|
||||
n_iter = self.P3.nodes() # rebuild same iterator
|
||||
G.remove_nodes_from(n_iter) # remove nbunch of nodes (nbunch=iterator)
|
||||
assert sorted(G.nodes(), key=str) == ["A", "B", "C", "D", "E", "F", "G", "H"]
|
||||
|
||||
def test_nbunch_graph(self):
|
||||
G = self.G()
|
||||
G.add_nodes_from(["A", "B", "C", "D", "E", "F", "G", "H"])
|
||||
nbunch = self.K3
|
||||
G.add_nodes_from(nbunch)
|
||||
assert sorted(G.nodes(), key=str), [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"E",
|
||||
"F",
|
||||
"G",
|
||||
"H",
|
||||
]
|
||||
|
||||
# Edges
|
||||
|
||||
def test_add_edge(self):
|
||||
G = self.G()
|
||||
pytest.raises(TypeError, G.add_edge, "A")
|
||||
|
||||
G.add_edge("A", "B") # testing add_edge()
|
||||
G.add_edge("A", "B") # should fail silently
|
||||
assert G.has_edge("A", "B")
|
||||
assert not G.has_edge("A", "C")
|
||||
assert G.has_edge(*("A", "B"))
|
||||
if G.is_directed():
|
||||
assert not G.has_edge("B", "A")
|
||||
else:
|
||||
# G is undirected, so B->A is an edge
|
||||
assert G.has_edge("B", "A")
|
||||
|
||||
G.add_edge("A", "C") # test directedness
|
||||
G.add_edge("C", "A")
|
||||
G.remove_edge("C", "A")
|
||||
if G.is_directed():
|
||||
assert G.has_edge("A", "C")
|
||||
else:
|
||||
assert not G.has_edge("A", "C")
|
||||
assert not G.has_edge("C", "A")
|
||||
|
||||
def test_self_loop(self):
|
||||
G = self.G()
|
||||
G.add_edge("A", "A") # test self loops
|
||||
assert G.has_edge("A", "A")
|
||||
G.remove_edge("A", "A")
|
||||
G.add_edge("X", "X")
|
||||
assert G.has_node("X")
|
||||
G.remove_node("X")
|
||||
G.add_edge("A", "Z") # should add the node silently
|
||||
assert G.has_node("Z")
|
||||
|
||||
def test_add_edges_from(self):
|
||||
G = self.G()
|
||||
G.add_edges_from([("B", "C")]) # test add_edges_from()
|
||||
assert G.has_edge("B", "C")
|
||||
if G.is_directed():
|
||||
assert not G.has_edge("C", "B")
|
||||
else:
|
||||
assert G.has_edge("C", "B") # undirected
|
||||
|
||||
G.add_edges_from([("D", "F"), ("B", "D")])
|
||||
assert G.has_edge("D", "F")
|
||||
assert G.has_edge("B", "D")
|
||||
|
||||
if G.is_directed():
|
||||
assert not G.has_edge("D", "B")
|
||||
else:
|
||||
assert G.has_edge("D", "B") # undirected
|
||||
|
||||
def test_add_edges_from2(self):
|
||||
G = self.G()
|
||||
# after failing silently, should add 2nd edge
|
||||
G.add_edges_from([tuple("IJ"), list("KK"), tuple("JK")])
|
||||
assert G.has_edge(*("I", "J"))
|
||||
assert G.has_edge(*("K", "K"))
|
||||
assert G.has_edge(*("J", "K"))
|
||||
if G.is_directed():
|
||||
assert not G.has_edge(*("K", "J"))
|
||||
else:
|
||||
assert G.has_edge(*("K", "J"))
|
||||
|
||||
def test_add_edges_from3(self):
|
||||
G = self.G()
|
||||
G.add_edges_from(zip(list("ACD"), list("CDE")))
|
||||
assert G.has_edge("D", "E")
|
||||
assert not G.has_edge("E", "C")
|
||||
|
||||
def test_remove_edge(self):
|
||||
G = self.G()
|
||||
G.add_nodes_from([1, 2, 3, "A", "B", "C", "D", "E", "F", "G", "H"])
|
||||
|
||||
G.add_edges_from(zip(list("MNOP"), list("NOPM")))
|
||||
assert G.has_edge("O", "P")
|
||||
assert G.has_edge("P", "M")
|
||||
G.remove_node("P") # tests remove_node()'s handling of edges.
|
||||
assert not G.has_edge("P", "M")
|
||||
pytest.raises(TypeError, G.remove_edge, "M")
|
||||
|
||||
G.add_edge("N", "M")
|
||||
assert G.has_edge("M", "N")
|
||||
G.remove_edge("M", "N")
|
||||
assert not G.has_edge("M", "N")
|
||||
|
||||
# self loop fails silently
|
||||
G.remove_edges_from([list("HI"), list("DF"), tuple("KK"), tuple("JK")])
|
||||
assert not G.has_edge("H", "I")
|
||||
assert not G.has_edge("J", "K")
|
||||
G.remove_edges_from([list("IJ"), list("KK"), list("JK")])
|
||||
assert not G.has_edge("I", "J")
|
||||
G.remove_nodes_from(set("ZEFHIMNO"))
|
||||
G.add_edge("J", "K")
|
||||
|
||||
def test_edges_nbunch(self):
|
||||
# Test G.edges(nbunch) with various forms of nbunch
|
||||
G = self.G()
|
||||
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")])
|
||||
# node not in nbunch should be quietly ignored
|
||||
pytest.raises(nx.NetworkXError, G.edges, 6)
|
||||
assert list(G.edges("Z")) == [] # iterable non-node
|
||||
# nbunch can be an empty list
|
||||
assert list(G.edges([])) == []
|
||||
if G.is_directed():
|
||||
elist = [("A", "B"), ("A", "C"), ("B", "D")]
|
||||
else:
|
||||
elist = [("A", "B"), ("A", "C"), ("B", "C"), ("B", "D")]
|
||||
# nbunch can be a list
|
||||
assert edges_equal(list(G.edges(["A", "B"])), elist)
|
||||
# nbunch can be a set
|
||||
assert edges_equal(G.edges({"A", "B"}), elist)
|
||||
# nbunch can be a graph
|
||||
G1 = self.G()
|
||||
G1.add_nodes_from("AB")
|
||||
assert edges_equal(G.edges(G1), elist)
|
||||
# nbunch can be a dict with nodes as keys
|
||||
ndict = {"A": "thing1", "B": "thing2"}
|
||||
assert edges_equal(G.edges(ndict), elist)
|
||||
# nbunch can be a single node
|
||||
assert edges_equal(list(G.edges("A")), [("A", "B"), ("A", "C")])
|
||||
assert nodes_equal(sorted(G), ["A", "B", "C", "D"])
|
||||
|
||||
# nbunch can be nothing (whole graph)
|
||||
assert edges_equal(
|
||||
list(G.edges()),
|
||||
[("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")],
|
||||
)
|
||||
|
||||
def test_degree(self):
|
||||
G = self.G()
|
||||
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")])
|
||||
assert G.degree("A") == 2
|
||||
|
||||
# degree of single node in iterable container must return dict
|
||||
assert list(G.degree(["A"])) == [("A", 2)]
|
||||
assert sorted(d for n, d in G.degree(["A", "B"])) == [2, 3]
|
||||
assert sorted(d for n, d in G.degree()) == [2, 2, 3, 3]
|
||||
|
||||
def test_degree2(self):
|
||||
H = self.G()
|
||||
H.add_edges_from([(1, 24), (1, 2)])
|
||||
assert sorted(d for n, d in H.degree([1, 24])) == [1, 2]
|
||||
|
||||
def test_degree_graph(self):
|
||||
P3 = nx.path_graph(3)
|
||||
P5 = nx.path_graph(5)
|
||||
# silently ignore nodes not in P3
|
||||
assert dict(d for n, d in P3.degree(["A", "B"])) == {}
|
||||
# nbunch can be a graph
|
||||
assert sorted(d for n, d in P5.degree(P3)) == [1, 2, 2]
|
||||
# nbunch can be a graph that's way too big
|
||||
assert sorted(d for n, d in P3.degree(P5)) == [1, 1, 2]
|
||||
assert list(P5.degree([])) == []
|
||||
assert dict(P5.degree([])) == {}
|
||||
|
||||
def test_null(self):
|
||||
null = nx.null_graph()
|
||||
assert list(null.degree()) == []
|
||||
assert dict(null.degree()) == {}
|
||||
|
||||
def test_order_size(self):
|
||||
G = self.G()
|
||||
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")])
|
||||
assert G.order() == 4
|
||||
assert G.size() == 5
|
||||
assert G.number_of_edges() == 5
|
||||
assert G.number_of_edges("A", "B") == 1
|
||||
assert G.number_of_edges("A", "D") == 0
|
||||
|
||||
def test_copy(self):
|
||||
G = self.G()
|
||||
H = G.copy() # copy
|
||||
assert H.adj == G.adj
|
||||
assert H.name == G.name
|
||||
assert H is not G
|
||||
|
||||
def test_subgraph(self):
|
||||
G = self.G()
|
||||
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")])
|
||||
SG = G.subgraph(["A", "B", "D"])
|
||||
assert nodes_equal(list(SG), ["A", "B", "D"])
|
||||
assert edges_equal(list(SG.edges()), [("A", "B"), ("B", "D")])
|
||||
|
||||
def test_to_directed(self):
|
||||
G = self.G()
|
||||
if not G.is_directed():
|
||||
G.add_edges_from(
|
||||
[("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")]
|
||||
)
|
||||
|
||||
DG = G.to_directed()
|
||||
assert DG is not G # directed copy or copy
|
||||
|
||||
assert DG.is_directed()
|
||||
assert DG.name == G.name
|
||||
assert DG.adj == G.adj
|
||||
assert sorted(DG.out_edges(list("AB"))) == [
|
||||
("A", "B"),
|
||||
("A", "C"),
|
||||
("B", "A"),
|
||||
("B", "C"),
|
||||
("B", "D"),
|
||||
]
|
||||
DG.remove_edge("A", "B")
|
||||
assert DG.has_edge("B", "A") # this removes B-A but not A-B
|
||||
assert not DG.has_edge("A", "B")
|
||||
|
||||
def test_to_undirected(self):
|
||||
G = self.G()
|
||||
if G.is_directed():
|
||||
G.add_edges_from(
|
||||
[("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")]
|
||||
)
|
||||
UG = G.to_undirected() # to_undirected
|
||||
assert UG is not G
|
||||
assert not UG.is_directed()
|
||||
assert G.is_directed()
|
||||
assert UG.name == G.name
|
||||
assert UG.adj != G.adj
|
||||
assert sorted(UG.edges(list("AB"))) == [
|
||||
("A", "B"),
|
||||
("A", "C"),
|
||||
("B", "C"),
|
||||
("B", "D"),
|
||||
]
|
||||
assert sorted(UG.edges(["A", "B"])) == [
|
||||
("A", "B"),
|
||||
("A", "C"),
|
||||
("B", "C"),
|
||||
("B", "D"),
|
||||
]
|
||||
UG.remove_edge("A", "B")
|
||||
assert not UG.has_edge("B", "A")
|
||||
assert not UG.has_edge("A", "B")
|
||||
|
||||
def test_neighbors(self):
|
||||
G = self.G()
|
||||
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")])
|
||||
G.add_nodes_from("GJK")
|
||||
assert sorted(G["A"]) == ["B", "C"]
|
||||
assert sorted(G.neighbors("A")) == ["B", "C"]
|
||||
assert sorted(G.neighbors("A")) == ["B", "C"]
|
||||
assert sorted(G.neighbors("G")) == []
|
||||
pytest.raises(nx.NetworkXError, G.neighbors, "j")
|
||||
|
||||
def test_iterators(self):
|
||||
G = self.G()
|
||||
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")])
|
||||
G.add_nodes_from("GJK")
|
||||
assert sorted(G.nodes()) == ["A", "B", "C", "D", "G", "J", "K"]
|
||||
assert edges_equal(
|
||||
G.edges(), [("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")]
|
||||
)
|
||||
|
||||
assert sorted(v for k, v in G.degree()) == [0, 0, 0, 2, 2, 3, 3]
|
||||
assert sorted(G.degree(), key=str) == [
|
||||
("A", 2),
|
||||
("B", 3),
|
||||
("C", 3),
|
||||
("D", 2),
|
||||
("G", 0),
|
||||
("J", 0),
|
||||
("K", 0),
|
||||
]
|
||||
assert sorted(G.neighbors("A")) == ["B", "C"]
|
||||
pytest.raises(nx.NetworkXError, G.neighbors, "X")
|
||||
G.clear()
|
||||
assert nx.number_of_nodes(G) == 0
|
||||
assert nx.number_of_edges(G) == 0
|
||||
|
||||
def test_null_subgraph(self):
|
||||
# Subgraph of a null graph is a null graph
|
||||
nullgraph = nx.null_graph()
|
||||
G = nx.null_graph()
|
||||
H = G.subgraph([])
|
||||
assert nx.is_isomorphic(H, nullgraph)
|
||||
|
||||
def test_empty_subgraph(self):
|
||||
# Subgraph of an empty graph is an empty graph. test 1
|
||||
nullgraph = nx.null_graph()
|
||||
E5 = nx.empty_graph(5)
|
||||
E10 = nx.empty_graph(10)
|
||||
H = E10.subgraph([])
|
||||
assert nx.is_isomorphic(H, nullgraph)
|
||||
H = E10.subgraph([1, 2, 3, 4, 5])
|
||||
assert nx.is_isomorphic(H, E5)
|
||||
|
||||
def test_complete_subgraph(self):
|
||||
# Subgraph of a complete graph is a complete graph
|
||||
K1 = nx.complete_graph(1)
|
||||
K3 = nx.complete_graph(3)
|
||||
K5 = nx.complete_graph(5)
|
||||
H = K5.subgraph([1, 2, 3])
|
||||
assert nx.is_isomorphic(H, K3)
|
||||
|
||||
def test_subgraph_nbunch(self):
|
||||
nullgraph = nx.null_graph()
|
||||
K1 = nx.complete_graph(1)
|
||||
K3 = nx.complete_graph(3)
|
||||
K5 = nx.complete_graph(5)
|
||||
# Test G.subgraph(nbunch), where nbunch is a single node
|
||||
H = K5.subgraph(1)
|
||||
assert nx.is_isomorphic(H, K1)
|
||||
# Test G.subgraph(nbunch), where nbunch is a set
|
||||
H = K5.subgraph({1})
|
||||
assert nx.is_isomorphic(H, K1)
|
||||
# Test G.subgraph(nbunch), where nbunch is an iterator
|
||||
H = K5.subgraph(iter(K3))
|
||||
assert nx.is_isomorphic(H, K3)
|
||||
# Test G.subgraph(nbunch), where nbunch is another graph
|
||||
H = K5.subgraph(K3)
|
||||
assert nx.is_isomorphic(H, K3)
|
||||
H = K5.subgraph([9])
|
||||
assert nx.is_isomorphic(H, nullgraph)
|
||||
|
||||
def test_node_tuple_issue(self):
|
||||
H = self.G()
|
||||
# Test error handling of tuple as a node
|
||||
pytest.raises(nx.NetworkXError, H.remove_node, (1, 2))
|
||||
H.remove_nodes_from([(1, 2)]) # no error
|
||||
pytest.raises(nx.NetworkXError, H.neighbors, (1, 2))
|
||||
362
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_coreviews.py
vendored
Normal file
362
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_coreviews.py
vendored
Normal file
@@ -0,0 +1,362 @@
|
||||
import pickle
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
|
||||
|
||||
class TestAtlasView:
|
||||
# node->data
|
||||
def setup_method(self):
|
||||
self.d = {0: {"color": "blue", "weight": 1.2}, 1: {}, 2: {"color": 1}}
|
||||
self.av = nx.classes.coreviews.AtlasView(self.d)
|
||||
|
||||
def test_pickle(self):
|
||||
view = self.av
|
||||
pview = pickle.loads(pickle.dumps(view, -1))
|
||||
assert view == pview
|
||||
assert view.__slots__ == pview.__slots__
|
||||
pview = pickle.loads(pickle.dumps(view))
|
||||
assert view == pview
|
||||
assert view.__slots__ == pview.__slots__
|
||||
|
||||
def test_len(self):
|
||||
assert len(self.av) == len(self.d)
|
||||
|
||||
def test_iter(self):
|
||||
assert list(self.av) == list(self.d)
|
||||
|
||||
def test_getitem(self):
|
||||
assert self.av[1] is self.d[1]
|
||||
assert self.av[2]["color"] == 1
|
||||
pytest.raises(KeyError, self.av.__getitem__, 3)
|
||||
|
||||
def test_copy(self):
|
||||
avcopy = self.av.copy()
|
||||
assert avcopy[0] == self.av[0]
|
||||
assert avcopy == self.av
|
||||
assert avcopy[0] is not self.av[0]
|
||||
assert avcopy is not self.av
|
||||
avcopy[5] = {}
|
||||
assert avcopy != self.av
|
||||
|
||||
avcopy[0]["ht"] = 4
|
||||
assert avcopy[0] != self.av[0]
|
||||
self.av[0]["ht"] = 4
|
||||
assert avcopy[0] == self.av[0]
|
||||
del self.av[0]["ht"]
|
||||
|
||||
assert not hasattr(self.av, "__setitem__")
|
||||
|
||||
def test_items(self):
|
||||
assert sorted(self.av.items()) == sorted(self.d.items())
|
||||
|
||||
def test_str(self):
|
||||
out = str(self.d)
|
||||
assert str(self.av) == out
|
||||
|
||||
def test_repr(self):
|
||||
out = "AtlasView(" + str(self.d) + ")"
|
||||
assert repr(self.av) == out
|
||||
|
||||
|
||||
class TestAdjacencyView:
|
||||
# node->nbr->data
|
||||
def setup_method(self):
|
||||
dd = {"color": "blue", "weight": 1.2}
|
||||
self.nd = {0: dd, 1: {}, 2: {"color": 1}}
|
||||
self.adj = {3: self.nd, 0: {3: dd}, 1: {}, 2: {3: {"color": 1}}}
|
||||
self.adjview = nx.classes.coreviews.AdjacencyView(self.adj)
|
||||
|
||||
def test_pickle(self):
|
||||
view = self.adjview
|
||||
pview = pickle.loads(pickle.dumps(view, -1))
|
||||
assert view == pview
|
||||
assert view.__slots__ == pview.__slots__
|
||||
|
||||
def test_len(self):
|
||||
assert len(self.adjview) == len(self.adj)
|
||||
|
||||
def test_iter(self):
|
||||
assert list(self.adjview) == list(self.adj)
|
||||
|
||||
def test_getitem(self):
|
||||
assert self.adjview[1] is not self.adj[1]
|
||||
assert self.adjview[3][0] is self.adjview[0][3]
|
||||
assert self.adjview[2][3]["color"] == 1
|
||||
pytest.raises(KeyError, self.adjview.__getitem__, 4)
|
||||
|
||||
def test_copy(self):
|
||||
avcopy = self.adjview.copy()
|
||||
assert avcopy[0] == self.adjview[0]
|
||||
assert avcopy[0] is not self.adjview[0]
|
||||
|
||||
avcopy[2][3]["ht"] = 4
|
||||
assert avcopy[2] != self.adjview[2]
|
||||
self.adjview[2][3]["ht"] = 4
|
||||
assert avcopy[2] == self.adjview[2]
|
||||
del self.adjview[2][3]["ht"]
|
||||
|
||||
assert not hasattr(self.adjview, "__setitem__")
|
||||
|
||||
def test_items(self):
|
||||
view_items = sorted((n, dict(d)) for n, d in self.adjview.items())
|
||||
assert view_items == sorted(self.adj.items())
|
||||
|
||||
def test_str(self):
|
||||
out = str(dict(self.adj))
|
||||
assert str(self.adjview) == out
|
||||
|
||||
def test_repr(self):
|
||||
out = self.adjview.__class__.__name__ + "(" + str(self.adj) + ")"
|
||||
assert repr(self.adjview) == out
|
||||
|
||||
|
||||
class TestMultiAdjacencyView(TestAdjacencyView):
|
||||
# node->nbr->key->data
|
||||
def setup_method(self):
|
||||
dd = {"color": "blue", "weight": 1.2}
|
||||
self.kd = {0: dd, 1: {}, 2: {"color": 1}}
|
||||
self.nd = {3: self.kd, 0: {3: dd}, 1: {0: {}}, 2: {3: {"color": 1}}}
|
||||
self.adj = {3: self.nd, 0: {3: {3: dd}}, 1: {}, 2: {3: {8: {}}}}
|
||||
self.adjview = nx.classes.coreviews.MultiAdjacencyView(self.adj)
|
||||
|
||||
def test_getitem(self):
|
||||
assert self.adjview[1] is not self.adj[1]
|
||||
assert self.adjview[3][0][3] is self.adjview[0][3][3]
|
||||
assert self.adjview[3][2][3]["color"] == 1
|
||||
pytest.raises(KeyError, self.adjview.__getitem__, 4)
|
||||
|
||||
def test_copy(self):
|
||||
avcopy = self.adjview.copy()
|
||||
assert avcopy[0] == self.adjview[0]
|
||||
assert avcopy[0] is not self.adjview[0]
|
||||
|
||||
avcopy[2][3][8]["ht"] = 4
|
||||
assert avcopy[2] != self.adjview[2]
|
||||
self.adjview[2][3][8]["ht"] = 4
|
||||
assert avcopy[2] == self.adjview[2]
|
||||
del self.adjview[2][3][8]["ht"]
|
||||
|
||||
assert not hasattr(self.adjview, "__setitem__")
|
||||
|
||||
|
||||
class TestUnionAtlas:
|
||||
# node->data
|
||||
def setup_method(self):
|
||||
self.s = {0: {"color": "blue", "weight": 1.2}, 1: {}, 2: {"color": 1}}
|
||||
self.p = {3: {"color": "blue", "weight": 1.2}, 4: {}, 2: {"watch": 2}}
|
||||
self.av = nx.classes.coreviews.UnionAtlas(self.s, self.p)
|
||||
|
||||
def test_pickle(self):
|
||||
view = self.av
|
||||
pview = pickle.loads(pickle.dumps(view, -1))
|
||||
assert view == pview
|
||||
assert view.__slots__ == pview.__slots__
|
||||
|
||||
def test_len(self):
|
||||
assert len(self.av) == len(self.s.keys() | self.p.keys()) == 5
|
||||
|
||||
def test_iter(self):
|
||||
assert set(self.av) == set(self.s) | set(self.p)
|
||||
|
||||
def test_getitem(self):
|
||||
assert self.av[0] is self.s[0]
|
||||
assert self.av[4] is self.p[4]
|
||||
assert self.av[2]["color"] == 1
|
||||
pytest.raises(KeyError, self.av[2].__getitem__, "watch")
|
||||
pytest.raises(KeyError, self.av.__getitem__, 8)
|
||||
|
||||
def test_copy(self):
|
||||
avcopy = self.av.copy()
|
||||
assert avcopy[0] == self.av[0]
|
||||
assert avcopy[0] is not self.av[0]
|
||||
assert avcopy is not self.av
|
||||
avcopy[5] = {}
|
||||
assert avcopy != self.av
|
||||
|
||||
avcopy[0]["ht"] = 4
|
||||
assert avcopy[0] != self.av[0]
|
||||
self.av[0]["ht"] = 4
|
||||
assert avcopy[0] == self.av[0]
|
||||
del self.av[0]["ht"]
|
||||
|
||||
assert not hasattr(self.av, "__setitem__")
|
||||
|
||||
def test_items(self):
|
||||
expected = dict(self.p.items())
|
||||
expected.update(self.s)
|
||||
assert sorted(self.av.items()) == sorted(expected.items())
|
||||
|
||||
def test_str(self):
|
||||
out = str(dict(self.av))
|
||||
assert str(self.av) == out
|
||||
|
||||
def test_repr(self):
|
||||
out = f"{self.av.__class__.__name__}({self.s}, {self.p})"
|
||||
assert repr(self.av) == out
|
||||
|
||||
|
||||
class TestUnionAdjacency:
|
||||
# node->nbr->data
|
||||
def setup_method(self):
|
||||
dd = {"color": "blue", "weight": 1.2}
|
||||
self.nd = {0: dd, 1: {}, 2: {"color": 1}}
|
||||
self.s = {3: self.nd, 0: {}, 1: {}, 2: {3: {"color": 1}}}
|
||||
self.p = {3: {}, 0: {3: dd}, 1: {0: {}}, 2: {1: {"color": 1}}}
|
||||
self.adjview = nx.classes.coreviews.UnionAdjacency(self.s, self.p)
|
||||
|
||||
def test_pickle(self):
|
||||
view = self.adjview
|
||||
pview = pickle.loads(pickle.dumps(view, -1))
|
||||
assert view == pview
|
||||
assert view.__slots__ == pview.__slots__
|
||||
|
||||
def test_len(self):
|
||||
assert len(self.adjview) == len(self.s)
|
||||
|
||||
def test_iter(self):
|
||||
assert sorted(self.adjview) == sorted(self.s)
|
||||
|
||||
def test_getitem(self):
|
||||
assert self.adjview[1] is not self.s[1]
|
||||
assert self.adjview[3][0] is self.adjview[0][3]
|
||||
assert self.adjview[2][3]["color"] == 1
|
||||
pytest.raises(KeyError, self.adjview.__getitem__, 4)
|
||||
|
||||
def test_copy(self):
|
||||
avcopy = self.adjview.copy()
|
||||
assert avcopy[0] == self.adjview[0]
|
||||
assert avcopy[0] is not self.adjview[0]
|
||||
|
||||
avcopy[2][3]["ht"] = 4
|
||||
assert avcopy[2] != self.adjview[2]
|
||||
self.adjview[2][3]["ht"] = 4
|
||||
assert avcopy[2] == self.adjview[2]
|
||||
del self.adjview[2][3]["ht"]
|
||||
|
||||
assert not hasattr(self.adjview, "__setitem__")
|
||||
|
||||
def test_str(self):
|
||||
out = str(dict(self.adjview))
|
||||
assert str(self.adjview) == out
|
||||
|
||||
def test_repr(self):
|
||||
clsname = self.adjview.__class__.__name__
|
||||
out = f"{clsname}({self.s}, {self.p})"
|
||||
assert repr(self.adjview) == out
|
||||
|
||||
|
||||
class TestUnionMultiInner(TestUnionAdjacency):
|
||||
# nbr->key->data
|
||||
def setup_method(self):
|
||||
dd = {"color": "blue", "weight": 1.2}
|
||||
self.kd = {7: {}, "ekey": {}, 9: {"color": 1}}
|
||||
self.s = {3: self.kd, 0: {7: dd}, 1: {}, 2: {"key": {"color": 1}}}
|
||||
self.p = {3: {}, 0: {3: dd}, 1: {}, 2: {1: {"span": 2}}}
|
||||
self.adjview = nx.classes.coreviews.UnionMultiInner(self.s, self.p)
|
||||
|
||||
def test_len(self):
|
||||
assert len(self.adjview) == len(self.s.keys() | self.p.keys()) == 4
|
||||
|
||||
def test_getitem(self):
|
||||
assert self.adjview[1] is not self.s[1]
|
||||
assert self.adjview[0][7] is self.adjview[0][3]
|
||||
assert self.adjview[2]["key"]["color"] == 1
|
||||
assert self.adjview[2][1]["span"] == 2
|
||||
pytest.raises(KeyError, self.adjview.__getitem__, 4)
|
||||
pytest.raises(KeyError, self.adjview[1].__getitem__, "key")
|
||||
|
||||
def test_copy(self):
|
||||
avcopy = self.adjview.copy()
|
||||
assert avcopy[0] == self.adjview[0]
|
||||
assert avcopy[0] is not self.adjview[0]
|
||||
|
||||
avcopy[2][1]["width"] = 8
|
||||
assert avcopy[2] != self.adjview[2]
|
||||
self.adjview[2][1]["width"] = 8
|
||||
assert avcopy[2] == self.adjview[2]
|
||||
del self.adjview[2][1]["width"]
|
||||
|
||||
assert not hasattr(self.adjview, "__setitem__")
|
||||
assert hasattr(avcopy, "__setitem__")
|
||||
|
||||
|
||||
class TestUnionMultiAdjacency(TestUnionAdjacency):
|
||||
# node->nbr->key->data
|
||||
def setup_method(self):
|
||||
dd = {"color": "blue", "weight": 1.2}
|
||||
self.kd = {7: {}, 8: {}, 9: {"color": 1}}
|
||||
self.nd = {3: self.kd, 0: {9: dd}, 1: {8: {}}, 2: {9: {"color": 1}}}
|
||||
self.s = {3: self.nd, 0: {3: {7: dd}}, 1: {}, 2: {3: {8: {}}}}
|
||||
self.p = {3: {}, 0: {3: {9: dd}}, 1: {}, 2: {1: {8: {}}}}
|
||||
self.adjview = nx.classes.coreviews.UnionMultiAdjacency(self.s, self.p)
|
||||
|
||||
def test_getitem(self):
|
||||
assert self.adjview[1] is not self.s[1]
|
||||
assert self.adjview[3][0][9] is self.adjview[0][3][9]
|
||||
assert self.adjview[3][2][9]["color"] == 1
|
||||
pytest.raises(KeyError, self.adjview.__getitem__, 4)
|
||||
|
||||
def test_copy(self):
|
||||
avcopy = self.adjview.copy()
|
||||
assert avcopy[0] == self.adjview[0]
|
||||
assert avcopy[0] is not self.adjview[0]
|
||||
|
||||
avcopy[2][3][8]["ht"] = 4
|
||||
assert avcopy[2] != self.adjview[2]
|
||||
self.adjview[2][3][8]["ht"] = 4
|
||||
assert avcopy[2] == self.adjview[2]
|
||||
del self.adjview[2][3][8]["ht"]
|
||||
|
||||
assert not hasattr(self.adjview, "__setitem__")
|
||||
assert hasattr(avcopy, "__setitem__")
|
||||
|
||||
|
||||
class TestFilteredGraphs:
|
||||
def setup_method(self):
|
||||
self.Graphs = [nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph]
|
||||
|
||||
def test_hide_show_nodes(self):
|
||||
SubGraph = nx.subgraph_view
|
||||
for Graph in self.Graphs:
|
||||
G = nx.path_graph(4, Graph)
|
||||
SG = G.subgraph([2, 3])
|
||||
RG = SubGraph(G, filter_node=nx.filters.hide_nodes([0, 1]))
|
||||
assert SG.nodes == RG.nodes
|
||||
assert SG.edges == RG.edges
|
||||
SGC = SG.copy()
|
||||
RGC = RG.copy()
|
||||
assert SGC.nodes == RGC.nodes
|
||||
assert SGC.edges == RGC.edges
|
||||
|
||||
def test_str_repr(self):
|
||||
SubGraph = nx.subgraph_view
|
||||
for Graph in self.Graphs:
|
||||
G = nx.path_graph(4, Graph)
|
||||
SG = G.subgraph([2, 3])
|
||||
RG = SubGraph(G, filter_node=nx.filters.hide_nodes([0, 1]))
|
||||
str(SG.adj)
|
||||
str(RG.adj)
|
||||
repr(SG.adj)
|
||||
repr(RG.adj)
|
||||
str(SG.adj[2])
|
||||
str(RG.adj[2])
|
||||
repr(SG.adj[2])
|
||||
repr(RG.adj[2])
|
||||
|
||||
def test_copy(self):
|
||||
SubGraph = nx.subgraph_view
|
||||
for Graph in self.Graphs:
|
||||
G = nx.path_graph(4, Graph)
|
||||
SG = G.subgraph([2, 3])
|
||||
RG = SubGraph(G, filter_node=nx.filters.hide_nodes([0, 1]))
|
||||
RsG = SubGraph(G, filter_node=nx.filters.show_nodes([2, 3]))
|
||||
assert G.adj.copy() == G.adj
|
||||
assert G.adj[2].copy() == G.adj[2]
|
||||
assert SG.adj.copy() == SG.adj
|
||||
assert SG.adj[2].copy() == SG.adj[2]
|
||||
assert RG.adj.copy() == RG.adj
|
||||
assert RG.adj[2].copy() == RG.adj[2]
|
||||
assert RsG.adj.copy() == RsG.adj
|
||||
assert RsG.adj[2].copy() == RsG.adj[2]
|
||||
331
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_digraph.py
vendored
Normal file
331
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_digraph.py
vendored
Normal file
@@ -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)) == []
|
||||
110
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_digraph_historical.py
vendored
Normal file
110
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_digraph_historical.py
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
"""Original NetworkX graph tests"""
|
||||
import pytest
|
||||
|
||||
import networkx
|
||||
import networkx as nx
|
||||
|
||||
from .historical_tests import HistoricalTests
|
||||
|
||||
|
||||
class TestDiGraphHistorical(HistoricalTests):
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
HistoricalTests.setup_class()
|
||||
cls.G = nx.DiGraph
|
||||
|
||||
def test_in_degree(self):
|
||||
G = self.G()
|
||||
G.add_nodes_from("GJK")
|
||||
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("B", "C"), ("C", "D")])
|
||||
|
||||
assert sorted(d for n, d in G.in_degree()) == [0, 0, 0, 0, 1, 2, 2]
|
||||
assert dict(G.in_degree()) == {
|
||||
"A": 0,
|
||||
"C": 2,
|
||||
"B": 1,
|
||||
"D": 2,
|
||||
"G": 0,
|
||||
"K": 0,
|
||||
"J": 0,
|
||||
}
|
||||
|
||||
def test_out_degree(self):
|
||||
G = self.G()
|
||||
G.add_nodes_from("GJK")
|
||||
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("B", "C"), ("C", "D")])
|
||||
assert sorted(v for k, v in G.in_degree()) == [0, 0, 0, 0, 1, 2, 2]
|
||||
assert dict(G.out_degree()) == {
|
||||
"A": 2,
|
||||
"C": 1,
|
||||
"B": 2,
|
||||
"D": 0,
|
||||
"G": 0,
|
||||
"K": 0,
|
||||
"J": 0,
|
||||
}
|
||||
|
||||
def test_degree_digraph(self):
|
||||
H = nx.DiGraph()
|
||||
H.add_edges_from([(1, 24), (1, 2)])
|
||||
assert sorted(d for n, d in H.in_degree([1, 24])) == [0, 1]
|
||||
assert sorted(d for n, d in H.out_degree([1, 24])) == [0, 2]
|
||||
assert sorted(d for n, d in H.degree([1, 24])) == [1, 2]
|
||||
|
||||
def test_neighbors(self):
|
||||
G = self.G()
|
||||
G.add_nodes_from("GJK")
|
||||
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("B", "C"), ("C", "D")])
|
||||
|
||||
assert sorted(G.neighbors("C")) == ["D"]
|
||||
assert sorted(G["C"]) == ["D"]
|
||||
assert sorted(G.neighbors("A")) == ["B", "C"]
|
||||
pytest.raises(nx.NetworkXError, G.neighbors, "j")
|
||||
pytest.raises(nx.NetworkXError, G.neighbors, "j")
|
||||
|
||||
def test_successors(self):
|
||||
G = self.G()
|
||||
G.add_nodes_from("GJK")
|
||||
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("B", "C"), ("C", "D")])
|
||||
assert sorted(G.successors("A")) == ["B", "C"]
|
||||
assert sorted(G.successors("A")) == ["B", "C"]
|
||||
assert sorted(G.successors("G")) == []
|
||||
assert sorted(G.successors("D")) == []
|
||||
assert sorted(G.successors("G")) == []
|
||||
pytest.raises(nx.NetworkXError, G.successors, "j")
|
||||
pytest.raises(nx.NetworkXError, G.successors, "j")
|
||||
|
||||
def test_predecessors(self):
|
||||
G = self.G()
|
||||
G.add_nodes_from("GJK")
|
||||
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("B", "C"), ("C", "D")])
|
||||
assert sorted(G.predecessors("C")) == ["A", "B"]
|
||||
assert sorted(G.predecessors("C")) == ["A", "B"]
|
||||
assert sorted(G.predecessors("G")) == []
|
||||
assert sorted(G.predecessors("A")) == []
|
||||
assert sorted(G.predecessors("G")) == []
|
||||
assert sorted(G.predecessors("A")) == []
|
||||
assert sorted(G.successors("D")) == []
|
||||
|
||||
pytest.raises(nx.NetworkXError, G.predecessors, "j")
|
||||
pytest.raises(nx.NetworkXError, G.predecessors, "j")
|
||||
|
||||
def test_reverse(self):
|
||||
G = nx.complete_graph(10)
|
||||
H = G.to_directed()
|
||||
HR = H.reverse()
|
||||
assert nx.is_isomorphic(H, HR)
|
||||
assert sorted(H.edges()) == sorted(HR.edges())
|
||||
|
||||
def test_reverse2(self):
|
||||
H = nx.DiGraph()
|
||||
foo = [H.add_edge(u, u + 1) for u in range(5)]
|
||||
HR = H.reverse()
|
||||
for u in range(5):
|
||||
assert HR.has_edge(u + 1, u)
|
||||
|
||||
def test_reverse3(self):
|
||||
H = nx.DiGraph()
|
||||
H.add_nodes_from([1, 2, 3, 4])
|
||||
HR = H.reverse()
|
||||
assert sorted(HR.nodes()) == [1, 2, 3, 4]
|
||||
177
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_filters.py
vendored
Normal file
177
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_filters.py
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
|
||||
|
||||
class TestFilterFactory:
|
||||
def test_no_filter(self):
|
||||
nf = nx.filters.no_filter
|
||||
assert nf()
|
||||
assert nf(1)
|
||||
assert nf(2, 1)
|
||||
|
||||
def test_hide_nodes(self):
|
||||
f = nx.classes.filters.hide_nodes([1, 2, 3])
|
||||
assert not f(1)
|
||||
assert not f(2)
|
||||
assert not f(3)
|
||||
assert f(4)
|
||||
assert f(0)
|
||||
assert f("a")
|
||||
pytest.raises(TypeError, f, 1, 2)
|
||||
pytest.raises(TypeError, f)
|
||||
|
||||
def test_show_nodes(self):
|
||||
f = nx.classes.filters.show_nodes([1, 2, 3])
|
||||
assert f(1)
|
||||
assert f(2)
|
||||
assert f(3)
|
||||
assert not f(4)
|
||||
assert not f(0)
|
||||
assert not f("a")
|
||||
pytest.raises(TypeError, f, 1, 2)
|
||||
pytest.raises(TypeError, f)
|
||||
|
||||
def test_hide_edges(self):
|
||||
factory = nx.classes.filters.hide_edges
|
||||
f = factory([(1, 2), (3, 4)])
|
||||
assert not f(1, 2)
|
||||
assert not f(3, 4)
|
||||
assert not f(4, 3)
|
||||
assert f(2, 3)
|
||||
assert f(0, -1)
|
||||
assert f("a", "b")
|
||||
pytest.raises(TypeError, f, 1, 2, 3)
|
||||
pytest.raises(TypeError, f, 1)
|
||||
pytest.raises(TypeError, f)
|
||||
pytest.raises(TypeError, factory, [1, 2, 3])
|
||||
pytest.raises(ValueError, factory, [(1, 2, 3)])
|
||||
|
||||
def test_show_edges(self):
|
||||
factory = nx.classes.filters.show_edges
|
||||
f = factory([(1, 2), (3, 4)])
|
||||
assert f(1, 2)
|
||||
assert f(3, 4)
|
||||
assert f(4, 3)
|
||||
assert not f(2, 3)
|
||||
assert not f(0, -1)
|
||||
assert not f("a", "b")
|
||||
pytest.raises(TypeError, f, 1, 2, 3)
|
||||
pytest.raises(TypeError, f, 1)
|
||||
pytest.raises(TypeError, f)
|
||||
pytest.raises(TypeError, factory, [1, 2, 3])
|
||||
pytest.raises(ValueError, factory, [(1, 2, 3)])
|
||||
|
||||
def test_hide_diedges(self):
|
||||
factory = nx.classes.filters.hide_diedges
|
||||
f = factory([(1, 2), (3, 4)])
|
||||
assert not f(1, 2)
|
||||
assert not f(3, 4)
|
||||
assert f(4, 3)
|
||||
assert f(2, 3)
|
||||
assert f(0, -1)
|
||||
assert f("a", "b")
|
||||
pytest.raises(TypeError, f, 1, 2, 3)
|
||||
pytest.raises(TypeError, f, 1)
|
||||
pytest.raises(TypeError, f)
|
||||
pytest.raises(TypeError, factory, [1, 2, 3])
|
||||
pytest.raises(ValueError, factory, [(1, 2, 3)])
|
||||
|
||||
def test_show_diedges(self):
|
||||
factory = nx.classes.filters.show_diedges
|
||||
f = factory([(1, 2), (3, 4)])
|
||||
assert f(1, 2)
|
||||
assert f(3, 4)
|
||||
assert not f(4, 3)
|
||||
assert not f(2, 3)
|
||||
assert not f(0, -1)
|
||||
assert not f("a", "b")
|
||||
pytest.raises(TypeError, f, 1, 2, 3)
|
||||
pytest.raises(TypeError, f, 1)
|
||||
pytest.raises(TypeError, f)
|
||||
pytest.raises(TypeError, factory, [1, 2, 3])
|
||||
pytest.raises(ValueError, factory, [(1, 2, 3)])
|
||||
|
||||
def test_hide_multiedges(self):
|
||||
factory = nx.classes.filters.hide_multiedges
|
||||
f = factory([(1, 2, 0), (3, 4, 1), (1, 2, 1)])
|
||||
assert not f(1, 2, 0)
|
||||
assert not f(1, 2, 1)
|
||||
assert f(1, 2, 2)
|
||||
assert f(3, 4, 0)
|
||||
assert not f(3, 4, 1)
|
||||
assert not f(4, 3, 1)
|
||||
assert f(4, 3, 0)
|
||||
assert f(2, 3, 0)
|
||||
assert f(0, -1, 0)
|
||||
assert f("a", "b", 0)
|
||||
pytest.raises(TypeError, f, 1, 2, 3, 4)
|
||||
pytest.raises(TypeError, f, 1, 2)
|
||||
pytest.raises(TypeError, f, 1)
|
||||
pytest.raises(TypeError, f)
|
||||
pytest.raises(TypeError, factory, [1, 2, 3])
|
||||
pytest.raises(ValueError, factory, [(1, 2)])
|
||||
pytest.raises(ValueError, factory, [(1, 2, 3, 4)])
|
||||
|
||||
def test_show_multiedges(self):
|
||||
factory = nx.classes.filters.show_multiedges
|
||||
f = factory([(1, 2, 0), (3, 4, 1), (1, 2, 1)])
|
||||
assert f(1, 2, 0)
|
||||
assert f(1, 2, 1)
|
||||
assert not f(1, 2, 2)
|
||||
assert not f(3, 4, 0)
|
||||
assert f(3, 4, 1)
|
||||
assert f(4, 3, 1)
|
||||
assert not f(4, 3, 0)
|
||||
assert not f(2, 3, 0)
|
||||
assert not f(0, -1, 0)
|
||||
assert not f("a", "b", 0)
|
||||
pytest.raises(TypeError, f, 1, 2, 3, 4)
|
||||
pytest.raises(TypeError, f, 1, 2)
|
||||
pytest.raises(TypeError, f, 1)
|
||||
pytest.raises(TypeError, f)
|
||||
pytest.raises(TypeError, factory, [1, 2, 3])
|
||||
pytest.raises(ValueError, factory, [(1, 2)])
|
||||
pytest.raises(ValueError, factory, [(1, 2, 3, 4)])
|
||||
|
||||
def test_hide_multidiedges(self):
|
||||
factory = nx.classes.filters.hide_multidiedges
|
||||
f = factory([(1, 2, 0), (3, 4, 1), (1, 2, 1)])
|
||||
assert not f(1, 2, 0)
|
||||
assert not f(1, 2, 1)
|
||||
assert f(1, 2, 2)
|
||||
assert f(3, 4, 0)
|
||||
assert not f(3, 4, 1)
|
||||
assert f(4, 3, 1)
|
||||
assert f(4, 3, 0)
|
||||
assert f(2, 3, 0)
|
||||
assert f(0, -1, 0)
|
||||
assert f("a", "b", 0)
|
||||
pytest.raises(TypeError, f, 1, 2, 3, 4)
|
||||
pytest.raises(TypeError, f, 1, 2)
|
||||
pytest.raises(TypeError, f, 1)
|
||||
pytest.raises(TypeError, f)
|
||||
pytest.raises(TypeError, factory, [1, 2, 3])
|
||||
pytest.raises(ValueError, factory, [(1, 2)])
|
||||
pytest.raises(ValueError, factory, [(1, 2, 3, 4)])
|
||||
|
||||
def test_show_multidiedges(self):
|
||||
factory = nx.classes.filters.show_multidiedges
|
||||
f = factory([(1, 2, 0), (3, 4, 1), (1, 2, 1)])
|
||||
assert f(1, 2, 0)
|
||||
assert f(1, 2, 1)
|
||||
assert not f(1, 2, 2)
|
||||
assert not f(3, 4, 0)
|
||||
assert f(3, 4, 1)
|
||||
assert not f(4, 3, 1)
|
||||
assert not f(4, 3, 0)
|
||||
assert not f(2, 3, 0)
|
||||
assert not f(0, -1, 0)
|
||||
assert not f("a", "b", 0)
|
||||
pytest.raises(TypeError, f, 1, 2, 3, 4)
|
||||
pytest.raises(TypeError, f, 1, 2)
|
||||
pytest.raises(TypeError, f, 1)
|
||||
pytest.raises(TypeError, f)
|
||||
pytest.raises(TypeError, factory, [1, 2, 3])
|
||||
pytest.raises(ValueError, factory, [(1, 2)])
|
||||
pytest.raises(ValueError, factory, [(1, 2, 3, 4)])
|
||||
787
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_function.py
vendored
Normal file
787
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_function.py
vendored
Normal file
@@ -0,0 +1,787 @@
|
||||
import random
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.utils import edges_equal, nodes_equal
|
||||
|
||||
|
||||
def test_degree_histogram_empty():
|
||||
G = nx.Graph()
|
||||
assert nx.degree_histogram(G) == []
|
||||
|
||||
|
||||
class TestFunction:
|
||||
def setup_method(self):
|
||||
self.G = nx.Graph({0: [1, 2, 3], 1: [1, 2, 0], 4: []}, name="Test")
|
||||
self.Gdegree = {0: 3, 1: 2, 2: 2, 3: 1, 4: 0}
|
||||
self.Gnodes = list(range(5))
|
||||
self.Gedges = [(0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2)]
|
||||
self.DG = nx.DiGraph({0: [1, 2, 3], 1: [1, 2, 0], 4: []})
|
||||
self.DGin_degree = {0: 1, 1: 2, 2: 2, 3: 1, 4: 0}
|
||||
self.DGout_degree = {0: 3, 1: 3, 2: 0, 3: 0, 4: 0}
|
||||
self.DGnodes = list(range(5))
|
||||
self.DGedges = [(0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2)]
|
||||
|
||||
def test_nodes(self):
|
||||
assert nodes_equal(self.G.nodes(), list(nx.nodes(self.G)))
|
||||
assert nodes_equal(self.DG.nodes(), list(nx.nodes(self.DG)))
|
||||
|
||||
def test_edges(self):
|
||||
assert edges_equal(self.G.edges(), list(nx.edges(self.G)))
|
||||
assert sorted(self.DG.edges()) == sorted(nx.edges(self.DG))
|
||||
assert edges_equal(
|
||||
self.G.edges(nbunch=[0, 1, 3]), list(nx.edges(self.G, nbunch=[0, 1, 3]))
|
||||
)
|
||||
assert sorted(self.DG.edges(nbunch=[0, 1, 3])) == sorted(
|
||||
nx.edges(self.DG, nbunch=[0, 1, 3])
|
||||
)
|
||||
|
||||
def test_degree(self):
|
||||
assert edges_equal(self.G.degree(), list(nx.degree(self.G)))
|
||||
assert sorted(self.DG.degree()) == sorted(nx.degree(self.DG))
|
||||
assert edges_equal(
|
||||
self.G.degree(nbunch=[0, 1]), list(nx.degree(self.G, nbunch=[0, 1]))
|
||||
)
|
||||
assert sorted(self.DG.degree(nbunch=[0, 1])) == sorted(
|
||||
nx.degree(self.DG, nbunch=[0, 1])
|
||||
)
|
||||
assert edges_equal(
|
||||
self.G.degree(weight="weight"), list(nx.degree(self.G, weight="weight"))
|
||||
)
|
||||
assert sorted(self.DG.degree(weight="weight")) == sorted(
|
||||
nx.degree(self.DG, weight="weight")
|
||||
)
|
||||
|
||||
def test_neighbors(self):
|
||||
assert list(self.G.neighbors(1)) == list(nx.neighbors(self.G, 1))
|
||||
assert list(self.DG.neighbors(1)) == list(nx.neighbors(self.DG, 1))
|
||||
|
||||
def test_number_of_nodes(self):
|
||||
assert self.G.number_of_nodes() == nx.number_of_nodes(self.G)
|
||||
assert self.DG.number_of_nodes() == nx.number_of_nodes(self.DG)
|
||||
|
||||
def test_number_of_edges(self):
|
||||
assert self.G.number_of_edges() == nx.number_of_edges(self.G)
|
||||
assert self.DG.number_of_edges() == nx.number_of_edges(self.DG)
|
||||
|
||||
def test_is_directed(self):
|
||||
assert self.G.is_directed() == nx.is_directed(self.G)
|
||||
assert self.DG.is_directed() == nx.is_directed(self.DG)
|
||||
|
||||
def test_add_star(self):
|
||||
G = self.G.copy()
|
||||
nlist = [12, 13, 14, 15]
|
||||
nx.add_star(G, nlist)
|
||||
assert edges_equal(G.edges(nlist), [(12, 13), (12, 14), (12, 15)])
|
||||
|
||||
G = self.G.copy()
|
||||
nx.add_star(G, nlist, weight=2.0)
|
||||
assert edges_equal(
|
||||
G.edges(nlist, data=True),
|
||||
[
|
||||
(12, 13, {"weight": 2.0}),
|
||||
(12, 14, {"weight": 2.0}),
|
||||
(12, 15, {"weight": 2.0}),
|
||||
],
|
||||
)
|
||||
|
||||
G = self.G.copy()
|
||||
nlist = [12]
|
||||
nx.add_star(G, nlist)
|
||||
assert nodes_equal(G, list(self.G) + nlist)
|
||||
|
||||
G = self.G.copy()
|
||||
nlist = []
|
||||
nx.add_star(G, nlist)
|
||||
assert nodes_equal(G.nodes, self.Gnodes)
|
||||
assert edges_equal(G.edges, self.G.edges)
|
||||
|
||||
def test_add_path(self):
|
||||
G = self.G.copy()
|
||||
nlist = [12, 13, 14, 15]
|
||||
nx.add_path(G, nlist)
|
||||
assert edges_equal(G.edges(nlist), [(12, 13), (13, 14), (14, 15)])
|
||||
G = self.G.copy()
|
||||
nx.add_path(G, nlist, weight=2.0)
|
||||
assert edges_equal(
|
||||
G.edges(nlist, data=True),
|
||||
[
|
||||
(12, 13, {"weight": 2.0}),
|
||||
(13, 14, {"weight": 2.0}),
|
||||
(14, 15, {"weight": 2.0}),
|
||||
],
|
||||
)
|
||||
|
||||
G = self.G.copy()
|
||||
nlist = ["node"]
|
||||
nx.add_path(G, nlist)
|
||||
assert edges_equal(G.edges(nlist), [])
|
||||
assert nodes_equal(G, list(self.G) + ["node"])
|
||||
|
||||
G = self.G.copy()
|
||||
nlist = iter(["node"])
|
||||
nx.add_path(G, nlist)
|
||||
assert edges_equal(G.edges(["node"]), [])
|
||||
assert nodes_equal(G, list(self.G) + ["node"])
|
||||
|
||||
G = self.G.copy()
|
||||
nlist = [12]
|
||||
nx.add_path(G, nlist)
|
||||
assert edges_equal(G.edges(nlist), [])
|
||||
assert nodes_equal(G, list(self.G) + [12])
|
||||
|
||||
G = self.G.copy()
|
||||
nlist = iter([12])
|
||||
nx.add_path(G, nlist)
|
||||
assert edges_equal(G.edges([12]), [])
|
||||
assert nodes_equal(G, list(self.G) + [12])
|
||||
|
||||
G = self.G.copy()
|
||||
nlist = []
|
||||
nx.add_path(G, nlist)
|
||||
assert edges_equal(G.edges, self.G.edges)
|
||||
assert nodes_equal(G, list(self.G))
|
||||
|
||||
G = self.G.copy()
|
||||
nlist = iter([])
|
||||
nx.add_path(G, nlist)
|
||||
assert edges_equal(G.edges, self.G.edges)
|
||||
assert nodes_equal(G, list(self.G))
|
||||
|
||||
def test_add_cycle(self):
|
||||
G = self.G.copy()
|
||||
nlist = [12, 13, 14, 15]
|
||||
oklists = [
|
||||
[(12, 13), (12, 15), (13, 14), (14, 15)],
|
||||
[(12, 13), (13, 14), (14, 15), (15, 12)],
|
||||
]
|
||||
nx.add_cycle(G, nlist)
|
||||
assert sorted(G.edges(nlist)) in oklists
|
||||
G = self.G.copy()
|
||||
oklists = [
|
||||
[
|
||||
(12, 13, {"weight": 1.0}),
|
||||
(12, 15, {"weight": 1.0}),
|
||||
(13, 14, {"weight": 1.0}),
|
||||
(14, 15, {"weight": 1.0}),
|
||||
],
|
||||
[
|
||||
(12, 13, {"weight": 1.0}),
|
||||
(13, 14, {"weight": 1.0}),
|
||||
(14, 15, {"weight": 1.0}),
|
||||
(15, 12, {"weight": 1.0}),
|
||||
],
|
||||
]
|
||||
nx.add_cycle(G, nlist, weight=1.0)
|
||||
assert sorted(G.edges(nlist, data=True)) in oklists
|
||||
|
||||
G = self.G.copy()
|
||||
nlist = [12]
|
||||
nx.add_cycle(G, nlist)
|
||||
assert nodes_equal(G, list(self.G) + nlist)
|
||||
|
||||
G = self.G.copy()
|
||||
nlist = []
|
||||
nx.add_cycle(G, nlist)
|
||||
assert nodes_equal(G.nodes, self.Gnodes)
|
||||
assert edges_equal(G.edges, self.G.edges)
|
||||
|
||||
def test_subgraph(self):
|
||||
assert (
|
||||
self.G.subgraph([0, 1, 2, 4]).adj == nx.subgraph(self.G, [0, 1, 2, 4]).adj
|
||||
)
|
||||
assert (
|
||||
self.DG.subgraph([0, 1, 2, 4]).adj == nx.subgraph(self.DG, [0, 1, 2, 4]).adj
|
||||
)
|
||||
assert (
|
||||
self.G.subgraph([0, 1, 2, 4]).adj
|
||||
== nx.induced_subgraph(self.G, [0, 1, 2, 4]).adj
|
||||
)
|
||||
assert (
|
||||
self.DG.subgraph([0, 1, 2, 4]).adj
|
||||
== nx.induced_subgraph(self.DG, [0, 1, 2, 4]).adj
|
||||
)
|
||||
# subgraph-subgraph chain is allowed in function interface
|
||||
H = nx.induced_subgraph(self.G.subgraph([0, 1, 2, 4]), [0, 1, 4])
|
||||
assert H._graph is not self.G
|
||||
assert H.adj == self.G.subgraph([0, 1, 4]).adj
|
||||
|
||||
def test_edge_subgraph(self):
|
||||
assert (
|
||||
self.G.edge_subgraph([(1, 2), (0, 3)]).adj
|
||||
== nx.edge_subgraph(self.G, [(1, 2), (0, 3)]).adj
|
||||
)
|
||||
assert (
|
||||
self.DG.edge_subgraph([(1, 2), (0, 3)]).adj
|
||||
== nx.edge_subgraph(self.DG, [(1, 2), (0, 3)]).adj
|
||||
)
|
||||
|
||||
def test_create_empty_copy(self):
|
||||
G = nx.create_empty_copy(self.G, with_data=False)
|
||||
assert nodes_equal(G, list(self.G))
|
||||
assert G.graph == {}
|
||||
assert G._node == {}.fromkeys(self.G.nodes(), {})
|
||||
assert G._adj == {}.fromkeys(self.G.nodes(), {})
|
||||
G = nx.create_empty_copy(self.G)
|
||||
assert nodes_equal(G, list(self.G))
|
||||
assert G.graph == self.G.graph
|
||||
assert G._node == self.G._node
|
||||
assert G._adj == {}.fromkeys(self.G.nodes(), {})
|
||||
|
||||
def test_degree_histogram(self):
|
||||
assert nx.degree_histogram(self.G) == [1, 1, 1, 1, 1]
|
||||
|
||||
def test_density(self):
|
||||
assert nx.density(self.G) == 0.5
|
||||
assert nx.density(self.DG) == 0.3
|
||||
G = nx.Graph()
|
||||
G.add_node(1)
|
||||
assert nx.density(G) == 0.0
|
||||
|
||||
def test_density_selfloop(self):
|
||||
G = nx.Graph()
|
||||
G.add_edge(1, 1)
|
||||
assert nx.density(G) == 0.0
|
||||
G.add_edge(1, 2)
|
||||
assert nx.density(G) == 2.0
|
||||
|
||||
def test_freeze(self):
|
||||
G = nx.freeze(self.G)
|
||||
assert G.frozen
|
||||
pytest.raises(nx.NetworkXError, G.add_node, 1)
|
||||
pytest.raises(nx.NetworkXError, G.add_nodes_from, [1])
|
||||
pytest.raises(nx.NetworkXError, G.remove_node, 1)
|
||||
pytest.raises(nx.NetworkXError, G.remove_nodes_from, [1])
|
||||
pytest.raises(nx.NetworkXError, G.add_edge, 1, 2)
|
||||
pytest.raises(nx.NetworkXError, G.add_edges_from, [(1, 2)])
|
||||
pytest.raises(nx.NetworkXError, G.remove_edge, 1, 2)
|
||||
pytest.raises(nx.NetworkXError, G.remove_edges_from, [(1, 2)])
|
||||
pytest.raises(nx.NetworkXError, G.clear_edges)
|
||||
pytest.raises(nx.NetworkXError, G.clear)
|
||||
|
||||
def test_is_frozen(self):
|
||||
assert not nx.is_frozen(self.G)
|
||||
G = nx.freeze(self.G)
|
||||
assert G.frozen == nx.is_frozen(self.G)
|
||||
assert G.frozen
|
||||
|
||||
def test_node_attributes_are_still_mutable_on_frozen_graph(self):
|
||||
G = nx.freeze(nx.path_graph(3))
|
||||
node = G.nodes[0]
|
||||
node["node_attribute"] = True
|
||||
assert node["node_attribute"] == True
|
||||
|
||||
def test_edge_attributes_are_still_mutable_on_frozen_graph(self):
|
||||
G = nx.freeze(nx.path_graph(3))
|
||||
edge = G.edges[(0, 1)]
|
||||
edge["edge_attribute"] = True
|
||||
assert edge["edge_attribute"] == True
|
||||
|
||||
def test_neighbors_complete_graph(self):
|
||||
graph = nx.complete_graph(100)
|
||||
pop = random.sample(list(graph), 1)
|
||||
nbors = list(nx.neighbors(graph, pop[0]))
|
||||
# should be all the other vertices in the graph
|
||||
assert len(nbors) == len(graph) - 1
|
||||
|
||||
graph = nx.path_graph(100)
|
||||
node = random.sample(list(graph), 1)[0]
|
||||
nbors = list(nx.neighbors(graph, node))
|
||||
# should be all the other vertices in the graph
|
||||
if node != 0 and node != 99:
|
||||
assert len(nbors) == 2
|
||||
else:
|
||||
assert len(nbors) == 1
|
||||
|
||||
# create a star graph with 99 outer nodes
|
||||
graph = nx.star_graph(99)
|
||||
nbors = list(nx.neighbors(graph, 0))
|
||||
assert len(nbors) == 99
|
||||
|
||||
def test_non_neighbors(self):
|
||||
graph = nx.complete_graph(100)
|
||||
pop = random.sample(list(graph), 1)
|
||||
nbors = nx.non_neighbors(graph, pop[0])
|
||||
# should be all the other vertices in the graph
|
||||
assert len(nbors) == 0
|
||||
|
||||
graph = nx.path_graph(100)
|
||||
node = random.sample(list(graph), 1)[0]
|
||||
nbors = nx.non_neighbors(graph, node)
|
||||
# should be all the other vertices in the graph
|
||||
if node != 0 and node != 99:
|
||||
assert len(nbors) == 97
|
||||
else:
|
||||
assert len(nbors) == 98
|
||||
|
||||
# create a star graph with 99 outer nodes
|
||||
graph = nx.star_graph(99)
|
||||
nbors = nx.non_neighbors(graph, 0)
|
||||
assert len(nbors) == 0
|
||||
|
||||
# disconnected graph
|
||||
graph = nx.Graph()
|
||||
graph.add_nodes_from(range(10))
|
||||
nbors = nx.non_neighbors(graph, 0)
|
||||
assert len(nbors) == 9
|
||||
|
||||
def test_non_edges(self):
|
||||
# All possible edges exist
|
||||
graph = nx.complete_graph(5)
|
||||
nedges = list(nx.non_edges(graph))
|
||||
assert len(nedges) == 0
|
||||
|
||||
graph = nx.path_graph(4)
|
||||
expected = [(0, 2), (0, 3), (1, 3)]
|
||||
nedges = list(nx.non_edges(graph))
|
||||
for u, v in expected:
|
||||
assert (u, v) in nedges or (v, u) in nedges
|
||||
|
||||
graph = nx.star_graph(4)
|
||||
expected = [(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
|
||||
nedges = list(nx.non_edges(graph))
|
||||
for u, v in expected:
|
||||
assert (u, v) in nedges or (v, u) in nedges
|
||||
|
||||
# Directed graphs
|
||||
graph = nx.DiGraph()
|
||||
graph.add_edges_from([(0, 2), (2, 0), (2, 1)])
|
||||
expected = [(0, 1), (1, 0), (1, 2)]
|
||||
nedges = list(nx.non_edges(graph))
|
||||
for e in expected:
|
||||
assert e in nedges
|
||||
|
||||
def test_is_weighted(self):
|
||||
G = nx.Graph()
|
||||
assert not nx.is_weighted(G)
|
||||
|
||||
G = nx.path_graph(4)
|
||||
assert not nx.is_weighted(G)
|
||||
assert not nx.is_weighted(G, (2, 3))
|
||||
|
||||
G.add_node(4)
|
||||
G.add_edge(3, 4, weight=4)
|
||||
assert not nx.is_weighted(G)
|
||||
assert nx.is_weighted(G, (3, 4))
|
||||
|
||||
G = nx.DiGraph()
|
||||
G.add_weighted_edges_from(
|
||||
[
|
||||
("0", "3", 3),
|
||||
("0", "1", -5),
|
||||
("1", "0", -5),
|
||||
("0", "2", 2),
|
||||
("1", "2", 4),
|
||||
("2", "3", 1),
|
||||
]
|
||||
)
|
||||
assert nx.is_weighted(G)
|
||||
assert nx.is_weighted(G, ("1", "0"))
|
||||
|
||||
G = G.to_undirected()
|
||||
assert nx.is_weighted(G)
|
||||
assert nx.is_weighted(G, ("1", "0"))
|
||||
|
||||
pytest.raises(nx.NetworkXError, nx.is_weighted, G, (1, 2))
|
||||
|
||||
def test_is_negatively_weighted(self):
|
||||
G = nx.Graph()
|
||||
assert not nx.is_negatively_weighted(G)
|
||||
|
||||
G.add_node(1)
|
||||
G.add_nodes_from([2, 3, 4, 5])
|
||||
assert not nx.is_negatively_weighted(G)
|
||||
|
||||
G.add_edge(1, 2, weight=4)
|
||||
assert not nx.is_negatively_weighted(G, (1, 2))
|
||||
|
||||
G.add_edges_from([(1, 3), (2, 4), (2, 6)])
|
||||
G[1][3]["color"] = "blue"
|
||||
assert not nx.is_negatively_weighted(G)
|
||||
assert not nx.is_negatively_weighted(G, (1, 3))
|
||||
|
||||
G[2][4]["weight"] = -2
|
||||
assert nx.is_negatively_weighted(G, (2, 4))
|
||||
assert nx.is_negatively_weighted(G)
|
||||
|
||||
G = nx.DiGraph()
|
||||
G.add_weighted_edges_from(
|
||||
[
|
||||
("0", "3", 3),
|
||||
("0", "1", -5),
|
||||
("1", "0", -2),
|
||||
("0", "2", 2),
|
||||
("1", "2", -3),
|
||||
("2", "3", 1),
|
||||
]
|
||||
)
|
||||
assert nx.is_negatively_weighted(G)
|
||||
assert not nx.is_negatively_weighted(G, ("0", "3"))
|
||||
assert nx.is_negatively_weighted(G, ("1", "0"))
|
||||
|
||||
pytest.raises(nx.NetworkXError, nx.is_negatively_weighted, G, (1, 4))
|
||||
|
||||
|
||||
class TestCommonNeighbors:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.func = staticmethod(nx.common_neighbors)
|
||||
|
||||
def test_func(G, u, v, expected):
|
||||
result = sorted(cls.func(G, u, v))
|
||||
assert result == expected
|
||||
|
||||
cls.test = staticmethod(test_func)
|
||||
|
||||
def test_K5(self):
|
||||
G = nx.complete_graph(5)
|
||||
self.test(G, 0, 1, [2, 3, 4])
|
||||
|
||||
def test_P3(self):
|
||||
G = nx.path_graph(3)
|
||||
self.test(G, 0, 2, [1])
|
||||
|
||||
def test_S4(self):
|
||||
G = nx.star_graph(4)
|
||||
self.test(G, 1, 2, [0])
|
||||
|
||||
def test_digraph(self):
|
||||
with pytest.raises(nx.NetworkXNotImplemented):
|
||||
G = nx.DiGraph()
|
||||
G.add_edges_from([(0, 1), (1, 2)])
|
||||
self.func(G, 0, 2)
|
||||
|
||||
def test_nonexistent_nodes(self):
|
||||
G = nx.complete_graph(5)
|
||||
pytest.raises(nx.NetworkXError, nx.common_neighbors, G, 5, 4)
|
||||
pytest.raises(nx.NetworkXError, nx.common_neighbors, G, 4, 5)
|
||||
pytest.raises(nx.NetworkXError, nx.common_neighbors, G, 5, 6)
|
||||
|
||||
def test_custom1(self):
|
||||
"""Case of no common neighbors."""
|
||||
G = nx.Graph()
|
||||
G.add_nodes_from([0, 1])
|
||||
self.test(G, 0, 1, [])
|
||||
|
||||
def test_custom2(self):
|
||||
"""Case of equal nodes."""
|
||||
G = nx.complete_graph(4)
|
||||
self.test(G, 0, 0, [1, 2, 3])
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"graph_type", (nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph)
|
||||
)
|
||||
def test_set_node_attributes(graph_type):
|
||||
# Test single value
|
||||
G = nx.path_graph(3, create_using=graph_type)
|
||||
vals = 100
|
||||
attr = "hello"
|
||||
nx.set_node_attributes(G, vals, attr)
|
||||
assert G.nodes[0][attr] == vals
|
||||
assert G.nodes[1][attr] == vals
|
||||
assert G.nodes[2][attr] == vals
|
||||
|
||||
# Test dictionary
|
||||
G = nx.path_graph(3, create_using=graph_type)
|
||||
vals = dict(zip(sorted(G.nodes()), range(len(G))))
|
||||
attr = "hi"
|
||||
nx.set_node_attributes(G, vals, attr)
|
||||
assert G.nodes[0][attr] == 0
|
||||
assert G.nodes[1][attr] == 1
|
||||
assert G.nodes[2][attr] == 2
|
||||
|
||||
# Test dictionary of dictionaries
|
||||
G = nx.path_graph(3, create_using=graph_type)
|
||||
d = {"hi": 0, "hello": 200}
|
||||
vals = dict.fromkeys(G.nodes(), d)
|
||||
vals.pop(0)
|
||||
nx.set_node_attributes(G, vals)
|
||||
assert G.nodes[0] == {}
|
||||
assert G.nodes[1]["hi"] == 0
|
||||
assert G.nodes[2]["hello"] == 200
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("values", "name"),
|
||||
(
|
||||
({0: "red", 1: "blue"}, "color"), # values dictionary
|
||||
({0: {"color": "red"}, 1: {"color": "blue"}}, None), # dict-of-dict
|
||||
),
|
||||
)
|
||||
def test_set_node_attributes_ignores_extra_nodes(values, name):
|
||||
"""
|
||||
When `values` is a dict or dict-of-dict keyed by nodes, ensure that keys
|
||||
that correspond to nodes not in G are ignored.
|
||||
"""
|
||||
G = nx.Graph()
|
||||
G.add_node(0)
|
||||
nx.set_node_attributes(G, values, name)
|
||||
assert G.nodes[0]["color"] == "red"
|
||||
assert 1 not in G.nodes
|
||||
|
||||
|
||||
@pytest.mark.parametrize("graph_type", (nx.Graph, nx.DiGraph))
|
||||
def test_set_edge_attributes(graph_type):
|
||||
# Test single value
|
||||
G = nx.path_graph(3, create_using=graph_type)
|
||||
attr = "hello"
|
||||
vals = 3
|
||||
nx.set_edge_attributes(G, vals, attr)
|
||||
assert G[0][1][attr] == vals
|
||||
assert G[1][2][attr] == vals
|
||||
|
||||
# Test multiple values
|
||||
G = nx.path_graph(3, create_using=graph_type)
|
||||
attr = "hi"
|
||||
edges = [(0, 1), (1, 2)]
|
||||
vals = dict(zip(edges, range(len(edges))))
|
||||
nx.set_edge_attributes(G, vals, attr)
|
||||
assert G[0][1][attr] == 0
|
||||
assert G[1][2][attr] == 1
|
||||
|
||||
# Test dictionary of dictionaries
|
||||
G = nx.path_graph(3, create_using=graph_type)
|
||||
d = {"hi": 0, "hello": 200}
|
||||
edges = [(0, 1)]
|
||||
vals = dict.fromkeys(edges, d)
|
||||
nx.set_edge_attributes(G, vals)
|
||||
assert G[0][1]["hi"] == 0
|
||||
assert G[0][1]["hello"] == 200
|
||||
assert G[1][2] == {}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("values", "name"),
|
||||
(
|
||||
({(0, 1): 1.0, (0, 2): 2.0}, "weight"), # values dict
|
||||
({(0, 1): {"weight": 1.0}, (0, 2): {"weight": 2.0}}, None), # values dod
|
||||
),
|
||||
)
|
||||
def test_set_edge_attributes_ignores_extra_edges(values, name):
|
||||
"""If `values` is a dict or dict-of-dicts containing edges that are not in
|
||||
G, data associate with these edges should be ignored.
|
||||
"""
|
||||
G = nx.Graph([(0, 1)])
|
||||
nx.set_edge_attributes(G, values, name)
|
||||
assert G[0][1]["weight"] == 1.0
|
||||
assert (0, 2) not in G.edges
|
||||
|
||||
|
||||
@pytest.mark.parametrize("graph_type", (nx.MultiGraph, nx.MultiDiGraph))
|
||||
def test_set_edge_attributes_multi(graph_type):
|
||||
# Test single value
|
||||
G = nx.path_graph(3, create_using=graph_type)
|
||||
attr = "hello"
|
||||
vals = 3
|
||||
nx.set_edge_attributes(G, vals, attr)
|
||||
assert G[0][1][0][attr] == vals
|
||||
assert G[1][2][0][attr] == vals
|
||||
|
||||
# Test multiple values
|
||||
G = nx.path_graph(3, create_using=graph_type)
|
||||
attr = "hi"
|
||||
edges = [(0, 1, 0), (1, 2, 0)]
|
||||
vals = dict(zip(edges, range(len(edges))))
|
||||
nx.set_edge_attributes(G, vals, attr)
|
||||
assert G[0][1][0][attr] == 0
|
||||
assert G[1][2][0][attr] == 1
|
||||
|
||||
# Test dictionary of dictionaries
|
||||
G = nx.path_graph(3, create_using=graph_type)
|
||||
d = {"hi": 0, "hello": 200}
|
||||
edges = [(0, 1, 0)]
|
||||
vals = dict.fromkeys(edges, d)
|
||||
nx.set_edge_attributes(G, vals)
|
||||
assert G[0][1][0]["hi"] == 0
|
||||
assert G[0][1][0]["hello"] == 200
|
||||
assert G[1][2][0] == {}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("values", "name"),
|
||||
(
|
||||
({(0, 1, 0): 1.0, (0, 2, 0): 2.0}, "weight"), # values dict
|
||||
({(0, 1, 0): {"weight": 1.0}, (0, 2, 0): {"weight": 2.0}}, None), # values dod
|
||||
),
|
||||
)
|
||||
def test_set_edge_attributes_multi_ignores_extra_edges(values, name):
|
||||
"""If `values` is a dict or dict-of-dicts containing edges that are not in
|
||||
G, data associate with these edges should be ignored.
|
||||
"""
|
||||
G = nx.MultiGraph([(0, 1, 0), (0, 1, 1)])
|
||||
nx.set_edge_attributes(G, values, name)
|
||||
assert G[0][1][0]["weight"] == 1.0
|
||||
assert G[0][1][1] == {}
|
||||
assert (0, 2) not in G.edges()
|
||||
|
||||
|
||||
def test_get_node_attributes():
|
||||
graphs = [nx.Graph(), nx.DiGraph(), nx.MultiGraph(), nx.MultiDiGraph()]
|
||||
for G in graphs:
|
||||
G = nx.path_graph(3, create_using=G)
|
||||
attr = "hello"
|
||||
vals = 100
|
||||
nx.set_node_attributes(G, vals, attr)
|
||||
attrs = nx.get_node_attributes(G, attr)
|
||||
assert attrs[0] == vals
|
||||
assert attrs[1] == vals
|
||||
assert attrs[2] == vals
|
||||
default_val = 1
|
||||
G.add_node(4)
|
||||
attrs = nx.get_node_attributes(G, attr, default=default_val)
|
||||
assert attrs[4] == default_val
|
||||
|
||||
|
||||
def test_get_edge_attributes():
|
||||
graphs = [nx.Graph(), nx.DiGraph(), nx.MultiGraph(), nx.MultiDiGraph()]
|
||||
for G in graphs:
|
||||
G = nx.path_graph(3, create_using=G)
|
||||
attr = "hello"
|
||||
vals = 100
|
||||
nx.set_edge_attributes(G, vals, attr)
|
||||
attrs = nx.get_edge_attributes(G, attr)
|
||||
assert len(attrs) == 2
|
||||
|
||||
for edge in G.edges:
|
||||
assert attrs[edge] == vals
|
||||
|
||||
default_val = vals
|
||||
G.add_edge(4, 5)
|
||||
deafult_attrs = nx.get_edge_attributes(G, attr, default=default_val)
|
||||
assert len(deafult_attrs) == 3
|
||||
|
||||
for edge in G.edges:
|
||||
assert deafult_attrs[edge] == vals
|
||||
|
||||
|
||||
def test_is_empty():
|
||||
graphs = [nx.Graph(), nx.DiGraph(), nx.MultiGraph(), nx.MultiDiGraph()]
|
||||
for G in graphs:
|
||||
assert nx.is_empty(G)
|
||||
G.add_nodes_from(range(5))
|
||||
assert nx.is_empty(G)
|
||||
G.add_edges_from([(1, 2), (3, 4)])
|
||||
assert not nx.is_empty(G)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"graph_type", [nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph]
|
||||
)
|
||||
def test_selfloops(graph_type):
|
||||
G = nx.complete_graph(3, create_using=graph_type)
|
||||
G.add_edge(0, 0)
|
||||
assert nodes_equal(nx.nodes_with_selfloops(G), [0])
|
||||
assert edges_equal(nx.selfloop_edges(G), [(0, 0)])
|
||||
assert edges_equal(nx.selfloop_edges(G, data=True), [(0, 0, {})])
|
||||
assert nx.number_of_selfloops(G) == 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"graph_type", [nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph]
|
||||
)
|
||||
def test_selfloop_edges_attr(graph_type):
|
||||
G = nx.complete_graph(3, create_using=graph_type)
|
||||
G.add_edge(0, 0)
|
||||
G.add_edge(1, 1, weight=2)
|
||||
assert edges_equal(
|
||||
nx.selfloop_edges(G, data=True), [(0, 0, {}), (1, 1, {"weight": 2})]
|
||||
)
|
||||
assert edges_equal(nx.selfloop_edges(G, data="weight"), [(0, 0, None), (1, 1, 2)])
|
||||
|
||||
|
||||
def test_selfloop_edges_multi_with_data_and_keys():
|
||||
G = nx.complete_graph(3, create_using=nx.MultiGraph)
|
||||
G.add_edge(0, 0, weight=10)
|
||||
G.add_edge(0, 0, weight=100)
|
||||
assert edges_equal(
|
||||
nx.selfloop_edges(G, data="weight", keys=True), [(0, 0, 0, 10), (0, 0, 1, 100)]
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("graph_type", [nx.Graph, nx.DiGraph])
|
||||
def test_selfloops_removal(graph_type):
|
||||
G = nx.complete_graph(3, create_using=graph_type)
|
||||
G.add_edge(0, 0)
|
||||
G.remove_edges_from(nx.selfloop_edges(G, keys=True))
|
||||
G.add_edge(0, 0)
|
||||
G.remove_edges_from(nx.selfloop_edges(G, data=True))
|
||||
G.add_edge(0, 0)
|
||||
G.remove_edges_from(nx.selfloop_edges(G, keys=True, data=True))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("graph_type", [nx.MultiGraph, nx.MultiDiGraph])
|
||||
def test_selfloops_removal_multi(graph_type):
|
||||
"""test removing selfloops behavior vis-a-vis altering a dict while iterating.
|
||||
cf. gh-4068"""
|
||||
G = nx.complete_graph(3, create_using=graph_type)
|
||||
# Defaults - see gh-4080
|
||||
G.add_edge(0, 0)
|
||||
G.add_edge(0, 0)
|
||||
G.remove_edges_from(nx.selfloop_edges(G))
|
||||
assert (0, 0) not in G.edges()
|
||||
# With keys
|
||||
G.add_edge(0, 0)
|
||||
G.add_edge(0, 0)
|
||||
with pytest.raises(RuntimeError):
|
||||
G.remove_edges_from(nx.selfloop_edges(G, keys=True))
|
||||
# With data
|
||||
G.add_edge(0, 0)
|
||||
G.add_edge(0, 0)
|
||||
with pytest.raises(TypeError):
|
||||
G.remove_edges_from(nx.selfloop_edges(G, data=True))
|
||||
# With keys and data
|
||||
G.add_edge(0, 0)
|
||||
G.add_edge(0, 0)
|
||||
with pytest.raises(RuntimeError):
|
||||
G.remove_edges_from(nx.selfloop_edges(G, data=True, keys=True))
|
||||
|
||||
|
||||
def test_pathweight():
|
||||
valid_path = [1, 2, 3]
|
||||
invalid_path = [1, 3, 2]
|
||||
graphs = [nx.Graph(), nx.DiGraph(), nx.MultiGraph(), nx.MultiDiGraph()]
|
||||
edges = [
|
||||
(1, 2, {"cost": 5, "dist": 6}),
|
||||
(2, 3, {"cost": 3, "dist": 4}),
|
||||
(1, 2, {"cost": 1, "dist": 2}),
|
||||
]
|
||||
for graph in graphs:
|
||||
graph.add_edges_from(edges)
|
||||
assert nx.path_weight(graph, valid_path, "cost") == 4
|
||||
assert nx.path_weight(graph, valid_path, "dist") == 6
|
||||
pytest.raises(nx.NetworkXNoPath, nx.path_weight, graph, invalid_path, "cost")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"G", (nx.Graph(), nx.DiGraph(), nx.MultiGraph(), nx.MultiDiGraph())
|
||||
)
|
||||
def test_ispath(G):
|
||||
G.add_edges_from([(1, 2), (2, 3), (1, 2), (3, 4)])
|
||||
valid_path = [1, 2, 3, 4]
|
||||
invalid_path = [1, 2, 4, 3] # wrong node order
|
||||
another_invalid_path = [1, 2, 3, 4, 5] # contains node not in G
|
||||
assert nx.is_path(G, valid_path)
|
||||
assert not nx.is_path(G, invalid_path)
|
||||
assert not nx.is_path(G, another_invalid_path)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("G", (nx.Graph(), nx.DiGraph()))
|
||||
def test_restricted_view(G):
|
||||
G.add_edges_from([(0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2)])
|
||||
G.add_node(4)
|
||||
H = nx.restricted_view(G, [0, 2, 5], [(1, 2), (3, 4)])
|
||||
assert set(H.nodes()) == {1, 3, 4}
|
||||
assert set(H.edges()) == {(1, 1)}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("G", (nx.MultiGraph(), nx.MultiDiGraph()))
|
||||
def test_restricted_view_multi(G):
|
||||
G.add_edges_from(
|
||||
[(0, 1, 0), (0, 2, 0), (0, 3, 0), (0, 1, 1), (1, 0, 0), (1, 1, 0), (1, 2, 0)]
|
||||
)
|
||||
G.add_node(4)
|
||||
H = nx.restricted_view(G, [0, 2, 5], [(1, 2, 0), (3, 4, 0)])
|
||||
assert set(H.nodes()) == {1, 3, 4}
|
||||
assert set(H.edges()) == {(1, 1)}
|
||||
920
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_graph.py
vendored
Normal file
920
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_graph.py
vendored
Normal file
@@ -0,0 +1,920 @@
|
||||
import gc
|
||||
import pickle
|
||||
import platform
|
||||
import weakref
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.utils import edges_equal, graphs_equal, nodes_equal
|
||||
|
||||
|
||||
class BaseGraphTester:
|
||||
"""Tests for data-structure independent graph class features."""
|
||||
|
||||
def test_contains(self):
|
||||
G = self.K3
|
||||
assert 1 in G
|
||||
assert 4 not in G
|
||||
assert "b" not in G
|
||||
assert [] not in G # no exception for nonhashable
|
||||
assert {1: 1} not in G # no exception for nonhashable
|
||||
|
||||
def test_order(self):
|
||||
G = self.K3
|
||||
assert len(G) == 3
|
||||
assert G.order() == 3
|
||||
assert G.number_of_nodes() == 3
|
||||
|
||||
def test_nodes(self):
|
||||
G = self.K3
|
||||
assert isinstance(G._node, G.node_dict_factory)
|
||||
assert isinstance(G._adj, G.adjlist_outer_dict_factory)
|
||||
assert all(
|
||||
isinstance(adj, G.adjlist_inner_dict_factory) for adj in G._adj.values()
|
||||
)
|
||||
assert sorted(G.nodes()) == self.k3nodes
|
||||
assert sorted(G.nodes(data=True)) == [(0, {}), (1, {}), (2, {})]
|
||||
|
||||
def test_none_node(self):
|
||||
G = self.Graph()
|
||||
with pytest.raises(ValueError):
|
||||
G.add_node(None)
|
||||
with pytest.raises(ValueError):
|
||||
G.add_nodes_from([None])
|
||||
with pytest.raises(ValueError):
|
||||
G.add_edge(0, None)
|
||||
with pytest.raises(ValueError):
|
||||
G.add_edges_from([(0, None)])
|
||||
|
||||
def test_has_node(self):
|
||||
G = self.K3
|
||||
assert G.has_node(1)
|
||||
assert not G.has_node(4)
|
||||
assert not G.has_node([]) # no exception for nonhashable
|
||||
assert not G.has_node({1: 1}) # no exception for nonhashable
|
||||
|
||||
def test_has_edge(self):
|
||||
G = self.K3
|
||||
assert G.has_edge(0, 1)
|
||||
assert not G.has_edge(0, -1)
|
||||
|
||||
def test_neighbors(self):
|
||||
G = self.K3
|
||||
assert sorted(G.neighbors(0)) == [1, 2]
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
G.neighbors(-1)
|
||||
|
||||
@pytest.mark.skipif(
|
||||
platform.python_implementation() == "PyPy", reason="PyPy gc is different"
|
||||
)
|
||||
def test_memory_leak(self):
|
||||
G = self.Graph()
|
||||
|
||||
def count_objects_of_type(_type):
|
||||
# Iterating over all objects tracked by gc can include weak references
|
||||
# whose weakly-referenced objects may no longer exist. Calling `isinstance`
|
||||
# on such a weak reference will raise ReferenceError. There are at least
|
||||
# three workarounds for this: one is to compare type names instead of using
|
||||
# `isinstance` such as `type(obj).__name__ == typename`, another is to use
|
||||
# `type(obj) == _type`, and the last is to ignore ProxyTypes as we do below.
|
||||
# NOTE: even if this safeguard is deemed unnecessary to pass NetworkX tests,
|
||||
# we should still keep it for maximum safety for other NetworkX backends.
|
||||
return sum(
|
||||
1
|
||||
for obj in gc.get_objects()
|
||||
if not isinstance(obj, weakref.ProxyTypes) and isinstance(obj, _type)
|
||||
)
|
||||
|
||||
gc.collect()
|
||||
before = count_objects_of_type(self.Graph)
|
||||
G.copy()
|
||||
gc.collect()
|
||||
after = count_objects_of_type(self.Graph)
|
||||
assert before == after
|
||||
|
||||
# test a subgraph of the base class
|
||||
class MyGraph(self.Graph):
|
||||
pass
|
||||
|
||||
gc.collect()
|
||||
G = MyGraph()
|
||||
before = count_objects_of_type(MyGraph)
|
||||
G.copy()
|
||||
gc.collect()
|
||||
after = count_objects_of_type(MyGraph)
|
||||
assert before == after
|
||||
|
||||
def test_edges(self):
|
||||
G = self.K3
|
||||
assert isinstance(G._adj, G.adjlist_outer_dict_factory)
|
||||
assert edges_equal(G.edges(), [(0, 1), (0, 2), (1, 2)])
|
||||
assert edges_equal(G.edges(0), [(0, 1), (0, 2)])
|
||||
assert edges_equal(G.edges([0, 1]), [(0, 1), (0, 2), (1, 2)])
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
G.edges(-1)
|
||||
|
||||
def test_degree(self):
|
||||
G = self.K3
|
||||
assert sorted(G.degree()) == [(0, 2), (1, 2), (2, 2)]
|
||||
assert dict(G.degree()) == {0: 2, 1: 2, 2: 2}
|
||||
assert G.degree(0) == 2
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
G.degree(-1) # node not in graph
|
||||
|
||||
def test_size(self):
|
||||
G = self.K3
|
||||
assert G.size() == 3
|
||||
assert G.number_of_edges() == 3
|
||||
|
||||
def test_nbunch_iter(self):
|
||||
G = self.K3
|
||||
assert nodes_equal(G.nbunch_iter(), self.k3nodes) # all nodes
|
||||
assert nodes_equal(G.nbunch_iter(0), [0]) # single node
|
||||
assert nodes_equal(G.nbunch_iter([0, 1]), [0, 1]) # sequence
|
||||
# sequence with none in graph
|
||||
assert nodes_equal(G.nbunch_iter([-1]), [])
|
||||
# string sequence with none in graph
|
||||
assert nodes_equal(G.nbunch_iter("foo"), [])
|
||||
# node not in graph doesn't get caught upon creation of iterator
|
||||
bunch = G.nbunch_iter(-1)
|
||||
# but gets caught when iterator used
|
||||
with pytest.raises(nx.NetworkXError, match="is not a node or a sequence"):
|
||||
list(bunch)
|
||||
# unhashable doesn't get caught upon creation of iterator
|
||||
bunch = G.nbunch_iter([0, 1, 2, {}])
|
||||
# but gets caught when iterator hits the unhashable
|
||||
with pytest.raises(
|
||||
nx.NetworkXError, match="in sequence nbunch is not a valid node"
|
||||
):
|
||||
list(bunch)
|
||||
|
||||
def test_nbunch_iter_node_format_raise(self):
|
||||
# Tests that a node that would have failed string formatting
|
||||
# doesn't cause an error when attempting to raise a
|
||||
# :exc:`nx.NetworkXError`.
|
||||
|
||||
# For more information, see pull request #1813.
|
||||
G = self.Graph()
|
||||
nbunch = [("x", set())]
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
list(G.nbunch_iter(nbunch))
|
||||
|
||||
def test_selfloop_degree(self):
|
||||
G = self.Graph()
|
||||
G.add_edge(1, 1)
|
||||
assert sorted(G.degree()) == [(1, 2)]
|
||||
assert dict(G.degree()) == {1: 2}
|
||||
assert G.degree(1) == 2
|
||||
assert sorted(G.degree([1])) == [(1, 2)]
|
||||
assert G.degree(1, weight="weight") == 2
|
||||
|
||||
def test_selfloops(self):
|
||||
G = self.K3.copy()
|
||||
G.add_edge(0, 0)
|
||||
assert nodes_equal(nx.nodes_with_selfloops(G), [0])
|
||||
assert edges_equal(nx.selfloop_edges(G), [(0, 0)])
|
||||
assert nx.number_of_selfloops(G) == 1
|
||||
G.remove_edge(0, 0)
|
||||
G.add_edge(0, 0)
|
||||
G.remove_edges_from([(0, 0)])
|
||||
G.add_edge(1, 1)
|
||||
G.remove_node(1)
|
||||
G.add_edge(0, 0)
|
||||
G.add_edge(1, 1)
|
||||
G.remove_nodes_from([0, 1])
|
||||
|
||||
def test_cache_reset(self):
|
||||
G = self.K3.copy()
|
||||
old_adj = G.adj
|
||||
assert id(G.adj) == id(old_adj)
|
||||
G._adj = {}
|
||||
assert id(G.adj) != id(old_adj)
|
||||
|
||||
old_nodes = G.nodes
|
||||
assert id(G.nodes) == id(old_nodes)
|
||||
G._node = {}
|
||||
assert id(G.nodes) != id(old_nodes)
|
||||
|
||||
def test_attributes_cached(self):
|
||||
G = self.K3.copy()
|
||||
assert id(G.nodes) == id(G.nodes)
|
||||
assert id(G.edges) == id(G.edges)
|
||||
assert id(G.degree) == id(G.degree)
|
||||
assert id(G.adj) == id(G.adj)
|
||||
|
||||
|
||||
class BaseAttrGraphTester(BaseGraphTester):
|
||||
"""Tests of graph class attribute features."""
|
||||
|
||||
def test_weighted_degree(self):
|
||||
G = self.Graph()
|
||||
G.add_edge(1, 2, weight=2, other=3)
|
||||
G.add_edge(2, 3, weight=3, other=4)
|
||||
assert sorted(d for n, d in G.degree(weight="weight")) == [2, 3, 5]
|
||||
assert dict(G.degree(weight="weight")) == {1: 2, 2: 5, 3: 3}
|
||||
assert G.degree(1, weight="weight") == 2
|
||||
assert nodes_equal((G.degree([1], weight="weight")), [(1, 2)])
|
||||
|
||||
assert nodes_equal((d for n, d in G.degree(weight="other")), [3, 7, 4])
|
||||
assert dict(G.degree(weight="other")) == {1: 3, 2: 7, 3: 4}
|
||||
assert G.degree(1, weight="other") == 3
|
||||
assert edges_equal((G.degree([1], weight="other")), [(1, 3)])
|
||||
|
||||
def add_attributes(self, G):
|
||||
G.graph["foo"] = []
|
||||
G.nodes[0]["foo"] = []
|
||||
G.remove_edge(1, 2)
|
||||
ll = []
|
||||
G.add_edge(1, 2, foo=ll)
|
||||
G.add_edge(2, 1, foo=ll)
|
||||
|
||||
def test_name(self):
|
||||
G = self.Graph(name="")
|
||||
assert G.name == ""
|
||||
G = self.Graph(name="test")
|
||||
assert G.name == "test"
|
||||
|
||||
def test_str_unnamed(self):
|
||||
G = self.Graph()
|
||||
G.add_edges_from([(1, 2), (2, 3)])
|
||||
assert str(G) == f"{type(G).__name__} with 3 nodes and 2 edges"
|
||||
|
||||
def test_str_named(self):
|
||||
G = self.Graph(name="foo")
|
||||
G.add_edges_from([(1, 2), (2, 3)])
|
||||
assert str(G) == f"{type(G).__name__} named 'foo' with 3 nodes and 2 edges"
|
||||
|
||||
def test_graph_chain(self):
|
||||
G = self.Graph([(0, 1), (1, 2)])
|
||||
DG = G.to_directed(as_view=True)
|
||||
SDG = DG.subgraph([0, 1])
|
||||
RSDG = SDG.reverse(copy=False)
|
||||
assert G is DG._graph
|
||||
assert DG is SDG._graph
|
||||
assert SDG is RSDG._graph
|
||||
|
||||
def test_copy(self):
|
||||
G = self.Graph()
|
||||
G.add_node(0)
|
||||
G.add_edge(1, 2)
|
||||
self.add_attributes(G)
|
||||
# copy edge datadict but any container attr are same
|
||||
H = G.copy()
|
||||
self.graphs_equal(H, G)
|
||||
self.different_attrdict(H, G)
|
||||
self.shallow_copy_attrdict(H, G)
|
||||
|
||||
def test_class_copy(self):
|
||||
G = self.Graph()
|
||||
G.add_node(0)
|
||||
G.add_edge(1, 2)
|
||||
self.add_attributes(G)
|
||||
# copy edge datadict but any container attr are same
|
||||
H = G.__class__(G)
|
||||
self.graphs_equal(H, G)
|
||||
self.different_attrdict(H, G)
|
||||
self.shallow_copy_attrdict(H, G)
|
||||
|
||||
def test_fresh_copy(self):
|
||||
G = self.Graph()
|
||||
G.add_node(0)
|
||||
G.add_edge(1, 2)
|
||||
self.add_attributes(G)
|
||||
# copy graph structure but use fresh datadict
|
||||
H = G.__class__()
|
||||
H.add_nodes_from(G)
|
||||
H.add_edges_from(G.edges())
|
||||
assert len(G.nodes[0]) == 1
|
||||
ddict = G.adj[1][2][0] if G.is_multigraph() else G.adj[1][2]
|
||||
assert len(ddict) == 1
|
||||
assert len(H.nodes[0]) == 0
|
||||
ddict = H.adj[1][2][0] if H.is_multigraph() else H.adj[1][2]
|
||||
assert len(ddict) == 0
|
||||
|
||||
def is_deepcopy(self, H, G):
|
||||
self.graphs_equal(H, G)
|
||||
self.different_attrdict(H, G)
|
||||
self.deep_copy_attrdict(H, G)
|
||||
|
||||
def deep_copy_attrdict(self, H, G):
|
||||
self.deepcopy_graph_attr(H, G)
|
||||
self.deepcopy_node_attr(H, G)
|
||||
self.deepcopy_edge_attr(H, G)
|
||||
|
||||
def deepcopy_graph_attr(self, H, G):
|
||||
assert G.graph["foo"] == H.graph["foo"]
|
||||
G.graph["foo"].append(1)
|
||||
assert G.graph["foo"] != H.graph["foo"]
|
||||
|
||||
def deepcopy_node_attr(self, H, G):
|
||||
assert G.nodes[0]["foo"] == H.nodes[0]["foo"]
|
||||
G.nodes[0]["foo"].append(1)
|
||||
assert G.nodes[0]["foo"] != H.nodes[0]["foo"]
|
||||
|
||||
def deepcopy_edge_attr(self, H, G):
|
||||
assert G[1][2]["foo"] == H[1][2]["foo"]
|
||||
G[1][2]["foo"].append(1)
|
||||
assert G[1][2]["foo"] != H[1][2]["foo"]
|
||||
|
||||
def is_shallow_copy(self, H, G):
|
||||
self.graphs_equal(H, G)
|
||||
self.shallow_copy_attrdict(H, G)
|
||||
|
||||
def shallow_copy_attrdict(self, H, G):
|
||||
self.shallow_copy_graph_attr(H, G)
|
||||
self.shallow_copy_node_attr(H, G)
|
||||
self.shallow_copy_edge_attr(H, G)
|
||||
|
||||
def shallow_copy_graph_attr(self, H, G):
|
||||
assert G.graph["foo"] == H.graph["foo"]
|
||||
G.graph["foo"].append(1)
|
||||
assert G.graph["foo"] == H.graph["foo"]
|
||||
|
||||
def shallow_copy_node_attr(self, H, G):
|
||||
assert G.nodes[0]["foo"] == H.nodes[0]["foo"]
|
||||
G.nodes[0]["foo"].append(1)
|
||||
assert G.nodes[0]["foo"] == H.nodes[0]["foo"]
|
||||
|
||||
def shallow_copy_edge_attr(self, H, G):
|
||||
assert G[1][2]["foo"] == H[1][2]["foo"]
|
||||
G[1][2]["foo"].append(1)
|
||||
assert G[1][2]["foo"] == H[1][2]["foo"]
|
||||
|
||||
def same_attrdict(self, H, G):
|
||||
old_foo = H[1][2]["foo"]
|
||||
H.adj[1][2]["foo"] = "baz"
|
||||
assert G.edges == H.edges
|
||||
H.adj[1][2]["foo"] = old_foo
|
||||
assert G.edges == H.edges
|
||||
|
||||
old_foo = H.nodes[0]["foo"]
|
||||
H.nodes[0]["foo"] = "baz"
|
||||
assert G.nodes == H.nodes
|
||||
H.nodes[0]["foo"] = old_foo
|
||||
assert G.nodes == H.nodes
|
||||
|
||||
def different_attrdict(self, H, G):
|
||||
old_foo = H[1][2]["foo"]
|
||||
H.adj[1][2]["foo"] = "baz"
|
||||
assert G._adj != H._adj
|
||||
H.adj[1][2]["foo"] = old_foo
|
||||
assert G._adj == H._adj
|
||||
|
||||
old_foo = H.nodes[0]["foo"]
|
||||
H.nodes[0]["foo"] = "baz"
|
||||
assert G._node != H._node
|
||||
H.nodes[0]["foo"] = old_foo
|
||||
assert G._node == H._node
|
||||
|
||||
def graphs_equal(self, H, G):
|
||||
assert G._adj == H._adj
|
||||
assert G._node == H._node
|
||||
assert G.graph == H.graph
|
||||
assert G.name == H.name
|
||||
if not G.is_directed() and not H.is_directed():
|
||||
assert H._adj[1][2] is H._adj[2][1]
|
||||
assert G._adj[1][2] is G._adj[2][1]
|
||||
else: # at least one is directed
|
||||
if not G.is_directed():
|
||||
G._pred = G._adj
|
||||
G._succ = G._adj
|
||||
if not H.is_directed():
|
||||
H._pred = H._adj
|
||||
H._succ = H._adj
|
||||
assert G._pred == H._pred
|
||||
assert G._succ == H._succ
|
||||
assert H._succ[1][2] is H._pred[2][1]
|
||||
assert G._succ[1][2] is G._pred[2][1]
|
||||
|
||||
def test_graph_attr(self):
|
||||
G = self.K3.copy()
|
||||
G.graph["foo"] = "bar"
|
||||
assert isinstance(G.graph, G.graph_attr_dict_factory)
|
||||
assert G.graph["foo"] == "bar"
|
||||
del G.graph["foo"]
|
||||
assert G.graph == {}
|
||||
H = self.Graph(foo="bar")
|
||||
assert H.graph["foo"] == "bar"
|
||||
|
||||
def test_node_attr(self):
|
||||
G = self.K3.copy()
|
||||
G.add_node(1, foo="bar")
|
||||
assert all(
|
||||
isinstance(d, G.node_attr_dict_factory) for u, d in G.nodes(data=True)
|
||||
)
|
||||
assert nodes_equal(G.nodes(), [0, 1, 2])
|
||||
assert nodes_equal(G.nodes(data=True), [(0, {}), (1, {"foo": "bar"}), (2, {})])
|
||||
G.nodes[1]["foo"] = "baz"
|
||||
assert nodes_equal(G.nodes(data=True), [(0, {}), (1, {"foo": "baz"}), (2, {})])
|
||||
assert nodes_equal(G.nodes(data="foo"), [(0, None), (1, "baz"), (2, None)])
|
||||
assert nodes_equal(
|
||||
G.nodes(data="foo", default="bar"), [(0, "bar"), (1, "baz"), (2, "bar")]
|
||||
)
|
||||
|
||||
def test_node_attr2(self):
|
||||
G = self.K3.copy()
|
||||
a = {"foo": "bar"}
|
||||
G.add_node(3, **a)
|
||||
assert nodes_equal(G.nodes(), [0, 1, 2, 3])
|
||||
assert nodes_equal(
|
||||
G.nodes(data=True), [(0, {}), (1, {}), (2, {}), (3, {"foo": "bar"})]
|
||||
)
|
||||
|
||||
def test_edge_lookup(self):
|
||||
G = self.Graph()
|
||||
G.add_edge(1, 2, foo="bar")
|
||||
assert edges_equal(G.edges[1, 2], {"foo": "bar"})
|
||||
|
||||
def test_edge_attr(self):
|
||||
G = self.Graph()
|
||||
G.add_edge(1, 2, foo="bar")
|
||||
assert all(
|
||||
isinstance(d, G.edge_attr_dict_factory) for u, v, d in G.edges(data=True)
|
||||
)
|
||||
assert edges_equal(G.edges(data=True), [(1, 2, {"foo": "bar"})])
|
||||
assert edges_equal(G.edges(data="foo"), [(1, 2, "bar")])
|
||||
|
||||
def test_edge_attr2(self):
|
||||
G = self.Graph()
|
||||
G.add_edges_from([(1, 2), (3, 4)], foo="foo")
|
||||
assert edges_equal(
|
||||
G.edges(data=True), [(1, 2, {"foo": "foo"}), (3, 4, {"foo": "foo"})]
|
||||
)
|
||||
assert edges_equal(G.edges(data="foo"), [(1, 2, "foo"), (3, 4, "foo")])
|
||||
|
||||
def test_edge_attr3(self):
|
||||
G = self.Graph()
|
||||
G.add_edges_from([(1, 2, {"weight": 32}), (3, 4, {"weight": 64})], foo="foo")
|
||||
assert edges_equal(
|
||||
G.edges(data=True),
|
||||
[
|
||||
(1, 2, {"foo": "foo", "weight": 32}),
|
||||
(3, 4, {"foo": "foo", "weight": 64}),
|
||||
],
|
||||
)
|
||||
|
||||
G.remove_edges_from([(1, 2), (3, 4)])
|
||||
G.add_edge(1, 2, data=7, spam="bar", bar="foo")
|
||||
assert edges_equal(
|
||||
G.edges(data=True), [(1, 2, {"data": 7, "spam": "bar", "bar": "foo"})]
|
||||
)
|
||||
|
||||
def test_edge_attr4(self):
|
||||
G = self.Graph()
|
||||
G.add_edge(1, 2, data=7, spam="bar", bar="foo")
|
||||
assert edges_equal(
|
||||
G.edges(data=True), [(1, 2, {"data": 7, "spam": "bar", "bar": "foo"})]
|
||||
)
|
||||
G[1][2]["data"] = 10 # OK to set data like this
|
||||
assert edges_equal(
|
||||
G.edges(data=True), [(1, 2, {"data": 10, "spam": "bar", "bar": "foo"})]
|
||||
)
|
||||
|
||||
G.adj[1][2]["data"] = 20
|
||||
assert edges_equal(
|
||||
G.edges(data=True), [(1, 2, {"data": 20, "spam": "bar", "bar": "foo"})]
|
||||
)
|
||||
G.edges[1, 2]["data"] = 21 # another spelling, "edge"
|
||||
assert edges_equal(
|
||||
G.edges(data=True), [(1, 2, {"data": 21, "spam": "bar", "bar": "foo"})]
|
||||
)
|
||||
G.adj[1][2]["listdata"] = [20, 200]
|
||||
G.adj[1][2]["weight"] = 20
|
||||
dd = {
|
||||
"data": 21,
|
||||
"spam": "bar",
|
||||
"bar": "foo",
|
||||
"listdata": [20, 200],
|
||||
"weight": 20,
|
||||
}
|
||||
assert edges_equal(G.edges(data=True), [(1, 2, dd)])
|
||||
|
||||
def test_to_undirected(self):
|
||||
G = self.K3
|
||||
self.add_attributes(G)
|
||||
H = nx.Graph(G)
|
||||
self.is_shallow_copy(H, G)
|
||||
self.different_attrdict(H, G)
|
||||
H = G.to_undirected()
|
||||
self.is_deepcopy(H, G)
|
||||
|
||||
def test_to_directed_as_view(self):
|
||||
H = nx.path_graph(2, create_using=self.Graph)
|
||||
H2 = H.to_directed(as_view=True)
|
||||
assert H is H2._graph
|
||||
assert H2.has_edge(0, 1)
|
||||
assert H2.has_edge(1, 0) or H.is_directed()
|
||||
pytest.raises(nx.NetworkXError, H2.add_node, -1)
|
||||
pytest.raises(nx.NetworkXError, H2.add_edge, 1, 2)
|
||||
H.add_edge(1, 2)
|
||||
assert H2.has_edge(1, 2)
|
||||
assert H2.has_edge(2, 1) or H.is_directed()
|
||||
|
||||
def test_to_undirected_as_view(self):
|
||||
H = nx.path_graph(2, create_using=self.Graph)
|
||||
H2 = H.to_undirected(as_view=True)
|
||||
assert H is H2._graph
|
||||
assert H2.has_edge(0, 1)
|
||||
assert H2.has_edge(1, 0)
|
||||
pytest.raises(nx.NetworkXError, H2.add_node, -1)
|
||||
pytest.raises(nx.NetworkXError, H2.add_edge, 1, 2)
|
||||
H.add_edge(1, 2)
|
||||
assert H2.has_edge(1, 2)
|
||||
assert H2.has_edge(2, 1)
|
||||
|
||||
def test_directed_class(self):
|
||||
G = self.Graph()
|
||||
|
||||
class newGraph(G.to_undirected_class()):
|
||||
def to_directed_class(self):
|
||||
return newDiGraph
|
||||
|
||||
def to_undirected_class(self):
|
||||
return newGraph
|
||||
|
||||
class newDiGraph(G.to_directed_class()):
|
||||
def to_directed_class(self):
|
||||
return newDiGraph
|
||||
|
||||
def to_undirected_class(self):
|
||||
return newGraph
|
||||
|
||||
G = newDiGraph() if G.is_directed() else newGraph()
|
||||
H = G.to_directed()
|
||||
assert isinstance(H, newDiGraph)
|
||||
H = G.to_undirected()
|
||||
assert isinstance(H, newGraph)
|
||||
|
||||
def test_to_directed(self):
|
||||
G = self.K3
|
||||
self.add_attributes(G)
|
||||
H = nx.DiGraph(G)
|
||||
self.is_shallow_copy(H, G)
|
||||
self.different_attrdict(H, G)
|
||||
H = G.to_directed()
|
||||
self.is_deepcopy(H, G)
|
||||
|
||||
def test_subgraph(self):
|
||||
G = self.K3
|
||||
self.add_attributes(G)
|
||||
H = G.subgraph([0, 1, 2, 5])
|
||||
self.graphs_equal(H, G)
|
||||
self.same_attrdict(H, G)
|
||||
self.shallow_copy_attrdict(H, G)
|
||||
|
||||
H = G.subgraph(0)
|
||||
assert H.adj == {0: {}}
|
||||
H = G.subgraph([])
|
||||
assert H.adj == {}
|
||||
assert G.adj != {}
|
||||
|
||||
def test_selfloops_attr(self):
|
||||
G = self.K3.copy()
|
||||
G.add_edge(0, 0)
|
||||
G.add_edge(1, 1, weight=2)
|
||||
assert edges_equal(
|
||||
nx.selfloop_edges(G, data=True), [(0, 0, {}), (1, 1, {"weight": 2})]
|
||||
)
|
||||
assert edges_equal(
|
||||
nx.selfloop_edges(G, data="weight"), [(0, 0, None), (1, 1, 2)]
|
||||
)
|
||||
|
||||
|
||||
class TestGraph(BaseAttrGraphTester):
|
||||
"""Tests specific to dict-of-dict-of-dict graph data structure"""
|
||||
|
||||
def setup_method(self):
|
||||
self.Graph = nx.Graph
|
||||
# build dict-of-dict-of-dict K3
|
||||
ed1, ed2, ed3 = ({}, {}, {})
|
||||
self.k3adj = {0: {1: ed1, 2: ed2}, 1: {0: ed1, 2: ed3}, 2: {0: ed2, 1: ed3}}
|
||||
self.k3edges = [(0, 1), (0, 2), (1, 2)]
|
||||
self.k3nodes = [0, 1, 2]
|
||||
self.K3 = self.Graph()
|
||||
self.K3._adj = self.k3adj
|
||||
self.K3._node = {}
|
||||
self.K3._node[0] = {}
|
||||
self.K3._node[1] = {}
|
||||
self.K3._node[2] = {}
|
||||
|
||||
def test_pickle(self):
|
||||
G = self.K3
|
||||
pg = pickle.loads(pickle.dumps(G, -1))
|
||||
self.graphs_equal(pg, G)
|
||||
pg = pickle.loads(pickle.dumps(G))
|
||||
self.graphs_equal(pg, G)
|
||||
|
||||
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: {}})]
|
||||
|
||||
def test_adjacency(self):
|
||||
G = self.K3
|
||||
assert dict(G.adjacency()) == {
|
||||
0: {1: {}, 2: {}},
|
||||
1: {0: {}, 2: {}},
|
||||
2: {0: {}, 1: {}},
|
||||
}
|
||||
|
||||
def test_getitem(self):
|
||||
G = self.K3
|
||||
assert G.adj[0] == {1: {}, 2: {}}
|
||||
assert G[0] == {1: {}, 2: {}}
|
||||
with pytest.raises(KeyError):
|
||||
G.__getitem__("j")
|
||||
with pytest.raises(TypeError):
|
||||
G.__getitem__(["A"])
|
||||
|
||||
def test_add_node(self):
|
||||
G = self.Graph()
|
||||
G.add_node(0)
|
||||
assert G.adj == {0: {}}
|
||||
# test add attributes
|
||||
G.add_node(1, c="red")
|
||||
G.add_node(2, c="blue")
|
||||
G.add_node(3, c="red")
|
||||
assert G.nodes[1]["c"] == "red"
|
||||
assert G.nodes[2]["c"] == "blue"
|
||||
assert G.nodes[3]["c"] == "red"
|
||||
# test updating attributes
|
||||
G.add_node(1, c="blue")
|
||||
G.add_node(2, c="red")
|
||||
G.add_node(3, c="blue")
|
||||
assert G.nodes[1]["c"] == "blue"
|
||||
assert G.nodes[2]["c"] == "red"
|
||||
assert G.nodes[3]["c"] == "blue"
|
||||
|
||||
def test_add_nodes_from(self):
|
||||
G = self.Graph()
|
||||
G.add_nodes_from([0, 1, 2])
|
||||
assert G.adj == {0: {}, 1: {}, 2: {}}
|
||||
# test add attributes
|
||||
G.add_nodes_from([0, 1, 2], c="red")
|
||||
assert G.nodes[0]["c"] == "red"
|
||||
assert G.nodes[2]["c"] == "red"
|
||||
# test that attribute dicts are not the same
|
||||
assert G.nodes[0] is not G.nodes[1]
|
||||
# test updating attributes
|
||||
G.add_nodes_from([0, 1, 2], c="blue")
|
||||
assert G.nodes[0]["c"] == "blue"
|
||||
assert G.nodes[2]["c"] == "blue"
|
||||
assert G.nodes[0] is not G.nodes[1]
|
||||
# test tuple input
|
||||
H = self.Graph()
|
||||
H.add_nodes_from(G.nodes(data=True))
|
||||
assert H.nodes[0]["c"] == "blue"
|
||||
assert H.nodes[2]["c"] == "blue"
|
||||
assert H.nodes[0] is not H.nodes[1]
|
||||
# specific overrides general
|
||||
H.add_nodes_from([0, (1, {"c": "green"}), (3, {"c": "cyan"})], c="red")
|
||||
assert H.nodes[0]["c"] == "red"
|
||||
assert H.nodes[1]["c"] == "green"
|
||||
assert H.nodes[2]["c"] == "blue"
|
||||
assert H.nodes[3]["c"] == "cyan"
|
||||
|
||||
def test_remove_node(self):
|
||||
G = self.K3.copy()
|
||||
G.remove_node(0)
|
||||
assert G.adj == {1: {2: {}}, 2: {1: {}}}
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
G.remove_node(-1)
|
||||
|
||||
# generator here to implement list,set,string...
|
||||
|
||||
def test_remove_nodes_from(self):
|
||||
G = self.K3.copy()
|
||||
G.remove_nodes_from([0, 1])
|
||||
assert G.adj == {2: {}}
|
||||
G.remove_nodes_from([-1]) # silent fail
|
||||
|
||||
def test_add_edge(self):
|
||||
G = self.Graph()
|
||||
G.add_edge(0, 1)
|
||||
assert G.adj == {0: {1: {}}, 1: {0: {}}}
|
||||
G = self.Graph()
|
||||
G.add_edge(*(0, 1))
|
||||
assert G.adj == {0: {1: {}}, 1: {0: {}}}
|
||||
G = self.Graph()
|
||||
with pytest.raises(ValueError):
|
||||
G.add_edge(None, "anything")
|
||||
|
||||
def test_add_edges_from(self):
|
||||
G = self.Graph()
|
||||
G.add_edges_from([(0, 1), (0, 2, {"weight": 3})])
|
||||
assert G.adj == {
|
||||
0: {1: {}, 2: {"weight": 3}},
|
||||
1: {0: {}},
|
||||
2: {0: {"weight": 3}},
|
||||
}
|
||||
G = self.Graph()
|
||||
G.add_edges_from([(0, 1), (0, 2, {"weight": 3}), (1, 2, {"data": 4})], data=2)
|
||||
assert G.adj == {
|
||||
0: {1: {"data": 2}, 2: {"weight": 3, "data": 2}},
|
||||
1: {0: {"data": 2}, 2: {"data": 4}},
|
||||
2: {0: {"weight": 3, "data": 2}, 1: {"data": 4}},
|
||||
}
|
||||
|
||||
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):
|
||||
G.add_edges_from([(None, 3), (3, 2)]) # None cannot be a node
|
||||
|
||||
def test_remove_edge(self):
|
||||
G = self.K3.copy()
|
||||
G.remove_edge(0, 1)
|
||||
assert G.adj == {0: {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.adj == {0: {2: {}}, 1: {2: {}}, 2: {0: {}, 1: {}}}
|
||||
G.remove_edges_from([(0, 0)]) # silent fail
|
||||
|
||||
def test_clear(self):
|
||||
G = self.K3.copy()
|
||||
G.graph["name"] = "K3"
|
||||
G.clear()
|
||||
assert list(G.nodes) == []
|
||||
assert G.adj == {}
|
||||
assert G.graph == {}
|
||||
|
||||
def test_clear_edges(self):
|
||||
G = self.K3.copy()
|
||||
G.graph["name"] = "K3"
|
||||
nodes = list(G.nodes)
|
||||
G.clear_edges()
|
||||
assert list(G.nodes) == nodes
|
||||
assert G.adj == {0: {}, 1: {}, 2: {}}
|
||||
assert list(G.edges) == []
|
||||
assert G.graph["name"] == "K3"
|
||||
|
||||
def test_edges_data(self):
|
||||
G = self.K3
|
||||
all_edges = [(0, 1, {}), (0, 2, {}), (1, 2, {})]
|
||||
assert edges_equal(G.edges(data=True), all_edges)
|
||||
assert edges_equal(G.edges(0, data=True), [(0, 1, {}), (0, 2, {})])
|
||||
assert edges_equal(G.edges([0, 1], data=True), all_edges)
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
G.edges(-1, True)
|
||||
|
||||
def test_get_edge_data(self):
|
||||
G = self.K3.copy()
|
||||
assert G.get_edge_data(0, 1) == {}
|
||||
assert G[0][1] == {}
|
||||
assert G.get_edge_data(10, 20) is None
|
||||
assert G.get_edge_data(-1, 0) is None
|
||||
assert G.get_edge_data(-1, 0, default=1) == 1
|
||||
|
||||
def test_update(self):
|
||||
# specify both edges and nodes
|
||||
G = self.K3.copy()
|
||||
G.update(nodes=[3, (4, {"size": 2})], edges=[(4, 5), (6, 7, {"weight": 2})])
|
||||
nlist = [
|
||||
(0, {}),
|
||||
(1, {}),
|
||||
(2, {}),
|
||||
(3, {}),
|
||||
(4, {"size": 2}),
|
||||
(5, {}),
|
||||
(6, {}),
|
||||
(7, {}),
|
||||
]
|
||||
assert sorted(G.nodes.data()) == nlist
|
||||
if G.is_directed():
|
||||
elist = [
|
||||
(0, 1, {}),
|
||||
(0, 2, {}),
|
||||
(1, 0, {}),
|
||||
(1, 2, {}),
|
||||
(2, 0, {}),
|
||||
(2, 1, {}),
|
||||
(4, 5, {}),
|
||||
(6, 7, {"weight": 2}),
|
||||
]
|
||||
else:
|
||||
elist = [
|
||||
(0, 1, {}),
|
||||
(0, 2, {}),
|
||||
(1, 2, {}),
|
||||
(4, 5, {}),
|
||||
(6, 7, {"weight": 2}),
|
||||
]
|
||||
assert sorted(G.edges.data()) == elist
|
||||
assert G.graph == {}
|
||||
|
||||
# no keywords -- order is edges, nodes
|
||||
G = self.K3.copy()
|
||||
G.update([(4, 5), (6, 7, {"weight": 2})], [3, (4, {"size": 2})])
|
||||
assert sorted(G.nodes.data()) == nlist
|
||||
assert sorted(G.edges.data()) == elist
|
||||
assert G.graph == {}
|
||||
|
||||
# update using only a graph
|
||||
G = self.Graph()
|
||||
G.graph["foo"] = "bar"
|
||||
G.add_node(2, data=4)
|
||||
G.add_edge(0, 1, weight=0.5)
|
||||
GG = G.copy()
|
||||
H = self.Graph()
|
||||
GG.update(H)
|
||||
assert graphs_equal(G, GG)
|
||||
H.update(G)
|
||||
assert graphs_equal(H, G)
|
||||
|
||||
# update nodes only
|
||||
H = self.Graph()
|
||||
H.update(nodes=[3, 4])
|
||||
assert H.nodes ^ {3, 4} == set()
|
||||
assert H.size() == 0
|
||||
|
||||
# update edges only
|
||||
H = self.Graph()
|
||||
H.update(edges=[(3, 4)])
|
||||
assert sorted(H.edges.data()) == [(3, 4, {})]
|
||||
assert H.size() == 1
|
||||
|
||||
# No inputs -> exception
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
nx.Graph().update()
|
||||
|
||||
|
||||
class TestEdgeSubgraph:
|
||||
"""Unit tests for the :meth:`Graph.edge_subgraph` method."""
|
||||
|
||||
def setup_method(self):
|
||||
# Create a path graph on five nodes.
|
||||
G = 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_correct_nodes(self):
|
||||
"""Tests that the subgraph has the correct nodes."""
|
||||
assert [0, 1, 3, 4] == sorted(self.H.nodes())
|
||||
|
||||
def test_correct_edges(self):
|
||||
"""Tests that the subgraph has the correct edges."""
|
||||
assert [(0, 1, "edge01"), (3, 4, "edge34")] == sorted(self.H.edges(data="name"))
|
||||
|
||||
def test_add_node(self):
|
||||
"""Tests that adding a node to the original graph does not
|
||||
affect the nodes of the subgraph.
|
||||
|
||||
"""
|
||||
self.G.add_node(5)
|
||||
assert [0, 1, 3, 4] == sorted(self.H.nodes())
|
||||
|
||||
def test_remove_node(self):
|
||||
"""Tests that removing a node in the original graph does
|
||||
affect the nodes of the subgraph.
|
||||
|
||||
"""
|
||||
self.G.remove_node(0)
|
||||
assert [1, 3, 4] == sorted(self.H.nodes())
|
||||
|
||||
def test_node_attr_dict(self):
|
||||
"""Tests that the node attribute dictionary of the two graphs is
|
||||
the same object.
|
||||
|
||||
"""
|
||||
for v in self.H:
|
||||
assert self.G.nodes[v] == self.H.nodes[v]
|
||||
# Making a change to G should make a change in H and vice versa.
|
||||
self.G.nodes[0]["name"] = "foo"
|
||||
assert self.G.nodes[0] == self.H.nodes[0]
|
||||
self.H.nodes[1]["name"] = "bar"
|
||||
assert self.G.nodes[1] == self.H.nodes[1]
|
||||
|
||||
def test_edge_attr_dict(self):
|
||||
"""Tests that the edge attribute dictionary of the two graphs is
|
||||
the same object.
|
||||
|
||||
"""
|
||||
for u, v in self.H.edges():
|
||||
assert self.G.edges[u, v] == self.H.edges[u, v]
|
||||
# Making a change to G should make a change in H and vice versa.
|
||||
self.G.edges[0, 1]["name"] = "foo"
|
||||
assert self.G.edges[0, 1]["name"] == self.H.edges[0, 1]["name"]
|
||||
self.H.edges[3, 4]["name"] = "bar"
|
||||
assert self.G.edges[3, 4]["name"] == self.H.edges[3, 4]["name"]
|
||||
|
||||
def test_graph_attr_dict(self):
|
||||
"""Tests that the graph attribute dictionary of the two graphs
|
||||
is the same object.
|
||||
|
||||
"""
|
||||
assert self.G.graph is self.H.graph
|
||||
12
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_graph_historical.py
vendored
Normal file
12
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_graph_historical.py
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
"""Original NetworkX graph tests"""
|
||||
import networkx
|
||||
import networkx as nx
|
||||
|
||||
from .historical_tests import HistoricalTests
|
||||
|
||||
|
||||
class TestGraphHistorical(HistoricalTests):
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
HistoricalTests.setup_class()
|
||||
cls.G = nx.Graph
|
||||
350
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_graphviews.py
vendored
Normal file
350
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_graphviews.py
vendored
Normal file
@@ -0,0 +1,350 @@
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.utils import edges_equal, nodes_equal
|
||||
|
||||
# Note: SubGraph views are not tested here. They have their own testing file
|
||||
|
||||
|
||||
class TestReverseView:
|
||||
def setup_method(self):
|
||||
self.G = nx.path_graph(9, create_using=nx.DiGraph())
|
||||
self.rv = nx.reverse_view(self.G)
|
||||
|
||||
def test_pickle(self):
|
||||
import pickle
|
||||
|
||||
rv = self.rv
|
||||
prv = pickle.loads(pickle.dumps(rv, -1))
|
||||
assert rv._node == prv._node
|
||||
assert rv._adj == prv._adj
|
||||
assert rv.graph == prv.graph
|
||||
|
||||
def test_contains(self):
|
||||
assert (2, 3) in self.G.edges
|
||||
assert (3, 2) not in self.G.edges
|
||||
assert (2, 3) not in self.rv.edges
|
||||
assert (3, 2) in self.rv.edges
|
||||
|
||||
def test_iter(self):
|
||||
expected = sorted(tuple(reversed(e)) for e in self.G.edges)
|
||||
assert sorted(self.rv.edges) == expected
|
||||
|
||||
def test_exceptions(self):
|
||||
G = nx.Graph()
|
||||
pytest.raises(nx.NetworkXNotImplemented, nx.reverse_view, G)
|
||||
|
||||
def test_subclass(self):
|
||||
class MyGraph(nx.DiGraph):
|
||||
def my_method(self):
|
||||
return "me"
|
||||
|
||||
def to_directed_class(self):
|
||||
return MyGraph()
|
||||
|
||||
M = MyGraph()
|
||||
M.add_edge(1, 2)
|
||||
RM = nx.reverse_view(M)
|
||||
print("RM class", RM.__class__)
|
||||
RMC = RM.copy()
|
||||
print("RMC class", RMC.__class__)
|
||||
print(RMC.edges)
|
||||
assert RMC.has_edge(2, 1)
|
||||
assert RMC.my_method() == "me"
|
||||
|
||||
|
||||
class TestMultiReverseView:
|
||||
def setup_method(self):
|
||||
self.G = nx.path_graph(9, create_using=nx.MultiDiGraph())
|
||||
self.G.add_edge(4, 5)
|
||||
self.rv = nx.reverse_view(self.G)
|
||||
|
||||
def test_pickle(self):
|
||||
import pickle
|
||||
|
||||
rv = self.rv
|
||||
prv = pickle.loads(pickle.dumps(rv, -1))
|
||||
assert rv._node == prv._node
|
||||
assert rv._adj == prv._adj
|
||||
assert rv.graph == prv.graph
|
||||
|
||||
def test_contains(self):
|
||||
assert (2, 3, 0) in self.G.edges
|
||||
assert (3, 2, 0) not in self.G.edges
|
||||
assert (2, 3, 0) not in self.rv.edges
|
||||
assert (3, 2, 0) in self.rv.edges
|
||||
assert (5, 4, 1) in self.rv.edges
|
||||
assert (4, 5, 1) not in self.rv.edges
|
||||
|
||||
def test_iter(self):
|
||||
expected = sorted((v, u, k) for u, v, k in self.G.edges)
|
||||
assert sorted(self.rv.edges) == expected
|
||||
|
||||
def test_exceptions(self):
|
||||
MG = nx.MultiGraph(self.G)
|
||||
pytest.raises(nx.NetworkXNotImplemented, nx.reverse_view, MG)
|
||||
|
||||
|
||||
def test_generic_multitype():
|
||||
nxg = nx.graphviews
|
||||
G = nx.DiGraph([(1, 2)])
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
nxg.generic_graph_view(G, create_using=nx.MultiGraph)
|
||||
G = nx.MultiDiGraph([(1, 2)])
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
nxg.generic_graph_view(G, create_using=nx.DiGraph)
|
||||
|
||||
|
||||
class TestToDirected:
|
||||
def setup_method(self):
|
||||
self.G = nx.path_graph(9)
|
||||
self.dv = nx.to_directed(self.G)
|
||||
self.MG = nx.path_graph(9, create_using=nx.MultiGraph())
|
||||
self.Mdv = nx.to_directed(self.MG)
|
||||
|
||||
def test_directed(self):
|
||||
assert not self.G.is_directed()
|
||||
assert self.dv.is_directed()
|
||||
|
||||
def test_already_directed(self):
|
||||
dd = nx.to_directed(self.dv)
|
||||
Mdd = nx.to_directed(self.Mdv)
|
||||
assert edges_equal(dd.edges, self.dv.edges)
|
||||
assert edges_equal(Mdd.edges, self.Mdv.edges)
|
||||
|
||||
def test_pickle(self):
|
||||
import pickle
|
||||
|
||||
dv = self.dv
|
||||
pdv = pickle.loads(pickle.dumps(dv, -1))
|
||||
assert dv._node == pdv._node
|
||||
assert dv._succ == pdv._succ
|
||||
assert dv._pred == pdv._pred
|
||||
assert dv.graph == pdv.graph
|
||||
|
||||
def test_contains(self):
|
||||
assert (2, 3) in self.G.edges
|
||||
assert (3, 2) in self.G.edges
|
||||
assert (2, 3) in self.dv.edges
|
||||
assert (3, 2) in self.dv.edges
|
||||
|
||||
def test_iter(self):
|
||||
revd = [tuple(reversed(e)) for e in self.G.edges]
|
||||
expected = sorted(list(self.G.edges) + revd)
|
||||
assert sorted(self.dv.edges) == expected
|
||||
|
||||
|
||||
class TestToUndirected:
|
||||
def setup_method(self):
|
||||
self.DG = nx.path_graph(9, create_using=nx.DiGraph())
|
||||
self.uv = nx.to_undirected(self.DG)
|
||||
self.MDG = nx.path_graph(9, create_using=nx.MultiDiGraph())
|
||||
self.Muv = nx.to_undirected(self.MDG)
|
||||
|
||||
def test_directed(self):
|
||||
assert self.DG.is_directed()
|
||||
assert not self.uv.is_directed()
|
||||
|
||||
def test_already_directed(self):
|
||||
uu = nx.to_undirected(self.uv)
|
||||
Muu = nx.to_undirected(self.Muv)
|
||||
assert edges_equal(uu.edges, self.uv.edges)
|
||||
assert edges_equal(Muu.edges, self.Muv.edges)
|
||||
|
||||
def test_pickle(self):
|
||||
import pickle
|
||||
|
||||
uv = self.uv
|
||||
puv = pickle.loads(pickle.dumps(uv, -1))
|
||||
assert uv._node == puv._node
|
||||
assert uv._adj == puv._adj
|
||||
assert uv.graph == puv.graph
|
||||
assert hasattr(uv, "_graph")
|
||||
|
||||
def test_contains(self):
|
||||
assert (2, 3) in self.DG.edges
|
||||
assert (3, 2) not in self.DG.edges
|
||||
assert (2, 3) in self.uv.edges
|
||||
assert (3, 2) in self.uv.edges
|
||||
|
||||
def test_iter(self):
|
||||
expected = sorted(self.DG.edges)
|
||||
assert sorted(self.uv.edges) == expected
|
||||
|
||||
|
||||
class TestChainsOfViews:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.G = nx.path_graph(9)
|
||||
cls.DG = nx.path_graph(9, create_using=nx.DiGraph())
|
||||
cls.MG = nx.path_graph(9, create_using=nx.MultiGraph())
|
||||
cls.MDG = nx.path_graph(9, create_using=nx.MultiDiGraph())
|
||||
cls.Gv = nx.to_undirected(cls.DG)
|
||||
cls.DGv = nx.to_directed(cls.G)
|
||||
cls.MGv = nx.to_undirected(cls.MDG)
|
||||
cls.MDGv = nx.to_directed(cls.MG)
|
||||
cls.Rv = cls.DG.reverse()
|
||||
cls.MRv = cls.MDG.reverse()
|
||||
cls.graphs = [
|
||||
cls.G,
|
||||
cls.DG,
|
||||
cls.MG,
|
||||
cls.MDG,
|
||||
cls.Gv,
|
||||
cls.DGv,
|
||||
cls.MGv,
|
||||
cls.MDGv,
|
||||
cls.Rv,
|
||||
cls.MRv,
|
||||
]
|
||||
for G in cls.graphs:
|
||||
G.edges, G.nodes, G.degree
|
||||
|
||||
def test_pickle(self):
|
||||
import pickle
|
||||
|
||||
for G in self.graphs:
|
||||
H = pickle.loads(pickle.dumps(G, -1))
|
||||
assert edges_equal(H.edges, G.edges)
|
||||
assert nodes_equal(H.nodes, G.nodes)
|
||||
|
||||
def test_subgraph_of_subgraph(self):
|
||||
SGv = nx.subgraph(self.G, range(3, 7))
|
||||
SDGv = nx.subgraph(self.DG, range(3, 7))
|
||||
SMGv = nx.subgraph(self.MG, range(3, 7))
|
||||
SMDGv = nx.subgraph(self.MDG, range(3, 7))
|
||||
for G in self.graphs + [SGv, SDGv, SMGv, SMDGv]:
|
||||
SG = nx.induced_subgraph(G, [4, 5, 6])
|
||||
assert list(SG) == [4, 5, 6]
|
||||
SSG = SG.subgraph([6, 7])
|
||||
assert list(SSG) == [6]
|
||||
# subgraph-subgraph chain is short-cut in base class method
|
||||
assert SSG._graph is G
|
||||
|
||||
def test_restricted_induced_subgraph_chains(self):
|
||||
"""Test subgraph chains that both restrict and show nodes/edges.
|
||||
|
||||
A restricted_view subgraph should allow induced subgraphs using
|
||||
G.subgraph that automagically without a chain (meaning the result
|
||||
is a subgraph view of the original graph not a subgraph-of-subgraph.
|
||||
"""
|
||||
hide_nodes = [3, 4, 5]
|
||||
hide_edges = [(6, 7)]
|
||||
RG = nx.restricted_view(self.G, hide_nodes, hide_edges)
|
||||
nodes = [4, 5, 6, 7, 8]
|
||||
SG = nx.induced_subgraph(RG, nodes)
|
||||
SSG = RG.subgraph(nodes)
|
||||
assert RG._graph is self.G
|
||||
assert SSG._graph is self.G
|
||||
assert SG._graph is RG
|
||||
assert edges_equal(SG.edges, SSG.edges)
|
||||
# should be same as morphing the graph
|
||||
CG = self.G.copy()
|
||||
CG.remove_nodes_from(hide_nodes)
|
||||
CG.remove_edges_from(hide_edges)
|
||||
assert edges_equal(CG.edges(nodes), SSG.edges)
|
||||
CG.remove_nodes_from([0, 1, 2, 3])
|
||||
assert edges_equal(CG.edges, SSG.edges)
|
||||
# switch order: subgraph first, then restricted view
|
||||
SSSG = self.G.subgraph(nodes)
|
||||
RSG = nx.restricted_view(SSSG, hide_nodes, hide_edges)
|
||||
assert RSG._graph is not self.G
|
||||
assert edges_equal(RSG.edges, CG.edges)
|
||||
|
||||
def test_subgraph_copy(self):
|
||||
for origG in self.graphs:
|
||||
G = nx.Graph(origG)
|
||||
SG = G.subgraph([4, 5, 6])
|
||||
H = SG.copy()
|
||||
assert type(G) == type(H)
|
||||
|
||||
def test_subgraph_todirected(self):
|
||||
SG = nx.induced_subgraph(self.G, [4, 5, 6])
|
||||
SSG = SG.to_directed()
|
||||
assert sorted(SSG) == [4, 5, 6]
|
||||
assert sorted(SSG.edges) == [(4, 5), (5, 4), (5, 6), (6, 5)]
|
||||
|
||||
def test_subgraph_toundirected(self):
|
||||
SG = nx.induced_subgraph(self.G, [4, 5, 6])
|
||||
SSG = SG.to_undirected()
|
||||
assert list(SSG) == [4, 5, 6]
|
||||
assert sorted(SSG.edges) == [(4, 5), (5, 6)]
|
||||
|
||||
def test_reverse_subgraph_toundirected(self):
|
||||
G = self.DG.reverse(copy=False)
|
||||
SG = G.subgraph([4, 5, 6])
|
||||
SSG = SG.to_undirected()
|
||||
assert list(SSG) == [4, 5, 6]
|
||||
assert sorted(SSG.edges) == [(4, 5), (5, 6)]
|
||||
|
||||
def test_reverse_reverse_copy(self):
|
||||
G = self.DG.reverse(copy=False)
|
||||
H = G.reverse(copy=True)
|
||||
assert H.nodes == self.DG.nodes
|
||||
assert H.edges == self.DG.edges
|
||||
G = self.MDG.reverse(copy=False)
|
||||
H = G.reverse(copy=True)
|
||||
assert H.nodes == self.MDG.nodes
|
||||
assert H.edges == self.MDG.edges
|
||||
|
||||
def test_subgraph_edgesubgraph_toundirected(self):
|
||||
G = self.G.copy()
|
||||
SG = G.subgraph([4, 5, 6])
|
||||
SSG = SG.edge_subgraph([(4, 5), (5, 4)])
|
||||
USSG = SSG.to_undirected()
|
||||
assert list(USSG) == [4, 5]
|
||||
assert sorted(USSG.edges) == [(4, 5)]
|
||||
|
||||
def test_copy_subgraph(self):
|
||||
G = self.G.copy()
|
||||
SG = G.subgraph([4, 5, 6])
|
||||
CSG = SG.copy(as_view=True)
|
||||
DCSG = SG.copy(as_view=False)
|
||||
assert hasattr(CSG, "_graph") # is a view
|
||||
assert not hasattr(DCSG, "_graph") # not a view
|
||||
|
||||
def test_copy_disubgraph(self):
|
||||
G = self.DG.copy()
|
||||
SG = G.subgraph([4, 5, 6])
|
||||
CSG = SG.copy(as_view=True)
|
||||
DCSG = SG.copy(as_view=False)
|
||||
assert hasattr(CSG, "_graph") # is a view
|
||||
assert not hasattr(DCSG, "_graph") # not a view
|
||||
|
||||
def test_copy_multidisubgraph(self):
|
||||
G = self.MDG.copy()
|
||||
SG = G.subgraph([4, 5, 6])
|
||||
CSG = SG.copy(as_view=True)
|
||||
DCSG = SG.copy(as_view=False)
|
||||
assert hasattr(CSG, "_graph") # is a view
|
||||
assert not hasattr(DCSG, "_graph") # not a view
|
||||
|
||||
def test_copy_multisubgraph(self):
|
||||
G = self.MG.copy()
|
||||
SG = G.subgraph([4, 5, 6])
|
||||
CSG = SG.copy(as_view=True)
|
||||
DCSG = SG.copy(as_view=False)
|
||||
assert hasattr(CSG, "_graph") # is a view
|
||||
assert not hasattr(DCSG, "_graph") # not a view
|
||||
|
||||
def test_copy_of_view(self):
|
||||
G = nx.MultiGraph(self.MGv)
|
||||
assert G.__class__.__name__ == "MultiGraph"
|
||||
G = G.copy(as_view=True)
|
||||
assert G.__class__.__name__ == "MultiGraph"
|
||||
|
||||
def test_subclass(self):
|
||||
class MyGraph(nx.DiGraph):
|
||||
def my_method(self):
|
||||
return "me"
|
||||
|
||||
def to_directed_class(self):
|
||||
return MyGraph()
|
||||
|
||||
for origG in self.graphs:
|
||||
G = MyGraph(origG)
|
||||
SG = G.subgraph([4, 5, 6])
|
||||
H = SG.copy()
|
||||
assert SG.my_method() == "me"
|
||||
assert H.my_method() == "me"
|
||||
assert 3 not in H or 3 in SG
|
||||
459
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_multidigraph.py
vendored
Normal file
459
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_multidigraph.py
vendored
Normal file
@@ -0,0 +1,459 @@
|
||||
from collections import UserDict
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.utils import edges_equal
|
||||
|
||||
from .test_multigraph import BaseMultiGraphTester
|
||||
from .test_multigraph import TestEdgeSubgraph as _TestMultiGraphEdgeSubgraph
|
||||
from .test_multigraph import TestMultiGraph as _TestMultiGraph
|
||||
|
||||
|
||||
class BaseMultiDiGraphTester(BaseMultiGraphTester):
|
||||
def test_edges(self):
|
||||
G = self.K3
|
||||
edges = [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]
|
||||
assert sorted(G.edges()) == edges
|
||||
assert sorted(G.edges(0)) == [(0, 1), (0, 2)]
|
||||
pytest.raises((KeyError, nx.NetworkXError), G.edges, -1)
|
||||
|
||||
def test_edges_data(self):
|
||||
G = self.K3
|
||||
edges = [(0, 1, {}), (0, 2, {}), (1, 0, {}), (1, 2, {}), (2, 0, {}), (2, 1, {})]
|
||||
assert sorted(G.edges(data=True)) == edges
|
||||
assert sorted(G.edges(0, data=True)) == [(0, 1, {}), (0, 2, {})]
|
||||
pytest.raises((KeyError, nx.NetworkXError), G.neighbors, -1)
|
||||
|
||||
def test_edges_multi(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)]
|
||||
G.add_edge(0, 1)
|
||||
assert sorted(G.edges()) == [
|
||||
(0, 1),
|
||||
(0, 1),
|
||||
(0, 2),
|
||||
(1, 0),
|
||||
(1, 2),
|
||||
(2, 0),
|
||||
(2, 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)]
|
||||
pytest.raises((KeyError, nx.NetworkXError), G.out_edges, -1)
|
||||
assert sorted(G.out_edges(0, keys=True)) == [(0, 1, 0), (0, 2, 0)]
|
||||
|
||||
def test_out_edges_multi(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)]
|
||||
G.add_edge(0, 1, 2)
|
||||
assert sorted(G.out_edges()) == [
|
||||
(0, 1),
|
||||
(0, 1),
|
||||
(0, 2),
|
||||
(1, 0),
|
||||
(1, 2),
|
||||
(2, 0),
|
||||
(2, 1),
|
||||
]
|
||||
|
||||
def test_out_edges_data(self):
|
||||
G = self.K3
|
||||
assert sorted(G.edges(0, data=True)) == [(0, 1, {}), (0, 2, {})]
|
||||
G.remove_edge(0, 1)
|
||||
G.add_edge(0, 1, data=1)
|
||||
assert sorted(G.edges(0, data=True)) == [(0, 1, {"data": 1}), (0, 2, {})]
|
||||
assert sorted(G.edges(0, data="data")) == [(0, 1, 1), (0, 2, None)]
|
||||
assert sorted(G.edges(0, data="data", default=-1)) == [(0, 1, 1), (0, 2, -1)]
|
||||
|
||||
def test_in_edges(self):
|
||||
G = self.K3
|
||||
assert sorted(G.in_edges()) == [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]
|
||||
assert sorted(G.in_edges(0)) == [(1, 0), (2, 0)]
|
||||
pytest.raises((KeyError, nx.NetworkXError), G.in_edges, -1)
|
||||
G.add_edge(0, 1, 2)
|
||||
assert sorted(G.in_edges()) == [
|
||||
(0, 1),
|
||||
(0, 1),
|
||||
(0, 2),
|
||||
(1, 0),
|
||||
(1, 2),
|
||||
(2, 0),
|
||||
(2, 1),
|
||||
]
|
||||
assert sorted(G.in_edges(0, keys=True)) == [(1, 0, 0), (2, 0, 0)]
|
||||
|
||||
def test_in_edges_no_keys(self):
|
||||
G = self.K3
|
||||
assert sorted(G.in_edges()) == [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]
|
||||
assert sorted(G.in_edges(0)) == [(1, 0), (2, 0)]
|
||||
G.add_edge(0, 1, 2)
|
||||
assert sorted(G.in_edges()) == [
|
||||
(0, 1),
|
||||
(0, 1),
|
||||
(0, 2),
|
||||
(1, 0),
|
||||
(1, 2),
|
||||
(2, 0),
|
||||
(2, 1),
|
||||
]
|
||||
|
||||
assert sorted(G.in_edges(data=True, keys=False)) == [
|
||||
(0, 1, {}),
|
||||
(0, 1, {}),
|
||||
(0, 2, {}),
|
||||
(1, 0, {}),
|
||||
(1, 2, {}),
|
||||
(2, 0, {}),
|
||||
(2, 1, {}),
|
||||
]
|
||||
|
||||
def test_in_edges_data(self):
|
||||
G = self.K3
|
||||
assert sorted(G.in_edges(0, data=True)) == [(1, 0, {}), (2, 0, {})]
|
||||
G.remove_edge(1, 0)
|
||||
G.add_edge(1, 0, data=1)
|
||||
assert sorted(G.in_edges(0, data=True)) == [(1, 0, {"data": 1}), (2, 0, {})]
|
||||
assert sorted(G.in_edges(0, data="data")) == [(1, 0, 1), (2, 0, None)]
|
||||
assert sorted(G.in_edges(0, data="data", default=-1)) == [(1, 0, 1), (2, 0, -1)]
|
||||
|
||||
def is_shallow(self, H, G):
|
||||
# graph
|
||||
assert G.graph["foo"] == H.graph["foo"]
|
||||
G.graph["foo"].append(1)
|
||||
assert G.graph["foo"] == H.graph["foo"]
|
||||
# node
|
||||
assert G.nodes[0]["foo"] == H.nodes[0]["foo"]
|
||||
G.nodes[0]["foo"].append(1)
|
||||
assert G.nodes[0]["foo"] == H.nodes[0]["foo"]
|
||||
# edge
|
||||
assert G[1][2][0]["foo"] == H[1][2][0]["foo"]
|
||||
G[1][2][0]["foo"].append(1)
|
||||
assert G[1][2][0]["foo"] == H[1][2][0]["foo"]
|
||||
|
||||
def is_deep(self, H, G):
|
||||
# graph
|
||||
assert G.graph["foo"] == H.graph["foo"]
|
||||
G.graph["foo"].append(1)
|
||||
assert G.graph["foo"] != H.graph["foo"]
|
||||
# node
|
||||
assert G.nodes[0]["foo"] == H.nodes[0]["foo"]
|
||||
G.nodes[0]["foo"].append(1)
|
||||
assert G.nodes[0]["foo"] != H.nodes[0]["foo"]
|
||||
# edge
|
||||
assert G[1][2][0]["foo"] == H[1][2][0]["foo"]
|
||||
G[1][2][0]["foo"].append(1)
|
||||
assert G[1][2][0]["foo"] != H[1][2][0]["foo"]
|
||||
|
||||
def test_to_undirected(self):
|
||||
# MultiDiGraph -> MultiGraph changes number of edges so it is
|
||||
# not a copy operation... use is_shallow, not is_shallow_copy
|
||||
G = self.K3
|
||||
self.add_attributes(G)
|
||||
H = nx.MultiGraph(G)
|
||||
# self.is_shallow(H,G)
|
||||
# the result is traversal order dependent so we
|
||||
# can't use the is_shallow() test here.
|
||||
try:
|
||||
assert edges_equal(H.edges(), [(0, 1), (1, 2), (2, 0)])
|
||||
except AssertionError:
|
||||
assert edges_equal(H.edges(), [(0, 1), (1, 2), (1, 2), (2, 0)])
|
||||
H = G.to_undirected()
|
||||
self.is_deep(H, G)
|
||||
|
||||
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]
|
||||
pytest.raises((KeyError, 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]
|
||||
pytest.raises((KeyError, nx.NetworkXError), G.predecessors, -1)
|
||||
|
||||
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)]
|
||||
G.add_edge(0, 1, weight=0.3, other=1.2)
|
||||
assert sorted(G.degree(weight="weight")) == [(0, 4.3), (1, 4.3), (2, 4)]
|
||||
assert sorted(G.degree(weight="other")) == [(0, 5.2), (1, 5.2), (2, 4)]
|
||||
|
||||
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)]
|
||||
assert G.in_degree(0, weight="weight") == 2
|
||||
|
||||
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)]
|
||||
assert G.out_degree(0, weight="weight") == 2
|
||||
|
||||
def test_size(self):
|
||||
G = self.K3
|
||||
assert G.size() == 6
|
||||
assert G.number_of_edges() == 6
|
||||
G.add_edge(0, 1, weight=0.3, other=1.2)
|
||||
assert round(G.size(weight="weight"), 2) == 6.3
|
||||
assert round(G.size(weight="other"), 2) == 7.2
|
||||
|
||||
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.MultiDiGraph([(0, 1), (0, 1)])
|
||||
R = G.reverse()
|
||||
assert sorted(R.edges()) == [(1, 0), (1, 0)]
|
||||
R.remove_edge(1, 0)
|
||||
assert sorted(R.edges()) == [(1, 0)]
|
||||
assert sorted(G.edges()) == [(0, 1), (0, 1)]
|
||||
|
||||
def test_reverse_nocopy(self):
|
||||
G = nx.MultiDiGraph([(0, 1), (0, 1)])
|
||||
R = G.reverse(copy=False)
|
||||
assert sorted(R.edges()) == [(1, 0), (1, 0)]
|
||||
pytest.raises(nx.NetworkXError, R.remove_edge, 1, 0)
|
||||
|
||||
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 TestMultiDiGraph(BaseMultiDiGraphTester, _TestMultiGraph):
|
||||
def setup_method(self):
|
||||
self.Graph = nx.MultiDiGraph
|
||||
# build K3
|
||||
self.k3edges = [(0, 1), (0, 2), (1, 2)]
|
||||
self.k3nodes = [0, 1, 2]
|
||||
self.K3 = self.Graph()
|
||||
self.K3._succ = {0: {}, 1: {}, 2: {}}
|
||||
# K3._adj is synced with K3._succ
|
||||
self.K3._pred = {0: {}, 1: {}, 2: {}}
|
||||
for u in self.k3nodes:
|
||||
for v in self.k3nodes:
|
||||
if u == v:
|
||||
continue
|
||||
d = {0: {}}
|
||||
self.K3._succ[u][v] = d
|
||||
self.K3._pred[v][u] = d
|
||||
self.K3._node = {}
|
||||
self.K3._node[0] = {}
|
||||
self.K3._node[1] = {}
|
||||
self.K3._node[2] = {}
|
||||
|
||||
def test_add_edge(self):
|
||||
G = self.Graph()
|
||||
G.add_edge(0, 1)
|
||||
assert G._adj == {0: {1: {0: {}}}, 1: {}}
|
||||
assert G._succ == {0: {1: {0: {}}}, 1: {}}
|
||||
assert G._pred == {0: {}, 1: {0: {0: {}}}}
|
||||
G = self.Graph()
|
||||
G.add_edge(*(0, 1))
|
||||
assert G._adj == {0: {1: {0: {}}}, 1: {}}
|
||||
assert G._succ == {0: {1: {0: {}}}, 1: {}}
|
||||
assert G._pred == {0: {}, 1: {0: {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, 1, {"weight": 3})])
|
||||
assert G._adj == {0: {1: {0: {}, 1: {"weight": 3}}}, 1: {}}
|
||||
assert G._succ == {0: {1: {0: {}, 1: {"weight": 3}}}, 1: {}}
|
||||
assert G._pred == {0: {}, 1: {0: {0: {}, 1: {"weight": 3}}}}
|
||||
|
||||
G.add_edges_from([(0, 1), (0, 1, {"weight": 3})], weight=2)
|
||||
assert G._succ == {
|
||||
0: {1: {0: {}, 1: {"weight": 3}, 2: {"weight": 2}, 3: {"weight": 3}}},
|
||||
1: {},
|
||||
}
|
||||
assert G._pred == {
|
||||
0: {},
|
||||
1: {0: {0: {}, 1: {"weight": 3}, 2: {"weight": 2}, 3: {"weight": 3}}},
|
||||
}
|
||||
|
||||
G = self.Graph()
|
||||
edges = [
|
||||
(0, 1, {"weight": 3}),
|
||||
(0, 1, (("weight", 2),)),
|
||||
(0, 1, 5),
|
||||
(0, 1, "s"),
|
||||
]
|
||||
G.add_edges_from(edges)
|
||||
keydict = {0: {"weight": 3}, 1: {"weight": 2}, 5: {}, "s": {}}
|
||||
assert G._succ == {0: {1: keydict}, 1: {}}
|
||||
assert G._pred == {1: {0: keydict}, 0: {}}
|
||||
|
||||
# too few in tuple
|
||||
pytest.raises(nx.NetworkXError, G.add_edges_from, [(0,)])
|
||||
# too many in tuple
|
||||
pytest.raises(nx.NetworkXError, G.add_edges_from, [(0, 1, 2, 3, 4)])
|
||||
# not a tuple
|
||||
pytest.raises(TypeError, G.add_edges_from, [0])
|
||||
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
|
||||
G.remove_edge(0, 1)
|
||||
assert G._succ == {
|
||||
0: {2: {0: {}}},
|
||||
1: {0: {0: {}}, 2: {0: {}}},
|
||||
2: {0: {0: {}}, 1: {0: {}}},
|
||||
}
|
||||
assert G._pred == {
|
||||
0: {1: {0: {}}, 2: {0: {}}},
|
||||
1: {2: {0: {}}},
|
||||
2: {0: {0: {}}, 1: {0: {}}},
|
||||
}
|
||||
pytest.raises((KeyError, nx.NetworkXError), G.remove_edge, -1, 0)
|
||||
pytest.raises((KeyError, nx.NetworkXError), G.remove_edge, 0, 2, key=1)
|
||||
|
||||
def test_remove_multiedge(self):
|
||||
G = self.K3
|
||||
G.add_edge(0, 1, key="parallel edge")
|
||||
G.remove_edge(0, 1, key="parallel edge")
|
||||
assert G._adj == {
|
||||
0: {1: {0: {}}, 2: {0: {}}},
|
||||
1: {0: {0: {}}, 2: {0: {}}},
|
||||
2: {0: {0: {}}, 1: {0: {}}},
|
||||
}
|
||||
|
||||
assert G._succ == {
|
||||
0: {1: {0: {}}, 2: {0: {}}},
|
||||
1: {0: {0: {}}, 2: {0: {}}},
|
||||
2: {0: {0: {}}, 1: {0: {}}},
|
||||
}
|
||||
|
||||
assert G._pred == {
|
||||
0: {1: {0: {}}, 2: {0: {}}},
|
||||
1: {0: {0: {}}, 2: {0: {}}},
|
||||
2: {0: {0: {}}, 1: {0: {}}},
|
||||
}
|
||||
G.remove_edge(0, 1)
|
||||
assert G._succ == {
|
||||
0: {2: {0: {}}},
|
||||
1: {0: {0: {}}, 2: {0: {}}},
|
||||
2: {0: {0: {}}, 1: {0: {}}},
|
||||
}
|
||||
assert G._pred == {
|
||||
0: {1: {0: {}}, 2: {0: {}}},
|
||||
1: {2: {0: {}}},
|
||||
2: {0: {0: {}}, 1: {0: {}}},
|
||||
}
|
||||
pytest.raises((KeyError, nx.NetworkXError), G.remove_edge, -1, 0)
|
||||
|
||||
def test_remove_edges_from(self):
|
||||
G = self.K3
|
||||
G.remove_edges_from([(0, 1)])
|
||||
assert G._succ == {
|
||||
0: {2: {0: {}}},
|
||||
1: {0: {0: {}}, 2: {0: {}}},
|
||||
2: {0: {0: {}}, 1: {0: {}}},
|
||||
}
|
||||
assert G._pred == {
|
||||
0: {1: {0: {}}, 2: {0: {}}},
|
||||
1: {2: {0: {}}},
|
||||
2: {0: {0: {}}, 1: {0: {}}},
|
||||
}
|
||||
G.remove_edges_from([(0, 0)]) # silent fail
|
||||
|
||||
|
||||
class TestEdgeSubgraph(_TestMultiGraphEdgeSubgraph):
|
||||
"""Unit tests for the :meth:`MultiDiGraph.edge_subgraph` method."""
|
||||
|
||||
def setup_method(self):
|
||||
# Create a quadruply-linked path graph on five nodes.
|
||||
G = nx.MultiDiGraph()
|
||||
nx.add_path(G, range(5))
|
||||
nx.add_path(G, range(5))
|
||||
nx.add_path(G, reversed(range(5)))
|
||||
nx.add_path(G, reversed(range(5)))
|
||||
# Add some node, edge, and graph attributes.
|
||||
for i in range(5):
|
||||
G.nodes[i]["name"] = f"node{i}"
|
||||
G.adj[0][1][0]["name"] = "edge010"
|
||||
G.adj[0][1][1]["name"] = "edge011"
|
||||
G.adj[3][4][0]["name"] = "edge340"
|
||||
G.adj[3][4][1]["name"] = "edge341"
|
||||
G.graph["name"] = "graph"
|
||||
# Get the subgraph induced by one of the first edges and one of
|
||||
# the last edges.
|
||||
self.G = G
|
||||
self.H = G.edge_subgraph([(0, 1, 0), (3, 4, 1)])
|
||||
|
||||
|
||||
class CustomDictClass(UserDict):
|
||||
pass
|
||||
|
||||
|
||||
class MultiDiGraphSubClass(nx.MultiDiGraph):
|
||||
node_dict_factory = CustomDictClass # type: ignore[assignment]
|
||||
node_attr_dict_factory = CustomDictClass # type: ignore[assignment]
|
||||
adjlist_outer_dict_factory = CustomDictClass # type: ignore[assignment]
|
||||
adjlist_inner_dict_factory = CustomDictClass # type: ignore[assignment]
|
||||
edge_key_dict_factory = CustomDictClass # type: ignore[assignment]
|
||||
edge_attr_dict_factory = CustomDictClass # type: ignore[assignment]
|
||||
graph_attr_dict_factory = CustomDictClass # type: ignore[assignment]
|
||||
|
||||
|
||||
class TestMultiDiGraphSubclass(TestMultiDiGraph):
|
||||
def setup_method(self):
|
||||
self.Graph = MultiDiGraphSubClass
|
||||
# build K3
|
||||
self.k3edges = [(0, 1), (0, 2), (1, 2)]
|
||||
self.k3nodes = [0, 1, 2]
|
||||
self.K3 = self.Graph()
|
||||
self.K3._succ = self.K3.adjlist_outer_dict_factory(
|
||||
{
|
||||
0: self.K3.adjlist_inner_dict_factory(),
|
||||
1: self.K3.adjlist_inner_dict_factory(),
|
||||
2: self.K3.adjlist_inner_dict_factory(),
|
||||
}
|
||||
)
|
||||
# K3._adj is synced with K3._succ
|
||||
self.K3._pred = {0: {}, 1: {}, 2: {}}
|
||||
for u in self.k3nodes:
|
||||
for v in self.k3nodes:
|
||||
if u == v:
|
||||
continue
|
||||
d = {0: {}}
|
||||
self.K3._succ[u][v] = d
|
||||
self.K3._pred[v][u] = d
|
||||
self.K3._node = self.K3.node_dict_factory()
|
||||
self.K3._node[0] = self.K3.node_attr_dict_factory()
|
||||
self.K3._node[1] = self.K3.node_attr_dict_factory()
|
||||
self.K3._node[2] = self.K3.node_attr_dict_factory()
|
||||
528
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_multigraph.py
vendored
Normal file
528
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_multigraph.py
vendored
Normal file
@@ -0,0 +1,528 @@
|
||||
from collections import UserDict
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.utils import edges_equal
|
||||
|
||||
from .test_graph import BaseAttrGraphTester
|
||||
from .test_graph import TestGraph as _TestGraph
|
||||
|
||||
|
||||
class BaseMultiGraphTester(BaseAttrGraphTester):
|
||||
def test_has_edge(self):
|
||||
G = self.K3
|
||||
assert G.has_edge(0, 1)
|
||||
assert not G.has_edge(0, -1)
|
||||
assert G.has_edge(0, 1, 0)
|
||||
assert not G.has_edge(0, 1, 1)
|
||||
|
||||
def test_get_edge_data(self):
|
||||
G = self.K3
|
||||
assert G.get_edge_data(0, 1) == {0: {}}
|
||||
assert G[0][1] == {0: {}}
|
||||
assert G[0][1][0] == {}
|
||||
assert G.get_edge_data(10, 20) is None
|
||||
assert G.get_edge_data(0, 1, 0) == {}
|
||||
|
||||
def test_adjacency(self):
|
||||
G = self.K3
|
||||
assert dict(G.adjacency()) == {
|
||||
0: {1: {0: {}}, 2: {0: {}}},
|
||||
1: {0: {0: {}}, 2: {0: {}}},
|
||||
2: {0: {0: {}}, 1: {0: {}}},
|
||||
}
|
||||
|
||||
def deepcopy_edge_attr(self, H, G):
|
||||
assert G[1][2][0]["foo"] == H[1][2][0]["foo"]
|
||||
G[1][2][0]["foo"].append(1)
|
||||
assert G[1][2][0]["foo"] != H[1][2][0]["foo"]
|
||||
|
||||
def shallow_copy_edge_attr(self, H, G):
|
||||
assert G[1][2][0]["foo"] == H[1][2][0]["foo"]
|
||||
G[1][2][0]["foo"].append(1)
|
||||
assert G[1][2][0]["foo"] == H[1][2][0]["foo"]
|
||||
|
||||
def graphs_equal(self, H, G):
|
||||
assert G._adj == H._adj
|
||||
assert G._node == H._node
|
||||
assert G.graph == H.graph
|
||||
assert G.name == H.name
|
||||
if not G.is_directed() and not H.is_directed():
|
||||
assert H._adj[1][2][0] is H._adj[2][1][0]
|
||||
assert G._adj[1][2][0] is G._adj[2][1][0]
|
||||
else: # at least one is directed
|
||||
if not G.is_directed():
|
||||
G._pred = G._adj
|
||||
G._succ = G._adj
|
||||
if not H.is_directed():
|
||||
H._pred = H._adj
|
||||
H._succ = H._adj
|
||||
assert G._pred == H._pred
|
||||
assert G._succ == H._succ
|
||||
assert H._succ[1][2][0] is H._pred[2][1][0]
|
||||
assert G._succ[1][2][0] is G._pred[2][1][0]
|
||||
|
||||
def same_attrdict(self, H, G):
|
||||
# same attrdict in the edgedata
|
||||
old_foo = H[1][2][0]["foo"]
|
||||
H.adj[1][2][0]["foo"] = "baz"
|
||||
assert G._adj == H._adj
|
||||
H.adj[1][2][0]["foo"] = old_foo
|
||||
assert G._adj == H._adj
|
||||
|
||||
old_foo = H.nodes[0]["foo"]
|
||||
H.nodes[0]["foo"] = "baz"
|
||||
assert G._node == H._node
|
||||
H.nodes[0]["foo"] = old_foo
|
||||
assert G._node == H._node
|
||||
|
||||
def different_attrdict(self, H, G):
|
||||
# used by graph_equal_but_different
|
||||
old_foo = H[1][2][0]["foo"]
|
||||
H.adj[1][2][0]["foo"] = "baz"
|
||||
assert G._adj != H._adj
|
||||
H.adj[1][2][0]["foo"] = old_foo
|
||||
assert G._adj == H._adj
|
||||
|
||||
old_foo = H.nodes[0]["foo"]
|
||||
H.nodes[0]["foo"] = "baz"
|
||||
assert G._node != H._node
|
||||
H.nodes[0]["foo"] = old_foo
|
||||
assert G._node == H._node
|
||||
|
||||
def test_to_undirected(self):
|
||||
G = self.K3
|
||||
self.add_attributes(G)
|
||||
H = nx.MultiGraph(G)
|
||||
self.is_shallow_copy(H, G)
|
||||
H = G.to_undirected()
|
||||
self.is_deepcopy(H, G)
|
||||
|
||||
def test_to_directed(self):
|
||||
G = self.K3
|
||||
self.add_attributes(G)
|
||||
H = nx.MultiDiGraph(G)
|
||||
self.is_shallow_copy(H, G)
|
||||
H = G.to_directed()
|
||||
self.is_deepcopy(H, G)
|
||||
|
||||
def test_number_of_edges_selfloops(self):
|
||||
G = self.K3
|
||||
G.add_edge(0, 0)
|
||||
G.add_edge(0, 0)
|
||||
G.add_edge(0, 0, key="parallel edge")
|
||||
G.remove_edge(0, 0, key="parallel edge")
|
||||
assert G.number_of_edges(0, 0) == 2
|
||||
G.remove_edge(0, 0)
|
||||
assert G.number_of_edges(0, 0) == 1
|
||||
|
||||
def test_edge_lookup(self):
|
||||
G = self.Graph()
|
||||
G.add_edge(1, 2, foo="bar")
|
||||
G.add_edge(1, 2, "key", foo="biz")
|
||||
assert edges_equal(G.edges[1, 2, 0], {"foo": "bar"})
|
||||
assert edges_equal(G.edges[1, 2, "key"], {"foo": "biz"})
|
||||
|
||||
def test_edge_attr(self):
|
||||
G = self.Graph()
|
||||
G.add_edge(1, 2, key="k1", foo="bar")
|
||||
G.add_edge(1, 2, key="k2", foo="baz")
|
||||
assert isinstance(G.get_edge_data(1, 2), G.edge_key_dict_factory)
|
||||
assert all(
|
||||
isinstance(d, G.edge_attr_dict_factory) for u, v, d in G.edges(data=True)
|
||||
)
|
||||
assert edges_equal(
|
||||
G.edges(keys=True, data=True),
|
||||
[(1, 2, "k1", {"foo": "bar"}), (1, 2, "k2", {"foo": "baz"})],
|
||||
)
|
||||
assert edges_equal(
|
||||
G.edges(keys=True, data="foo"), [(1, 2, "k1", "bar"), (1, 2, "k2", "baz")]
|
||||
)
|
||||
|
||||
def test_edge_attr4(self):
|
||||
G = self.Graph()
|
||||
G.add_edge(1, 2, key=0, data=7, spam="bar", bar="foo")
|
||||
assert edges_equal(
|
||||
G.edges(data=True), [(1, 2, {"data": 7, "spam": "bar", "bar": "foo"})]
|
||||
)
|
||||
G[1][2][0]["data"] = 10 # OK to set data like this
|
||||
assert edges_equal(
|
||||
G.edges(data=True), [(1, 2, {"data": 10, "spam": "bar", "bar": "foo"})]
|
||||
)
|
||||
|
||||
G.adj[1][2][0]["data"] = 20
|
||||
assert edges_equal(
|
||||
G.edges(data=True), [(1, 2, {"data": 20, "spam": "bar", "bar": "foo"})]
|
||||
)
|
||||
G.edges[1, 2, 0]["data"] = 21 # another spelling, "edge"
|
||||
assert edges_equal(
|
||||
G.edges(data=True), [(1, 2, {"data": 21, "spam": "bar", "bar": "foo"})]
|
||||
)
|
||||
G.adj[1][2][0]["listdata"] = [20, 200]
|
||||
G.adj[1][2][0]["weight"] = 20
|
||||
assert edges_equal(
|
||||
G.edges(data=True),
|
||||
[
|
||||
(
|
||||
1,
|
||||
2,
|
||||
{
|
||||
"data": 21,
|
||||
"spam": "bar",
|
||||
"bar": "foo",
|
||||
"listdata": [20, 200],
|
||||
"weight": 20,
|
||||
},
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
class TestMultiGraph(BaseMultiGraphTester, _TestGraph):
|
||||
def setup_method(self):
|
||||
self.Graph = nx.MultiGraph
|
||||
# build K3
|
||||
ed1, ed2, ed3 = ({0: {}}, {0: {}}, {0: {}})
|
||||
self.k3adj = {0: {1: ed1, 2: ed2}, 1: {0: ed1, 2: ed3}, 2: {0: ed2, 1: ed3}}
|
||||
self.k3edges = [(0, 1), (0, 2), (1, 2)]
|
||||
self.k3nodes = [0, 1, 2]
|
||||
self.K3 = self.Graph()
|
||||
self.K3._adj = self.k3adj
|
||||
self.K3._node = {}
|
||||
self.K3._node[0] = {}
|
||||
self.K3._node[1] = {}
|
||||
self.K3._node[2] = {}
|
||||
|
||||
def test_data_input(self):
|
||||
G = self.Graph({1: [2], 2: [1]}, name="test")
|
||||
assert G.name == "test"
|
||||
expected = [(1, {2: {0: {}}}), (2, {1: {0: {}}})]
|
||||
assert sorted(G.adj.items()) == expected
|
||||
|
||||
def test_data_multigraph_input(self):
|
||||
# standard case with edge keys and edge data
|
||||
edata0 = {"w": 200, "s": "foo"}
|
||||
edata1 = {"w": 201, "s": "bar"}
|
||||
keydict = {0: edata0, 1: edata1}
|
||||
dododod = {"a": {"b": keydict}}
|
||||
|
||||
multiple_edge = [("a", "b", 0, edata0), ("a", "b", 1, edata1)]
|
||||
single_edge = [("a", "b", 0, keydict)]
|
||||
|
||||
G = self.Graph(dododod, multigraph_input=True)
|
||||
assert list(G.edges(keys=True, data=True)) == multiple_edge
|
||||
G = self.Graph(dododod, multigraph_input=None)
|
||||
assert list(G.edges(keys=True, data=True)) == multiple_edge
|
||||
G = self.Graph(dododod, multigraph_input=False)
|
||||
assert list(G.edges(keys=True, data=True)) == single_edge
|
||||
|
||||
# test round-trip to_dict_of_dict and MultiGraph constructor
|
||||
G = self.Graph(dododod, multigraph_input=True)
|
||||
H = self.Graph(nx.to_dict_of_dicts(G))
|
||||
assert nx.is_isomorphic(G, H) is True # test that default is True
|
||||
for mgi in [True, False]:
|
||||
H = self.Graph(nx.to_dict_of_dicts(G), multigraph_input=mgi)
|
||||
assert nx.is_isomorphic(G, H) == mgi
|
||||
|
||||
# Set up cases for when incoming_graph_data is not multigraph_input
|
||||
etraits = {"w": 200, "s": "foo"}
|
||||
egraphics = {"color": "blue", "shape": "box"}
|
||||
edata = {"traits": etraits, "graphics": egraphics}
|
||||
dodod1 = {"a": {"b": edata}}
|
||||
dodod2 = {"a": {"b": etraits}}
|
||||
dodod3 = {"a": {"b": {"traits": etraits, "s": "foo"}}}
|
||||
dol = {"a": ["b"]}
|
||||
|
||||
multiple_edge = [("a", "b", "traits", etraits), ("a", "b", "graphics", egraphics)]
|
||||
single_edge = [("a", "b", 0, {})] # type: ignore[var-annotated]
|
||||
single_edge1 = [("a", "b", 0, edata)]
|
||||
single_edge2 = [("a", "b", 0, etraits)]
|
||||
single_edge3 = [("a", "b", 0, {"traits": etraits, "s": "foo"})]
|
||||
|
||||
cases = [ # (dod, mgi, edges)
|
||||
(dodod1, True, multiple_edge),
|
||||
(dodod1, False, single_edge1),
|
||||
(dodod2, False, single_edge2),
|
||||
(dodod3, False, single_edge3),
|
||||
(dol, False, single_edge),
|
||||
]
|
||||
|
||||
@pytest.mark.parametrize("dod, mgi, edges", cases)
|
||||
def test_non_multigraph_input(self, dod, mgi, edges):
|
||||
G = self.Graph(dod, multigraph_input=mgi)
|
||||
assert list(G.edges(keys=True, data=True)) == edges
|
||||
G = nx.to_networkx_graph(dod, create_using=self.Graph, multigraph_input=mgi)
|
||||
assert list(G.edges(keys=True, data=True)) == edges
|
||||
|
||||
mgi_none_cases = [
|
||||
(dodod1, multiple_edge),
|
||||
(dodod2, single_edge2),
|
||||
(dodod3, single_edge3),
|
||||
]
|
||||
|
||||
@pytest.mark.parametrize("dod, edges", mgi_none_cases)
|
||||
def test_non_multigraph_input_mgi_none(self, dod, edges):
|
||||
# test constructor without to_networkx_graph for mgi=None
|
||||
G = self.Graph(dod)
|
||||
assert list(G.edges(keys=True, data=True)) == edges
|
||||
|
||||
raise_cases = [dodod2, dodod3, dol]
|
||||
|
||||
@pytest.mark.parametrize("dod", raise_cases)
|
||||
def test_non_multigraph_input_raise(self, dod):
|
||||
# cases where NetworkXError is raised
|
||||
pytest.raises(nx.NetworkXError, self.Graph, dod, multigraph_input=True)
|
||||
pytest.raises(
|
||||
nx.NetworkXError,
|
||||
nx.to_networkx_graph,
|
||||
dod,
|
||||
create_using=self.Graph,
|
||||
multigraph_input=True,
|
||||
)
|
||||
|
||||
def test_getitem(self):
|
||||
G = self.K3
|
||||
assert G[0] == {1: {0: {}}, 2: {0: {}}}
|
||||
with pytest.raises(KeyError):
|
||||
G.__getitem__("j")
|
||||
with pytest.raises(TypeError):
|
||||
G.__getitem__(["A"])
|
||||
|
||||
def test_remove_node(self):
|
||||
G = self.K3
|
||||
G.remove_node(0)
|
||||
assert G.adj == {1: {2: {0: {}}}, 2: {1: {0: {}}}}
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
G.remove_node(-1)
|
||||
|
||||
def test_add_edge(self):
|
||||
G = self.Graph()
|
||||
G.add_edge(0, 1)
|
||||
assert G.adj == {0: {1: {0: {}}}, 1: {0: {0: {}}}}
|
||||
G = self.Graph()
|
||||
G.add_edge(*(0, 1))
|
||||
assert G.adj == {0: {1: {0: {}}}, 1: {0: {0: {}}}}
|
||||
G = self.Graph()
|
||||
with pytest.raises(ValueError):
|
||||
G.add_edge(None, "anything")
|
||||
|
||||
def test_add_edge_conflicting_key(self):
|
||||
G = self.Graph()
|
||||
G.add_edge(0, 1, key=1)
|
||||
G.add_edge(0, 1)
|
||||
assert G.number_of_edges() == 2
|
||||
G = self.Graph()
|
||||
G.add_edges_from([(0, 1, 1, {})])
|
||||
G.add_edges_from([(0, 1)])
|
||||
assert G.number_of_edges() == 2
|
||||
|
||||
def test_add_edges_from(self):
|
||||
G = self.Graph()
|
||||
G.add_edges_from([(0, 1), (0, 1, {"weight": 3})])
|
||||
assert G.adj == {
|
||||
0: {1: {0: {}, 1: {"weight": 3}}},
|
||||
1: {0: {0: {}, 1: {"weight": 3}}},
|
||||
}
|
||||
G.add_edges_from([(0, 1), (0, 1, {"weight": 3})], weight=2)
|
||||
assert G.adj == {
|
||||
0: {1: {0: {}, 1: {"weight": 3}, 2: {"weight": 2}, 3: {"weight": 3}}},
|
||||
1: {0: {0: {}, 1: {"weight": 3}, 2: {"weight": 2}, 3: {"weight": 3}}},
|
||||
}
|
||||
G = self.Graph()
|
||||
edges = [
|
||||
(0, 1, {"weight": 3}),
|
||||
(0, 1, (("weight", 2),)),
|
||||
(0, 1, 5),
|
||||
(0, 1, "s"),
|
||||
]
|
||||
G.add_edges_from(edges)
|
||||
keydict = {0: {"weight": 3}, 1: {"weight": 2}, 5: {}, "s": {}}
|
||||
assert G._adj == {0: {1: keydict}, 1: {0: keydict}}
|
||||
|
||||
# too few in tuple
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
G.add_edges_from([(0,)])
|
||||
# too many in tuple
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
G.add_edges_from([(0, 1, 2, 3, 4)])
|
||||
# not a tuple
|
||||
with pytest.raises(TypeError):
|
||||
G.add_edges_from([0])
|
||||
|
||||
def test_multigraph_add_edges_from_four_tuple_misordered(self):
|
||||
"""add_edges_from expects 4-tuples of the format (u, v, key, data_dict).
|
||||
|
||||
Ensure 4-tuples of form (u, v, data_dict, key) raise exception.
|
||||
"""
|
||||
G = nx.MultiGraph()
|
||||
with pytest.raises(TypeError):
|
||||
# key/data values flipped in 4-tuple
|
||||
G.add_edges_from([(0, 1, {"color": "red"}, 0)])
|
||||
|
||||
def test_remove_edge(self):
|
||||
G = self.K3
|
||||
G.remove_edge(0, 1)
|
||||
assert G.adj == {0: {2: {0: {}}}, 1: {2: {0: {}}}, 2: {0: {0: {}}, 1: {0: {}}}}
|
||||
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
G.remove_edge(-1, 0)
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
G.remove_edge(0, 2, key=1)
|
||||
|
||||
def test_remove_edges_from(self):
|
||||
G = self.K3.copy()
|
||||
G.remove_edges_from([(0, 1)])
|
||||
kd = {0: {}}
|
||||
assert G.adj == {0: {2: kd}, 1: {2: kd}, 2: {0: kd, 1: kd}}
|
||||
G.remove_edges_from([(0, 0)]) # silent fail
|
||||
self.K3.add_edge(0, 1)
|
||||
G = self.K3.copy()
|
||||
G.remove_edges_from(list(G.edges(data=True, keys=True)))
|
||||
assert G.adj == {0: {}, 1: {}, 2: {}}
|
||||
G = self.K3.copy()
|
||||
G.remove_edges_from(list(G.edges(data=False, keys=True)))
|
||||
assert G.adj == {0: {}, 1: {}, 2: {}}
|
||||
G = self.K3.copy()
|
||||
G.remove_edges_from(list(G.edges(data=False, keys=False)))
|
||||
assert G.adj == {0: {}, 1: {}, 2: {}}
|
||||
G = self.K3.copy()
|
||||
G.remove_edges_from([(0, 1, 0), (0, 2, 0, {}), (1, 2)])
|
||||
assert G.adj == {0: {1: {1: {}}}, 1: {0: {1: {}}}, 2: {}}
|
||||
|
||||
def test_remove_multiedge(self):
|
||||
G = self.K3
|
||||
G.add_edge(0, 1, key="parallel edge")
|
||||
G.remove_edge(0, 1, key="parallel edge")
|
||||
assert G.adj == {
|
||||
0: {1: {0: {}}, 2: {0: {}}},
|
||||
1: {0: {0: {}}, 2: {0: {}}},
|
||||
2: {0: {0: {}}, 1: {0: {}}},
|
||||
}
|
||||
G.remove_edge(0, 1)
|
||||
kd = {0: {}}
|
||||
assert G.adj == {0: {2: kd}, 1: {2: kd}, 2: {0: kd, 1: kd}}
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
G.remove_edge(-1, 0)
|
||||
|
||||
|
||||
class TestEdgeSubgraph:
|
||||
"""Unit tests for the :meth:`MultiGraph.edge_subgraph` method."""
|
||||
|
||||
def setup_method(self):
|
||||
# Create a doubly-linked path graph on five nodes.
|
||||
G = nx.MultiGraph()
|
||||
nx.add_path(G, range(5))
|
||||
nx.add_path(G, range(5))
|
||||
# Add some node, edge, and graph attributes.
|
||||
for i in range(5):
|
||||
G.nodes[i]["name"] = f"node{i}"
|
||||
G.adj[0][1][0]["name"] = "edge010"
|
||||
G.adj[0][1][1]["name"] = "edge011"
|
||||
G.adj[3][4][0]["name"] = "edge340"
|
||||
G.adj[3][4][1]["name"] = "edge341"
|
||||
G.graph["name"] = "graph"
|
||||
# Get the subgraph induced by one of the first edges and one of
|
||||
# the last edges.
|
||||
self.G = G
|
||||
self.H = G.edge_subgraph([(0, 1, 0), (3, 4, 1)])
|
||||
|
||||
def test_correct_nodes(self):
|
||||
"""Tests that the subgraph has the correct nodes."""
|
||||
assert [0, 1, 3, 4] == sorted(self.H.nodes())
|
||||
|
||||
def test_correct_edges(self):
|
||||
"""Tests that the subgraph has the correct edges."""
|
||||
assert [(0, 1, 0, "edge010"), (3, 4, 1, "edge341")] == sorted(
|
||||
self.H.edges(keys=True, data="name")
|
||||
)
|
||||
|
||||
def test_add_node(self):
|
||||
"""Tests that adding a node to the original graph does not
|
||||
affect the nodes of the subgraph.
|
||||
|
||||
"""
|
||||
self.G.add_node(5)
|
||||
assert [0, 1, 3, 4] == sorted(self.H.nodes())
|
||||
|
||||
def test_remove_node(self):
|
||||
"""Tests that removing a node in the original graph does
|
||||
affect the nodes of the subgraph.
|
||||
|
||||
"""
|
||||
self.G.remove_node(0)
|
||||
assert [1, 3, 4] == sorted(self.H.nodes())
|
||||
|
||||
def test_node_attr_dict(self):
|
||||
"""Tests that the node attribute dictionary of the two graphs is
|
||||
the same object.
|
||||
|
||||
"""
|
||||
for v in self.H:
|
||||
assert self.G.nodes[v] == self.H.nodes[v]
|
||||
# Making a change to G should make a change in H and vice versa.
|
||||
self.G.nodes[0]["name"] = "foo"
|
||||
assert self.G.nodes[0] == self.H.nodes[0]
|
||||
self.H.nodes[1]["name"] = "bar"
|
||||
assert self.G.nodes[1] == self.H.nodes[1]
|
||||
|
||||
def test_edge_attr_dict(self):
|
||||
"""Tests that the edge attribute dictionary of the two graphs is
|
||||
the same object.
|
||||
|
||||
"""
|
||||
for u, v, k in self.H.edges(keys=True):
|
||||
assert self.G._adj[u][v][k] == self.H._adj[u][v][k]
|
||||
# Making a change to G should make a change in H and vice versa.
|
||||
self.G._adj[0][1][0]["name"] = "foo"
|
||||
assert self.G._adj[0][1][0]["name"] == self.H._adj[0][1][0]["name"]
|
||||
self.H._adj[3][4][1]["name"] = "bar"
|
||||
assert self.G._adj[3][4][1]["name"] == self.H._adj[3][4][1]["name"]
|
||||
|
||||
def test_graph_attr_dict(self):
|
||||
"""Tests that the graph attribute dictionary of the two graphs
|
||||
is the same object.
|
||||
|
||||
"""
|
||||
assert self.G.graph is self.H.graph
|
||||
|
||||
|
||||
class CustomDictClass(UserDict):
|
||||
pass
|
||||
|
||||
|
||||
class MultiGraphSubClass(nx.MultiGraph):
|
||||
node_dict_factory = CustomDictClass # type: ignore[assignment]
|
||||
node_attr_dict_factory = CustomDictClass # type: ignore[assignment]
|
||||
adjlist_outer_dict_factory = CustomDictClass # type: ignore[assignment]
|
||||
adjlist_inner_dict_factory = CustomDictClass # type: ignore[assignment]
|
||||
edge_key_dict_factory = CustomDictClass # type: ignore[assignment]
|
||||
edge_attr_dict_factory = CustomDictClass # type: ignore[assignment]
|
||||
graph_attr_dict_factory = CustomDictClass # type: ignore[assignment]
|
||||
|
||||
|
||||
class TestMultiGraphSubclass(TestMultiGraph):
|
||||
def setup_method(self):
|
||||
self.Graph = MultiGraphSubClass
|
||||
# build K3
|
||||
self.k3edges = [(0, 1), (0, 2), (1, 2)]
|
||||
self.k3nodes = [0, 1, 2]
|
||||
self.K3 = self.Graph()
|
||||
self.K3._adj = self.K3.adjlist_outer_dict_factory(
|
||||
{
|
||||
0: self.K3.adjlist_inner_dict_factory(),
|
||||
1: self.K3.adjlist_inner_dict_factory(),
|
||||
2: self.K3.adjlist_inner_dict_factory(),
|
||||
}
|
||||
)
|
||||
self.K3._pred = {0: {}, 1: {}, 2: {}}
|
||||
for u in self.k3nodes:
|
||||
for v in self.k3nodes:
|
||||
if u != v:
|
||||
d = {0: {}}
|
||||
self.K3._adj[u][v] = d
|
||||
self.K3._adj[v][u] = d
|
||||
self.K3._node = self.K3.node_dict_factory()
|
||||
self.K3._node[0] = self.K3.node_attr_dict_factory()
|
||||
self.K3._node[1] = self.K3.node_attr_dict_factory()
|
||||
self.K3._node[2] = self.K3.node_attr_dict_factory()
|
||||
1427
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_reportviews.py
vendored
Normal file
1427
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_reportviews.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
131
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_special.py
vendored
Normal file
131
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_special.py
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
import networkx as nx
|
||||
|
||||
from .test_digraph import BaseDiGraphTester
|
||||
from .test_digraph import TestDiGraph as _TestDiGraph
|
||||
from .test_graph import BaseGraphTester
|
||||
from .test_graph import TestGraph as _TestGraph
|
||||
from .test_multidigraph import TestMultiDiGraph as _TestMultiDiGraph
|
||||
from .test_multigraph import TestMultiGraph as _TestMultiGraph
|
||||
|
||||
|
||||
def test_factories():
|
||||
class mydict1(dict):
|
||||
pass
|
||||
|
||||
class mydict2(dict):
|
||||
pass
|
||||
|
||||
class mydict3(dict):
|
||||
pass
|
||||
|
||||
class mydict4(dict):
|
||||
pass
|
||||
|
||||
class mydict5(dict):
|
||||
pass
|
||||
|
||||
for Graph in (nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph):
|
||||
# print("testing class: ", Graph.__name__)
|
||||
class MyGraph(Graph):
|
||||
node_dict_factory = mydict1
|
||||
adjlist_outer_dict_factory = mydict2
|
||||
adjlist_inner_dict_factory = mydict3
|
||||
edge_key_dict_factory = mydict4
|
||||
edge_attr_dict_factory = mydict5
|
||||
|
||||
G = MyGraph()
|
||||
assert isinstance(G._node, mydict1)
|
||||
assert isinstance(G._adj, mydict2)
|
||||
G.add_node(1)
|
||||
assert isinstance(G._adj[1], mydict3)
|
||||
if G.is_directed():
|
||||
assert isinstance(G._pred, mydict2)
|
||||
assert isinstance(G._succ, mydict2)
|
||||
assert isinstance(G._pred[1], mydict3)
|
||||
G.add_edge(1, 2)
|
||||
if G.is_multigraph():
|
||||
assert isinstance(G._adj[1][2], mydict4)
|
||||
assert isinstance(G._adj[1][2][0], mydict5)
|
||||
else:
|
||||
assert isinstance(G._adj[1][2], mydict5)
|
||||
|
||||
|
||||
class TestSpecialGraph(_TestGraph):
|
||||
def setup_method(self):
|
||||
_TestGraph.setup_method(self)
|
||||
self.Graph = nx.Graph
|
||||
|
||||
|
||||
class TestThinGraph(BaseGraphTester):
|
||||
def setup_method(self):
|
||||
all_edge_dict = {"weight": 1}
|
||||
|
||||
class MyGraph(nx.Graph):
|
||||
def edge_attr_dict_factory(self):
|
||||
return all_edge_dict
|
||||
|
||||
self.Graph = MyGraph
|
||||
# build dict-of-dict-of-dict K3
|
||||
ed1, ed2, ed3 = (all_edge_dict, all_edge_dict, all_edge_dict)
|
||||
self.k3adj = {0: {1: ed1, 2: ed2}, 1: {0: ed1, 2: ed3}, 2: {0: ed2, 1: ed3}}
|
||||
self.k3edges = [(0, 1), (0, 2), (1, 2)]
|
||||
self.k3nodes = [0, 1, 2]
|
||||
self.K3 = self.Graph()
|
||||
self.K3._adj = self.k3adj
|
||||
self.K3._node = {}
|
||||
self.K3._node[0] = {}
|
||||
self.K3._node[1] = {}
|
||||
self.K3._node[2] = {}
|
||||
|
||||
|
||||
class TestSpecialDiGraph(_TestDiGraph):
|
||||
def setup_method(self):
|
||||
_TestDiGraph.setup_method(self)
|
||||
self.Graph = nx.DiGraph
|
||||
|
||||
|
||||
class TestThinDiGraph(BaseDiGraphTester):
|
||||
def setup_method(self):
|
||||
all_edge_dict = {"weight": 1}
|
||||
|
||||
class MyGraph(nx.DiGraph):
|
||||
def edge_attr_dict_factory(self):
|
||||
return all_edge_dict
|
||||
|
||||
self.Graph = MyGraph
|
||||
# build dict-of-dict-of-dict K3
|
||||
ed1, ed2, ed3 = (all_edge_dict, all_edge_dict, all_edge_dict)
|
||||
ed4, ed5, ed6 = (all_edge_dict, all_edge_dict, all_edge_dict)
|
||||
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 = (all_edge_dict, all_edge_dict)
|
||||
self.P3 = self.Graph()
|
||||
self.P3._succ = {0: {1: ed1}, 1: {2: ed2}, 2: {}}
|
||||
# P3._adj is synced with P3._succ
|
||||
self.P3._pred = {0: {}, 1: {0: ed1}, 2: {1: ed2}}
|
||||
self.P3._node = {}
|
||||
self.P3._node[0] = {}
|
||||
self.P3._node[1] = {}
|
||||
self.P3._node[2] = {}
|
||||
|
||||
|
||||
class TestSpecialMultiGraph(_TestMultiGraph):
|
||||
def setup_method(self):
|
||||
_TestMultiGraph.setup_method(self)
|
||||
self.Graph = nx.MultiGraph
|
||||
|
||||
|
||||
class TestSpecialMultiDiGraph(_TestMultiDiGraph):
|
||||
def setup_method(self):
|
||||
_TestMultiDiGraph.setup_method(self)
|
||||
self.Graph = nx.MultiDiGraph
|
||||
362
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_subgraphviews.py
vendored
Normal file
362
.CondaPkg/env/Lib/site-packages/networkx/classes/tests/test_subgraphviews.py
vendored
Normal file
@@ -0,0 +1,362 @@
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.utils import edges_equal
|
||||
|
||||
|
||||
class TestSubGraphView:
|
||||
gview = staticmethod(nx.subgraph_view)
|
||||
graph = nx.Graph
|
||||
hide_edges_filter = staticmethod(nx.filters.hide_edges)
|
||||
show_edges_filter = staticmethod(nx.filters.show_edges)
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.G = nx.path_graph(9, create_using=cls.graph())
|
||||
cls.hide_edges_w_hide_nodes = {(3, 4), (4, 5), (5, 6)}
|
||||
|
||||
def test_hidden_nodes(self):
|
||||
hide_nodes = [4, 5, 111]
|
||||
nodes_gone = nx.filters.hide_nodes(hide_nodes)
|
||||
gview = self.gview
|
||||
G = gview(self.G, filter_node=nodes_gone)
|
||||
assert self.G.nodes - G.nodes == {4, 5}
|
||||
assert self.G.edges - G.edges == self.hide_edges_w_hide_nodes
|
||||
if G.is_directed():
|
||||
assert list(G[3]) == []
|
||||
assert list(G[2]) == [3]
|
||||
else:
|
||||
assert list(G[3]) == [2]
|
||||
assert set(G[2]) == {1, 3}
|
||||
pytest.raises(KeyError, G.__getitem__, 4)
|
||||
pytest.raises(KeyError, G.__getitem__, 112)
|
||||
pytest.raises(KeyError, G.__getitem__, 111)
|
||||
assert G.degree(3) == (3 if G.is_multigraph() else 1)
|
||||
assert G.size() == (7 if G.is_multigraph() else 5)
|
||||
|
||||
def test_hidden_edges(self):
|
||||
hide_edges = [(2, 3), (8, 7), (222, 223)]
|
||||
edges_gone = self.hide_edges_filter(hide_edges)
|
||||
gview = self.gview
|
||||
G = gview(self.G, filter_edge=edges_gone)
|
||||
assert self.G.nodes == G.nodes
|
||||
if G.is_directed():
|
||||
assert self.G.edges - G.edges == {(2, 3)}
|
||||
assert list(G[2]) == []
|
||||
assert list(G.pred[3]) == []
|
||||
assert list(G.pred[2]) == [1]
|
||||
assert G.size() == 7
|
||||
else:
|
||||
assert self.G.edges - G.edges == {(2, 3), (7, 8)}
|
||||
assert list(G[2]) == [1]
|
||||
assert G.size() == 6
|
||||
assert list(G[3]) == [4]
|
||||
pytest.raises(KeyError, G.__getitem__, 221)
|
||||
pytest.raises(KeyError, G.__getitem__, 222)
|
||||
assert G.degree(3) == 1
|
||||
|
||||
def test_shown_node(self):
|
||||
induced_subgraph = nx.filters.show_nodes([2, 3, 111])
|
||||
gview = self.gview
|
||||
G = gview(self.G, filter_node=induced_subgraph)
|
||||
assert set(G.nodes) == {2, 3}
|
||||
if G.is_directed():
|
||||
assert list(G[3]) == []
|
||||
else:
|
||||
assert list(G[3]) == [2]
|
||||
assert list(G[2]) == [3]
|
||||
pytest.raises(KeyError, G.__getitem__, 4)
|
||||
pytest.raises(KeyError, G.__getitem__, 112)
|
||||
pytest.raises(KeyError, G.__getitem__, 111)
|
||||
assert G.degree(3) == (3 if G.is_multigraph() else 1)
|
||||
assert G.size() == (3 if G.is_multigraph() else 1)
|
||||
|
||||
def test_shown_edges(self):
|
||||
show_edges = [(2, 3), (8, 7), (222, 223)]
|
||||
edge_subgraph = self.show_edges_filter(show_edges)
|
||||
G = self.gview(self.G, filter_edge=edge_subgraph)
|
||||
assert self.G.nodes == G.nodes
|
||||
if G.is_directed():
|
||||
assert G.edges == {(2, 3)}
|
||||
assert list(G[3]) == []
|
||||
assert list(G[2]) == [3]
|
||||
assert list(G.pred[3]) == [2]
|
||||
assert list(G.pred[2]) == []
|
||||
assert G.size() == 1
|
||||
else:
|
||||
assert G.edges == {(2, 3), (7, 8)}
|
||||
assert list(G[3]) == [2]
|
||||
assert list(G[2]) == [3]
|
||||
assert G.size() == 2
|
||||
pytest.raises(KeyError, G.__getitem__, 221)
|
||||
pytest.raises(KeyError, G.__getitem__, 222)
|
||||
assert G.degree(3) == 1
|
||||
|
||||
|
||||
class TestSubDiGraphView(TestSubGraphView):
|
||||
gview = staticmethod(nx.subgraph_view)
|
||||
graph = nx.DiGraph
|
||||
hide_edges_filter = staticmethod(nx.filters.hide_diedges)
|
||||
show_edges_filter = staticmethod(nx.filters.show_diedges)
|
||||
hide_edges = [(2, 3), (8, 7), (222, 223)]
|
||||
excluded = {(2, 3), (3, 4), (4, 5), (5, 6)}
|
||||
|
||||
def test_inoutedges(self):
|
||||
edges_gone = self.hide_edges_filter(self.hide_edges)
|
||||
hide_nodes = [4, 5, 111]
|
||||
nodes_gone = nx.filters.hide_nodes(hide_nodes)
|
||||
G = self.gview(self.G, filter_node=nodes_gone, filter_edge=edges_gone)
|
||||
|
||||
assert self.G.in_edges - G.in_edges == self.excluded
|
||||
assert self.G.out_edges - G.out_edges == self.excluded
|
||||
|
||||
def test_pred(self):
|
||||
edges_gone = self.hide_edges_filter(self.hide_edges)
|
||||
hide_nodes = [4, 5, 111]
|
||||
nodes_gone = nx.filters.hide_nodes(hide_nodes)
|
||||
G = self.gview(self.G, filter_node=nodes_gone, filter_edge=edges_gone)
|
||||
|
||||
assert list(G.pred[2]) == [1]
|
||||
assert list(G.pred[6]) == []
|
||||
|
||||
def test_inout_degree(self):
|
||||
edges_gone = self.hide_edges_filter(self.hide_edges)
|
||||
hide_nodes = [4, 5, 111]
|
||||
nodes_gone = nx.filters.hide_nodes(hide_nodes)
|
||||
G = self.gview(self.G, filter_node=nodes_gone, filter_edge=edges_gone)
|
||||
|
||||
assert G.degree(2) == 1
|
||||
assert G.out_degree(2) == 0
|
||||
assert G.in_degree(2) == 1
|
||||
assert G.size() == 4
|
||||
|
||||
|
||||
# multigraph
|
||||
class TestMultiGraphView(TestSubGraphView):
|
||||
gview = staticmethod(nx.subgraph_view)
|
||||
graph = nx.MultiGraph
|
||||
hide_edges_filter = staticmethod(nx.filters.hide_multiedges)
|
||||
show_edges_filter = staticmethod(nx.filters.show_multiedges)
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.G = nx.path_graph(9, create_using=cls.graph())
|
||||
multiedges = {(2, 3, 4), (2, 3, 5)}
|
||||
cls.G.add_edges_from(multiedges)
|
||||
cls.hide_edges_w_hide_nodes = {(3, 4, 0), (4, 5, 0), (5, 6, 0)}
|
||||
|
||||
def test_hidden_edges(self):
|
||||
hide_edges = [(2, 3, 4), (2, 3, 3), (8, 7, 0), (222, 223, 0)]
|
||||
edges_gone = self.hide_edges_filter(hide_edges)
|
||||
G = self.gview(self.G, filter_edge=edges_gone)
|
||||
assert self.G.nodes == G.nodes
|
||||
if G.is_directed():
|
||||
assert self.G.edges - G.edges == {(2, 3, 4)}
|
||||
assert list(G[3]) == [4]
|
||||
assert list(G[2]) == [3]
|
||||
assert list(G.pred[3]) == [2] # only one 2 but two edges
|
||||
assert list(G.pred[2]) == [1]
|
||||
assert G.size() == 9
|
||||
else:
|
||||
assert self.G.edges - G.edges == {(2, 3, 4), (7, 8, 0)}
|
||||
assert list(G[3]) == [2, 4]
|
||||
assert list(G[2]) == [1, 3]
|
||||
assert G.size() == 8
|
||||
assert G.degree(3) == 3
|
||||
pytest.raises(KeyError, G.__getitem__, 221)
|
||||
pytest.raises(KeyError, G.__getitem__, 222)
|
||||
|
||||
def test_shown_edges(self):
|
||||
show_edges = [(2, 3, 4), (2, 3, 3), (8, 7, 0), (222, 223, 0)]
|
||||
edge_subgraph = self.show_edges_filter(show_edges)
|
||||
G = self.gview(self.G, filter_edge=edge_subgraph)
|
||||
assert self.G.nodes == G.nodes
|
||||
if G.is_directed():
|
||||
assert G.edges == {(2, 3, 4)}
|
||||
assert list(G[3]) == []
|
||||
assert list(G.pred[3]) == [2]
|
||||
assert list(G.pred[2]) == []
|
||||
assert G.size() == 1
|
||||
else:
|
||||
assert G.edges == {(2, 3, 4), (7, 8, 0)}
|
||||
assert G.size() == 2
|
||||
assert list(G[3]) == [2]
|
||||
assert G.degree(3) == 1
|
||||
assert list(G[2]) == [3]
|
||||
pytest.raises(KeyError, G.__getitem__, 221)
|
||||
pytest.raises(KeyError, G.__getitem__, 222)
|
||||
|
||||
|
||||
# multidigraph
|
||||
class TestMultiDiGraphView(TestMultiGraphView, TestSubDiGraphView):
|
||||
gview = staticmethod(nx.subgraph_view)
|
||||
graph = nx.MultiDiGraph
|
||||
hide_edges_filter = staticmethod(nx.filters.hide_multidiedges)
|
||||
show_edges_filter = staticmethod(nx.filters.show_multidiedges)
|
||||
hide_edges = [(2, 3, 0), (8, 7, 0), (222, 223, 0)]
|
||||
excluded = {(2, 3, 0), (3, 4, 0), (4, 5, 0), (5, 6, 0)}
|
||||
|
||||
def test_inout_degree(self):
|
||||
edges_gone = self.hide_edges_filter(self.hide_edges)
|
||||
hide_nodes = [4, 5, 111]
|
||||
nodes_gone = nx.filters.hide_nodes(hide_nodes)
|
||||
G = self.gview(self.G, filter_node=nodes_gone, filter_edge=edges_gone)
|
||||
|
||||
assert G.degree(2) == 3
|
||||
assert G.out_degree(2) == 2
|
||||
assert G.in_degree(2) == 1
|
||||
assert G.size() == 6
|
||||
|
||||
|
||||
# induced_subgraph
|
||||
class TestInducedSubGraph:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.K3 = G = nx.complete_graph(3)
|
||||
G.graph["foo"] = []
|
||||
G.nodes[0]["foo"] = []
|
||||
G.remove_edge(1, 2)
|
||||
ll = []
|
||||
G.add_edge(1, 2, foo=ll)
|
||||
G.add_edge(2, 1, foo=ll)
|
||||
|
||||
def test_full_graph(self):
|
||||
G = self.K3
|
||||
H = nx.induced_subgraph(G, [0, 1, 2, 5])
|
||||
assert H.name == G.name
|
||||
self.graphs_equal(H, G)
|
||||
self.same_attrdict(H, G)
|
||||
|
||||
def test_partial_subgraph(self):
|
||||
G = self.K3
|
||||
H = nx.induced_subgraph(G, 0)
|
||||
assert dict(H.adj) == {0: {}}
|
||||
assert dict(G.adj) != {0: {}}
|
||||
|
||||
H = nx.induced_subgraph(G, [0, 1])
|
||||
assert dict(H.adj) == {0: {1: {}}, 1: {0: {}}}
|
||||
|
||||
def same_attrdict(self, H, G):
|
||||
old_foo = H[1][2]["foo"]
|
||||
H.edges[1, 2]["foo"] = "baz"
|
||||
assert G.edges == H.edges
|
||||
H.edges[1, 2]["foo"] = old_foo
|
||||
assert G.edges == H.edges
|
||||
old_foo = H.nodes[0]["foo"]
|
||||
H.nodes[0]["foo"] = "baz"
|
||||
assert G.nodes == H.nodes
|
||||
H.nodes[0]["foo"] = old_foo
|
||||
assert G.nodes == H.nodes
|
||||
|
||||
def graphs_equal(self, H, G):
|
||||
assert G._adj == H._adj
|
||||
assert G._node == H._node
|
||||
assert G.graph == H.graph
|
||||
assert G.name == H.name
|
||||
if not G.is_directed() and not H.is_directed():
|
||||
assert H._adj[1][2] is H._adj[2][1]
|
||||
assert G._adj[1][2] is G._adj[2][1]
|
||||
else: # at least one is directed
|
||||
if not G.is_directed():
|
||||
G._pred = G._adj
|
||||
G._succ = G._adj
|
||||
if not H.is_directed():
|
||||
H._pred = H._adj
|
||||
H._succ = H._adj
|
||||
assert G._pred == H._pred
|
||||
assert G._succ == H._succ
|
||||
assert H._succ[1][2] is H._pred[2][1]
|
||||
assert G._succ[1][2] is G._pred[2][1]
|
||||
|
||||
|
||||
# edge_subgraph
|
||||
class TestEdgeSubGraph:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
# Create a path graph on five nodes.
|
||||
cls.G = G = 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.
|
||||
cls.H = nx.edge_subgraph(G, [(0, 1), (3, 4)])
|
||||
|
||||
def test_correct_nodes(self):
|
||||
"""Tests that the subgraph has the correct nodes."""
|
||||
assert [(0, "node0"), (1, "node1"), (3, "node3"), (4, "node4")] == sorted(
|
||||
self.H.nodes.data("name")
|
||||
)
|
||||
|
||||
def test_correct_edges(self):
|
||||
"""Tests that the subgraph has the correct edges."""
|
||||
assert edges_equal(
|
||||
[(0, 1, "edge01"), (3, 4, "edge34")], self.H.edges.data("name")
|
||||
)
|
||||
|
||||
def test_add_node(self):
|
||||
"""Tests that adding a node to the original graph does not
|
||||
affect the nodes of the subgraph.
|
||||
|
||||
"""
|
||||
self.G.add_node(5)
|
||||
assert [0, 1, 3, 4] == sorted(self.H.nodes)
|
||||
self.G.remove_node(5)
|
||||
|
||||
def test_remove_node(self):
|
||||
"""Tests that removing a node in the original graph
|
||||
removes the nodes of the subgraph.
|
||||
|
||||
"""
|
||||
self.G.remove_node(0)
|
||||
assert [1, 3, 4] == sorted(self.H.nodes)
|
||||
self.G.add_node(0, name="node0")
|
||||
self.G.add_edge(0, 1, name="edge01")
|
||||
|
||||
def test_node_attr_dict(self):
|
||||
"""Tests that the node attribute dictionary of the two graphs is
|
||||
the same object.
|
||||
|
||||
"""
|
||||
for v in self.H:
|
||||
assert self.G.nodes[v] == self.H.nodes[v]
|
||||
# Making a change to G should make a change in H and vice versa.
|
||||
self.G.nodes[0]["name"] = "foo"
|
||||
assert self.G.nodes[0] == self.H.nodes[0]
|
||||
self.H.nodes[1]["name"] = "bar"
|
||||
assert self.G.nodes[1] == self.H.nodes[1]
|
||||
# Revert the change, so tests pass with pytest-randomly
|
||||
self.G.nodes[0]["name"] = "node0"
|
||||
self.H.nodes[1]["name"] = "node1"
|
||||
|
||||
def test_edge_attr_dict(self):
|
||||
"""Tests that the edge attribute dictionary of the two graphs is
|
||||
the same object.
|
||||
|
||||
"""
|
||||
for u, v in self.H.edges():
|
||||
assert self.G.edges[u, v] == self.H.edges[u, v]
|
||||
# Making a change to G should make a change in H and vice versa.
|
||||
self.G.edges[0, 1]["name"] = "foo"
|
||||
assert self.G.edges[0, 1]["name"] == self.H.edges[0, 1]["name"]
|
||||
self.H.edges[3, 4]["name"] = "bar"
|
||||
assert self.G.edges[3, 4]["name"] == self.H.edges[3, 4]["name"]
|
||||
# Revert the change, so tests pass with pytest-randomly
|
||||
self.G.edges[0, 1]["name"] = "edge01"
|
||||
self.H.edges[3, 4]["name"] = "edge34"
|
||||
|
||||
def test_graph_attr_dict(self):
|
||||
"""Tests that the graph attribute dictionary of the two graphs
|
||||
is the same object.
|
||||
|
||||
"""
|
||||
assert self.G.graph is self.H.graph
|
||||
|
||||
def test_readonly(self):
|
||||
"""Tests that the subgraph cannot change the graph structure"""
|
||||
pytest.raises(nx.NetworkXError, self.H.add_node, 5)
|
||||
pytest.raises(nx.NetworkXError, self.H.remove_node, 0)
|
||||
pytest.raises(nx.NetworkXError, self.H.add_edge, 5, 6)
|
||||
pytest.raises(nx.NetworkXError, self.H.remove_edge, 0, 1)
|
||||
Reference in New Issue
Block a user