Fixed database typo and removed unnecessary class identifier.

This commit is contained in:
Batuhan Berk Başoğlu 2020-10-14 10:10:37 -04:00
parent 00ad49a143
commit 45fb349a7d
5098 changed files with 952558 additions and 85 deletions

View file

@ -0,0 +1,233 @@
import pytest
np = pytest.importorskip("numpy")
import random
import networkx as nx
from networkx.algorithms import approximation as approx
from networkx.algorithms import threshold
progress = 0
# store the random numbers after setting a global seed
np.random.seed(42)
np_rv = np.random.rand()
random.seed(42)
py_rv = random.random()
def t(f, *args, **kwds):
"""call one function and check if global RNG changed"""
global progress
progress += 1
print(progress, ",", end="")
f(*args, **kwds)
after_np_rv = np.random.rand()
# if np_rv != after_np_rv:
# print(np_rv, after_np_rv, "don't match np!")
assert np_rv == after_np_rv
np.random.seed(42)
after_py_rv = random.random()
# if py_rv != after_py_rv:
# print(py_rv, after_py_rv, "don't match py!")
assert py_rv == after_py_rv
random.seed(42)
def run_all_random_functions(seed):
n = 20
m = 10
k = l = 2
s = v = 10
p = q = p1 = p2 = p_in = p_out = 0.4
alpha = radius = theta = 0.75
sizes = (20, 20, 10)
colors = [1, 2, 3]
G = nx.barbell_graph(12, 20)
deg_sequence = [3, 2, 1, 3, 2, 1, 3, 2, 1, 2, 1, 2, 1]
in_degree_sequence = w = sequence = aseq = bseq = deg_sequence
# print("starting...")
t(nx.maximal_independent_set, G, seed=seed)
t(nx.rich_club_coefficient, G, seed=seed, normalized=False)
t(nx.random_reference, G, seed=seed)
t(nx.lattice_reference, G, seed=seed)
t(nx.sigma, G, 1, 2, seed=seed)
t(nx.omega, G, 1, 2, seed=seed)
# print("out of smallworld.py")
t(nx.double_edge_swap, G, seed=seed)
# print("starting connected_double_edge_swap")
t(nx.connected_double_edge_swap, nx.complete_graph(9), seed=seed)
# print("ending connected_double_edge_swap")
t(nx.random_layout, G, seed=seed)
t(nx.fruchterman_reingold_layout, G, seed=seed)
t(nx.algebraic_connectivity, G, seed=seed)
t(nx.fiedler_vector, G, seed=seed)
t(nx.spectral_ordering, G, seed=seed)
# print('starting average_clustering')
t(approx.average_clustering, G, seed=seed)
t(nx.betweenness_centrality, G, seed=seed)
t(nx.edge_betweenness_centrality, G, seed=seed)
t(nx.edge_betweenness, G, seed=seed)
t(nx.approximate_current_flow_betweenness_centrality, G, seed=seed)
# print("kernighan")
t(nx.algorithms.community.kernighan_lin_bisection, G, seed=seed)
# nx.algorithms.community.asyn_lpa_communities(G, seed=seed)
t(nx.algorithms.tree.greedy_branching, G, seed=seed)
t(nx.algorithms.tree.Edmonds, G, seed=seed)
# print('done with graph argument functions')
t(nx.spectral_graph_forge, G, alpha, seed=seed)
t(nx.algorithms.community.asyn_fluidc, G, k, max_iter=1, seed=seed)
t(
nx.algorithms.connectivity.edge_augmentation.greedy_k_edge_augmentation,
G,
k,
seed=seed,
)
t(nx.algorithms.coloring.strategy_random_sequential, G, colors, seed=seed)
cs = ["d", "i", "i", "d", "d", "i"]
t(threshold.swap_d, cs, seed=seed)
t(nx.configuration_model, deg_sequence, seed=seed)
t(
nx.directed_configuration_model,
in_degree_sequence,
in_degree_sequence,
seed=seed,
)
t(nx.expected_degree_graph, w, seed=seed)
t(nx.random_degree_sequence_graph, sequence, seed=seed)
joint_degrees = {
1: {4: 1},
2: {2: 2, 3: 2, 4: 2},
3: {2: 2, 4: 1},
4: {1: 1, 2: 2, 3: 1},
}
t(nx.joint_degree_graph, joint_degrees, seed=seed)
joint_degree_sequence = [
(1, 0),
(1, 0),
(1, 0),
(2, 0),
(1, 0),
(2, 1),
(0, 1),
(0, 1),
]
t(nx.random_clustered_graph, joint_degree_sequence, seed=seed)
constructor = [(3, 3, 0.5), (10, 10, 0.7)]
t(nx.random_shell_graph, constructor, seed=seed)
mapping = {1: 0.4, 2: 0.3, 3: 0.3}
t(nx.utils.random_weighted_sample, mapping, k, seed=seed)
t(nx.utils.weighted_choice, mapping, seed=seed)
t(nx.algorithms.bipartite.configuration_model, aseq, bseq, seed=seed)
t(nx.algorithms.bipartite.preferential_attachment_graph, aseq, p, seed=seed)
def kernel_integral(u, w, z):
return z - w
t(nx.random_kernel_graph, n, kernel_integral, seed=seed)
sizes = [75, 75, 300]
probs = [[0.25, 0.05, 0.02], [0.05, 0.35, 0.07], [0.02, 0.07, 0.40]]
t(nx.stochastic_block_model, sizes, probs, seed=seed)
t(nx.random_partition_graph, sizes, p_in, p_out, seed=seed)
# print("starting generator functions")
t(threshold.random_threshold_sequence, n, p, seed=seed)
t(nx.tournament.random_tournament, n, seed=seed)
t(nx.relaxed_caveman_graph, l, k, p, seed=seed)
t(nx.planted_partition_graph, l, k, p_in, p_out, seed=seed)
t(nx.gaussian_random_partition_graph, n, s, v, p_in, p_out, seed=seed)
t(nx.gn_graph, n, seed=seed)
t(nx.gnr_graph, n, p, seed=seed)
t(nx.gnc_graph, n, seed=seed)
t(nx.scale_free_graph, n, seed=seed)
t(nx.directed.random_uniform_k_out_graph, n, k, seed=seed)
t(nx.random_k_out_graph, n, k, alpha, seed=seed)
N = 1000
t(nx.partial_duplication_graph, N, n, p, q, seed=seed)
t(nx.duplication_divergence_graph, n, p, seed=seed)
t(nx.random_geometric_graph, n, radius, seed=seed)
t(nx.soft_random_geometric_graph, n, radius, seed=seed)
t(nx.geographical_threshold_graph, n, theta, seed=seed)
t(nx.waxman_graph, n, seed=seed)
t(nx.navigable_small_world_graph, n, seed=seed)
t(nx.thresholded_random_geometric_graph, n, radius, theta, seed=seed)
t(nx.uniform_random_intersection_graph, n, m, p, seed=seed)
t(nx.k_random_intersection_graph, n, m, k, seed=seed)
t(nx.general_random_intersection_graph, n, 2, [0.1, 0.5], seed=seed)
t(nx.fast_gnp_random_graph, n, p, seed=seed)
t(nx.gnp_random_graph, n, p, seed=seed)
t(nx.dense_gnm_random_graph, n, m, seed=seed)
t(nx.gnm_random_graph, n, m, seed=seed)
t(nx.newman_watts_strogatz_graph, n, k, p, seed=seed)
t(nx.watts_strogatz_graph, n, k, p, seed=seed)
t(nx.connected_watts_strogatz_graph, n, k, p, seed=seed)
t(nx.random_regular_graph, 3, n, seed=seed)
t(nx.barabasi_albert_graph, n, m, seed=seed)
t(nx.extended_barabasi_albert_graph, n, m, p, q, seed=seed)
t(nx.powerlaw_cluster_graph, n, m, p, seed=seed)
t(nx.random_lobster, n, p1, p2, seed=seed)
t(nx.random_powerlaw_tree, n, seed=seed, tries=5000)
t(nx.random_powerlaw_tree_sequence, 10, seed=seed, tries=5000)
t(nx.random_tree, n, seed=seed)
t(nx.utils.powerlaw_sequence, n, seed=seed)
t(nx.utils.zipf_rv, 2.3, seed=seed)
cdist = [0.2, 0.4, 0.5, 0.7, 0.9, 1.0]
t(nx.utils.discrete_sequence, n, cdistribution=cdist, seed=seed)
t(nx.algorithms.bipartite.random_graph, n, m, p, seed=seed)
t(nx.algorithms.bipartite.gnmk_random_graph, n, m, k, seed=seed)
LFR = nx.generators.LFR_benchmark_graph
t(
LFR,
25,
3,
1.5,
0.1,
average_degree=3,
min_community=10,
seed=seed,
max_community=20,
)
t(nx.random_internet_as_graph, n, seed=seed)
# print("done")
# choose to test an integer seed, or whether a single RNG can be everywhere
# np_rng = np.random.RandomState(14)
# seed = np_rng
# seed = 14
@pytest.mark.slow
# print("NetworkX Version:", nx.__version__)
def test_rng_interface():
global progress
# try different kinds of seeds
for seed in [14, np.random.RandomState(14)]:
np.random.seed(42)
random.seed(42)
run_all_random_functions(seed)
progress = 0
# check that both global RNGs are unaffected
after_np_rv = np.random.rand()
# if np_rv != after_np_rv:
# print(np_rv, after_np_rv, "don't match np!")
assert np_rv == after_np_rv
after_py_rv = random.random()
# if py_rv != after_py_rv:
# print(py_rv, after_py_rv, "don't match py!")
assert py_rv == after_py_rv
# print("\nDone testing seed:", seed)
# test_rng_interface()

View file

@ -0,0 +1,281 @@
import pytest
import networkx as nx
from networkx.testing import assert_nodes_equal, assert_edges_equal, assert_graphs_equal
from networkx.convert import (
to_networkx_graph,
to_dict_of_dicts,
from_dict_of_dicts,
to_dict_of_lists,
from_dict_of_lists,
)
from networkx.generators.classic import barbell_graph, cycle_graph
class TestConvert:
def edgelists_equal(self, e1, e2):
return sorted(sorted(e) for e in e1) == sorted(sorted(e) for e in e2)
def test_simple_graphs(self):
for dest, source in [
(to_dict_of_dicts, from_dict_of_dicts),
(to_dict_of_lists, from_dict_of_lists),
]:
G = barbell_graph(10, 3)
G.graph = {}
dod = dest(G)
# Dict of [dicts, lists]
GG = source(dod)
assert_graphs_equal(G, GG)
GW = to_networkx_graph(dod)
assert_graphs_equal(G, GW)
GI = nx.Graph(dod)
assert_graphs_equal(G, GI)
# With nodelist keyword
P4 = nx.path_graph(4)
P3 = nx.path_graph(3)
P4.graph = {}
P3.graph = {}
dod = dest(P4, nodelist=[0, 1, 2])
Gdod = nx.Graph(dod)
assert_graphs_equal(Gdod, P3)
def test_exceptions(self):
# NX graph
class G:
adj = None
pytest.raises(nx.NetworkXError, to_networkx_graph, G)
# pygraphviz agraph
class G:
is_strict = None
pytest.raises(nx.NetworkXError, to_networkx_graph, G)
# Dict of [dicts, lists]
G = {"a": 0}
pytest.raises(TypeError, to_networkx_graph, G)
# list or generator of edges
class G:
next = None
pytest.raises(nx.NetworkXError, to_networkx_graph, G)
# no match
pytest.raises(nx.NetworkXError, to_networkx_graph, "a")
def test_digraphs(self):
for dest, source in [
(to_dict_of_dicts, from_dict_of_dicts),
(to_dict_of_lists, from_dict_of_lists),
]:
G = cycle_graph(10)
# Dict of [dicts, lists]
dod = dest(G)
GG = source(dod)
assert_nodes_equal(sorted(G.nodes()), sorted(GG.nodes()))
assert_edges_equal(sorted(G.edges()), sorted(GG.edges()))
GW = to_networkx_graph(dod)
assert_nodes_equal(sorted(G.nodes()), sorted(GW.nodes()))
assert_edges_equal(sorted(G.edges()), sorted(GW.edges()))
GI = nx.Graph(dod)
assert_nodes_equal(sorted(G.nodes()), sorted(GI.nodes()))
assert_edges_equal(sorted(G.edges()), sorted(GI.edges()))
G = cycle_graph(10, create_using=nx.DiGraph)
dod = dest(G)
GG = source(dod, create_using=nx.DiGraph)
assert sorted(G.nodes()) == sorted(GG.nodes())
assert sorted(G.edges()) == sorted(GG.edges())
GW = to_networkx_graph(dod, create_using=nx.DiGraph)
assert sorted(G.nodes()) == sorted(GW.nodes())
assert sorted(G.edges()) == sorted(GW.edges())
GI = nx.DiGraph(dod)
assert sorted(G.nodes()) == sorted(GI.nodes())
assert sorted(G.edges()) == sorted(GI.edges())
def test_graph(self):
g = nx.cycle_graph(10)
G = nx.Graph()
G.add_nodes_from(g)
G.add_weighted_edges_from((u, v, u) for u, v in g.edges())
# Dict of dicts
dod = to_dict_of_dicts(G)
GG = from_dict_of_dicts(dod, create_using=nx.Graph)
assert_nodes_equal(sorted(G.nodes()), sorted(GG.nodes()))
assert_edges_equal(sorted(G.edges()), sorted(GG.edges()))
GW = to_networkx_graph(dod, create_using=nx.Graph)
assert_nodes_equal(sorted(G.nodes()), sorted(GW.nodes()))
assert_edges_equal(sorted(G.edges()), sorted(GW.edges()))
GI = nx.Graph(dod)
assert sorted(G.nodes()) == sorted(GI.nodes())
assert sorted(G.edges()) == sorted(GI.edges())
# Dict of lists
dol = to_dict_of_lists(G)
GG = from_dict_of_lists(dol, create_using=nx.Graph)
# dict of lists throws away edge data so set it to none
enone = [(u, v, {}) for (u, v, d) in G.edges(data=True)]
assert_nodes_equal(sorted(G.nodes()), sorted(GG.nodes()))
assert_edges_equal(enone, sorted(GG.edges(data=True)))
GW = to_networkx_graph(dol, create_using=nx.Graph)
assert_nodes_equal(sorted(G.nodes()), sorted(GW.nodes()))
assert_edges_equal(enone, sorted(GW.edges(data=True)))
GI = nx.Graph(dol)
assert_nodes_equal(sorted(G.nodes()), sorted(GI.nodes()))
assert_edges_equal(enone, sorted(GI.edges(data=True)))
def test_with_multiedges_self_loops(self):
G = cycle_graph(10)
XG = nx.Graph()
XG.add_nodes_from(G)
XG.add_weighted_edges_from((u, v, u) for u, v in G.edges())
XGM = nx.MultiGraph()
XGM.add_nodes_from(G)
XGM.add_weighted_edges_from((u, v, u) for u, v in G.edges())
XGM.add_edge(0, 1, weight=2) # multiedge
XGS = nx.Graph()
XGS.add_nodes_from(G)
XGS.add_weighted_edges_from((u, v, u) for u, v in G.edges())
XGS.add_edge(0, 0, weight=100) # self loop
# Dict of dicts
# with self loops, OK
dod = to_dict_of_dicts(XGS)
GG = from_dict_of_dicts(dod, create_using=nx.Graph)
assert_nodes_equal(XGS.nodes(), GG.nodes())
assert_edges_equal(XGS.edges(), GG.edges())
GW = to_networkx_graph(dod, create_using=nx.Graph)
assert_nodes_equal(XGS.nodes(), GW.nodes())
assert_edges_equal(XGS.edges(), GW.edges())
GI = nx.Graph(dod)
assert_nodes_equal(XGS.nodes(), GI.nodes())
assert_edges_equal(XGS.edges(), GI.edges())
# Dict of lists
# with self loops, OK
dol = to_dict_of_lists(XGS)
GG = from_dict_of_lists(dol, create_using=nx.Graph)
# dict of lists throws away edge data so set it to none
enone = [(u, v, {}) for (u, v, d) in XGS.edges(data=True)]
assert_nodes_equal(sorted(XGS.nodes()), sorted(GG.nodes()))
assert_edges_equal(enone, sorted(GG.edges(data=True)))
GW = to_networkx_graph(dol, create_using=nx.Graph)
assert_nodes_equal(sorted(XGS.nodes()), sorted(GW.nodes()))
assert_edges_equal(enone, sorted(GW.edges(data=True)))
GI = nx.Graph(dol)
assert_nodes_equal(sorted(XGS.nodes()), sorted(GI.nodes()))
assert_edges_equal(enone, sorted(GI.edges(data=True)))
# Dict of dicts
# with multiedges, OK
dod = to_dict_of_dicts(XGM)
GG = from_dict_of_dicts(dod, create_using=nx.MultiGraph, multigraph_input=True)
assert_nodes_equal(sorted(XGM.nodes()), sorted(GG.nodes()))
assert_edges_equal(sorted(XGM.edges()), sorted(GG.edges()))
GW = to_networkx_graph(dod, create_using=nx.MultiGraph, multigraph_input=True)
assert_nodes_equal(sorted(XGM.nodes()), sorted(GW.nodes()))
assert_edges_equal(sorted(XGM.edges()), sorted(GW.edges()))
GI = nx.MultiGraph(dod) # convert can't tell whether to duplicate edges!
assert_nodes_equal(sorted(XGM.nodes()), sorted(GI.nodes()))
# assert_not_equal(sorted(XGM.edges()), sorted(GI.edges()))
assert not sorted(XGM.edges()) == sorted(GI.edges())
GE = from_dict_of_dicts(dod, create_using=nx.MultiGraph, multigraph_input=False)
assert_nodes_equal(sorted(XGM.nodes()), sorted(GE.nodes()))
assert sorted(XGM.edges()) != sorted(GE.edges())
GI = nx.MultiGraph(XGM)
assert_nodes_equal(sorted(XGM.nodes()), sorted(GI.nodes()))
assert_edges_equal(sorted(XGM.edges()), sorted(GI.edges()))
GM = nx.MultiGraph(G)
assert_nodes_equal(sorted(GM.nodes()), sorted(G.nodes()))
assert_edges_equal(sorted(GM.edges()), sorted(G.edges()))
# Dict of lists
# with multiedges, OK, but better write as DiGraph else you'll
# get double edges
dol = to_dict_of_lists(G)
GG = from_dict_of_lists(dol, create_using=nx.MultiGraph)
assert_nodes_equal(sorted(G.nodes()), sorted(GG.nodes()))
assert_edges_equal(sorted(G.edges()), sorted(GG.edges()))
GW = to_networkx_graph(dol, create_using=nx.MultiGraph)
assert_nodes_equal(sorted(G.nodes()), sorted(GW.nodes()))
assert_edges_equal(sorted(G.edges()), sorted(GW.edges()))
GI = nx.MultiGraph(dol)
assert_nodes_equal(sorted(G.nodes()), sorted(GI.nodes()))
assert_edges_equal(sorted(G.edges()), sorted(GI.edges()))
def test_edgelists(self):
P = nx.path_graph(4)
e = [(0, 1), (1, 2), (2, 3)]
G = nx.Graph(e)
assert_nodes_equal(sorted(G.nodes()), sorted(P.nodes()))
assert_edges_equal(sorted(G.edges()), sorted(P.edges()))
assert_edges_equal(sorted(G.edges(data=True)), sorted(P.edges(data=True)))
e = [(0, 1, {}), (1, 2, {}), (2, 3, {})]
G = nx.Graph(e)
assert_nodes_equal(sorted(G.nodes()), sorted(P.nodes()))
assert_edges_equal(sorted(G.edges()), sorted(P.edges()))
assert_edges_equal(sorted(G.edges(data=True)), sorted(P.edges(data=True)))
e = ((n, n + 1) for n in range(3))
G = nx.Graph(e)
assert_nodes_equal(sorted(G.nodes()), sorted(P.nodes()))
assert_edges_equal(sorted(G.edges()), sorted(P.edges()))
assert_edges_equal(sorted(G.edges(data=True)), sorted(P.edges(data=True)))
def test_directed_to_undirected(self):
edges1 = [(0, 1), (1, 2), (2, 0)]
edges2 = [(0, 1), (1, 2), (0, 2)]
assert self.edgelists_equal(nx.Graph(nx.DiGraph(edges1)).edges(), edges1)
assert self.edgelists_equal(nx.Graph(nx.DiGraph(edges2)).edges(), edges1)
assert self.edgelists_equal(nx.MultiGraph(nx.DiGraph(edges1)).edges(), edges1)
assert self.edgelists_equal(nx.MultiGraph(nx.DiGraph(edges2)).edges(), edges1)
assert self.edgelists_equal(
nx.MultiGraph(nx.MultiDiGraph(edges1)).edges(), edges1
)
assert self.edgelists_equal(
nx.MultiGraph(nx.MultiDiGraph(edges2)).edges(), edges1
)
assert self.edgelists_equal(nx.Graph(nx.MultiDiGraph(edges1)).edges(), edges1)
assert self.edgelists_equal(nx.Graph(nx.MultiDiGraph(edges2)).edges(), edges1)
def test_attribute_dict_integrity(self):
# we must not replace dict-like graph data structures with dicts
G = nx.OrderedGraph()
G.add_nodes_from("abc")
H = to_networkx_graph(G, create_using=nx.OrderedGraph)
assert list(H.nodes) == list(G.nodes)
H = nx.OrderedDiGraph(G)
assert list(H.nodes) == list(G.nodes)
def test_to_edgelist(self):
G = nx.Graph([(1, 1)])
elist = nx.to_edgelist(G, nodelist=list(G))
assert_edges_equal(G.edges(data=True), elist)
def test_custom_node_attr_dict_safekeeping(self):
class custom_dict(dict):
pass
class Custom(nx.Graph):
node_attr_dict_factory = custom_dict
g = nx.Graph()
g.add_node(1, weight=1)
h = Custom(g)
assert isinstance(g._node[1], dict)
assert isinstance(h._node[1], custom_dict)
# this raise exception
# h._node.update((n, dd.copy()) for n, dd in g.nodes.items())
# assert isinstance(h._node[1], custom_dict)

View file

@ -0,0 +1,434 @@
import pytest
np = pytest.importorskip("numpy")
np_assert_equal = np.testing.assert_equal
import networkx as nx
from networkx.generators.classic import barbell_graph, cycle_graph, path_graph
from networkx.testing.utils import assert_graphs_equal
class TestConvertNumpy:
def setup_method(self):
self.G1 = barbell_graph(10, 3)
self.G2 = cycle_graph(10, create_using=nx.DiGraph)
self.G3 = self.create_weighted(nx.Graph())
self.G4 = self.create_weighted(nx.DiGraph())
def test_exceptions(self):
G = np.array("a")
pytest.raises(nx.NetworkXError, nx.to_networkx_graph, G)
def create_weighted(self, G):
g = cycle_graph(4)
G.add_nodes_from(g)
G.add_weighted_edges_from((u, v, 10 + u) for u, v in g.edges())
return G
def assert_equal(self, G1, G2):
assert sorted(G1.nodes()) == sorted(G2.nodes())
assert sorted(G1.edges()) == sorted(G2.edges())
def identity_conversion(self, G, A, create_using):
assert A.sum() > 0
GG = nx.from_numpy_matrix(A, create_using=create_using)
self.assert_equal(G, GG)
GW = nx.to_networkx_graph(A, create_using=create_using)
self.assert_equal(G, GW)
GI = nx.empty_graph(0, create_using).__class__(A)
self.assert_equal(G, GI)
def test_shape(self):
"Conversion from non-square array."
A = np.array([[1, 2, 3], [4, 5, 6]])
pytest.raises(nx.NetworkXError, nx.from_numpy_matrix, A)
def test_identity_graph_matrix(self):
"Conversion from graph to matrix to graph."
A = nx.to_numpy_matrix(self.G1)
self.identity_conversion(self.G1, A, nx.Graph())
def test_identity_graph_array(self):
"Conversion from graph to array to graph."
A = nx.to_numpy_matrix(self.G1)
A = np.asarray(A)
self.identity_conversion(self.G1, A, nx.Graph())
def test_identity_digraph_matrix(self):
"""Conversion from digraph to matrix to digraph."""
A = nx.to_numpy_matrix(self.G2)
self.identity_conversion(self.G2, A, nx.DiGraph())
def test_identity_digraph_array(self):
"""Conversion from digraph to array to digraph."""
A = nx.to_numpy_matrix(self.G2)
A = np.asarray(A)
self.identity_conversion(self.G2, A, nx.DiGraph())
def test_identity_weighted_graph_matrix(self):
"""Conversion from weighted graph to matrix to weighted graph."""
A = nx.to_numpy_matrix(self.G3)
self.identity_conversion(self.G3, A, nx.Graph())
def test_identity_weighted_graph_array(self):
"""Conversion from weighted graph to array to weighted graph."""
A = nx.to_numpy_matrix(self.G3)
A = np.asarray(A)
self.identity_conversion(self.G3, A, nx.Graph())
def test_identity_weighted_digraph_matrix(self):
"""Conversion from weighted digraph to matrix to weighted digraph."""
A = nx.to_numpy_matrix(self.G4)
self.identity_conversion(self.G4, A, nx.DiGraph())
def test_identity_weighted_digraph_array(self):
"""Conversion from weighted digraph to array to weighted digraph."""
A = nx.to_numpy_matrix(self.G4)
A = np.asarray(A)
self.identity_conversion(self.G4, A, nx.DiGraph())
def test_nodelist(self):
"""Conversion from graph to matrix to graph with nodelist."""
P4 = path_graph(4)
P3 = path_graph(3)
nodelist = list(P3)
A = nx.to_numpy_matrix(P4, nodelist=nodelist)
GA = nx.Graph(A)
self.assert_equal(GA, P3)
# Make nodelist ambiguous by containing duplicates.
nodelist += [nodelist[0]]
pytest.raises(nx.NetworkXError, nx.to_numpy_matrix, P3, nodelist=nodelist)
def test_weight_keyword(self):
WP4 = nx.Graph()
WP4.add_edges_from((n, n + 1, dict(weight=0.5, other=0.3)) for n in range(3))
P4 = path_graph(4)
A = nx.to_numpy_matrix(P4)
np_assert_equal(A, nx.to_numpy_matrix(WP4, weight=None))
np_assert_equal(0.5 * A, nx.to_numpy_matrix(WP4))
np_assert_equal(0.3 * A, nx.to_numpy_matrix(WP4, weight="other"))
def test_from_numpy_matrix_type(self):
A = np.matrix([[1]])
G = nx.from_numpy_matrix(A)
assert type(G[0][0]["weight"]) == int
A = np.matrix([[1]]).astype(np.float)
G = nx.from_numpy_matrix(A)
assert type(G[0][0]["weight"]) == float
A = np.matrix([[1]]).astype(np.str)
G = nx.from_numpy_matrix(A)
assert type(G[0][0]["weight"]) == str
A = np.matrix([[1]]).astype(np.bool)
G = nx.from_numpy_matrix(A)
assert type(G[0][0]["weight"]) == bool
A = np.matrix([[1]]).astype(np.complex)
G = nx.from_numpy_matrix(A)
assert type(G[0][0]["weight"]) == complex
A = np.matrix([[1]]).astype(np.object)
pytest.raises(TypeError, nx.from_numpy_matrix, A)
G = nx.cycle_graph(3)
A = nx.adj_matrix(G).todense()
H = nx.from_numpy_matrix(A)
assert all(type(m) == int and type(n) == int for m, n in H.edges())
H = nx.from_numpy_array(A)
assert all(type(m) == int and type(n) == int for m, n in H.edges())
def test_from_numpy_matrix_dtype(self):
dt = [("weight", float), ("cost", int)]
A = np.matrix([[(1.0, 2)]], dtype=dt)
G = nx.from_numpy_matrix(A)
assert type(G[0][0]["weight"]) == float
assert type(G[0][0]["cost"]) == int
assert G[0][0]["cost"] == 2
assert G[0][0]["weight"] == 1.0
def test_to_numpy_recarray(self):
G = nx.Graph()
G.add_edge(1, 2, weight=7.0, cost=5)
A = nx.to_numpy_recarray(G, dtype=[("weight", float), ("cost", int)])
assert sorted(A.dtype.names) == ["cost", "weight"]
assert A.weight[0, 1] == 7.0
assert A.weight[0, 0] == 0.0
assert A.cost[0, 1] == 5
assert A.cost[0, 0] == 0
def test_numpy_multigraph(self):
G = nx.MultiGraph()
G.add_edge(1, 2, weight=7)
G.add_edge(1, 2, weight=70)
A = nx.to_numpy_matrix(G)
assert A[1, 0] == 77
A = nx.to_numpy_matrix(G, multigraph_weight=min)
assert A[1, 0] == 7
A = nx.to_numpy_matrix(G, multigraph_weight=max)
assert A[1, 0] == 70
def test_from_numpy_matrix_parallel_edges(self):
"""Tests that the :func:`networkx.from_numpy_matrix` function
interprets integer weights as the number of parallel edges when
creating a multigraph.
"""
A = np.matrix([[1, 1], [1, 2]])
# First, with a simple graph, each integer entry in the adjacency
# matrix is interpreted as the weight of a single edge in the graph.
expected = nx.DiGraph()
edges = [(0, 0), (0, 1), (1, 0)]
expected.add_weighted_edges_from([(u, v, 1) for (u, v) in edges])
expected.add_edge(1, 1, weight=2)
actual = nx.from_numpy_matrix(A, parallel_edges=True, create_using=nx.DiGraph)
assert_graphs_equal(actual, expected)
actual = nx.from_numpy_matrix(A, parallel_edges=False, create_using=nx.DiGraph)
assert_graphs_equal(actual, expected)
# Now each integer entry in the adjacency matrix is interpreted as the
# number of parallel edges in the graph if the appropriate keyword
# argument is specified.
edges = [(0, 0), (0, 1), (1, 0), (1, 1), (1, 1)]
expected = nx.MultiDiGraph()
expected.add_weighted_edges_from([(u, v, 1) for (u, v) in edges])
actual = nx.from_numpy_matrix(
A, parallel_edges=True, create_using=nx.MultiDiGraph
)
assert_graphs_equal(actual, expected)
expected = nx.MultiDiGraph()
expected.add_edges_from(set(edges), weight=1)
# The sole self-loop (edge 0) on vertex 1 should have weight 2.
expected[1][1][0]["weight"] = 2
actual = nx.from_numpy_matrix(
A, parallel_edges=False, create_using=nx.MultiDiGraph
)
assert_graphs_equal(actual, expected)
def test_symmetric(self):
"""Tests that a symmetric matrix has edges added only once to an
undirected multigraph when using :func:`networkx.from_numpy_matrix`.
"""
A = np.matrix([[0, 1], [1, 0]])
G = nx.from_numpy_matrix(A, create_using=nx.MultiGraph)
expected = nx.MultiGraph()
expected.add_edge(0, 1, weight=1)
assert_graphs_equal(G, expected)
def test_dtype_int_graph(self):
"""Test that setting dtype int actually gives an integer matrix.
For more information, see GitHub pull request #1363.
"""
G = nx.complete_graph(3)
A = nx.to_numpy_matrix(G, dtype=int)
assert A.dtype == int
def test_dtype_int_multigraph(self):
"""Test that setting dtype int actually gives an integer matrix.
For more information, see GitHub pull request #1363.
"""
G = nx.MultiGraph(nx.complete_graph(3))
A = nx.to_numpy_matrix(G, dtype=int)
assert A.dtype == int
class TestConvertNumpyArray:
def setup_method(self):
self.G1 = barbell_graph(10, 3)
self.G2 = cycle_graph(10, create_using=nx.DiGraph)
self.G3 = self.create_weighted(nx.Graph())
self.G4 = self.create_weighted(nx.DiGraph())
def create_weighted(self, G):
g = cycle_graph(4)
G.add_nodes_from(g)
G.add_weighted_edges_from((u, v, 10 + u) for u, v in g.edges())
return G
def assert_equal(self, G1, G2):
assert sorted(G1.nodes()) == sorted(G2.nodes())
assert sorted(G1.edges()) == sorted(G2.edges())
def identity_conversion(self, G, A, create_using):
assert A.sum() > 0
GG = nx.from_numpy_array(A, create_using=create_using)
self.assert_equal(G, GG)
GW = nx.to_networkx_graph(A, create_using=create_using)
self.assert_equal(G, GW)
GI = nx.empty_graph(0, create_using).__class__(A)
self.assert_equal(G, GI)
def test_shape(self):
"Conversion from non-square array."
A = np.array([[1, 2, 3], [4, 5, 6]])
pytest.raises(nx.NetworkXError, nx.from_numpy_array, A)
def test_identity_graph_array(self):
"Conversion from graph to array to graph."
A = nx.to_numpy_array(self.G1)
self.identity_conversion(self.G1, A, nx.Graph())
def test_identity_digraph_array(self):
"""Conversion from digraph to array to digraph."""
A = nx.to_numpy_array(self.G2)
self.identity_conversion(self.G2, A, nx.DiGraph())
def test_identity_weighted_graph_array(self):
"""Conversion from weighted graph to array to weighted graph."""
A = nx.to_numpy_array(self.G3)
self.identity_conversion(self.G3, A, nx.Graph())
def test_identity_weighted_digraph_array(self):
"""Conversion from weighted digraph to array to weighted digraph."""
A = nx.to_numpy_array(self.G4)
self.identity_conversion(self.G4, A, nx.DiGraph())
def test_nodelist(self):
"""Conversion from graph to array to graph with nodelist."""
P4 = path_graph(4)
P3 = path_graph(3)
nodelist = list(P3)
A = nx.to_numpy_array(P4, nodelist=nodelist)
GA = nx.Graph(A)
self.assert_equal(GA, P3)
# Make nodelist ambiguous by containing duplicates.
nodelist += [nodelist[0]]
pytest.raises(nx.NetworkXError, nx.to_numpy_array, P3, nodelist=nodelist)
def test_weight_keyword(self):
WP4 = nx.Graph()
WP4.add_edges_from((n, n + 1, dict(weight=0.5, other=0.3)) for n in range(3))
P4 = path_graph(4)
A = nx.to_numpy_array(P4)
np_assert_equal(A, nx.to_numpy_array(WP4, weight=None))
np_assert_equal(0.5 * A, nx.to_numpy_array(WP4))
np_assert_equal(0.3 * A, nx.to_numpy_array(WP4, weight="other"))
def test_from_numpy_array_type(self):
A = np.array([[1]])
G = nx.from_numpy_array(A)
assert type(G[0][0]["weight"]) == int
A = np.array([[1]]).astype(np.float)
G = nx.from_numpy_array(A)
assert type(G[0][0]["weight"]) == float
A = np.array([[1]]).astype(np.str)
G = nx.from_numpy_array(A)
assert type(G[0][0]["weight"]) == str
A = np.array([[1]]).astype(np.bool)
G = nx.from_numpy_array(A)
assert type(G[0][0]["weight"]) == bool
A = np.array([[1]]).astype(np.complex)
G = nx.from_numpy_array(A)
assert type(G[0][0]["weight"]) == complex
A = np.array([[1]]).astype(np.object)
pytest.raises(TypeError, nx.from_numpy_array, A)
def test_from_numpy_array_dtype(self):
dt = [("weight", float), ("cost", int)]
A = np.array([[(1.0, 2)]], dtype=dt)
G = nx.from_numpy_array(A)
assert type(G[0][0]["weight"]) == float
assert type(G[0][0]["cost"]) == int
assert G[0][0]["cost"] == 2
assert G[0][0]["weight"] == 1.0
def test_to_numpy_recarray(self):
G = nx.Graph()
G.add_edge(1, 2, weight=7.0, cost=5)
A = nx.to_numpy_recarray(G, dtype=[("weight", float), ("cost", int)])
assert sorted(A.dtype.names) == ["cost", "weight"]
assert A.weight[0, 1] == 7.0
assert A.weight[0, 0] == 0.0
assert A.cost[0, 1] == 5
assert A.cost[0, 0] == 0
def test_numpy_multigraph(self):
G = nx.MultiGraph()
G.add_edge(1, 2, weight=7)
G.add_edge(1, 2, weight=70)
A = nx.to_numpy_array(G)
assert A[1, 0] == 77
A = nx.to_numpy_array(G, multigraph_weight=min)
assert A[1, 0] == 7
A = nx.to_numpy_array(G, multigraph_weight=max)
assert A[1, 0] == 70
def test_from_numpy_array_parallel_edges(self):
"""Tests that the :func:`networkx.from_numpy_array` function
interprets integer weights as the number of parallel edges when
creating a multigraph.
"""
A = np.array([[1, 1], [1, 2]])
# First, with a simple graph, each integer entry in the adjacency
# matrix is interpreted as the weight of a single edge in the graph.
expected = nx.DiGraph()
edges = [(0, 0), (0, 1), (1, 0)]
expected.add_weighted_edges_from([(u, v, 1) for (u, v) in edges])
expected.add_edge(1, 1, weight=2)
actual = nx.from_numpy_array(A, parallel_edges=True, create_using=nx.DiGraph)
assert_graphs_equal(actual, expected)
actual = nx.from_numpy_array(A, parallel_edges=False, create_using=nx.DiGraph)
assert_graphs_equal(actual, expected)
# Now each integer entry in the adjacency matrix is interpreted as the
# number of parallel edges in the graph if the appropriate keyword
# argument is specified.
edges = [(0, 0), (0, 1), (1, 0), (1, 1), (1, 1)]
expected = nx.MultiDiGraph()
expected.add_weighted_edges_from([(u, v, 1) for (u, v) in edges])
actual = nx.from_numpy_array(
A, parallel_edges=True, create_using=nx.MultiDiGraph
)
assert_graphs_equal(actual, expected)
expected = nx.MultiDiGraph()
expected.add_edges_from(set(edges), weight=1)
# The sole self-loop (edge 0) on vertex 1 should have weight 2.
expected[1][1][0]["weight"] = 2
actual = nx.from_numpy_array(
A, parallel_edges=False, create_using=nx.MultiDiGraph
)
assert_graphs_equal(actual, expected)
def test_symmetric(self):
"""Tests that a symmetric array has edges added only once to an
undirected multigraph when using :func:`networkx.from_numpy_array`.
"""
A = np.array([[0, 1], [1, 0]])
G = nx.from_numpy_array(A, create_using=nx.MultiGraph)
expected = nx.MultiGraph()
expected.add_edge(0, 1, weight=1)
assert_graphs_equal(G, expected)
def test_dtype_int_graph(self):
"""Test that setting dtype int actually gives an integer array.
For more information, see GitHub pull request #1363.
"""
G = nx.complete_graph(3)
A = nx.to_numpy_array(G, dtype=int)
assert A.dtype == int
def test_dtype_int_multigraph(self):
"""Test that setting dtype int actually gives an integer array.
For more information, see GitHub pull request #1363.
"""
G = nx.MultiGraph(nx.complete_graph(3))
A = nx.to_numpy_array(G, dtype=int)
assert A.dtype == int

View file

@ -0,0 +1,286 @@
import pytest
import networkx as nx
from networkx.testing import assert_nodes_equal
from networkx.testing import assert_edges_equal
from networkx.testing import assert_graphs_equal
np = pytest.importorskip("numpy")
pd = pytest.importorskip("pandas")
class TestConvertPandas:
def setup_method(self):
self.rng = np.random.RandomState(seed=5)
ints = self.rng.randint(1, 11, size=(3, 2))
a = ["A", "B", "C"]
b = ["D", "A", "E"]
df = pd.DataFrame(ints, columns=["weight", "cost"])
df[0] = a # Column label 0 (int)
df["b"] = b # Column label 'b' (str)
self.df = df
mdf = pd.DataFrame([[4, 16, "A", "D"]], columns=["weight", "cost", 0, "b"])
self.mdf = df.append(mdf)
def test_exceptions(self):
G = pd.DataFrame(["a"]) # adj
pytest.raises(nx.NetworkXError, nx.to_networkx_graph, G)
G = pd.DataFrame(["a", 0.0]) # elist
pytest.raises(nx.NetworkXError, nx.to_networkx_graph, G)
df = pd.DataFrame([[1, 1], [1, 0]], dtype=int, index=[1, 2], columns=["a", "b"])
pytest.raises(nx.NetworkXError, nx.from_pandas_adjacency, df)
def test_from_edgelist_all_attr(self):
Gtrue = nx.Graph(
[
("E", "C", {"cost": 9, "weight": 10}),
("B", "A", {"cost": 1, "weight": 7}),
("A", "D", {"cost": 7, "weight": 4}),
]
)
G = nx.from_pandas_edgelist(self.df, 0, "b", True)
assert_graphs_equal(G, Gtrue)
# MultiGraph
MGtrue = nx.MultiGraph(Gtrue)
MGtrue.add_edge("A", "D", cost=16, weight=4)
MG = nx.from_pandas_edgelist(self.mdf, 0, "b", True, nx.MultiGraph())
assert_graphs_equal(MG, MGtrue)
def test_from_edgelist_multi_attr(self):
Gtrue = nx.Graph(
[
("E", "C", {"cost": 9, "weight": 10}),
("B", "A", {"cost": 1, "weight": 7}),
("A", "D", {"cost": 7, "weight": 4}),
]
)
G = nx.from_pandas_edgelist(self.df, 0, "b", ["weight", "cost"])
assert_graphs_equal(G, Gtrue)
def test_from_edgelist_multi_attr_incl_target(self):
Gtrue = nx.Graph(
[
("E", "C", {0: "C", "b": "E", "weight": 10}),
("B", "A", {0: "B", "b": "A", "weight": 7}),
("A", "D", {0: "A", "b": "D", "weight": 4}),
]
)
G = nx.from_pandas_edgelist(self.df, 0, "b", [0, "b", "weight"])
assert_graphs_equal(G, Gtrue)
def test_from_edgelist_multidigraph_and_edge_attr(self):
# example from issue #2374
edges = [
("X1", "X4", {"Co": "zA", "Mi": 0, "St": "X1"}),
("X1", "X4", {"Co": "zB", "Mi": 54, "St": "X2"}),
("X1", "X4", {"Co": "zB", "Mi": 49, "St": "X3"}),
("X1", "X4", {"Co": "zB", "Mi": 44, "St": "X4"}),
("Y1", "Y3", {"Co": "zC", "Mi": 0, "St": "Y1"}),
("Y1", "Y3", {"Co": "zC", "Mi": 34, "St": "Y2"}),
("Y1", "Y3", {"Co": "zC", "Mi": 29, "St": "X2"}),
("Y1", "Y3", {"Co": "zC", "Mi": 24, "St": "Y3"}),
("Z1", "Z3", {"Co": "zD", "Mi": 0, "St": "Z1"}),
("Z1", "Z3", {"Co": "zD", "Mi": 14, "St": "X3"}),
]
Gtrue = nx.MultiDiGraph(edges)
data = {
"O": ["X1", "X1", "X1", "X1", "Y1", "Y1", "Y1", "Y1", "Z1", "Z1"],
"D": ["X4", "X4", "X4", "X4", "Y3", "Y3", "Y3", "Y3", "Z3", "Z3"],
"St": ["X1", "X2", "X3", "X4", "Y1", "Y2", "X2", "Y3", "Z1", "X3"],
"Co": ["zA", "zB", "zB", "zB", "zC", "zC", "zC", "zC", "zD", "zD"],
"Mi": [0, 54, 49, 44, 0, 34, 29, 24, 0, 14],
}
df = pd.DataFrame.from_dict(data)
G1 = nx.from_pandas_edgelist(
df, source="O", target="D", edge_attr=True, create_using=nx.MultiDiGraph
)
G2 = nx.from_pandas_edgelist(
df,
source="O",
target="D",
edge_attr=["St", "Co", "Mi"],
create_using=nx.MultiDiGraph,
)
assert_graphs_equal(G1, Gtrue)
assert_graphs_equal(G2, Gtrue)
def test_from_edgelist_one_attr(self):
Gtrue = nx.Graph(
[
("E", "C", {"weight": 10}),
("B", "A", {"weight": 7}),
("A", "D", {"weight": 4}),
]
)
G = nx.from_pandas_edgelist(self.df, 0, "b", "weight")
assert_graphs_equal(G, Gtrue)
def test_from_edgelist_int_attr_name(self):
# note: this also tests that edge_attr can be `source`
Gtrue = nx.Graph(
[("E", "C", {0: "C"}), ("B", "A", {0: "B"}), ("A", "D", {0: "A"})]
)
G = nx.from_pandas_edgelist(self.df, 0, "b", 0)
assert_graphs_equal(G, Gtrue)
def test_from_edgelist_invalid_attr(self):
pytest.raises(
nx.NetworkXError, nx.from_pandas_edgelist, self.df, 0, "b", "misspell"
)
pytest.raises(nx.NetworkXError, nx.from_pandas_edgelist, self.df, 0, "b", 1)
# see Issue #3562
edgeframe = pd.DataFrame([[0, 1], [1, 2], [2, 0]], columns=["s", "t"])
pytest.raises(
nx.NetworkXError, nx.from_pandas_edgelist, edgeframe, "s", "t", True
)
pytest.raises(
nx.NetworkXError, nx.from_pandas_edgelist, edgeframe, "s", "t", "weight"
)
pytest.raises(
nx.NetworkXError,
nx.from_pandas_edgelist,
edgeframe,
"s",
"t",
["weight", "size"],
)
def test_from_edgelist_no_attr(self):
Gtrue = nx.Graph([("E", "C", {}), ("B", "A", {}), ("A", "D", {})])
G = nx.from_pandas_edgelist(self.df, 0, "b")
assert_graphs_equal(G, Gtrue)
def test_from_edgelist(self):
# Pandas DataFrame
G = nx.cycle_graph(10)
G.add_weighted_edges_from((u, v, u) for u, v in list(G.edges))
edgelist = nx.to_edgelist(G)
source = [s for s, t, d in edgelist]
target = [t for s, t, d in edgelist]
weight = [d["weight"] for s, t, d in edgelist]
edges = pd.DataFrame({"source": source, "target": target, "weight": weight})
GG = nx.from_pandas_edgelist(edges, edge_attr="weight")
assert_nodes_equal(G.nodes(), GG.nodes())
assert_edges_equal(G.edges(), GG.edges())
GW = nx.to_networkx_graph(edges, create_using=nx.Graph)
assert_nodes_equal(G.nodes(), GW.nodes())
assert_edges_equal(G.edges(), GW.edges())
def test_to_edgelist_default_source_or_target_col_exists(self):
G = nx.path_graph(10)
G.add_weighted_edges_from((u, v, u) for u, v in list(G.edges))
nx.set_edge_attributes(G, 0, name="source")
pytest.raises(nx.NetworkXError, nx.to_pandas_edgelist, G)
# drop source column to test an exception raised for the target column
for u, v, d in G.edges(data=True):
d.pop("source", None)
nx.set_edge_attributes(G, 0, name="target")
pytest.raises(nx.NetworkXError, nx.to_pandas_edgelist, G)
def test_to_edgelist_custom_source_or_target_col_exists(self):
G = nx.path_graph(10)
G.add_weighted_edges_from((u, v, u) for u, v in list(G.edges))
nx.set_edge_attributes(G, 0, name="source_col_name")
pytest.raises(
nx.NetworkXError, nx.to_pandas_edgelist, G, source="source_col_name"
)
# drop source column to test an exception raised for the target column
for u, v, d in G.edges(data=True):
d.pop("source_col_name", None)
nx.set_edge_attributes(G, 0, name="target_col_name")
pytest.raises(
nx.NetworkXError, nx.to_pandas_edgelist, G, target="target_col_name"
)
def test_from_adjacency(self):
nodelist = [1, 2]
dftrue = pd.DataFrame(
[[1, 1], [1, 0]], dtype=int, index=nodelist, columns=nodelist
)
G = nx.Graph([(1, 1), (1, 2)])
df = nx.to_pandas_adjacency(G, dtype=int)
pd.testing.assert_frame_equal(df, dftrue)
def test_roundtrip(self):
# edgelist
Gtrue = nx.Graph([(1, 1), (1, 2)])
df = nx.to_pandas_edgelist(Gtrue)
G = nx.from_pandas_edgelist(df)
assert_graphs_equal(Gtrue, G)
# adjacency
adj = {1: {1: {"weight": 1}, 2: {"weight": 1}}, 2: {1: {"weight": 1}}}
Gtrue = nx.Graph(adj)
df = nx.to_pandas_adjacency(Gtrue, dtype=int)
G = nx.from_pandas_adjacency(df)
assert_graphs_equal(Gtrue, G)
def test_from_adjacency_named(self):
# example from issue #3105
data = {
"A": {"A": 0, "B": 0, "C": 0},
"B": {"A": 1, "B": 0, "C": 0},
"C": {"A": 0, "B": 1, "C": 0},
}
dftrue = pd.DataFrame(data)
df = dftrue[["A", "C", "B"]]
G = nx.from_pandas_adjacency(df, create_using=nx.DiGraph())
df = nx.to_pandas_adjacency(G, dtype=np.intp)
pd.testing.assert_frame_equal(df, dftrue)
def test_edgekey_with_multigraph(self):
df = pd.DataFrame(
{
"attr1": {"A": "F1", "B": "F2", "C": "F3"},
"attr2": {"A": 1, "B": 0, "C": 0},
"attr3": {"A": 0, "B": 1, "C": 0},
"source": {"A": "N1", "B": "N2", "C": "N1"},
"target": {"A": "N2", "B": "N3", "C": "N1"},
}
)
Gtrue = nx.Graph(
[
("N1", "N2", {"F1": {"attr2": 1, "attr3": 0}}),
("N2", "N3", {"F2": {"attr2": 0, "attr3": 1}}),
("N1", "N1", {"F3": {"attr2": 0, "attr3": 0}}),
]
)
# example from issue #4065
G = nx.from_pandas_edgelist(
df,
source="source",
target="target",
edge_attr=["attr2", "attr3"],
edge_key="attr1",
create_using=nx.MultiGraph(),
)
assert_graphs_equal(G, Gtrue)
def test_edgekey_with_normal_graph_no_action(self):
Gtrue = nx.Graph(
[
("E", "C", {"cost": 9, "weight": 10}),
("B", "A", {"cost": 1, "weight": 7}),
("A", "D", {"cost": 7, "weight": 4}),
]
)
G = nx.from_pandas_edgelist(self.df, 0, "b", True, edge_key="weight")
assert_graphs_equal(G, Gtrue)
def test_nonexisting_edgekey_raises(self):
with pytest.raises(nx.exception.NetworkXError):
nx.from_pandas_edgelist(
self.df,
source="source",
target="target",
edge_key="Not_real",
edge_attr=True,
create_using=nx.MultiGraph(),
)

View file

@ -0,0 +1,258 @@
import pytest
import networkx as nx
from networkx.testing import assert_graphs_equal
from networkx.generators.classic import barbell_graph, cycle_graph, path_graph
class TestConvertNumpy:
@classmethod
def setup_class(cls):
global np, sp, sparse, np_assert_equal
np = pytest.importorskip("numpy")
sp = pytest.importorskip("scipy")
sparse = sp.sparse
np_assert_equal = np.testing.assert_equal
def setup_method(self):
self.G1 = barbell_graph(10, 3)
self.G2 = cycle_graph(10, create_using=nx.DiGraph)
self.G3 = self.create_weighted(nx.Graph())
self.G4 = self.create_weighted(nx.DiGraph())
def test_exceptions(self):
class G:
format = None
pytest.raises(nx.NetworkXError, nx.to_networkx_graph, G)
def create_weighted(self, G):
g = cycle_graph(4)
e = list(g.edges())
source = [u for u, v in e]
dest = [v for u, v in e]
weight = [s + 10 for s in source]
ex = zip(source, dest, weight)
G.add_weighted_edges_from(ex)
return G
def assert_isomorphic(self, G1, G2):
assert nx.is_isomorphic(G1, G2)
def identity_conversion(self, G, A, create_using):
GG = nx.from_scipy_sparse_matrix(A, create_using=create_using)
self.assert_isomorphic(G, GG)
GW = nx.to_networkx_graph(A, create_using=create_using)
self.assert_isomorphic(G, GW)
GI = nx.empty_graph(0, create_using).__class__(A)
self.assert_isomorphic(G, GI)
ACSR = A.tocsr()
GI = nx.empty_graph(0, create_using).__class__(ACSR)
self.assert_isomorphic(G, GI)
ACOO = A.tocoo()
GI = nx.empty_graph(0, create_using).__class__(ACOO)
self.assert_isomorphic(G, GI)
ACSC = A.tocsc()
GI = nx.empty_graph(0, create_using).__class__(ACSC)
self.assert_isomorphic(G, GI)
AD = A.todense()
GI = nx.empty_graph(0, create_using).__class__(AD)
self.assert_isomorphic(G, GI)
AA = A.toarray()
GI = nx.empty_graph(0, create_using).__class__(AA)
self.assert_isomorphic(G, GI)
def test_shape(self):
"Conversion from non-square sparse array."
A = sp.sparse.lil_matrix([[1, 2, 3], [4, 5, 6]])
pytest.raises(nx.NetworkXError, nx.from_scipy_sparse_matrix, A)
def test_identity_graph_matrix(self):
"Conversion from graph to sparse matrix to graph."
A = nx.to_scipy_sparse_matrix(self.G1)
self.identity_conversion(self.G1, A, nx.Graph())
def test_identity_digraph_matrix(self):
"Conversion from digraph to sparse matrix to digraph."
A = nx.to_scipy_sparse_matrix(self.G2)
self.identity_conversion(self.G2, A, nx.DiGraph())
def test_identity_weighted_graph_matrix(self):
"""Conversion from weighted graph to sparse matrix to weighted graph."""
A = nx.to_scipy_sparse_matrix(self.G3)
self.identity_conversion(self.G3, A, nx.Graph())
def test_identity_weighted_digraph_matrix(self):
"""Conversion from weighted digraph to sparse matrix to weighted digraph."""
A = nx.to_scipy_sparse_matrix(self.G4)
self.identity_conversion(self.G4, A, nx.DiGraph())
def test_nodelist(self):
"""Conversion from graph to sparse matrix to graph with nodelist."""
P4 = path_graph(4)
P3 = path_graph(3)
nodelist = list(P3.nodes())
A = nx.to_scipy_sparse_matrix(P4, nodelist=nodelist)
GA = nx.Graph(A)
self.assert_isomorphic(GA, P3)
# Make nodelist ambiguous by containing duplicates.
nodelist += [nodelist[0]]
pytest.raises(nx.NetworkXError, nx.to_numpy_matrix, P3, nodelist=nodelist)
def test_weight_keyword(self):
WP4 = nx.Graph()
WP4.add_edges_from((n, n + 1, dict(weight=0.5, other=0.3)) for n in range(3))
P4 = path_graph(4)
A = nx.to_scipy_sparse_matrix(P4)
np_assert_equal(
A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()
)
np_assert_equal(0.5 * A.todense(), nx.to_scipy_sparse_matrix(WP4).todense())
np_assert_equal(
0.3 * A.todense(), nx.to_scipy_sparse_matrix(WP4, weight="other").todense()
)
def test_format_keyword(self):
WP4 = nx.Graph()
WP4.add_edges_from((n, n + 1, dict(weight=0.5, other=0.3)) for n in range(3))
P4 = path_graph(4)
A = nx.to_scipy_sparse_matrix(P4, format="csr")
np_assert_equal(
A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()
)
A = nx.to_scipy_sparse_matrix(P4, format="csc")
np_assert_equal(
A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()
)
A = nx.to_scipy_sparse_matrix(P4, format="coo")
np_assert_equal(
A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()
)
A = nx.to_scipy_sparse_matrix(P4, format="bsr")
np_assert_equal(
A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()
)
A = nx.to_scipy_sparse_matrix(P4, format="lil")
np_assert_equal(
A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()
)
A = nx.to_scipy_sparse_matrix(P4, format="dia")
np_assert_equal(
A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()
)
A = nx.to_scipy_sparse_matrix(P4, format="dok")
np_assert_equal(
A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()
)
def test_format_keyword_raise(self):
with pytest.raises(nx.NetworkXError):
WP4 = nx.Graph()
WP4.add_edges_from(
(n, n + 1, dict(weight=0.5, other=0.3)) for n in range(3)
)
P4 = path_graph(4)
nx.to_scipy_sparse_matrix(P4, format="any_other")
def test_null_raise(self):
with pytest.raises(nx.NetworkXError):
nx.to_scipy_sparse_matrix(nx.Graph())
def test_empty(self):
G = nx.Graph()
G.add_node(1)
M = nx.to_scipy_sparse_matrix(G)
np_assert_equal(M.todense(), np.matrix([[0]]))
def test_ordering(self):
G = nx.DiGraph()
G.add_edge(1, 2)
G.add_edge(2, 3)
G.add_edge(3, 1)
M = nx.to_scipy_sparse_matrix(G, nodelist=[3, 2, 1])
np_assert_equal(M.todense(), np.matrix([[0, 0, 1], [1, 0, 0], [0, 1, 0]]))
def test_selfloop_graph(self):
G = nx.Graph([(1, 1)])
M = nx.to_scipy_sparse_matrix(G)
np_assert_equal(M.todense(), np.matrix([[1]]))
G.add_edges_from([(2, 3), (3, 4)])
M = nx.to_scipy_sparse_matrix(G, nodelist=[2, 3, 4])
np_assert_equal(M.todense(), np.matrix([[0, 1, 0], [1, 0, 1], [0, 1, 0]]))
def test_selfloop_digraph(self):
G = nx.DiGraph([(1, 1)])
M = nx.to_scipy_sparse_matrix(G)
np_assert_equal(M.todense(), np.matrix([[1]]))
G.add_edges_from([(2, 3), (3, 4)])
M = nx.to_scipy_sparse_matrix(G, nodelist=[2, 3, 4])
np_assert_equal(M.todense(), np.matrix([[0, 1, 0], [0, 0, 1], [0, 0, 0]]))
def test_from_scipy_sparse_matrix_parallel_edges(self):
"""Tests that the :func:`networkx.from_scipy_sparse_matrix` function
interprets integer weights as the number of parallel edges when
creating a multigraph.
"""
A = sparse.csr_matrix([[1, 1], [1, 2]])
# First, with a simple graph, each integer entry in the adjacency
# matrix is interpreted as the weight of a single edge in the graph.
expected = nx.DiGraph()
edges = [(0, 0), (0, 1), (1, 0)]
expected.add_weighted_edges_from([(u, v, 1) for (u, v) in edges])
expected.add_edge(1, 1, weight=2)
actual = nx.from_scipy_sparse_matrix(
A, parallel_edges=True, create_using=nx.DiGraph
)
assert_graphs_equal(actual, expected)
actual = nx.from_scipy_sparse_matrix(
A, parallel_edges=False, create_using=nx.DiGraph
)
assert_graphs_equal(actual, expected)
# Now each integer entry in the adjacency matrix is interpreted as the
# number of parallel edges in the graph if the appropriate keyword
# argument is specified.
edges = [(0, 0), (0, 1), (1, 0), (1, 1), (1, 1)]
expected = nx.MultiDiGraph()
expected.add_weighted_edges_from([(u, v, 1) for (u, v) in edges])
actual = nx.from_scipy_sparse_matrix(
A, parallel_edges=True, create_using=nx.MultiDiGraph
)
assert_graphs_equal(actual, expected)
expected = nx.MultiDiGraph()
expected.add_edges_from(set(edges), weight=1)
# The sole self-loop (edge 0) on vertex 1 should have weight 2.
expected[1][1][0]["weight"] = 2
actual = nx.from_scipy_sparse_matrix(
A, parallel_edges=False, create_using=nx.MultiDiGraph
)
assert_graphs_equal(actual, expected)
def test_symmetric(self):
"""Tests that a symmetric matrix has edges added only once to an
undirected multigraph when using
:func:`networkx.from_scipy_sparse_matrix`.
"""
A = sparse.csr_matrix([[0, 1], [1, 0]])
G = nx.from_scipy_sparse_matrix(A, create_using=nx.MultiGraph)
expected = nx.MultiGraph()
expected.add_edge(0, 1, weight=1)
assert_graphs_equal(G, expected)

View file

@ -0,0 +1,39 @@
import pytest
import networkx as nx
# smoke tests for exceptions
def test_raises_networkxexception():
with pytest.raises(nx.NetworkXException):
raise nx.NetworkXException
def test_raises_networkxerr():
with pytest.raises(nx.NetworkXError):
raise nx.NetworkXError
def test_raises_networkx_pointless_concept():
with pytest.raises(nx.NetworkXPointlessConcept):
raise nx.NetworkXPointlessConcept
def test_raises_networkxalgorithmerr():
with pytest.raises(nx.NetworkXAlgorithmError):
raise nx.NetworkXAlgorithmError
def test_raises_networkx_unfeasible():
with pytest.raises(nx.NetworkXUnfeasible):
raise nx.NetworkXUnfeasible
def test_raises_networkx_no_path():
with pytest.raises(nx.NetworkXNoPath):
raise nx.NetworkXNoPath
def test_raises_networkx_unbounded():
with pytest.raises(nx.NetworkXUnbounded):
raise nx.NetworkXUnbounded

View file

@ -0,0 +1,289 @@
import pytest
import networkx as nx
from networkx.generators.classic import empty_graph
from networkx.testing import assert_nodes_equal, assert_edges_equal
class TestRelabel:
def test_convert_node_labels_to_integers(self):
# test that empty graph converts fine for all options
G = empty_graph()
H = nx.convert_node_labels_to_integers(G, 100)
assert list(H.nodes()) == []
assert list(H.edges()) == []
for opt in ["default", "sorted", "increasing degree", "decreasing degree"]:
G = empty_graph()
H = nx.convert_node_labels_to_integers(G, 100, ordering=opt)
assert list(H.nodes()) == []
assert list(H.edges()) == []
G = empty_graph()
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "C"), ("C", "D")])
H = nx.convert_node_labels_to_integers(G)
degH = (d for n, d in H.degree())
degG = (d for n, d in G.degree())
assert sorted(degH) == sorted(degG)
H = nx.convert_node_labels_to_integers(G, 1000)
degH = (d for n, d in H.degree())
degG = (d for n, d in G.degree())
assert sorted(degH) == sorted(degG)
assert_nodes_equal(H.nodes(), [1000, 1001, 1002, 1003])
H = nx.convert_node_labels_to_integers(G, ordering="increasing degree")
degH = (d for n, d in H.degree())
degG = (d for n, d in G.degree())
assert sorted(degH) == sorted(degG)
assert H.degree(0) == 1
assert H.degree(1) == 2
assert H.degree(2) == 2
assert H.degree(3) == 3
H = nx.convert_node_labels_to_integers(G, ordering="decreasing degree")
degH = (d for n, d in H.degree())
degG = (d for n, d in G.degree())
assert sorted(degH) == sorted(degG)
assert H.degree(0) == 3
assert H.degree(1) == 2
assert H.degree(2) == 2
assert H.degree(3) == 1
H = nx.convert_node_labels_to_integers(
G, ordering="increasing degree", label_attribute="label"
)
degH = (d for n, d in H.degree())
degG = (d for n, d in G.degree())
assert sorted(degH) == sorted(degG)
assert H.degree(0) == 1
assert H.degree(1) == 2
assert H.degree(2) == 2
assert H.degree(3) == 3
# check mapping
assert H.nodes[3]["label"] == "C"
assert H.nodes[0]["label"] == "D"
assert H.nodes[1]["label"] == "A" or H.nodes[2]["label"] == "A"
assert H.nodes[1]["label"] == "B" or H.nodes[2]["label"] == "B"
def test_convert_to_integers2(self):
G = empty_graph()
G.add_edges_from([("C", "D"), ("A", "B"), ("A", "C"), ("B", "C")])
H = nx.convert_node_labels_to_integers(G, ordering="sorted")
degH = (d for n, d in H.degree())
degG = (d for n, d in G.degree())
assert sorted(degH) == sorted(degG)
H = nx.convert_node_labels_to_integers(
G, ordering="sorted", label_attribute="label"
)
assert H.nodes[0]["label"] == "A"
assert H.nodes[1]["label"] == "B"
assert H.nodes[2]["label"] == "C"
assert H.nodes[3]["label"] == "D"
def test_convert_to_integers_raise(self):
with pytest.raises(nx.NetworkXError):
G = nx.Graph()
H = nx.convert_node_labels_to_integers(G, ordering="increasing age")
def test_relabel_nodes_copy(self):
G = nx.empty_graph()
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "C"), ("C", "D")])
mapping = {"A": "aardvark", "B": "bear", "C": "cat", "D": "dog"}
H = nx.relabel_nodes(G, mapping)
assert_nodes_equal(H.nodes(), ["aardvark", "bear", "cat", "dog"])
def test_relabel_nodes_function(self):
G = nx.empty_graph()
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "C"), ("C", "D")])
# function mapping no longer encouraged but works
def mapping(n):
return ord(n)
H = nx.relabel_nodes(G, mapping)
assert_nodes_equal(H.nodes(), [65, 66, 67, 68])
def test_relabel_nodes_graph(self):
G = nx.Graph([("A", "B"), ("A", "C"), ("B", "C"), ("C", "D")])
mapping = {"A": "aardvark", "B": "bear", "C": "cat", "D": "dog"}
H = nx.relabel_nodes(G, mapping)
assert_nodes_equal(H.nodes(), ["aardvark", "bear", "cat", "dog"])
def test_relabel_nodes_orderedgraph(self):
G = nx.OrderedGraph()
G.add_nodes_from([1, 2, 3])
G.add_edges_from([(1, 3), (2, 3)])
mapping = {1: "a", 2: "b", 3: "c"}
H = nx.relabel_nodes(G, mapping)
assert list(H.nodes) == ["a", "b", "c"]
def test_relabel_nodes_digraph(self):
G = nx.DiGraph([("A", "B"), ("A", "C"), ("B", "C"), ("C", "D")])
mapping = {"A": "aardvark", "B": "bear", "C": "cat", "D": "dog"}
H = nx.relabel_nodes(G, mapping, copy=False)
assert_nodes_equal(H.nodes(), ["aardvark", "bear", "cat", "dog"])
def test_relabel_nodes_multigraph(self):
G = nx.MultiGraph([("a", "b"), ("a", "b")])
mapping = {"a": "aardvark", "b": "bear"}
G = nx.relabel_nodes(G, mapping, copy=False)
assert_nodes_equal(G.nodes(), ["aardvark", "bear"])
assert_edges_equal(G.edges(), [("aardvark", "bear"), ("aardvark", "bear")])
def test_relabel_nodes_multidigraph(self):
G = nx.MultiDiGraph([("a", "b"), ("a", "b")])
mapping = {"a": "aardvark", "b": "bear"}
G = nx.relabel_nodes(G, mapping, copy=False)
assert_nodes_equal(G.nodes(), ["aardvark", "bear"])
assert_edges_equal(G.edges(), [("aardvark", "bear"), ("aardvark", "bear")])
def test_relabel_isolated_nodes_to_same(self):
G = nx.Graph()
G.add_nodes_from(range(4))
mapping = {1: 1}
H = nx.relabel_nodes(G, mapping, copy=False)
assert_nodes_equal(H.nodes(), list(range(4)))
def test_relabel_nodes_missing(self):
with pytest.raises(KeyError):
G = nx.Graph([("A", "B"), ("A", "C"), ("B", "C"), ("C", "D")])
mapping = {0: "aardvark"}
G = nx.relabel_nodes(G, mapping, copy=False)
def test_relabel_copy_name(self):
G = nx.Graph()
H = nx.relabel_nodes(G, {}, copy=True)
assert H.graph == G.graph
H = nx.relabel_nodes(G, {}, copy=False)
assert H.graph == G.graph
G.name = "first"
H = nx.relabel_nodes(G, {}, copy=True)
assert H.graph == G.graph
H = nx.relabel_nodes(G, {}, copy=False)
assert H.graph == G.graph
def test_relabel_toposort(self):
K5 = nx.complete_graph(4)
G = nx.complete_graph(4)
G = nx.relabel_nodes(G, {i: i + 1 for i in range(4)}, copy=False)
nx.is_isomorphic(K5, G)
G = nx.complete_graph(4)
G = nx.relabel_nodes(G, {i: i - 1 for i in range(4)}, copy=False)
nx.is_isomorphic(K5, G)
def test_relabel_selfloop(self):
G = nx.DiGraph([(1, 1), (1, 2), (2, 3)])
G = nx.relabel_nodes(G, {1: "One", 2: "Two", 3: "Three"}, copy=False)
assert_nodes_equal(G.nodes(), ["One", "Three", "Two"])
G = nx.MultiDiGraph([(1, 1), (1, 2), (2, 3)])
G = nx.relabel_nodes(G, {1: "One", 2: "Two", 3: "Three"}, copy=False)
assert_nodes_equal(G.nodes(), ["One", "Three", "Two"])
G = nx.MultiDiGraph([(1, 1)])
G = nx.relabel_nodes(G, {1: 0}, copy=False)
assert_nodes_equal(G.nodes(), [0])
def test_relabel_multidigraph_inout_merge_nodes(self):
for MG in (nx.MultiGraph, nx.MultiDiGraph):
for cc in (True, False):
G = MG([(0, 4), (1, 4), (4, 2), (4, 3)])
G[0][4][0]["value"] = "a"
G[1][4][0]["value"] = "b"
G[4][2][0]["value"] = "c"
G[4][3][0]["value"] = "d"
G.add_edge(0, 4, key="x", value="e")
G.add_edge(4, 3, key="x", value="f")
mapping = {0: 9, 1: 9, 2: 9, 3: 9}
H = nx.relabel_nodes(G, mapping, copy=cc)
# No ordering on keys enforced
assert {"value": "a"} in H[9][4].values()
assert {"value": "b"} in H[9][4].values()
assert {"value": "c"} in H[4][9].values()
assert len(H[4][9]) == 3 if G.is_directed() else 6
assert {"value": "d"} in H[4][9].values()
assert {"value": "e"} in H[9][4].values()
assert {"value": "f"} in H[4][9].values()
assert len(H[9][4]) == 3 if G.is_directed() else 6
def test_relabel_multigraph_merge_inplace(self):
G = nx.MultiGraph([(0, 1), (0, 2), (0, 3), (0, 1), (0, 2), (0, 3)])
G[0][1][0]["value"] = "a"
G[0][2][0]["value"] = "b"
G[0][3][0]["value"] = "c"
mapping = {1: 4, 2: 4, 3: 4}
nx.relabel_nodes(G, mapping, copy=False)
# No ordering on keys enforced
assert {"value": "a"} in G[0][4].values()
assert {"value": "b"} in G[0][4].values()
assert {"value": "c"} in G[0][4].values()
def test_relabel_multidigraph_merge_inplace(self):
G = nx.MultiDiGraph([(0, 1), (0, 2), (0, 3)])
G[0][1][0]["value"] = "a"
G[0][2][0]["value"] = "b"
G[0][3][0]["value"] = "c"
mapping = {1: 4, 2: 4, 3: 4}
nx.relabel_nodes(G, mapping, copy=False)
# No ordering on keys enforced
assert {"value": "a"} in G[0][4].values()
assert {"value": "b"} in G[0][4].values()
assert {"value": "c"} in G[0][4].values()
def test_relabel_multidigraph_inout_copy(self):
G = nx.MultiDiGraph([(0, 4), (1, 4), (4, 2), (4, 3)])
G[0][4][0]["value"] = "a"
G[1][4][0]["value"] = "b"
G[4][2][0]["value"] = "c"
G[4][3][0]["value"] = "d"
G.add_edge(0, 4, key="x", value="e")
G.add_edge(4, 3, key="x", value="f")
mapping = {0: 9, 1: 9, 2: 9, 3: 9}
H = nx.relabel_nodes(G, mapping, copy=True)
# No ordering on keys enforced
assert {"value": "a"} in H[9][4].values()
assert {"value": "b"} in H[9][4].values()
assert {"value": "c"} in H[4][9].values()
assert len(H[4][9]) == 3
assert {"value": "d"} in H[4][9].values()
assert {"value": "e"} in H[9][4].values()
assert {"value": "f"} in H[4][9].values()
assert len(H[9][4]) == 3
def test_relabel_multigraph_merge_copy(self):
G = nx.MultiGraph([(0, 1), (0, 2), (0, 3)])
G[0][1][0]["value"] = "a"
G[0][2][0]["value"] = "b"
G[0][3][0]["value"] = "c"
mapping = {1: 4, 2: 4, 3: 4}
H = nx.relabel_nodes(G, mapping, copy=True)
assert {"value": "a"} in H[0][4].values()
assert {"value": "b"} in H[0][4].values()
assert {"value": "c"} in H[0][4].values()
def test_relabel_multidigraph_merge_copy(self):
G = nx.MultiDiGraph([(0, 1), (0, 2), (0, 3)])
G[0][1][0]["value"] = "a"
G[0][2][0]["value"] = "b"
G[0][3][0]["value"] = "c"
mapping = {1: 4, 2: 4, 3: 4}
H = nx.relabel_nodes(G, mapping, copy=True)
assert {"value": "a"} in H[0][4].values()
assert {"value": "b"} in H[0][4].values()
assert {"value": "c"} in H[0][4].values()
def test_relabel_multigraph_nonnumeric_key(self):
for MG in (nx.MultiGraph, nx.MultiDiGraph):
for cc in (True, False):
G = nx.MultiGraph()
G.add_edge(0, 1, key="I", value="a")
G.add_edge(0, 2, key="II", value="b")
G.add_edge(0, 3, key="II", value="c")
mapping = {1: 4, 2: 4, 3: 4}
nx.relabel_nodes(G, mapping, copy=False)
assert {"value": "a"} in G[0][4].values()
assert {"value": "b"} in G[0][4].values()
assert {"value": "c"} in G[0][4].values()
assert 0 in G[0][4]
assert "I" in G[0][4]
assert "II" in G[0][4]