update
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,75 +0,0 @@
|
||||
from itertools import groupby
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx import graph_atlas, graph_atlas_g
|
||||
from networkx.generators.atlas import NUM_GRAPHS
|
||||
from networkx.utils import edges_equal, nodes_equal, pairwise
|
||||
|
||||
|
||||
class TestAtlasGraph:
|
||||
"""Unit tests for the :func:`~networkx.graph_atlas` function."""
|
||||
|
||||
def test_index_too_small(self):
|
||||
with pytest.raises(ValueError):
|
||||
graph_atlas(-1)
|
||||
|
||||
def test_index_too_large(self):
|
||||
with pytest.raises(ValueError):
|
||||
graph_atlas(NUM_GRAPHS)
|
||||
|
||||
def test_graph(self):
|
||||
G = graph_atlas(6)
|
||||
assert nodes_equal(G.nodes(), range(3))
|
||||
assert edges_equal(G.edges(), [(0, 1), (0, 2)])
|
||||
|
||||
|
||||
class TestAtlasGraphG:
|
||||
"""Unit tests for the :func:`~networkx.graph_atlas_g` function."""
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.GAG = graph_atlas_g()
|
||||
|
||||
def test_sizes(self):
|
||||
G = self.GAG[0]
|
||||
assert G.number_of_nodes() == 0
|
||||
assert G.number_of_edges() == 0
|
||||
|
||||
G = self.GAG[7]
|
||||
assert G.number_of_nodes() == 3
|
||||
assert G.number_of_edges() == 3
|
||||
|
||||
def test_names(self):
|
||||
for i, G in enumerate(self.GAG):
|
||||
assert int(G.name[1:]) == i
|
||||
|
||||
def test_nondecreasing_nodes(self):
|
||||
# check for nondecreasing number of nodes
|
||||
for n1, n2 in pairwise(map(len, self.GAG)):
|
||||
assert n2 <= n1 + 1
|
||||
|
||||
def test_nondecreasing_edges(self):
|
||||
# check for nondecreasing number of edges (for fixed number of
|
||||
# nodes)
|
||||
for n, group in groupby(self.GAG, key=nx.number_of_nodes):
|
||||
for m1, m2 in pairwise(map(nx.number_of_edges, group)):
|
||||
assert m2 <= m1 + 1
|
||||
|
||||
def test_nondecreasing_degree_sequence(self):
|
||||
# Check for lexicographically nondecreasing degree sequences
|
||||
# (for fixed number of nodes and edges).
|
||||
#
|
||||
# There are three exceptions to this rule in the order given in
|
||||
# the "Atlas of Graphs" book, so we need to manually exclude
|
||||
# those.
|
||||
exceptions = [("G55", "G56"), ("G1007", "G1008"), ("G1012", "G1013")]
|
||||
for n, group in groupby(self.GAG, key=nx.number_of_nodes):
|
||||
for m, group in groupby(group, key=nx.number_of_edges):
|
||||
for G1, G2 in pairwise(group):
|
||||
if (G1.name, G2.name) in exceptions:
|
||||
continue
|
||||
d1 = sorted(d for v, d in G1.degree())
|
||||
d2 = sorted(d for v, d in G2.degree())
|
||||
assert d1 <= d2
|
||||
@@ -1,559 +0,0 @@
|
||||
"""
|
||||
====================
|
||||
Generators - Classic
|
||||
====================
|
||||
|
||||
Unit tests for various classic graph generators in generators/classic.py
|
||||
"""
|
||||
import itertools
|
||||
import typing
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.algorithms.isomorphism.isomorph import graph_could_be_isomorphic
|
||||
from networkx.utils import edges_equal, nodes_equal
|
||||
|
||||
is_isomorphic = graph_could_be_isomorphic
|
||||
|
||||
|
||||
class TestGeneratorClassic:
|
||||
def test_balanced_tree(self):
|
||||
# balanced_tree(r,h) is a tree with (r**(h+1)-1)/(r-1) edges
|
||||
for r, h in [(2, 2), (3, 3), (6, 2)]:
|
||||
t = nx.balanced_tree(r, h)
|
||||
order = t.order()
|
||||
assert order == (r ** (h + 1) - 1) / (r - 1)
|
||||
assert nx.is_connected(t)
|
||||
assert t.size() == order - 1
|
||||
dh = nx.degree_histogram(t)
|
||||
assert dh[0] == 0 # no nodes of 0
|
||||
assert dh[1] == r**h # nodes of degree 1 are leaves
|
||||
assert dh[r] == 1 # root is degree r
|
||||
assert dh[r + 1] == order - r**h - 1 # everyone else is degree r+1
|
||||
assert len(dh) == r + 2
|
||||
|
||||
def test_balanced_tree_star(self):
|
||||
# balanced_tree(r,1) is the r-star
|
||||
t = nx.balanced_tree(r=2, h=1)
|
||||
assert is_isomorphic(t, nx.star_graph(2))
|
||||
t = nx.balanced_tree(r=5, h=1)
|
||||
assert is_isomorphic(t, nx.star_graph(5))
|
||||
t = nx.balanced_tree(r=10, h=1)
|
||||
assert is_isomorphic(t, nx.star_graph(10))
|
||||
|
||||
def test_balanced_tree_path(self):
|
||||
"""Tests that the balanced tree with branching factor one is the
|
||||
path graph.
|
||||
|
||||
"""
|
||||
# A tree of height four has five levels.
|
||||
T = nx.balanced_tree(1, 4)
|
||||
P = nx.path_graph(5)
|
||||
assert is_isomorphic(T, P)
|
||||
|
||||
def test_full_rary_tree(self):
|
||||
r = 2
|
||||
n = 9
|
||||
t = nx.full_rary_tree(r, n)
|
||||
assert t.order() == n
|
||||
assert nx.is_connected(t)
|
||||
dh = nx.degree_histogram(t)
|
||||
assert dh[0] == 0 # no nodes of 0
|
||||
assert dh[1] == 5 # nodes of degree 1 are leaves
|
||||
assert dh[r] == 1 # root is degree r
|
||||
assert dh[r + 1] == 9 - 5 - 1 # everyone else is degree r+1
|
||||
assert len(dh) == r + 2
|
||||
|
||||
def test_full_rary_tree_balanced(self):
|
||||
t = nx.full_rary_tree(2, 15)
|
||||
th = nx.balanced_tree(2, 3)
|
||||
assert is_isomorphic(t, th)
|
||||
|
||||
def test_full_rary_tree_path(self):
|
||||
t = nx.full_rary_tree(1, 10)
|
||||
assert is_isomorphic(t, nx.path_graph(10))
|
||||
|
||||
def test_full_rary_tree_empty(self):
|
||||
t = nx.full_rary_tree(0, 10)
|
||||
assert is_isomorphic(t, nx.empty_graph(10))
|
||||
t = nx.full_rary_tree(3, 0)
|
||||
assert is_isomorphic(t, nx.empty_graph(0))
|
||||
|
||||
def test_full_rary_tree_3_20(self):
|
||||
t = nx.full_rary_tree(3, 20)
|
||||
assert t.order() == 20
|
||||
|
||||
def test_barbell_graph(self):
|
||||
# number of nodes = 2*m1 + m2 (2 m1-complete graphs + m2-path + 2 edges)
|
||||
# number of edges = 2*(nx.number_of_edges(m1-complete graph) + m2 + 1
|
||||
m1 = 3
|
||||
m2 = 5
|
||||
b = nx.barbell_graph(m1, m2)
|
||||
assert nx.number_of_nodes(b) == 2 * m1 + m2
|
||||
assert nx.number_of_edges(b) == m1 * (m1 - 1) + m2 + 1
|
||||
|
||||
m1 = 4
|
||||
m2 = 10
|
||||
b = nx.barbell_graph(m1, m2)
|
||||
assert nx.number_of_nodes(b) == 2 * m1 + m2
|
||||
assert nx.number_of_edges(b) == m1 * (m1 - 1) + m2 + 1
|
||||
|
||||
m1 = 3
|
||||
m2 = 20
|
||||
b = nx.barbell_graph(m1, m2)
|
||||
assert nx.number_of_nodes(b) == 2 * m1 + m2
|
||||
assert nx.number_of_edges(b) == m1 * (m1 - 1) + m2 + 1
|
||||
|
||||
# Raise NetworkXError if m1<2
|
||||
m1 = 1
|
||||
m2 = 20
|
||||
pytest.raises(nx.NetworkXError, nx.barbell_graph, m1, m2)
|
||||
|
||||
# Raise NetworkXError if m2<0
|
||||
m1 = 5
|
||||
m2 = -2
|
||||
pytest.raises(nx.NetworkXError, nx.barbell_graph, m1, m2)
|
||||
|
||||
# nx.barbell_graph(2,m) = nx.path_graph(m+4)
|
||||
m1 = 2
|
||||
m2 = 5
|
||||
b = nx.barbell_graph(m1, m2)
|
||||
assert is_isomorphic(b, nx.path_graph(m2 + 4))
|
||||
|
||||
m1 = 2
|
||||
m2 = 10
|
||||
b = nx.barbell_graph(m1, m2)
|
||||
assert is_isomorphic(b, nx.path_graph(m2 + 4))
|
||||
|
||||
m1 = 2
|
||||
m2 = 20
|
||||
b = nx.barbell_graph(m1, m2)
|
||||
assert is_isomorphic(b, nx.path_graph(m2 + 4))
|
||||
|
||||
pytest.raises(
|
||||
nx.NetworkXError, nx.barbell_graph, m1, m2, create_using=nx.DiGraph()
|
||||
)
|
||||
|
||||
mb = nx.barbell_graph(m1, m2, create_using=nx.MultiGraph())
|
||||
assert edges_equal(mb.edges(), b.edges())
|
||||
|
||||
def test_binomial_tree(self):
|
||||
graphs = (None, nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph)
|
||||
for create_using in graphs:
|
||||
for n in range(0, 4):
|
||||
b = nx.binomial_tree(n, create_using)
|
||||
assert nx.number_of_nodes(b) == 2**n
|
||||
assert nx.number_of_edges(b) == (2**n - 1)
|
||||
|
||||
def test_complete_graph(self):
|
||||
# complete_graph(m) is a connected graph with
|
||||
# m nodes and m*(m+1)/2 edges
|
||||
for m in [0, 1, 3, 5]:
|
||||
g = nx.complete_graph(m)
|
||||
assert nx.number_of_nodes(g) == m
|
||||
assert nx.number_of_edges(g) == m * (m - 1) // 2
|
||||
|
||||
mg = nx.complete_graph(m, create_using=nx.MultiGraph)
|
||||
assert edges_equal(mg.edges(), g.edges())
|
||||
|
||||
g = nx.complete_graph("abc")
|
||||
assert nodes_equal(g.nodes(), ["a", "b", "c"])
|
||||
assert g.size() == 3
|
||||
|
||||
# creates a self-loop... should it? <backward compatible says yes>
|
||||
g = nx.complete_graph("abcb")
|
||||
assert nodes_equal(g.nodes(), ["a", "b", "c"])
|
||||
assert g.size() == 4
|
||||
|
||||
g = nx.complete_graph("abcb", create_using=nx.MultiGraph)
|
||||
assert nodes_equal(g.nodes(), ["a", "b", "c"])
|
||||
assert g.size() == 6
|
||||
|
||||
def test_complete_digraph(self):
|
||||
# complete_graph(m) is a connected graph with
|
||||
# m nodes and m*(m+1)/2 edges
|
||||
for m in [0, 1, 3, 5]:
|
||||
g = nx.complete_graph(m, create_using=nx.DiGraph)
|
||||
assert nx.number_of_nodes(g) == m
|
||||
assert nx.number_of_edges(g) == m * (m - 1)
|
||||
|
||||
g = nx.complete_graph("abc", create_using=nx.DiGraph)
|
||||
assert len(g) == 3
|
||||
assert g.size() == 6
|
||||
assert g.is_directed()
|
||||
|
||||
def test_circular_ladder_graph(self):
|
||||
G = nx.circular_ladder_graph(5)
|
||||
pytest.raises(
|
||||
nx.NetworkXError, nx.circular_ladder_graph, 5, create_using=nx.DiGraph
|
||||
)
|
||||
mG = nx.circular_ladder_graph(5, create_using=nx.MultiGraph)
|
||||
assert edges_equal(mG.edges(), G.edges())
|
||||
|
||||
def test_circulant_graph(self):
|
||||
# Ci_n(1) is the cycle graph for all n
|
||||
Ci6_1 = nx.circulant_graph(6, [1])
|
||||
C6 = nx.cycle_graph(6)
|
||||
assert edges_equal(Ci6_1.edges(), C6.edges())
|
||||
|
||||
# Ci_n(1, 2, ..., n div 2) is the complete graph for all n
|
||||
Ci7 = nx.circulant_graph(7, [1, 2, 3])
|
||||
K7 = nx.complete_graph(7)
|
||||
assert edges_equal(Ci7.edges(), K7.edges())
|
||||
|
||||
# Ci_6(1, 3) is K_3,3 i.e. the utility graph
|
||||
Ci6_1_3 = nx.circulant_graph(6, [1, 3])
|
||||
K3_3 = nx.complete_bipartite_graph(3, 3)
|
||||
assert is_isomorphic(Ci6_1_3, K3_3)
|
||||
|
||||
def test_cycle_graph(self):
|
||||
G = nx.cycle_graph(4)
|
||||
assert edges_equal(G.edges(), [(0, 1), (0, 3), (1, 2), (2, 3)])
|
||||
mG = nx.cycle_graph(4, create_using=nx.MultiGraph)
|
||||
assert edges_equal(mG.edges(), [(0, 1), (0, 3), (1, 2), (2, 3)])
|
||||
G = nx.cycle_graph(4, create_using=nx.DiGraph)
|
||||
assert not G.has_edge(2, 1)
|
||||
assert G.has_edge(1, 2)
|
||||
assert G.is_directed()
|
||||
|
||||
G = nx.cycle_graph("abc")
|
||||
assert len(G) == 3
|
||||
assert G.size() == 3
|
||||
G = nx.cycle_graph("abcb")
|
||||
assert len(G) == 3
|
||||
assert G.size() == 2
|
||||
g = nx.cycle_graph("abc", nx.DiGraph)
|
||||
assert len(g) == 3
|
||||
assert g.size() == 3
|
||||
assert g.is_directed()
|
||||
g = nx.cycle_graph("abcb", nx.DiGraph)
|
||||
assert len(g) == 3
|
||||
assert g.size() == 4
|
||||
|
||||
def test_dorogovtsev_goltsev_mendes_graph(self):
|
||||
G = nx.dorogovtsev_goltsev_mendes_graph(0)
|
||||
assert edges_equal(G.edges(), [(0, 1)])
|
||||
assert nodes_equal(list(G), [0, 1])
|
||||
G = nx.dorogovtsev_goltsev_mendes_graph(1)
|
||||
assert edges_equal(G.edges(), [(0, 1), (0, 2), (1, 2)])
|
||||
assert nx.average_clustering(G) == 1.0
|
||||
assert sorted(nx.triangles(G).values()) == [1, 1, 1]
|
||||
G = nx.dorogovtsev_goltsev_mendes_graph(10)
|
||||
assert nx.number_of_nodes(G) == 29526
|
||||
assert nx.number_of_edges(G) == 59049
|
||||
assert G.degree(0) == 1024
|
||||
assert G.degree(1) == 1024
|
||||
assert G.degree(2) == 1024
|
||||
|
||||
pytest.raises(
|
||||
nx.NetworkXError,
|
||||
nx.dorogovtsev_goltsev_mendes_graph,
|
||||
7,
|
||||
create_using=nx.DiGraph,
|
||||
)
|
||||
pytest.raises(
|
||||
nx.NetworkXError,
|
||||
nx.dorogovtsev_goltsev_mendes_graph,
|
||||
7,
|
||||
create_using=nx.MultiGraph,
|
||||
)
|
||||
|
||||
def test_create_using(self):
|
||||
G = nx.empty_graph()
|
||||
assert isinstance(G, nx.Graph)
|
||||
pytest.raises(TypeError, nx.empty_graph, create_using=0.0)
|
||||
pytest.raises(TypeError, nx.empty_graph, create_using="Graph")
|
||||
|
||||
G = nx.empty_graph(create_using=nx.MultiGraph)
|
||||
assert isinstance(G, nx.MultiGraph)
|
||||
G = nx.empty_graph(create_using=nx.DiGraph)
|
||||
assert isinstance(G, nx.DiGraph)
|
||||
|
||||
G = nx.empty_graph(create_using=nx.DiGraph, default=nx.MultiGraph)
|
||||
assert isinstance(G, nx.DiGraph)
|
||||
G = nx.empty_graph(create_using=None, default=nx.MultiGraph)
|
||||
assert isinstance(G, nx.MultiGraph)
|
||||
G = nx.empty_graph(default=nx.MultiGraph)
|
||||
assert isinstance(G, nx.MultiGraph)
|
||||
|
||||
G = nx.path_graph(5)
|
||||
H = nx.empty_graph(create_using=G)
|
||||
assert not H.is_multigraph()
|
||||
assert not H.is_directed()
|
||||
assert len(H) == 0
|
||||
assert G is H
|
||||
|
||||
H = nx.empty_graph(create_using=nx.MultiGraph())
|
||||
assert H.is_multigraph()
|
||||
assert not H.is_directed()
|
||||
assert G is not H
|
||||
|
||||
# test for subclasses that also use typing.Protocol. See gh-6243
|
||||
class Mixin(typing.Protocol):
|
||||
pass
|
||||
|
||||
class MyGraph(Mixin, nx.DiGraph):
|
||||
pass
|
||||
|
||||
G = nx.empty_graph(create_using=MyGraph)
|
||||
|
||||
def test_empty_graph(self):
|
||||
G = nx.empty_graph()
|
||||
assert nx.number_of_nodes(G) == 0
|
||||
G = nx.empty_graph(42)
|
||||
assert nx.number_of_nodes(G) == 42
|
||||
assert nx.number_of_edges(G) == 0
|
||||
|
||||
G = nx.empty_graph("abc")
|
||||
assert len(G) == 3
|
||||
assert G.size() == 0
|
||||
|
||||
# create empty digraph
|
||||
G = nx.empty_graph(42, create_using=nx.DiGraph(name="duh"))
|
||||
assert nx.number_of_nodes(G) == 42
|
||||
assert nx.number_of_edges(G) == 0
|
||||
assert isinstance(G, nx.DiGraph)
|
||||
|
||||
# create empty multigraph
|
||||
G = nx.empty_graph(42, create_using=nx.MultiGraph(name="duh"))
|
||||
assert nx.number_of_nodes(G) == 42
|
||||
assert nx.number_of_edges(G) == 0
|
||||
assert isinstance(G, nx.MultiGraph)
|
||||
|
||||
# create empty graph from another
|
||||
pete = nx.petersen_graph()
|
||||
G = nx.empty_graph(42, create_using=pete)
|
||||
assert nx.number_of_nodes(G) == 42
|
||||
assert nx.number_of_edges(G) == 0
|
||||
assert isinstance(G, nx.Graph)
|
||||
|
||||
def test_ladder_graph(self):
|
||||
for i, G in [
|
||||
(0, nx.empty_graph(0)),
|
||||
(1, nx.path_graph(2)),
|
||||
(2, nx.hypercube_graph(2)),
|
||||
(10, nx.grid_graph([2, 10])),
|
||||
]:
|
||||
assert is_isomorphic(nx.ladder_graph(i), G)
|
||||
|
||||
pytest.raises(nx.NetworkXError, nx.ladder_graph, 2, create_using=nx.DiGraph)
|
||||
|
||||
g = nx.ladder_graph(2)
|
||||
mg = nx.ladder_graph(2, create_using=nx.MultiGraph)
|
||||
assert edges_equal(mg.edges(), g.edges())
|
||||
|
||||
def test_lollipop_graph_right_sizes(self):
|
||||
# number of nodes = m1 + m2
|
||||
# number of edges = nx.number_of_edges(nx.complete_graph(m1)) + m2
|
||||
for m1, m2 in [(3, 5), (4, 10), (3, 20)]:
|
||||
G = nx.lollipop_graph(m1, m2)
|
||||
assert nx.number_of_nodes(G) == m1 + m2
|
||||
assert nx.number_of_edges(G) == m1 * (m1 - 1) / 2 + m2
|
||||
for first, second in [("ab", ""), ("abc", "defg")]:
|
||||
m1, m2 = len(first), len(second)
|
||||
G = nx.lollipop_graph(first, second)
|
||||
assert nx.number_of_nodes(G) == m1 + m2
|
||||
assert nx.number_of_edges(G) == m1 * (m1 - 1) / 2 + m2
|
||||
|
||||
def test_lollipop_graph_exceptions(self):
|
||||
# Raise NetworkXError if m<2
|
||||
pytest.raises(nx.NetworkXError, nx.lollipop_graph, -1, 2)
|
||||
pytest.raises(nx.NetworkXError, nx.lollipop_graph, 1, 20)
|
||||
pytest.raises(nx.NetworkXError, nx.lollipop_graph, "", 20)
|
||||
pytest.raises(nx.NetworkXError, nx.lollipop_graph, "a", 20)
|
||||
|
||||
# Raise NetworkXError if n<0
|
||||
pytest.raises(nx.NetworkXError, nx.lollipop_graph, 5, -2)
|
||||
|
||||
# raise NetworkXError if create_using is directed
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
nx.lollipop_graph(2, 20, create_using=nx.DiGraph)
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
nx.lollipop_graph(2, 20, create_using=nx.MultiDiGraph)
|
||||
|
||||
def test_lollipop_graph_same_as_path_when_m1_is_2(self):
|
||||
# lollipop_graph(2,m) = path_graph(m+2)
|
||||
for m1, m2 in [(2, 0), (2, 5), (2, 10), ("ab", 20)]:
|
||||
G = nx.lollipop_graph(m1, m2)
|
||||
assert is_isomorphic(G, nx.path_graph(m2 + 2))
|
||||
|
||||
def test_lollipop_graph_for_multigraph(self):
|
||||
G = nx.lollipop_graph(5, 20)
|
||||
MG = nx.lollipop_graph(5, 20, create_using=nx.MultiGraph)
|
||||
assert edges_equal(MG.edges(), G.edges())
|
||||
|
||||
def test_lollipop_graph_mixing_input_types(self):
|
||||
cases = [(4, "abc"), ("abcd", 3), ([1, 2, 3, 4], "abc"), ("abcd", [1, 2, 3])]
|
||||
for m1, m2 in cases:
|
||||
G = nx.lollipop_graph(m1, m2)
|
||||
assert len(G) == 7
|
||||
assert G.size() == 9
|
||||
|
||||
def test_lollipop_graph_not_int_integer_inputs(self):
|
||||
# test non-int integers
|
||||
np = pytest.importorskip("numpy")
|
||||
G = nx.lollipop_graph(np.int32(4), np.int64(3))
|
||||
assert len(G) == 7
|
||||
assert G.size() == 9
|
||||
|
||||
def test_null_graph(self):
|
||||
assert nx.number_of_nodes(nx.null_graph()) == 0
|
||||
|
||||
def test_path_graph(self):
|
||||
p = nx.path_graph(0)
|
||||
assert is_isomorphic(p, nx.null_graph())
|
||||
|
||||
p = nx.path_graph(1)
|
||||
assert is_isomorphic(p, nx.empty_graph(1))
|
||||
|
||||
p = nx.path_graph(10)
|
||||
assert nx.is_connected(p)
|
||||
assert sorted(d for n, d in p.degree()) == [1, 1, 2, 2, 2, 2, 2, 2, 2, 2]
|
||||
assert p.order() - 1 == p.size()
|
||||
|
||||
dp = nx.path_graph(3, create_using=nx.DiGraph)
|
||||
assert dp.has_edge(0, 1)
|
||||
assert not dp.has_edge(1, 0)
|
||||
|
||||
mp = nx.path_graph(10, create_using=nx.MultiGraph)
|
||||
assert edges_equal(mp.edges(), p.edges())
|
||||
|
||||
G = nx.path_graph("abc")
|
||||
assert len(G) == 3
|
||||
assert G.size() == 2
|
||||
G = nx.path_graph("abcb")
|
||||
assert len(G) == 3
|
||||
assert G.size() == 2
|
||||
g = nx.path_graph("abc", nx.DiGraph)
|
||||
assert len(g) == 3
|
||||
assert g.size() == 2
|
||||
assert g.is_directed()
|
||||
g = nx.path_graph("abcb", nx.DiGraph)
|
||||
assert len(g) == 3
|
||||
assert g.size() == 3
|
||||
|
||||
G = nx.path_graph((1, 2, 3, 2, 4))
|
||||
assert G.has_edge(2, 4)
|
||||
|
||||
def test_star_graph(self):
|
||||
assert is_isomorphic(nx.star_graph(""), nx.empty_graph(0))
|
||||
assert is_isomorphic(nx.star_graph([]), nx.empty_graph(0))
|
||||
assert is_isomorphic(nx.star_graph(0), nx.empty_graph(1))
|
||||
assert is_isomorphic(nx.star_graph(1), nx.path_graph(2))
|
||||
assert is_isomorphic(nx.star_graph(2), nx.path_graph(3))
|
||||
assert is_isomorphic(nx.star_graph(5), nx.complete_bipartite_graph(1, 5))
|
||||
|
||||
s = nx.star_graph(10)
|
||||
assert sorted(d for n, d in s.degree()) == [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10]
|
||||
|
||||
pytest.raises(nx.NetworkXError, nx.star_graph, 10, create_using=nx.DiGraph)
|
||||
|
||||
ms = nx.star_graph(10, create_using=nx.MultiGraph)
|
||||
assert edges_equal(ms.edges(), s.edges())
|
||||
|
||||
G = nx.star_graph("abc")
|
||||
assert len(G) == 3
|
||||
assert G.size() == 2
|
||||
|
||||
G = nx.star_graph("abcb")
|
||||
assert len(G) == 3
|
||||
assert G.size() == 2
|
||||
G = nx.star_graph("abcb", create_using=nx.MultiGraph)
|
||||
assert len(G) == 3
|
||||
assert G.size() == 3
|
||||
|
||||
G = nx.star_graph("abcdefg")
|
||||
assert len(G) == 7
|
||||
assert G.size() == 6
|
||||
|
||||
def test_non_int_integers_for_star_graph(self):
|
||||
np = pytest.importorskip("numpy")
|
||||
G = nx.star_graph(np.int32(3))
|
||||
assert len(G) == 4
|
||||
assert G.size() == 3
|
||||
|
||||
def test_trivial_graph(self):
|
||||
assert nx.number_of_nodes(nx.trivial_graph()) == 1
|
||||
|
||||
def test_turan_graph(self):
|
||||
assert nx.number_of_edges(nx.turan_graph(13, 4)) == 63
|
||||
assert is_isomorphic(
|
||||
nx.turan_graph(13, 4), nx.complete_multipartite_graph(3, 4, 3, 3)
|
||||
)
|
||||
|
||||
def test_wheel_graph(self):
|
||||
for n, G in [
|
||||
("", nx.null_graph()),
|
||||
(0, nx.null_graph()),
|
||||
(1, nx.empty_graph(1)),
|
||||
(2, nx.path_graph(2)),
|
||||
(3, nx.complete_graph(3)),
|
||||
(4, nx.complete_graph(4)),
|
||||
]:
|
||||
g = nx.wheel_graph(n)
|
||||
assert is_isomorphic(g, G)
|
||||
|
||||
g = nx.wheel_graph(10)
|
||||
assert sorted(d for n, d in g.degree()) == [3, 3, 3, 3, 3, 3, 3, 3, 3, 9]
|
||||
|
||||
pytest.raises(nx.NetworkXError, nx.wheel_graph, 10, create_using=nx.DiGraph)
|
||||
|
||||
mg = nx.wheel_graph(10, create_using=nx.MultiGraph())
|
||||
assert edges_equal(mg.edges(), g.edges())
|
||||
|
||||
G = nx.wheel_graph("abc")
|
||||
assert len(G) == 3
|
||||
assert G.size() == 3
|
||||
|
||||
G = nx.wheel_graph("abcb")
|
||||
assert len(G) == 3
|
||||
assert G.size() == 4
|
||||
G = nx.wheel_graph("abcb", nx.MultiGraph)
|
||||
assert len(G) == 3
|
||||
assert G.size() == 6
|
||||
|
||||
def test_non_int_integers_for_wheel_graph(self):
|
||||
np = pytest.importorskip("numpy")
|
||||
G = nx.wheel_graph(np.int32(3))
|
||||
assert len(G) == 3
|
||||
assert G.size() == 3
|
||||
|
||||
def test_complete_0_partite_graph(self):
|
||||
"""Tests that the complete 0-partite graph is the null graph."""
|
||||
G = nx.complete_multipartite_graph()
|
||||
H = nx.null_graph()
|
||||
assert nodes_equal(G, H)
|
||||
assert edges_equal(G.edges(), H.edges())
|
||||
|
||||
def test_complete_1_partite_graph(self):
|
||||
"""Tests that the complete 1-partite graph is the empty graph."""
|
||||
G = nx.complete_multipartite_graph(3)
|
||||
H = nx.empty_graph(3)
|
||||
assert nodes_equal(G, H)
|
||||
assert edges_equal(G.edges(), H.edges())
|
||||
|
||||
def test_complete_2_partite_graph(self):
|
||||
"""Tests that the complete 2-partite graph is the complete bipartite
|
||||
graph.
|
||||
|
||||
"""
|
||||
G = nx.complete_multipartite_graph(2, 3)
|
||||
H = nx.complete_bipartite_graph(2, 3)
|
||||
assert nodes_equal(G, H)
|
||||
assert edges_equal(G.edges(), H.edges())
|
||||
|
||||
def test_complete_multipartite_graph(self):
|
||||
"""Tests for generating the complete multipartite graph."""
|
||||
G = nx.complete_multipartite_graph(2, 3, 4)
|
||||
blocks = [(0, 1), (2, 3, 4), (5, 6, 7, 8)]
|
||||
# Within each block, no two vertices should be adjacent.
|
||||
for block in blocks:
|
||||
for u, v in itertools.combinations_with_replacement(block, 2):
|
||||
assert v not in G[u]
|
||||
assert G.nodes[u] == G.nodes[v]
|
||||
# Across blocks, all vertices should be adjacent.
|
||||
for block1, block2 in itertools.combinations(blocks, 2):
|
||||
for u, v in itertools.product(block1, block2):
|
||||
assert v in G[u]
|
||||
assert G.nodes[u] != G.nodes[v]
|
||||
@@ -1,20 +0,0 @@
|
||||
"""Unit tests for the :mod:`networkx.generators.cographs` module.
|
||||
|
||||
"""
|
||||
|
||||
import networkx as nx
|
||||
|
||||
|
||||
def test_random_cograph():
|
||||
n = 3
|
||||
G = nx.random_cograph(n)
|
||||
|
||||
assert len(G) == 2**n
|
||||
|
||||
# Every connected subgraph of G has diameter <= 2
|
||||
if nx.is_connected(G):
|
||||
assert nx.diameter(G) <= 2
|
||||
else:
|
||||
components = nx.connected_components(G)
|
||||
for component in components:
|
||||
assert nx.diameter(G.subgraph(component)) <= 2
|
||||
@@ -1,362 +0,0 @@
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
|
||||
|
||||
def test_random_partition_graph():
|
||||
G = nx.random_partition_graph([3, 3, 3], 1, 0, seed=42)
|
||||
C = G.graph["partition"]
|
||||
assert C == [{0, 1, 2}, {3, 4, 5}, {6, 7, 8}]
|
||||
assert len(G) == 9
|
||||
assert len(list(G.edges())) == 9
|
||||
|
||||
G = nx.random_partition_graph([3, 3, 3], 0, 1)
|
||||
C = G.graph["partition"]
|
||||
assert C == [{0, 1, 2}, {3, 4, 5}, {6, 7, 8}]
|
||||
assert len(G) == 9
|
||||
assert len(list(G.edges())) == 27
|
||||
|
||||
G = nx.random_partition_graph([3, 3, 3], 1, 0, directed=True)
|
||||
C = G.graph["partition"]
|
||||
assert C == [{0, 1, 2}, {3, 4, 5}, {6, 7, 8}]
|
||||
assert len(G) == 9
|
||||
assert len(list(G.edges())) == 18
|
||||
|
||||
G = nx.random_partition_graph([3, 3, 3], 0, 1, directed=True)
|
||||
C = G.graph["partition"]
|
||||
assert C == [{0, 1, 2}, {3, 4, 5}, {6, 7, 8}]
|
||||
assert len(G) == 9
|
||||
assert len(list(G.edges())) == 54
|
||||
|
||||
G = nx.random_partition_graph([1, 2, 3, 4, 5], 0.5, 0.1)
|
||||
C = G.graph["partition"]
|
||||
assert C == [{0}, {1, 2}, {3, 4, 5}, {6, 7, 8, 9}, {10, 11, 12, 13, 14}]
|
||||
assert len(G) == 15
|
||||
|
||||
rpg = nx.random_partition_graph
|
||||
pytest.raises(nx.NetworkXError, rpg, [1, 2, 3], 1.1, 0.1)
|
||||
pytest.raises(nx.NetworkXError, rpg, [1, 2, 3], -0.1, 0.1)
|
||||
pytest.raises(nx.NetworkXError, rpg, [1, 2, 3], 0.1, 1.1)
|
||||
pytest.raises(nx.NetworkXError, rpg, [1, 2, 3], 0.1, -0.1)
|
||||
|
||||
|
||||
def test_planted_partition_graph():
|
||||
G = nx.planted_partition_graph(4, 3, 1, 0, seed=42)
|
||||
C = G.graph["partition"]
|
||||
assert len(C) == 4
|
||||
assert len(G) == 12
|
||||
assert len(list(G.edges())) == 12
|
||||
|
||||
G = nx.planted_partition_graph(4, 3, 0, 1)
|
||||
C = G.graph["partition"]
|
||||
assert len(C) == 4
|
||||
assert len(G) == 12
|
||||
assert len(list(G.edges())) == 54
|
||||
|
||||
G = nx.planted_partition_graph(10, 4, 0.5, 0.1, seed=42)
|
||||
C = G.graph["partition"]
|
||||
assert len(C) == 10
|
||||
assert len(G) == 40
|
||||
|
||||
G = nx.planted_partition_graph(4, 3, 1, 0, directed=True)
|
||||
C = G.graph["partition"]
|
||||
assert len(C) == 4
|
||||
assert len(G) == 12
|
||||
assert len(list(G.edges())) == 24
|
||||
|
||||
G = nx.planted_partition_graph(4, 3, 0, 1, directed=True)
|
||||
C = G.graph["partition"]
|
||||
assert len(C) == 4
|
||||
assert len(G) == 12
|
||||
assert len(list(G.edges())) == 108
|
||||
|
||||
G = nx.planted_partition_graph(10, 4, 0.5, 0.1, seed=42, directed=True)
|
||||
C = G.graph["partition"]
|
||||
assert len(C) == 10
|
||||
assert len(G) == 40
|
||||
|
||||
ppg = nx.planted_partition_graph
|
||||
pytest.raises(nx.NetworkXError, ppg, 3, 3, 1.1, 0.1)
|
||||
pytest.raises(nx.NetworkXError, ppg, 3, 3, -0.1, 0.1)
|
||||
pytest.raises(nx.NetworkXError, ppg, 3, 3, 0.1, 1.1)
|
||||
pytest.raises(nx.NetworkXError, ppg, 3, 3, 0.1, -0.1)
|
||||
|
||||
|
||||
def test_relaxed_caveman_graph():
|
||||
G = nx.relaxed_caveman_graph(4, 3, 0)
|
||||
assert len(G) == 12
|
||||
G = nx.relaxed_caveman_graph(4, 3, 1)
|
||||
assert len(G) == 12
|
||||
G = nx.relaxed_caveman_graph(4, 3, 0.5)
|
||||
assert len(G) == 12
|
||||
G = nx.relaxed_caveman_graph(4, 3, 0.5, seed=42)
|
||||
assert len(G) == 12
|
||||
|
||||
|
||||
def test_connected_caveman_graph():
|
||||
G = nx.connected_caveman_graph(4, 3)
|
||||
assert len(G) == 12
|
||||
|
||||
G = nx.connected_caveman_graph(1, 5)
|
||||
K5 = nx.complete_graph(5)
|
||||
K5.remove_edge(3, 4)
|
||||
assert nx.is_isomorphic(G, K5)
|
||||
|
||||
# need at least 2 nodes in each clique
|
||||
pytest.raises(nx.NetworkXError, nx.connected_caveman_graph, 4, 1)
|
||||
|
||||
|
||||
def test_caveman_graph():
|
||||
G = nx.caveman_graph(4, 3)
|
||||
assert len(G) == 12
|
||||
|
||||
G = nx.caveman_graph(5, 1)
|
||||
E5 = nx.empty_graph(5)
|
||||
assert nx.is_isomorphic(G, E5)
|
||||
|
||||
G = nx.caveman_graph(1, 5)
|
||||
K5 = nx.complete_graph(5)
|
||||
assert nx.is_isomorphic(G, K5)
|
||||
|
||||
|
||||
def test_gaussian_random_partition_graph():
|
||||
G = nx.gaussian_random_partition_graph(100, 10, 10, 0.3, 0.01)
|
||||
assert len(G) == 100
|
||||
G = nx.gaussian_random_partition_graph(100, 10, 10, 0.3, 0.01, directed=True)
|
||||
assert len(G) == 100
|
||||
G = nx.gaussian_random_partition_graph(
|
||||
100, 10, 10, 0.3, 0.01, directed=False, seed=42
|
||||
)
|
||||
assert len(G) == 100
|
||||
assert not isinstance(G, nx.DiGraph)
|
||||
G = nx.gaussian_random_partition_graph(
|
||||
100, 10, 10, 0.3, 0.01, directed=True, seed=42
|
||||
)
|
||||
assert len(G) == 100
|
||||
assert isinstance(G, nx.DiGraph)
|
||||
pytest.raises(
|
||||
nx.NetworkXError, nx.gaussian_random_partition_graph, 100, 101, 10, 1, 0
|
||||
)
|
||||
# Test when clusters are likely less than 1
|
||||
G = nx.gaussian_random_partition_graph(10, 0.5, 0.5, 0.5, 0.5, seed=1)
|
||||
assert len(G) == 10
|
||||
|
||||
|
||||
def test_ring_of_cliques():
|
||||
for i in range(2, 20, 3):
|
||||
for j in range(2, 20, 3):
|
||||
G = nx.ring_of_cliques(i, j)
|
||||
assert G.number_of_nodes() == i * j
|
||||
if i != 2 or j != 1:
|
||||
expected_num_edges = i * (((j * (j - 1)) // 2) + 1)
|
||||
else:
|
||||
# the edge that already exists cannot be duplicated
|
||||
expected_num_edges = i * (((j * (j - 1)) // 2) + 1) - 1
|
||||
assert G.number_of_edges() == expected_num_edges
|
||||
with pytest.raises(
|
||||
nx.NetworkXError, match="A ring of cliques must have at least two cliques"
|
||||
):
|
||||
nx.ring_of_cliques(1, 5)
|
||||
with pytest.raises(
|
||||
nx.NetworkXError, match="The cliques must have at least two nodes"
|
||||
):
|
||||
nx.ring_of_cliques(3, 0)
|
||||
|
||||
|
||||
def test_windmill_graph():
|
||||
for n in range(2, 20, 3):
|
||||
for k in range(2, 20, 3):
|
||||
G = nx.windmill_graph(n, k)
|
||||
assert G.number_of_nodes() == (k - 1) * n + 1
|
||||
assert G.number_of_edges() == n * k * (k - 1) / 2
|
||||
assert G.degree(0) == G.number_of_nodes() - 1
|
||||
for i in range(1, G.number_of_nodes()):
|
||||
assert G.degree(i) == k - 1
|
||||
with pytest.raises(
|
||||
nx.NetworkXError, match="A windmill graph must have at least two cliques"
|
||||
):
|
||||
nx.windmill_graph(1, 3)
|
||||
with pytest.raises(
|
||||
nx.NetworkXError, match="The cliques must have at least two nodes"
|
||||
):
|
||||
nx.windmill_graph(3, 0)
|
||||
|
||||
|
||||
def test_stochastic_block_model():
|
||||
sizes = [75, 75, 300]
|
||||
probs = [[0.25, 0.05, 0.02], [0.05, 0.35, 0.07], [0.02, 0.07, 0.40]]
|
||||
G = nx.stochastic_block_model(sizes, probs, seed=0)
|
||||
C = G.graph["partition"]
|
||||
assert len(C) == 3
|
||||
assert len(G) == 450
|
||||
assert G.size() == 22160
|
||||
|
||||
GG = nx.stochastic_block_model(sizes, probs, range(450), seed=0)
|
||||
assert G.nodes == GG.nodes
|
||||
|
||||
# Test Exceptions
|
||||
sbm = nx.stochastic_block_model
|
||||
badnodelist = list(range(400)) # not enough nodes to match sizes
|
||||
badprobs1 = [[0.25, 0.05, 1.02], [0.05, 0.35, 0.07], [0.02, 0.07, 0.40]]
|
||||
badprobs2 = [[0.25, 0.05, 0.02], [0.05, -0.35, 0.07], [0.02, 0.07, 0.40]]
|
||||
probs_rect1 = [[0.25, 0.05, 0.02], [0.05, -0.35, 0.07]]
|
||||
probs_rect2 = [[0.25, 0.05], [0.05, -0.35], [0.02, 0.07]]
|
||||
asymprobs = [[0.25, 0.05, 0.01], [0.05, -0.35, 0.07], [0.02, 0.07, 0.40]]
|
||||
pytest.raises(nx.NetworkXException, sbm, sizes, badprobs1)
|
||||
pytest.raises(nx.NetworkXException, sbm, sizes, badprobs2)
|
||||
pytest.raises(nx.NetworkXException, sbm, sizes, probs_rect1, directed=True)
|
||||
pytest.raises(nx.NetworkXException, sbm, sizes, probs_rect2, directed=True)
|
||||
pytest.raises(nx.NetworkXException, sbm, sizes, asymprobs, directed=False)
|
||||
pytest.raises(nx.NetworkXException, sbm, sizes, probs, badnodelist)
|
||||
nodelist = [0] + list(range(449)) # repeated node name in nodelist
|
||||
pytest.raises(nx.NetworkXException, sbm, sizes, probs, nodelist)
|
||||
|
||||
# Extra keyword arguments test
|
||||
GG = nx.stochastic_block_model(sizes, probs, seed=0, selfloops=True)
|
||||
assert G.nodes == GG.nodes
|
||||
GG = nx.stochastic_block_model(sizes, probs, selfloops=True, directed=True)
|
||||
assert G.nodes == GG.nodes
|
||||
GG = nx.stochastic_block_model(sizes, probs, seed=0, sparse=False)
|
||||
assert G.nodes == GG.nodes
|
||||
|
||||
|
||||
def test_generator():
|
||||
n = 250
|
||||
tau1 = 3
|
||||
tau2 = 1.5
|
||||
mu = 0.1
|
||||
G = nx.LFR_benchmark_graph(
|
||||
n, tau1, tau2, mu, average_degree=5, min_community=20, seed=10
|
||||
)
|
||||
assert len(G) == 250
|
||||
C = {frozenset(G.nodes[v]["community"]) for v in G}
|
||||
assert nx.community.is_partition(G.nodes(), C)
|
||||
|
||||
|
||||
def test_invalid_tau1():
|
||||
with pytest.raises(nx.NetworkXError, match="tau2 must be greater than one"):
|
||||
n = 100
|
||||
tau1 = 2
|
||||
tau2 = 1
|
||||
mu = 0.1
|
||||
nx.LFR_benchmark_graph(n, tau1, tau2, mu, min_degree=2)
|
||||
|
||||
|
||||
def test_invalid_tau2():
|
||||
with pytest.raises(nx.NetworkXError, match="tau1 must be greater than one"):
|
||||
n = 100
|
||||
tau1 = 1
|
||||
tau2 = 2
|
||||
mu = 0.1
|
||||
nx.LFR_benchmark_graph(n, tau1, tau2, mu, min_degree=2)
|
||||
|
||||
|
||||
def test_mu_too_large():
|
||||
with pytest.raises(nx.NetworkXError, match="mu must be in the interval \\[0, 1\\]"):
|
||||
n = 100
|
||||
tau1 = 2
|
||||
tau2 = 2
|
||||
mu = 1.1
|
||||
nx.LFR_benchmark_graph(n, tau1, tau2, mu, min_degree=2)
|
||||
|
||||
|
||||
def test_mu_too_small():
|
||||
with pytest.raises(nx.NetworkXError, match="mu must be in the interval \\[0, 1\\]"):
|
||||
n = 100
|
||||
tau1 = 2
|
||||
tau2 = 2
|
||||
mu = -1
|
||||
nx.LFR_benchmark_graph(n, tau1, tau2, mu, min_degree=2)
|
||||
|
||||
|
||||
def test_both_degrees_none():
|
||||
with pytest.raises(
|
||||
nx.NetworkXError,
|
||||
match="Must assign exactly one of min_degree and average_degree",
|
||||
):
|
||||
n = 100
|
||||
tau1 = 2
|
||||
tau2 = 2
|
||||
mu = 1
|
||||
nx.LFR_benchmark_graph(n, tau1, tau2, mu)
|
||||
|
||||
|
||||
def test_neither_degrees_none():
|
||||
with pytest.raises(
|
||||
nx.NetworkXError,
|
||||
match="Must assign exactly one of min_degree and average_degree",
|
||||
):
|
||||
n = 100
|
||||
tau1 = 2
|
||||
tau2 = 2
|
||||
mu = 1
|
||||
nx.LFR_benchmark_graph(n, tau1, tau2, mu, min_degree=2, average_degree=5)
|
||||
|
||||
|
||||
def test_max_iters_exeded():
|
||||
with pytest.raises(
|
||||
nx.ExceededMaxIterations,
|
||||
match="Could not assign communities; try increasing min_community",
|
||||
):
|
||||
n = 10
|
||||
tau1 = 2
|
||||
tau2 = 2
|
||||
mu = 0.1
|
||||
nx.LFR_benchmark_graph(n, tau1, tau2, mu, min_degree=2, max_iters=10, seed=1)
|
||||
|
||||
|
||||
def test_max_deg_out_of_range():
|
||||
with pytest.raises(
|
||||
nx.NetworkXError, match="max_degree must be in the interval \\(0, n\\]"
|
||||
):
|
||||
n = 10
|
||||
tau1 = 2
|
||||
tau2 = 2
|
||||
mu = 0.1
|
||||
nx.LFR_benchmark_graph(
|
||||
n, tau1, tau2, mu, max_degree=n + 1, max_iters=10, seed=1
|
||||
)
|
||||
|
||||
|
||||
def test_max_community():
|
||||
n = 250
|
||||
tau1 = 3
|
||||
tau2 = 1.5
|
||||
mu = 0.1
|
||||
G = nx.LFR_benchmark_graph(
|
||||
n,
|
||||
tau1,
|
||||
tau2,
|
||||
mu,
|
||||
average_degree=5,
|
||||
max_degree=100,
|
||||
min_community=50,
|
||||
max_community=200,
|
||||
seed=10,
|
||||
)
|
||||
assert len(G) == 250
|
||||
C = {frozenset(G.nodes[v]["community"]) for v in G}
|
||||
assert nx.community.is_partition(G.nodes(), C)
|
||||
|
||||
|
||||
def test_powerlaw_iterations_exceeded():
|
||||
with pytest.raises(
|
||||
nx.ExceededMaxIterations, match="Could not create power law sequence"
|
||||
):
|
||||
n = 100
|
||||
tau1 = 2
|
||||
tau2 = 2
|
||||
mu = 1
|
||||
nx.LFR_benchmark_graph(n, tau1, tau2, mu, min_degree=2, max_iters=0)
|
||||
|
||||
|
||||
def test_no_scipy_zeta():
|
||||
zeta2 = 1.6449340668482264
|
||||
assert abs(zeta2 - nx.generators.community._hurwitz_zeta(2, 1, 0.0001)) < 0.01
|
||||
|
||||
|
||||
def test_generate_min_degree_itr():
|
||||
with pytest.raises(
|
||||
nx.ExceededMaxIterations, match="Could not match average_degree"
|
||||
):
|
||||
nx.generators.community._generate_min_degree(2, 2, 1, 0.01, 0)
|
||||
@@ -1,230 +0,0 @@
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
|
||||
|
||||
class TestConfigurationModel:
|
||||
"""Unit tests for the :func:`~networkx.configuration_model`
|
||||
function.
|
||||
|
||||
"""
|
||||
|
||||
def test_empty_degree_sequence(self):
|
||||
"""Tests that an empty degree sequence yields the null graph."""
|
||||
G = nx.configuration_model([])
|
||||
assert len(G) == 0
|
||||
|
||||
def test_degree_zero(self):
|
||||
"""Tests that a degree sequence of all zeros yields the empty
|
||||
graph.
|
||||
|
||||
"""
|
||||
G = nx.configuration_model([0, 0, 0])
|
||||
assert len(G) == 3
|
||||
assert G.number_of_edges() == 0
|
||||
|
||||
def test_degree_sequence(self):
|
||||
"""Tests that the degree sequence of the generated graph matches
|
||||
the input degree sequence.
|
||||
|
||||
"""
|
||||
deg_seq = [5, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1]
|
||||
G = nx.configuration_model(deg_seq, seed=12345678)
|
||||
assert sorted((d for n, d in G.degree()), reverse=True) == [
|
||||
5,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
]
|
||||
assert sorted((d for n, d in G.degree(range(len(deg_seq)))), reverse=True) == [
|
||||
5,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
]
|
||||
|
||||
def test_random_seed(self):
|
||||
"""Tests that each call with the same random seed generates the
|
||||
same graph.
|
||||
|
||||
"""
|
||||
deg_seq = [3] * 12
|
||||
G1 = nx.configuration_model(deg_seq, seed=1000)
|
||||
G2 = nx.configuration_model(deg_seq, seed=1000)
|
||||
assert nx.is_isomorphic(G1, G2)
|
||||
G1 = nx.configuration_model(deg_seq, seed=10)
|
||||
G2 = nx.configuration_model(deg_seq, seed=10)
|
||||
assert nx.is_isomorphic(G1, G2)
|
||||
|
||||
def test_directed_disallowed(self):
|
||||
"""Tests that attempting to create a configuration model graph
|
||||
using a directed graph yields an exception.
|
||||
|
||||
"""
|
||||
with pytest.raises(nx.NetworkXNotImplemented):
|
||||
nx.configuration_model([], create_using=nx.DiGraph())
|
||||
|
||||
def test_odd_degree_sum(self):
|
||||
"""Tests that a degree sequence whose sum is odd yields an
|
||||
exception.
|
||||
|
||||
"""
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
nx.configuration_model([1, 2])
|
||||
|
||||
|
||||
def test_directed_configuration_raise_unequal():
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
zin = [5, 3, 3, 3, 3, 2, 2, 2, 1, 1]
|
||||
zout = [5, 3, 3, 3, 3, 2, 2, 2, 1, 2]
|
||||
nx.directed_configuration_model(zin, zout)
|
||||
|
||||
|
||||
def test_directed_configuration_model():
|
||||
G = nx.directed_configuration_model([], [], seed=0)
|
||||
assert len(G) == 0
|
||||
|
||||
|
||||
def test_simple_directed_configuration_model():
|
||||
G = nx.directed_configuration_model([1, 1], [1, 1], seed=0)
|
||||
assert len(G) == 2
|
||||
|
||||
|
||||
def test_expected_degree_graph_empty():
|
||||
# empty graph has empty degree sequence
|
||||
deg_seq = []
|
||||
G = nx.expected_degree_graph(deg_seq)
|
||||
assert dict(G.degree()) == {}
|
||||
|
||||
|
||||
def test_expected_degree_graph():
|
||||
# test that fixed seed delivers the same graph
|
||||
deg_seq = [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
|
||||
G1 = nx.expected_degree_graph(deg_seq, seed=1000)
|
||||
assert len(G1) == 12
|
||||
|
||||
G2 = nx.expected_degree_graph(deg_seq, seed=1000)
|
||||
assert nx.is_isomorphic(G1, G2)
|
||||
|
||||
G1 = nx.expected_degree_graph(deg_seq, seed=10)
|
||||
G2 = nx.expected_degree_graph(deg_seq, seed=10)
|
||||
assert nx.is_isomorphic(G1, G2)
|
||||
|
||||
|
||||
def test_expected_degree_graph_selfloops():
|
||||
deg_seq = [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
|
||||
G1 = nx.expected_degree_graph(deg_seq, seed=1000, selfloops=False)
|
||||
G2 = nx.expected_degree_graph(deg_seq, seed=1000, selfloops=False)
|
||||
assert nx.is_isomorphic(G1, G2)
|
||||
assert len(G1) == 12
|
||||
|
||||
|
||||
def test_expected_degree_graph_skew():
|
||||
deg_seq = [10, 2, 2, 2, 2]
|
||||
G1 = nx.expected_degree_graph(deg_seq, seed=1000)
|
||||
G2 = nx.expected_degree_graph(deg_seq, seed=1000)
|
||||
assert nx.is_isomorphic(G1, G2)
|
||||
assert len(G1) == 5
|
||||
|
||||
|
||||
def test_havel_hakimi_construction():
|
||||
G = nx.havel_hakimi_graph([])
|
||||
assert len(G) == 0
|
||||
|
||||
z = [1000, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1]
|
||||
pytest.raises(nx.NetworkXError, nx.havel_hakimi_graph, z)
|
||||
z = ["A", 3, 3, 3, 3, 2, 2, 2, 1, 1, 1]
|
||||
pytest.raises(nx.NetworkXError, nx.havel_hakimi_graph, z)
|
||||
|
||||
z = [5, 4, 3, 3, 3, 2, 2, 2]
|
||||
G = nx.havel_hakimi_graph(z)
|
||||
G = nx.configuration_model(z)
|
||||
z = [6, 5, 4, 4, 2, 1, 1, 1]
|
||||
pytest.raises(nx.NetworkXError, nx.havel_hakimi_graph, z)
|
||||
|
||||
z = [10, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2]
|
||||
|
||||
G = nx.havel_hakimi_graph(z)
|
||||
|
||||
pytest.raises(nx.NetworkXError, nx.havel_hakimi_graph, z, create_using=nx.DiGraph())
|
||||
|
||||
|
||||
def test_directed_havel_hakimi():
|
||||
# Test range of valid directed degree sequences
|
||||
n, r = 100, 10
|
||||
p = 1.0 / r
|
||||
for i in range(r):
|
||||
G1 = nx.erdos_renyi_graph(n, p * (i + 1), None, True)
|
||||
din1 = [d for n, d in G1.in_degree()]
|
||||
dout1 = [d for n, d in G1.out_degree()]
|
||||
G2 = nx.directed_havel_hakimi_graph(din1, dout1)
|
||||
din2 = [d for n, d in G2.in_degree()]
|
||||
dout2 = [d for n, d in G2.out_degree()]
|
||||
assert sorted(din1) == sorted(din2)
|
||||
assert sorted(dout1) == sorted(dout2)
|
||||
|
||||
# Test non-graphical sequence
|
||||
dout = [1000, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1]
|
||||
din = [103, 102, 102, 102, 102, 102, 102, 102, 102, 102]
|
||||
pytest.raises(nx.exception.NetworkXError, nx.directed_havel_hakimi_graph, din, dout)
|
||||
# Test valid sequences
|
||||
dout = [1, 1, 1, 1, 1, 2, 2, 2, 3, 4]
|
||||
din = [2, 2, 2, 2, 2, 2, 2, 2, 0, 2]
|
||||
G2 = nx.directed_havel_hakimi_graph(din, dout)
|
||||
dout2 = (d for n, d in G2.out_degree())
|
||||
din2 = (d for n, d in G2.in_degree())
|
||||
assert sorted(dout) == sorted(dout2)
|
||||
assert sorted(din) == sorted(din2)
|
||||
# Test unequal sums
|
||||
din = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
|
||||
pytest.raises(nx.exception.NetworkXError, nx.directed_havel_hakimi_graph, din, dout)
|
||||
# Test for negative values
|
||||
din = [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -2]
|
||||
pytest.raises(nx.exception.NetworkXError, nx.directed_havel_hakimi_graph, din, dout)
|
||||
|
||||
|
||||
def test_degree_sequence_tree():
|
||||
z = [1, 1, 1, 1, 1, 2, 2, 2, 3, 4]
|
||||
G = nx.degree_sequence_tree(z)
|
||||
assert len(G) == len(z)
|
||||
assert len(list(G.edges())) == sum(z) / 2
|
||||
|
||||
pytest.raises(
|
||||
nx.NetworkXError, nx.degree_sequence_tree, z, create_using=nx.DiGraph()
|
||||
)
|
||||
|
||||
z = [1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4]
|
||||
pytest.raises(nx.NetworkXError, nx.degree_sequence_tree, z)
|
||||
|
||||
|
||||
def test_random_degree_sequence_graph():
|
||||
d = [1, 2, 2, 3]
|
||||
G = nx.random_degree_sequence_graph(d, seed=42)
|
||||
assert d == sorted(d for n, d in G.degree())
|
||||
|
||||
|
||||
def test_random_degree_sequence_graph_raise():
|
||||
z = [1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4]
|
||||
pytest.raises(nx.NetworkXUnfeasible, nx.random_degree_sequence_graph, z)
|
||||
|
||||
|
||||
def test_random_degree_sequence_large():
|
||||
G1 = nx.fast_gnp_random_graph(100, 0.1, seed=42)
|
||||
d1 = (d for n, d in G1.degree())
|
||||
G2 = nx.random_degree_sequence_graph(d1, seed=42)
|
||||
d2 = (d for n, d in G2.degree())
|
||||
assert sorted(d1) == sorted(d2)
|
||||
@@ -1,172 +0,0 @@
|
||||
"""Generators - Directed Graphs
|
||||
----------------------------
|
||||
"""
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.classes import Graph, MultiDiGraph
|
||||
from networkx.generators.directed import (
|
||||
gn_graph,
|
||||
gnc_graph,
|
||||
gnr_graph,
|
||||
random_k_out_graph,
|
||||
random_uniform_k_out_graph,
|
||||
scale_free_graph,
|
||||
)
|
||||
|
||||
|
||||
class TestGeneratorsDirected:
|
||||
def test_smoke_test_random_graphs(self):
|
||||
gn_graph(100)
|
||||
gnr_graph(100, 0.5)
|
||||
gnc_graph(100)
|
||||
scale_free_graph(100)
|
||||
|
||||
gn_graph(100, seed=42)
|
||||
gnr_graph(100, 0.5, seed=42)
|
||||
gnc_graph(100, seed=42)
|
||||
scale_free_graph(100, seed=42)
|
||||
|
||||
def test_create_using_keyword_arguments(self):
|
||||
pytest.raises(nx.NetworkXError, gn_graph, 100, create_using=Graph())
|
||||
pytest.raises(nx.NetworkXError, gnr_graph, 100, 0.5, create_using=Graph())
|
||||
pytest.raises(nx.NetworkXError, gnc_graph, 100, create_using=Graph())
|
||||
pytest.raises(nx.NetworkXError, scale_free_graph, 100, create_using=Graph())
|
||||
G = gn_graph(100, seed=1)
|
||||
MG = gn_graph(100, create_using=MultiDiGraph(), seed=1)
|
||||
assert sorted(G.edges()) == sorted(MG.edges())
|
||||
G = gnr_graph(100, 0.5, seed=1)
|
||||
MG = gnr_graph(100, 0.5, create_using=MultiDiGraph(), seed=1)
|
||||
assert sorted(G.edges()) == sorted(MG.edges())
|
||||
G = gnc_graph(100, seed=1)
|
||||
MG = gnc_graph(100, create_using=MultiDiGraph(), seed=1)
|
||||
assert sorted(G.edges()) == sorted(MG.edges())
|
||||
|
||||
G = scale_free_graph(
|
||||
100,
|
||||
alpha=0.3,
|
||||
beta=0.4,
|
||||
gamma=0.3,
|
||||
delta_in=0.3,
|
||||
delta_out=0.1,
|
||||
initial_graph=nx.cycle_graph(4, create_using=MultiDiGraph),
|
||||
seed=1,
|
||||
)
|
||||
pytest.raises(ValueError, scale_free_graph, 100, 0.5, 0.4, 0.3)
|
||||
pytest.raises(ValueError, scale_free_graph, 100, alpha=-0.3)
|
||||
pytest.raises(ValueError, scale_free_graph, 100, beta=-0.3)
|
||||
pytest.raises(ValueError, scale_free_graph, 100, gamma=-0.3)
|
||||
|
||||
def test_parameters(self):
|
||||
G = nx.DiGraph()
|
||||
G.add_node(0)
|
||||
|
||||
def kernel(x):
|
||||
return x
|
||||
|
||||
assert nx.is_isomorphic(gn_graph(1), G)
|
||||
assert nx.is_isomorphic(gn_graph(1, kernel=kernel), G)
|
||||
assert nx.is_isomorphic(gnc_graph(1), G)
|
||||
assert nx.is_isomorphic(gnr_graph(1, 0.5), G)
|
||||
|
||||
|
||||
def test_scale_free_graph_create_using_with_initial_graph():
|
||||
G = nx.MultiGraph()
|
||||
with pytest.raises(
|
||||
ValueError,
|
||||
match="Cannot set both create_using and initial_graph. Set create_using=None.",
|
||||
):
|
||||
scale_free_graph(10, create_using=nx.Graph, initial_graph=G)
|
||||
|
||||
|
||||
def test_scale_free_graph_negative_delta():
|
||||
with pytest.raises(ValueError, match="delta_in must be >= 0."):
|
||||
scale_free_graph(10, create_using=None, delta_in=-1)
|
||||
with pytest.raises(ValueError, match="delta_out must be >= 0."):
|
||||
scale_free_graph(10, create_using=None, delta_out=-1)
|
||||
|
||||
|
||||
def test_non_numeric_ordering():
|
||||
G = MultiDiGraph([("a", "b"), ("b", "c"), ("c", "a")])
|
||||
s = scale_free_graph(3, initial_graph=G)
|
||||
assert len(s) == 3
|
||||
assert len(s.edges) == 3
|
||||
|
||||
|
||||
@pytest.mark.parametrize("ig", (nx.Graph(), nx.DiGraph([(0, 1)])))
|
||||
def test_scale_free_graph_initial_graph_kwarg(ig):
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
scale_free_graph(100, initial_graph=ig)
|
||||
|
||||
|
||||
class TestRandomKOutGraph:
|
||||
"""Unit tests for the
|
||||
:func:`~networkx.generators.directed.random_k_out_graph` function.
|
||||
|
||||
"""
|
||||
|
||||
def test_regularity(self):
|
||||
"""Tests that the generated graph is `k`-out-regular."""
|
||||
n = 10
|
||||
k = 3
|
||||
alpha = 1
|
||||
G = random_k_out_graph(n, k, alpha)
|
||||
assert all(d == k for v, d in G.out_degree())
|
||||
G = random_k_out_graph(n, k, alpha, seed=42)
|
||||
assert all(d == k for v, d in G.out_degree())
|
||||
|
||||
def test_no_self_loops(self):
|
||||
"""Tests for forbidding self-loops."""
|
||||
n = 10
|
||||
k = 3
|
||||
alpha = 1
|
||||
G = random_k_out_graph(n, k, alpha, self_loops=False)
|
||||
assert nx.number_of_selfloops(G) == 0
|
||||
|
||||
def test_negative_alpha(self):
|
||||
with pytest.raises(ValueError, match="alpha must be positive"):
|
||||
random_k_out_graph(10, 3, -1)
|
||||
|
||||
|
||||
class TestUniformRandomKOutGraph:
|
||||
"""Unit tests for the
|
||||
:func:`~networkx.generators.directed.random_uniform_k_out_graph`
|
||||
function.
|
||||
|
||||
"""
|
||||
|
||||
def test_regularity(self):
|
||||
"""Tests that the generated graph is `k`-out-regular."""
|
||||
n = 10
|
||||
k = 3
|
||||
G = random_uniform_k_out_graph(n, k)
|
||||
assert all(d == k for v, d in G.out_degree())
|
||||
G = random_uniform_k_out_graph(n, k, seed=42)
|
||||
assert all(d == k for v, d in G.out_degree())
|
||||
|
||||
def test_no_self_loops(self):
|
||||
"""Tests for forbidding self-loops."""
|
||||
n = 10
|
||||
k = 3
|
||||
G = random_uniform_k_out_graph(n, k, self_loops=False)
|
||||
assert nx.number_of_selfloops(G) == 0
|
||||
assert all(d == k for v, d in G.out_degree())
|
||||
|
||||
def test_with_replacement(self):
|
||||
n = 10
|
||||
k = 3
|
||||
G = random_uniform_k_out_graph(n, k, with_replacement=True)
|
||||
assert G.is_multigraph()
|
||||
assert all(d == k for v, d in G.out_degree())
|
||||
n = 10
|
||||
k = 9
|
||||
G = random_uniform_k_out_graph(n, k, with_replacement=False, self_loops=False)
|
||||
assert nx.number_of_selfloops(G) == 0
|
||||
assert all(d == k for v, d in G.out_degree())
|
||||
|
||||
def test_without_replacement(self):
|
||||
n = 10
|
||||
k = 3
|
||||
G = random_uniform_k_out_graph(n, k, with_replacement=False)
|
||||
assert not G.is_multigraph()
|
||||
assert all(d == k for v, d in G.out_degree())
|
||||
@@ -1,73 +0,0 @@
|
||||
"""Unit tests for the :mod:`networkx.generators.duplication` module.
|
||||
|
||||
"""
|
||||
import pytest
|
||||
|
||||
from networkx.exception import NetworkXError
|
||||
from networkx.generators.duplication import (
|
||||
duplication_divergence_graph,
|
||||
partial_duplication_graph,
|
||||
)
|
||||
|
||||
|
||||
class TestDuplicationDivergenceGraph:
|
||||
"""Unit tests for the
|
||||
:func:`networkx.generators.duplication.duplication_divergence_graph`
|
||||
function.
|
||||
|
||||
"""
|
||||
|
||||
def test_final_size(self):
|
||||
G = duplication_divergence_graph(3, 1)
|
||||
assert len(G) == 3
|
||||
G = duplication_divergence_graph(3, 1, seed=42)
|
||||
assert len(G) == 3
|
||||
|
||||
def test_probability_too_large(self):
|
||||
with pytest.raises(NetworkXError):
|
||||
duplication_divergence_graph(3, 2)
|
||||
|
||||
def test_probability_too_small(self):
|
||||
with pytest.raises(NetworkXError):
|
||||
duplication_divergence_graph(3, -1)
|
||||
|
||||
|
||||
class TestPartialDuplicationGraph:
|
||||
"""Unit tests for the
|
||||
:func:`networkx.generators.duplication.partial_duplication_graph`
|
||||
function.
|
||||
|
||||
"""
|
||||
|
||||
def test_final_size(self):
|
||||
N = 10
|
||||
n = 5
|
||||
p = 0.5
|
||||
q = 0.5
|
||||
G = partial_duplication_graph(N, n, p, q)
|
||||
assert len(G) == N
|
||||
G = partial_duplication_graph(N, n, p, q, seed=42)
|
||||
assert len(G) == N
|
||||
|
||||
def test_initial_clique_size(self):
|
||||
N = 10
|
||||
n = 10
|
||||
p = 0.5
|
||||
q = 0.5
|
||||
G = partial_duplication_graph(N, n, p, q)
|
||||
assert len(G) == n
|
||||
|
||||
def test_invalid_initial_size(self):
|
||||
with pytest.raises(NetworkXError):
|
||||
N = 5
|
||||
n = 10
|
||||
p = 0.5
|
||||
q = 0.5
|
||||
G = partial_duplication_graph(N, n, p, q)
|
||||
|
||||
def test_invalid_probabilities(self):
|
||||
N = 1
|
||||
n = 1
|
||||
for p, q in [(0.5, 2), (0.5, -1), (2, 0.5), (-1, 0.5)]:
|
||||
args = (N, n, p, q)
|
||||
pytest.raises(NetworkXError, partial_duplication_graph, *args)
|
||||
@@ -1,39 +0,0 @@
|
||||
"""
|
||||
ego graph
|
||||
---------
|
||||
"""
|
||||
|
||||
import networkx as nx
|
||||
from networkx.utils import edges_equal, nodes_equal
|
||||
|
||||
|
||||
class TestGeneratorEgo:
|
||||
def test_ego(self):
|
||||
G = nx.star_graph(3)
|
||||
H = nx.ego_graph(G, 0)
|
||||
assert nx.is_isomorphic(G, H)
|
||||
G.add_edge(1, 11)
|
||||
G.add_edge(2, 22)
|
||||
G.add_edge(3, 33)
|
||||
H = nx.ego_graph(G, 0)
|
||||
assert nx.is_isomorphic(nx.star_graph(3), H)
|
||||
G = nx.path_graph(3)
|
||||
H = nx.ego_graph(G, 0)
|
||||
assert edges_equal(H.edges(), [(0, 1)])
|
||||
H = nx.ego_graph(G, 0, undirected=True)
|
||||
assert edges_equal(H.edges(), [(0, 1)])
|
||||
H = nx.ego_graph(G, 0, center=False)
|
||||
assert edges_equal(H.edges(), [])
|
||||
|
||||
def test_ego_distance(self):
|
||||
G = nx.Graph()
|
||||
G.add_edge(0, 1, weight=2, distance=1)
|
||||
G.add_edge(1, 2, weight=2, distance=2)
|
||||
G.add_edge(2, 3, weight=2, distance=1)
|
||||
assert nodes_equal(nx.ego_graph(G, 0, radius=3).nodes(), [0, 1, 2, 3])
|
||||
eg = nx.ego_graph(G, 0, radius=3, distance="weight")
|
||||
assert nodes_equal(eg.nodes(), [0, 1])
|
||||
eg = nx.ego_graph(G, 0, radius=3, distance="weight", undirected=True)
|
||||
assert nodes_equal(eg.nodes(), [0, 1])
|
||||
eg = nx.ego_graph(G, 0, radius=3, distance="distance")
|
||||
assert nodes_equal(eg.nodes(), [0, 1, 2])
|
||||
@@ -1,87 +0,0 @@
|
||||
"""Unit tests for the :mod:`networkx.generators.expanders` module.
|
||||
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
|
||||
|
||||
@pytest.mark.parametrize("n", (2, 3, 5, 6, 10))
|
||||
def test_margulis_gabber_galil_graph_properties(n):
|
||||
g = nx.margulis_gabber_galil_graph(n)
|
||||
assert g.number_of_nodes() == n * n
|
||||
for node in g:
|
||||
assert g.degree(node) == 8
|
||||
assert len(node) == 2
|
||||
for i in node:
|
||||
assert int(i) == i
|
||||
assert 0 <= i < n
|
||||
|
||||
|
||||
@pytest.mark.parametrize("n", (2, 3, 5, 6, 10))
|
||||
def test_margulis_gabber_galil_graph_eigvals(n):
|
||||
np = pytest.importorskip("numpy")
|
||||
sp = pytest.importorskip("scipy")
|
||||
import scipy.linalg
|
||||
|
||||
g = nx.margulis_gabber_galil_graph(n)
|
||||
# Eigenvalues are already sorted using the scipy eigvalsh,
|
||||
# but the implementation in numpy does not guarantee order.
|
||||
w = sorted(sp.linalg.eigvalsh(nx.adjacency_matrix(g).toarray()))
|
||||
assert w[-2] < 5 * np.sqrt(2)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("p", (3, 5, 7, 11)) # Primes
|
||||
def test_chordal_cycle_graph(p):
|
||||
"""Test for the :func:`networkx.chordal_cycle_graph` function."""
|
||||
G = nx.chordal_cycle_graph(p)
|
||||
assert len(G) == p
|
||||
# TODO The second largest eigenvalue should be smaller than a constant,
|
||||
# independent of the number of nodes in the graph:
|
||||
#
|
||||
# eigs = sorted(sp.linalg.eigvalsh(nx.adjacency_matrix(G).toarray()))
|
||||
# assert_less(eigs[-2], ...)
|
||||
#
|
||||
|
||||
|
||||
@pytest.mark.parametrize("p", (3, 5, 7, 11, 13)) # Primes
|
||||
def test_paley_graph(p):
|
||||
"""Test for the :func:`networkx.paley_graph` function."""
|
||||
G = nx.paley_graph(p)
|
||||
# G has p nodes
|
||||
assert len(G) == p
|
||||
# G is (p-1)/2-regular
|
||||
in_degrees = {G.in_degree(node) for node in G.nodes}
|
||||
out_degrees = {G.out_degree(node) for node in G.nodes}
|
||||
assert len(in_degrees) == 1 and in_degrees.pop() == (p - 1) // 2
|
||||
assert len(out_degrees) == 1 and out_degrees.pop() == (p - 1) // 2
|
||||
|
||||
# If p = 1 mod 4, -1 is a square mod 4 and therefore the
|
||||
# edge in the Paley graph are symmetric.
|
||||
if p % 4 == 1:
|
||||
for u, v in G.edges:
|
||||
assert (v, u) in G.edges
|
||||
|
||||
|
||||
@pytest.mark.parametrize("graph_type", (nx.Graph, nx.DiGraph, nx.MultiDiGraph))
|
||||
def test_margulis_gabber_galil_graph_badinput(graph_type):
|
||||
with pytest.raises(
|
||||
nx.NetworkXError, match="`create_using` must be an undirected multigraph"
|
||||
):
|
||||
nx.margulis_gabber_galil_graph(3, create_using=graph_type)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("graph_type", (nx.Graph, nx.DiGraph, nx.MultiDiGraph))
|
||||
def test_chordal_cycle_graph_badinput(graph_type):
|
||||
with pytest.raises(
|
||||
nx.NetworkXError, match="`create_using` must be an undirected multigraph"
|
||||
):
|
||||
nx.chordal_cycle_graph(3, create_using=graph_type)
|
||||
|
||||
|
||||
def test_paley_graph_badinput():
|
||||
with pytest.raises(
|
||||
nx.NetworkXError, match="`create_using` cannot be a multigraph."
|
||||
):
|
||||
nx.paley_graph(3, create_using=nx.MultiGraph)
|
||||
@@ -1,331 +0,0 @@
|
||||
import math
|
||||
import random
|
||||
from itertools import combinations
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
|
||||
|
||||
def l1dist(x, y):
|
||||
return sum(abs(a - b) for a, b in zip(x, y))
|
||||
|
||||
|
||||
class TestRandomGeometricGraph:
|
||||
"""Unit tests for the :func:`~networkx.random_geometric_graph`
|
||||
function.
|
||||
|
||||
"""
|
||||
|
||||
def test_number_of_nodes(self):
|
||||
G = nx.random_geometric_graph(50, 0.25, seed=42)
|
||||
assert len(G) == 50
|
||||
G = nx.random_geometric_graph(range(50), 0.25, seed=42)
|
||||
assert len(G) == 50
|
||||
|
||||
def test_distances(self):
|
||||
"""Tests that pairs of vertices adjacent if and only if they are
|
||||
within the prescribed radius.
|
||||
|
||||
"""
|
||||
# Use the Euclidean metric, the default according to the
|
||||
# documentation.
|
||||
G = nx.random_geometric_graph(50, 0.25)
|
||||
for u, v in combinations(G, 2):
|
||||
# Adjacent vertices must be within the given distance.
|
||||
if v in G[u]:
|
||||
assert math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
|
||||
# Nonadjacent vertices must be at greater distance.
|
||||
else:
|
||||
assert not math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
|
||||
|
||||
def test_p(self):
|
||||
"""Tests for providing an alternate distance metric to the
|
||||
generator.
|
||||
|
||||
"""
|
||||
# Use the L1 metric.
|
||||
G = nx.random_geometric_graph(50, 0.25, p=1)
|
||||
for u, v in combinations(G, 2):
|
||||
# Adjacent vertices must be within the given distance.
|
||||
if v in G[u]:
|
||||
assert l1dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
|
||||
# Nonadjacent vertices must be at greater distance.
|
||||
else:
|
||||
assert not l1dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
|
||||
|
||||
def test_node_names(self):
|
||||
"""Tests using values other than sequential numbers as node IDs."""
|
||||
import string
|
||||
|
||||
nodes = list(string.ascii_lowercase)
|
||||
G = nx.random_geometric_graph(nodes, 0.25)
|
||||
assert len(G) == len(nodes)
|
||||
|
||||
for u, v in combinations(G, 2):
|
||||
# Adjacent vertices must be within the given distance.
|
||||
if v in G[u]:
|
||||
assert math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
|
||||
# Nonadjacent vertices must be at greater distance.
|
||||
else:
|
||||
assert not math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
|
||||
|
||||
|
||||
class TestSoftRandomGeometricGraph:
|
||||
"""Unit tests for the :func:`~networkx.soft_random_geometric_graph`
|
||||
function.
|
||||
|
||||
"""
|
||||
|
||||
def test_number_of_nodes(self):
|
||||
G = nx.soft_random_geometric_graph(50, 0.25, seed=42)
|
||||
assert len(G) == 50
|
||||
G = nx.soft_random_geometric_graph(range(50), 0.25, seed=42)
|
||||
assert len(G) == 50
|
||||
|
||||
def test_distances(self):
|
||||
"""Tests that pairs of vertices adjacent if and only if they are
|
||||
within the prescribed radius.
|
||||
|
||||
"""
|
||||
# Use the Euclidean metric, the default according to the
|
||||
# documentation.
|
||||
G = nx.soft_random_geometric_graph(50, 0.25)
|
||||
for u, v in combinations(G, 2):
|
||||
# Adjacent vertices must be within the given distance.
|
||||
if v in G[u]:
|
||||
assert math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
|
||||
|
||||
def test_p(self):
|
||||
"""Tests for providing an alternate distance metric to the
|
||||
generator.
|
||||
|
||||
"""
|
||||
|
||||
# Use the L1 metric.
|
||||
def dist(x, y):
|
||||
return sum(abs(a - b) for a, b in zip(x, y))
|
||||
|
||||
G = nx.soft_random_geometric_graph(50, 0.25, p=1)
|
||||
for u, v in combinations(G, 2):
|
||||
# Adjacent vertices must be within the given distance.
|
||||
if v in G[u]:
|
||||
assert dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
|
||||
|
||||
def test_node_names(self):
|
||||
"""Tests using values other than sequential numbers as node IDs."""
|
||||
import string
|
||||
|
||||
nodes = list(string.ascii_lowercase)
|
||||
G = nx.soft_random_geometric_graph(nodes, 0.25)
|
||||
assert len(G) == len(nodes)
|
||||
|
||||
for u, v in combinations(G, 2):
|
||||
# Adjacent vertices must be within the given distance.
|
||||
if v in G[u]:
|
||||
assert math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
|
||||
|
||||
def test_p_dist_default(self):
|
||||
"""Tests default p_dict = 0.5 returns graph with edge count <= RGG with
|
||||
same n, radius, dim and positions
|
||||
|
||||
"""
|
||||
nodes = 50
|
||||
dim = 2
|
||||
pos = {v: [random.random() for i in range(dim)] for v in range(nodes)}
|
||||
RGG = nx.random_geometric_graph(50, 0.25, pos=pos)
|
||||
SRGG = nx.soft_random_geometric_graph(50, 0.25, pos=pos)
|
||||
assert len(SRGG.edges()) <= len(RGG.edges())
|
||||
|
||||
def test_p_dist_zero(self):
|
||||
"""Tests if p_dict = 0 returns disconnected graph with 0 edges"""
|
||||
|
||||
def p_dist(dist):
|
||||
return 0
|
||||
|
||||
G = nx.soft_random_geometric_graph(50, 0.25, p_dist=p_dist)
|
||||
assert len(G.edges) == 0
|
||||
|
||||
|
||||
def join(G, u, v, theta, alpha, metric):
|
||||
"""Returns ``True`` if and only if the nodes whose attributes are
|
||||
``du`` and ``dv`` should be joined, according to the threshold
|
||||
condition for geographical threshold graphs.
|
||||
|
||||
``G`` is an undirected NetworkX graph, and ``u`` and ``v`` are nodes
|
||||
in that graph. The nodes must have node attributes ``'pos'`` and
|
||||
``'weight'``.
|
||||
|
||||
``metric`` is a distance metric.
|
||||
|
||||
"""
|
||||
du, dv = G.nodes[u], G.nodes[v]
|
||||
u_pos, v_pos = du["pos"], dv["pos"]
|
||||
u_weight, v_weight = du["weight"], dv["weight"]
|
||||
return (u_weight + v_weight) * metric(u_pos, v_pos) ** alpha >= theta
|
||||
|
||||
|
||||
class TestGeographicalThresholdGraph:
|
||||
"""Unit tests for the :func:`~networkx.geographical_threshold_graph`
|
||||
function.
|
||||
|
||||
"""
|
||||
|
||||
def test_number_of_nodes(self):
|
||||
G = nx.geographical_threshold_graph(50, 100, seed=42)
|
||||
assert len(G) == 50
|
||||
G = nx.geographical_threshold_graph(range(50), 100, seed=42)
|
||||
assert len(G) == 50
|
||||
|
||||
def test_distances(self):
|
||||
"""Tests that pairs of vertices adjacent if and only if their
|
||||
distances meet the given threshold.
|
||||
|
||||
"""
|
||||
# Use the Euclidean metric and alpha = -2
|
||||
# the default according to the documentation.
|
||||
G = nx.geographical_threshold_graph(50, 10)
|
||||
for u, v in combinations(G, 2):
|
||||
# Adjacent vertices must exceed the threshold.
|
||||
if v in G[u]:
|
||||
assert join(G, u, v, 10, -2, math.dist)
|
||||
# Nonadjacent vertices must not exceed the threshold.
|
||||
else:
|
||||
assert not join(G, u, v, 10, -2, math.dist)
|
||||
|
||||
def test_metric(self):
|
||||
"""Tests for providing an alternate distance metric to the
|
||||
generator.
|
||||
|
||||
"""
|
||||
# Use the L1 metric.
|
||||
G = nx.geographical_threshold_graph(50, 10, metric=l1dist)
|
||||
for u, v in combinations(G, 2):
|
||||
# Adjacent vertices must exceed the threshold.
|
||||
if v in G[u]:
|
||||
assert join(G, u, v, 10, -2, l1dist)
|
||||
# Nonadjacent vertices must not exceed the threshold.
|
||||
else:
|
||||
assert not join(G, u, v, 10, -2, l1dist)
|
||||
|
||||
def test_p_dist_zero(self):
|
||||
"""Tests if p_dict = 0 returns disconnected graph with 0 edges"""
|
||||
|
||||
def p_dist(dist):
|
||||
return 0
|
||||
|
||||
G = nx.geographical_threshold_graph(50, 1, p_dist=p_dist)
|
||||
assert len(G.edges) == 0
|
||||
|
||||
|
||||
class TestWaxmanGraph:
|
||||
"""Unit tests for the :func:`~networkx.waxman_graph` function."""
|
||||
|
||||
def test_number_of_nodes_1(self):
|
||||
G = nx.waxman_graph(50, 0.5, 0.1, seed=42)
|
||||
assert len(G) == 50
|
||||
G = nx.waxman_graph(range(50), 0.5, 0.1, seed=42)
|
||||
assert len(G) == 50
|
||||
|
||||
def test_number_of_nodes_2(self):
|
||||
G = nx.waxman_graph(50, 0.5, 0.1, L=1)
|
||||
assert len(G) == 50
|
||||
G = nx.waxman_graph(range(50), 0.5, 0.1, L=1)
|
||||
assert len(G) == 50
|
||||
|
||||
def test_metric(self):
|
||||
"""Tests for providing an alternate distance metric to the
|
||||
generator.
|
||||
|
||||
"""
|
||||
# Use the L1 metric.
|
||||
G = nx.waxman_graph(50, 0.5, 0.1, metric=l1dist)
|
||||
assert len(G) == 50
|
||||
|
||||
|
||||
class TestNavigableSmallWorldGraph:
|
||||
def test_navigable_small_world(self):
|
||||
G = nx.navigable_small_world_graph(5, p=1, q=0, seed=42)
|
||||
gg = nx.grid_2d_graph(5, 5).to_directed()
|
||||
assert nx.is_isomorphic(G, gg)
|
||||
|
||||
G = nx.navigable_small_world_graph(5, p=1, q=0, dim=3)
|
||||
gg = nx.grid_graph([5, 5, 5]).to_directed()
|
||||
assert nx.is_isomorphic(G, gg)
|
||||
|
||||
G = nx.navigable_small_world_graph(5, p=1, q=0, dim=1)
|
||||
gg = nx.grid_graph([5]).to_directed()
|
||||
assert nx.is_isomorphic(G, gg)
|
||||
|
||||
|
||||
class TestThresholdedRandomGeometricGraph:
|
||||
"""Unit tests for the :func:`~networkx.thresholded_random_geometric_graph`
|
||||
function.
|
||||
|
||||
"""
|
||||
|
||||
def test_number_of_nodes(self):
|
||||
G = nx.thresholded_random_geometric_graph(50, 0.2, 0.1, seed=42)
|
||||
assert len(G) == 50
|
||||
G = nx.thresholded_random_geometric_graph(range(50), 0.2, 0.1)
|
||||
assert len(G) == 50
|
||||
|
||||
def test_distances(self):
|
||||
"""Tests that pairs of vertices adjacent if and only if they are
|
||||
within the prescribed radius.
|
||||
|
||||
"""
|
||||
# Use the Euclidean metric, the default according to the
|
||||
# documentation.
|
||||
G = nx.thresholded_random_geometric_graph(50, 0.25, 0.1)
|
||||
for u, v in combinations(G, 2):
|
||||
# Adjacent vertices must be within the given distance.
|
||||
if v in G[u]:
|
||||
assert math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
|
||||
|
||||
def test_p(self):
|
||||
"""Tests for providing an alternate distance metric to the
|
||||
generator.
|
||||
|
||||
"""
|
||||
|
||||
# Use the L1 metric.
|
||||
def dist(x, y):
|
||||
return sum(abs(a - b) for a, b in zip(x, y))
|
||||
|
||||
G = nx.thresholded_random_geometric_graph(50, 0.25, 0.1, p=1)
|
||||
for u, v in combinations(G, 2):
|
||||
# Adjacent vertices must be within the given distance.
|
||||
if v in G[u]:
|
||||
assert dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
|
||||
|
||||
def test_node_names(self):
|
||||
"""Tests using values other than sequential numbers as node IDs."""
|
||||
import string
|
||||
|
||||
nodes = list(string.ascii_lowercase)
|
||||
G = nx.thresholded_random_geometric_graph(nodes, 0.25, 0.1)
|
||||
assert len(G) == len(nodes)
|
||||
|
||||
for u, v in combinations(G, 2):
|
||||
# Adjacent vertices must be within the given distance.
|
||||
if v in G[u]:
|
||||
assert math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
|
||||
|
||||
def test_theta(self):
|
||||
"""Tests that pairs of vertices adjacent if and only if their sum
|
||||
weights exceeds the threshold parameter theta.
|
||||
"""
|
||||
G = nx.thresholded_random_geometric_graph(50, 0.25, 0.1)
|
||||
|
||||
for u, v in combinations(G, 2):
|
||||
# Adjacent vertices must be within the given distance.
|
||||
if v in G[u]:
|
||||
assert (G.nodes[u]["weight"] + G.nodes[v]["weight"]) >= 0.1
|
||||
|
||||
|
||||
def test_geometric_edges_raises_no_pos():
|
||||
G = nx.path_graph(3)
|
||||
msg = "All nodes in `G` must have a 'pos' attribute"
|
||||
with pytest.raises(nx.NetworkXError, match=msg):
|
||||
nx.geometric_edges(G, radius=1)
|
||||
@@ -1,134 +0,0 @@
|
||||
"""Unit tests for the :mod:`networkx.generators.harary_graph` module.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.algorithms.isomorphism.isomorph import is_isomorphic
|
||||
from networkx.generators.harary_graph import hkn_harary_graph, hnm_harary_graph
|
||||
|
||||
|
||||
class TestHararyGraph:
|
||||
"""
|
||||
Suppose n nodes, m >= n-1 edges, d = 2m // n, r = 2m % n
|
||||
"""
|
||||
|
||||
def test_hnm_harary_graph(self):
|
||||
# When d is even and r = 0, the hnm_harary_graph(n,m) is
|
||||
# the circulant_graph(n, list(range(1,d/2+1)))
|
||||
for n, m in [(5, 5), (6, 12), (7, 14)]:
|
||||
G1 = hnm_harary_graph(n, m)
|
||||
d = 2 * m // n
|
||||
G2 = nx.circulant_graph(n, list(range(1, d // 2 + 1)))
|
||||
assert is_isomorphic(G1, G2)
|
||||
|
||||
# When d is even and r > 0, the hnm_harary_graph(n,m) is
|
||||
# the circulant_graph(n, list(range(1,d/2+1)))
|
||||
# with r edges added arbitrarily
|
||||
for n, m in [(5, 7), (6, 13), (7, 16)]:
|
||||
G1 = hnm_harary_graph(n, m)
|
||||
d = 2 * m // n
|
||||
G2 = nx.circulant_graph(n, list(range(1, d // 2 + 1)))
|
||||
assert set(G2.edges) < set(G1.edges)
|
||||
assert G1.number_of_edges() == m
|
||||
|
||||
# When d is odd and n is even and r = 0, the hnm_harary_graph(n,m)
|
||||
# is the circulant_graph(n, list(range(1,(d+1)/2) plus [n//2])
|
||||
for n, m in [(6, 9), (8, 12), (10, 15)]:
|
||||
G1 = hnm_harary_graph(n, m)
|
||||
d = 2 * m // n
|
||||
L = list(range(1, (d + 1) // 2))
|
||||
L.append(n // 2)
|
||||
G2 = nx.circulant_graph(n, L)
|
||||
assert is_isomorphic(G1, G2)
|
||||
|
||||
# When d is odd and n is even and r > 0, the hnm_harary_graph(n,m)
|
||||
# is the circulant_graph(n, list(range(1,(d+1)/2) plus [n//2])
|
||||
# with r edges added arbitrarily
|
||||
for n, m in [(6, 10), (8, 13), (10, 17)]:
|
||||
G1 = hnm_harary_graph(n, m)
|
||||
d = 2 * m // n
|
||||
L = list(range(1, (d + 1) // 2))
|
||||
L.append(n // 2)
|
||||
G2 = nx.circulant_graph(n, L)
|
||||
assert set(G2.edges) < set(G1.edges)
|
||||
assert G1.number_of_edges() == m
|
||||
|
||||
# When d is odd and n is odd, the hnm_harary_graph(n,m) is
|
||||
# the circulant_graph(n, list(range(1,(d+1)/2))
|
||||
# with m - n*(d-1)/2 edges added arbitrarily
|
||||
for n, m in [(5, 4), (7, 12), (9, 14)]:
|
||||
G1 = hnm_harary_graph(n, m)
|
||||
d = 2 * m // n
|
||||
L = list(range(1, (d + 1) // 2))
|
||||
G2 = nx.circulant_graph(n, L)
|
||||
assert set(G2.edges) < set(G1.edges)
|
||||
assert G1.number_of_edges() == m
|
||||
|
||||
# Raise NetworkXError if n<1
|
||||
n = 0
|
||||
m = 0
|
||||
pytest.raises(nx.NetworkXError, hnm_harary_graph, n, m)
|
||||
|
||||
# Raise NetworkXError if m < n-1
|
||||
n = 6
|
||||
m = 4
|
||||
pytest.raises(nx.NetworkXError, hnm_harary_graph, n, m)
|
||||
|
||||
# Raise NetworkXError if m > n(n-1)/2
|
||||
n = 6
|
||||
m = 16
|
||||
pytest.raises(nx.NetworkXError, hnm_harary_graph, n, m)
|
||||
|
||||
"""
|
||||
Suppose connectivity k, number of nodes n
|
||||
"""
|
||||
|
||||
def test_hkn_harary_graph(self):
|
||||
# When k == 1, the hkn_harary_graph(k,n) is
|
||||
# the path_graph(n)
|
||||
for k, n in [(1, 6), (1, 7)]:
|
||||
G1 = hkn_harary_graph(k, n)
|
||||
G2 = nx.path_graph(n)
|
||||
assert is_isomorphic(G1, G2)
|
||||
|
||||
# When k is even, the hkn_harary_graph(k,n) is
|
||||
# the circulant_graph(n, list(range(1,k/2+1)))
|
||||
for k, n in [(2, 6), (2, 7), (4, 6), (4, 7)]:
|
||||
G1 = hkn_harary_graph(k, n)
|
||||
G2 = nx.circulant_graph(n, list(range(1, k // 2 + 1)))
|
||||
assert is_isomorphic(G1, G2)
|
||||
|
||||
# When k is odd and n is even, the hkn_harary_graph(k,n) is
|
||||
# the circulant_graph(n, list(range(1,(k+1)/2)) plus [n/2])
|
||||
for k, n in [(3, 6), (5, 8), (7, 10)]:
|
||||
G1 = hkn_harary_graph(k, n)
|
||||
L = list(range(1, (k + 1) // 2))
|
||||
L.append(n // 2)
|
||||
G2 = nx.circulant_graph(n, L)
|
||||
assert is_isomorphic(G1, G2)
|
||||
|
||||
# When k is odd and n is odd, the hkn_harary_graph(k,n) is
|
||||
# the circulant_graph(n, list(range(1,(k+1)/2))) with
|
||||
# n//2+1 edges added between node i and node i+n//2+1
|
||||
for k, n in [(3, 5), (5, 9), (7, 11)]:
|
||||
G1 = hkn_harary_graph(k, n)
|
||||
G2 = nx.circulant_graph(n, list(range(1, (k + 1) // 2)))
|
||||
eSet1 = set(G1.edges)
|
||||
eSet2 = set(G2.edges)
|
||||
eSet3 = set()
|
||||
half = n // 2
|
||||
for i in range(0, half + 1):
|
||||
# add half+1 edges between i and i+half
|
||||
eSet3.add((i, (i + half) % n))
|
||||
assert eSet1 == eSet2 | eSet3
|
||||
|
||||
# Raise NetworkXError if k<1
|
||||
k = 0
|
||||
n = 0
|
||||
pytest.raises(nx.NetworkXError, hkn_harary_graph, k, n)
|
||||
|
||||
# Raise NetworkXError if n<k+1
|
||||
k = 6
|
||||
n = 6
|
||||
pytest.raises(nx.NetworkXError, hkn_harary_graph, k, n)
|
||||
@@ -1,176 +0,0 @@
|
||||
from pytest import approx
|
||||
|
||||
from networkx import is_connected, neighbors
|
||||
from networkx.generators.internet_as_graphs import random_internet_as_graph
|
||||
|
||||
|
||||
class TestInternetASTopology:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.n = 1000
|
||||
cls.seed = 42
|
||||
cls.G = random_internet_as_graph(cls.n, cls.seed)
|
||||
cls.T = []
|
||||
cls.M = []
|
||||
cls.C = []
|
||||
cls.CP = []
|
||||
cls.customers = {}
|
||||
cls.providers = {}
|
||||
|
||||
for i in cls.G.nodes():
|
||||
if cls.G.nodes[i]["type"] == "T":
|
||||
cls.T.append(i)
|
||||
elif cls.G.nodes[i]["type"] == "M":
|
||||
cls.M.append(i)
|
||||
elif cls.G.nodes[i]["type"] == "C":
|
||||
cls.C.append(i)
|
||||
elif cls.G.nodes[i]["type"] == "CP":
|
||||
cls.CP.append(i)
|
||||
else:
|
||||
raise ValueError("Inconsistent data in the graph node attributes")
|
||||
cls.set_customers(i)
|
||||
cls.set_providers(i)
|
||||
|
||||
@classmethod
|
||||
def set_customers(cls, i):
|
||||
if i not in cls.customers:
|
||||
cls.customers[i] = set()
|
||||
for j in neighbors(cls.G, i):
|
||||
e = cls.G.edges[(i, j)]
|
||||
if e["type"] == "transit":
|
||||
customer = int(e["customer"])
|
||||
if j == customer:
|
||||
cls.set_customers(j)
|
||||
cls.customers[i] = cls.customers[i].union(cls.customers[j])
|
||||
cls.customers[i].add(j)
|
||||
elif i != customer:
|
||||
raise ValueError(
|
||||
"Inconsistent data in the graph edge attributes"
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def set_providers(cls, i):
|
||||
if i not in cls.providers:
|
||||
cls.providers[i] = set()
|
||||
for j in neighbors(cls.G, i):
|
||||
e = cls.G.edges[(i, j)]
|
||||
if e["type"] == "transit":
|
||||
customer = int(e["customer"])
|
||||
if i == customer:
|
||||
cls.set_providers(j)
|
||||
cls.providers[i] = cls.providers[i].union(cls.providers[j])
|
||||
cls.providers[i].add(j)
|
||||
elif j != customer:
|
||||
raise ValueError(
|
||||
"Inconsistent data in the graph edge attributes"
|
||||
)
|
||||
|
||||
def test_wrong_input(self):
|
||||
G = random_internet_as_graph(0)
|
||||
assert len(G.nodes()) == 0
|
||||
|
||||
G = random_internet_as_graph(-1)
|
||||
assert len(G.nodes()) == 0
|
||||
|
||||
G = random_internet_as_graph(1)
|
||||
assert len(G.nodes()) == 1
|
||||
|
||||
def test_node_numbers(self):
|
||||
assert len(self.G.nodes()) == self.n
|
||||
assert len(self.T) < 7
|
||||
assert len(self.M) == round(self.n * 0.15)
|
||||
assert len(self.CP) == round(self.n * 0.05)
|
||||
numb = self.n - len(self.T) - len(self.M) - len(self.CP)
|
||||
assert len(self.C) == numb
|
||||
|
||||
def test_connectivity(self):
|
||||
assert is_connected(self.G)
|
||||
|
||||
def test_relationships(self):
|
||||
# T nodes are not customers of anyone
|
||||
for i in self.T:
|
||||
assert len(self.providers[i]) == 0
|
||||
|
||||
# C nodes are not providers of anyone
|
||||
for i in self.C:
|
||||
assert len(self.customers[i]) == 0
|
||||
|
||||
# CP nodes are not providers of anyone
|
||||
for i in self.CP:
|
||||
assert len(self.customers[i]) == 0
|
||||
|
||||
# test whether there is a customer-provider loop
|
||||
for i in self.G.nodes():
|
||||
assert len(self.customers[i].intersection(self.providers[i])) == 0
|
||||
|
||||
# test whether there is a peering with a customer or provider
|
||||
for i, j in self.G.edges():
|
||||
if self.G.edges[(i, j)]["type"] == "peer":
|
||||
assert j not in self.customers[i]
|
||||
assert i not in self.customers[j]
|
||||
assert j not in self.providers[i]
|
||||
assert i not in self.providers[j]
|
||||
|
||||
def test_degree_values(self):
|
||||
d_m = 0 # multihoming degree for M nodes
|
||||
d_cp = 0 # multihoming degree for CP nodes
|
||||
d_c = 0 # multihoming degree for C nodes
|
||||
p_m_m = 0 # avg number of peering edges between M and M
|
||||
p_cp_m = 0 # avg number of peering edges between CP and M
|
||||
p_cp_cp = 0 # avg number of peering edges between CP and CP
|
||||
t_m = 0 # probability M's provider is T
|
||||
t_cp = 0 # probability CP's provider is T
|
||||
t_c = 0 # probability C's provider is T
|
||||
|
||||
for i, j in self.G.edges():
|
||||
e = self.G.edges[(i, j)]
|
||||
if e["type"] == "transit":
|
||||
cust = int(e["customer"])
|
||||
if i == cust:
|
||||
prov = j
|
||||
elif j == cust:
|
||||
prov = i
|
||||
else:
|
||||
raise ValueError("Inconsistent data in the graph edge attributes")
|
||||
if cust in self.M:
|
||||
d_m += 1
|
||||
if self.G.nodes[prov]["type"] == "T":
|
||||
t_m += 1
|
||||
elif cust in self.C:
|
||||
d_c += 1
|
||||
if self.G.nodes[prov]["type"] == "T":
|
||||
t_c += 1
|
||||
elif cust in self.CP:
|
||||
d_cp += 1
|
||||
if self.G.nodes[prov]["type"] == "T":
|
||||
t_cp += 1
|
||||
else:
|
||||
raise ValueError("Inconsistent data in the graph edge attributes")
|
||||
elif e["type"] == "peer":
|
||||
if self.G.nodes[i]["type"] == "M" and self.G.nodes[j]["type"] == "M":
|
||||
p_m_m += 1
|
||||
if self.G.nodes[i]["type"] == "CP" and self.G.nodes[j]["type"] == "CP":
|
||||
p_cp_cp += 1
|
||||
if (
|
||||
self.G.nodes[i]["type"] == "M"
|
||||
and self.G.nodes[j]["type"] == "CP"
|
||||
or self.G.nodes[i]["type"] == "CP"
|
||||
and self.G.nodes[j]["type"] == "M"
|
||||
):
|
||||
p_cp_m += 1
|
||||
else:
|
||||
raise ValueError("Unexpected data in the graph edge attributes")
|
||||
|
||||
assert d_m / len(self.M) == approx((2 + (2.5 * self.n) / 10000), abs=1e-0)
|
||||
assert d_cp / len(self.CP) == approx((2 + (1.5 * self.n) / 10000), abs=1e-0)
|
||||
assert d_c / len(self.C) == approx((1 + (5 * self.n) / 100000), abs=1e-0)
|
||||
|
||||
assert p_m_m / len(self.M) == approx((1 + (2 * self.n) / 10000), abs=1e-0)
|
||||
assert p_cp_m / len(self.CP) == approx((0.2 + (2 * self.n) / 10000), abs=1e-0)
|
||||
assert p_cp_cp / len(self.CP) == approx(
|
||||
(0.05 + (2 * self.n) / 100000), abs=1e-0
|
||||
)
|
||||
|
||||
assert t_m / d_m == approx(0.375, abs=1e-1)
|
||||
assert t_cp / d_cp == approx(0.375, abs=1e-1)
|
||||
assert t_c / d_c == approx(0.125, abs=1e-1)
|
||||
@@ -1,28 +0,0 @@
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
|
||||
|
||||
class TestIntersectionGraph:
|
||||
def test_random_intersection_graph(self):
|
||||
G = nx.uniform_random_intersection_graph(10, 5, 0.5)
|
||||
assert len(G) == 10
|
||||
|
||||
def test_k_random_intersection_graph(self):
|
||||
G = nx.k_random_intersection_graph(10, 5, 2)
|
||||
assert len(G) == 10
|
||||
|
||||
def test_k_random_intersection_graph_seeded(self):
|
||||
G = nx.k_random_intersection_graph(10, 5, 2, seed=1234)
|
||||
assert len(G) == 10
|
||||
|
||||
def test_general_random_intersection_graph(self):
|
||||
G = nx.general_random_intersection_graph(10, 5, [0.1, 0.2, 0.2, 0.1, 0.1])
|
||||
assert len(G) == 10
|
||||
pytest.raises(
|
||||
ValueError,
|
||||
nx.general_random_intersection_graph,
|
||||
10,
|
||||
5,
|
||||
[0.1, 0.2, 0.2, 0.1],
|
||||
)
|
||||
@@ -1,145 +0,0 @@
|
||||
"""Unit tests for the :mod:`networkx.generators.interval_graph` module.
|
||||
|
||||
"""
|
||||
import math
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.generators.interval_graph import interval_graph
|
||||
from networkx.utils import edges_equal
|
||||
|
||||
|
||||
class TestIntervalGraph:
|
||||
"""Unit tests for :func:`networkx.generators.interval_graph.interval_graph`"""
|
||||
|
||||
def test_empty(self):
|
||||
"""Tests for trivial case of empty input"""
|
||||
assert len(interval_graph([])) == 0
|
||||
|
||||
def test_interval_graph_check_invalid(self):
|
||||
"""Tests for conditions that raise Exceptions"""
|
||||
|
||||
invalids_having_none = [None, (1, 2)]
|
||||
with pytest.raises(TypeError):
|
||||
interval_graph(invalids_having_none)
|
||||
|
||||
invalids_having_set = [{1, 2}]
|
||||
with pytest.raises(TypeError):
|
||||
interval_graph(invalids_having_set)
|
||||
|
||||
invalids_having_seq_but_not_length2 = [(1, 2, 3)]
|
||||
with pytest.raises(TypeError):
|
||||
interval_graph(invalids_having_seq_but_not_length2)
|
||||
|
||||
invalids_interval = [[3, 2]]
|
||||
with pytest.raises(ValueError):
|
||||
interval_graph(invalids_interval)
|
||||
|
||||
def test_interval_graph_0(self):
|
||||
intervals = [(1, 2), (1, 3)]
|
||||
|
||||
expected_graph = nx.Graph()
|
||||
expected_graph.add_edge(*intervals)
|
||||
|
||||
actual_g = interval_graph(intervals)
|
||||
|
||||
assert set(actual_g.nodes) == set(expected_graph.nodes)
|
||||
assert edges_equal(expected_graph, actual_g)
|
||||
|
||||
def test_interval_graph_1(self):
|
||||
intervals = [(1, 2), (2, 3), (3, 4), (1, 4)]
|
||||
|
||||
expected_graph = nx.Graph()
|
||||
expected_graph.add_nodes_from(intervals)
|
||||
e1 = ((1, 4), (1, 2))
|
||||
e2 = ((1, 4), (2, 3))
|
||||
e3 = ((1, 4), (3, 4))
|
||||
e4 = ((3, 4), (2, 3))
|
||||
e5 = ((1, 2), (2, 3))
|
||||
|
||||
expected_graph.add_edges_from([e1, e2, e3, e4, e5])
|
||||
|
||||
actual_g = interval_graph(intervals)
|
||||
|
||||
assert set(actual_g.nodes) == set(expected_graph.nodes)
|
||||
assert edges_equal(expected_graph, actual_g)
|
||||
|
||||
def test_interval_graph_2(self):
|
||||
intervals = [(1, 2), [3, 5], [6, 8], (9, 10)]
|
||||
|
||||
expected_graph = nx.Graph()
|
||||
expected_graph.add_nodes_from([(1, 2), (3, 5), (6, 8), (9, 10)])
|
||||
|
||||
actual_g = interval_graph(intervals)
|
||||
|
||||
assert set(actual_g.nodes) == set(expected_graph.nodes)
|
||||
assert edges_equal(expected_graph, actual_g)
|
||||
|
||||
def test_interval_graph_3(self):
|
||||
intervals = [(1, 4), [3, 5], [2.5, 4]]
|
||||
|
||||
expected_graph = nx.Graph()
|
||||
expected_graph.add_nodes_from([(1, 4), (3, 5), (2.5, 4)])
|
||||
e1 = ((1, 4), (3, 5))
|
||||
e2 = ((1, 4), (2.5, 4))
|
||||
e3 = ((3, 5), (2.5, 4))
|
||||
|
||||
expected_graph.add_edges_from([e1, e2, e3])
|
||||
|
||||
actual_g = interval_graph(intervals)
|
||||
|
||||
assert set(actual_g.nodes) == set(expected_graph.nodes)
|
||||
assert edges_equal(expected_graph, actual_g)
|
||||
|
||||
def test_interval_graph_4(self):
|
||||
"""test all possible overlaps"""
|
||||
intervals = [
|
||||
(0, 2),
|
||||
(-2, -1),
|
||||
(-2, 0),
|
||||
(-2, 1),
|
||||
(-2, 2),
|
||||
(-2, 3),
|
||||
(0, 1),
|
||||
(0, 2),
|
||||
(0, 3),
|
||||
(1, 2),
|
||||
(1, 3),
|
||||
(2, 3),
|
||||
(3, 4),
|
||||
]
|
||||
|
||||
expected_graph = nx.Graph()
|
||||
expected_graph.add_nodes_from(intervals)
|
||||
expected_nbrs = {
|
||||
(-2, 0),
|
||||
(-2, 1),
|
||||
(-2, 2),
|
||||
(-2, 3),
|
||||
(0, 1),
|
||||
(0, 2),
|
||||
(0, 3),
|
||||
(1, 2),
|
||||
(1, 3),
|
||||
(2, 3),
|
||||
}
|
||||
actual_g = nx.interval_graph(intervals)
|
||||
actual_nbrs = nx.neighbors(actual_g, (0, 2))
|
||||
|
||||
assert set(actual_nbrs) == expected_nbrs
|
||||
|
||||
def test_interval_graph_5(self):
|
||||
"""this test is to see that an interval supports infinite number"""
|
||||
intervals = {(-math.inf, 0), (-1, -1), (0.5, 0.5), (1, 1), (1, math.inf)}
|
||||
|
||||
expected_graph = nx.Graph()
|
||||
expected_graph.add_nodes_from(intervals)
|
||||
e1 = ((-math.inf, 0), (-1, -1))
|
||||
e2 = ((1, 1), (1, math.inf))
|
||||
|
||||
expected_graph.add_edges_from([e1, e2])
|
||||
actual_g = interval_graph(intervals)
|
||||
|
||||
assert set(actual_g.nodes) == set(expected_graph.nodes)
|
||||
assert edges_equal(expected_graph, actual_g)
|
||||
@@ -1,125 +0,0 @@
|
||||
import time
|
||||
|
||||
from networkx.algorithms.assortativity import degree_mixing_dict
|
||||
from networkx.generators import gnm_random_graph, powerlaw_cluster_graph
|
||||
from networkx.generators.joint_degree_seq import (
|
||||
directed_joint_degree_graph,
|
||||
is_valid_directed_joint_degree,
|
||||
is_valid_joint_degree,
|
||||
joint_degree_graph,
|
||||
)
|
||||
|
||||
|
||||
def test_is_valid_joint_degree():
|
||||
"""Tests for conditions that invalidate a joint degree dict"""
|
||||
|
||||
# valid joint degree that satisfies all five conditions
|
||||
joint_degrees = {
|
||||
1: {4: 1},
|
||||
2: {2: 2, 3: 2, 4: 2},
|
||||
3: {2: 2, 4: 1},
|
||||
4: {1: 1, 2: 2, 3: 1},
|
||||
}
|
||||
assert is_valid_joint_degree(joint_degrees)
|
||||
|
||||
# test condition 1
|
||||
# joint_degrees_1[1][4] not integer
|
||||
joint_degrees_1 = {
|
||||
1: {4: 1.5},
|
||||
2: {2: 2, 3: 2, 4: 2},
|
||||
3: {2: 2, 4: 1},
|
||||
4: {1: 1.5, 2: 2, 3: 1},
|
||||
}
|
||||
assert not is_valid_joint_degree(joint_degrees_1)
|
||||
|
||||
# test condition 2
|
||||
# degree_count[2] = sum(joint_degrees_2[2][j)/2, is not an int
|
||||
# degree_count[4] = sum(joint_degrees_2[4][j)/4, is not an int
|
||||
joint_degrees_2 = {
|
||||
1: {4: 1},
|
||||
2: {2: 2, 3: 2, 4: 3},
|
||||
3: {2: 2, 4: 1},
|
||||
4: {1: 1, 2: 3, 3: 1},
|
||||
}
|
||||
assert not is_valid_joint_degree(joint_degrees_2)
|
||||
|
||||
# test conditions 3 and 4
|
||||
# joint_degrees_3[1][4]>degree_count[1]*degree_count[4]
|
||||
joint_degrees_3 = {
|
||||
1: {4: 2},
|
||||
2: {2: 2, 3: 2, 4: 2},
|
||||
3: {2: 2, 4: 1},
|
||||
4: {1: 2, 2: 2, 3: 1},
|
||||
}
|
||||
assert not is_valid_joint_degree(joint_degrees_3)
|
||||
|
||||
# test condition 5
|
||||
# joint_degrees_5[1][1] not even
|
||||
joint_degrees_5 = {1: {1: 9}}
|
||||
assert not is_valid_joint_degree(joint_degrees_5)
|
||||
|
||||
|
||||
def test_joint_degree_graph(ntimes=10):
|
||||
for _ in range(ntimes):
|
||||
seed = int(time.time())
|
||||
|
||||
n, m, p = 20, 10, 1
|
||||
# generate random graph with model powerlaw_cluster and calculate
|
||||
# its joint degree
|
||||
g = powerlaw_cluster_graph(n, m, p, seed=seed)
|
||||
joint_degrees_g = degree_mixing_dict(g, normalized=False)
|
||||
|
||||
# generate simple undirected graph with given joint degree
|
||||
# joint_degrees_g
|
||||
G = joint_degree_graph(joint_degrees_g)
|
||||
joint_degrees_G = degree_mixing_dict(G, normalized=False)
|
||||
|
||||
# assert that the given joint degree is equal to the generated
|
||||
# graph's joint degree
|
||||
assert joint_degrees_g == joint_degrees_G
|
||||
|
||||
|
||||
def test_is_valid_directed_joint_degree():
|
||||
in_degrees = [0, 1, 1, 2]
|
||||
out_degrees = [1, 1, 1, 1]
|
||||
nkk = {1: {1: 2, 2: 2}}
|
||||
assert is_valid_directed_joint_degree(in_degrees, out_degrees, nkk)
|
||||
|
||||
# not realizable, values are not integers.
|
||||
nkk = {1: {1: 1.5, 2: 2.5}}
|
||||
assert not is_valid_directed_joint_degree(in_degrees, out_degrees, nkk)
|
||||
|
||||
# not realizable, number of edges between 1-2 are insufficient.
|
||||
nkk = {1: {1: 2, 2: 1}}
|
||||
assert not is_valid_directed_joint_degree(in_degrees, out_degrees, nkk)
|
||||
|
||||
# not realizable, in/out degree sequences have different number of nodes.
|
||||
out_degrees = [1, 1, 1]
|
||||
nkk = {1: {1: 2, 2: 2}}
|
||||
assert not is_valid_directed_joint_degree(in_degrees, out_degrees, nkk)
|
||||
|
||||
# not realizable, degree sequences have fewer than required nodes.
|
||||
in_degrees = [0, 1, 2]
|
||||
assert not is_valid_directed_joint_degree(in_degrees, out_degrees, nkk)
|
||||
|
||||
|
||||
def test_directed_joint_degree_graph(n=15, m=100, ntimes=1000):
|
||||
for _ in range(ntimes):
|
||||
# generate gnm random graph and calculate its joint degree.
|
||||
g = gnm_random_graph(n, m, None, directed=True)
|
||||
|
||||
# in-degree sequence of g as a list of integers.
|
||||
in_degrees = list(dict(g.in_degree()).values())
|
||||
# out-degree sequence of g as a list of integers.
|
||||
out_degrees = list(dict(g.out_degree()).values())
|
||||
nkk = degree_mixing_dict(g)
|
||||
|
||||
# generate simple directed graph with given degree sequence and joint
|
||||
# degree matrix.
|
||||
G = directed_joint_degree_graph(in_degrees, out_degrees, nkk)
|
||||
|
||||
# assert degree sequence correctness.
|
||||
assert in_degrees == list(dict(G.in_degree()).values())
|
||||
assert out_degrees == list(dict(G.out_degree()).values())
|
||||
# assert joint degree matrix correctness.
|
||||
assert nkk == degree_mixing_dict(G)
|
||||
@@ -1,246 +0,0 @@
|
||||
"""Unit tests for the :mod:`networkx.generators.lattice` module."""
|
||||
|
||||
from itertools import product
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.utils import edges_equal
|
||||
|
||||
|
||||
class TestGrid2DGraph:
|
||||
"""Unit tests for :func:`networkx.generators.lattice.grid_2d_graph`"""
|
||||
|
||||
def test_number_of_vertices(self):
|
||||
m, n = 5, 6
|
||||
G = nx.grid_2d_graph(m, n)
|
||||
assert len(G) == m * n
|
||||
|
||||
def test_degree_distribution(self):
|
||||
m, n = 5, 6
|
||||
G = nx.grid_2d_graph(m, n)
|
||||
expected_histogram = [0, 0, 4, 2 * (m + n) - 8, (m - 2) * (n - 2)]
|
||||
assert nx.degree_histogram(G) == expected_histogram
|
||||
|
||||
def test_directed(self):
|
||||
m, n = 5, 6
|
||||
G = nx.grid_2d_graph(m, n)
|
||||
H = nx.grid_2d_graph(m, n, create_using=nx.DiGraph())
|
||||
assert H.succ == G.adj
|
||||
assert H.pred == G.adj
|
||||
|
||||
def test_multigraph(self):
|
||||
m, n = 5, 6
|
||||
G = nx.grid_2d_graph(m, n)
|
||||
H = nx.grid_2d_graph(m, n, create_using=nx.MultiGraph())
|
||||
assert list(H.edges()) == list(G.edges())
|
||||
|
||||
def test_periodic(self):
|
||||
G = nx.grid_2d_graph(0, 0, periodic=True)
|
||||
assert dict(G.degree()) == {}
|
||||
|
||||
for m, n, H in [
|
||||
(2, 2, nx.cycle_graph(4)),
|
||||
(1, 7, nx.cycle_graph(7)),
|
||||
(7, 1, nx.cycle_graph(7)),
|
||||
(2, 5, nx.circular_ladder_graph(5)),
|
||||
(5, 2, nx.circular_ladder_graph(5)),
|
||||
(2, 4, nx.cubical_graph()),
|
||||
(4, 2, nx.cubical_graph()),
|
||||
]:
|
||||
G = nx.grid_2d_graph(m, n, periodic=True)
|
||||
assert nx.could_be_isomorphic(G, H)
|
||||
|
||||
def test_periodic_iterable(self):
|
||||
m, n = 3, 7
|
||||
for a, b in product([0, 1], [0, 1]):
|
||||
G = nx.grid_2d_graph(m, n, periodic=(a, b))
|
||||
assert G.number_of_nodes() == m * n
|
||||
assert G.number_of_edges() == (m + a - 1) * n + (n + b - 1) * m
|
||||
|
||||
def test_periodic_directed(self):
|
||||
G = nx.grid_2d_graph(4, 2, periodic=True)
|
||||
H = nx.grid_2d_graph(4, 2, periodic=True, create_using=nx.DiGraph())
|
||||
assert H.succ == G.adj
|
||||
assert H.pred == G.adj
|
||||
|
||||
def test_periodic_multigraph(self):
|
||||
G = nx.grid_2d_graph(4, 2, periodic=True)
|
||||
H = nx.grid_2d_graph(4, 2, periodic=True, create_using=nx.MultiGraph())
|
||||
assert list(G.edges()) == list(H.edges())
|
||||
|
||||
def test_exceptions(self):
|
||||
pytest.raises(nx.NetworkXError, nx.grid_2d_graph, -3, 2)
|
||||
pytest.raises(nx.NetworkXError, nx.grid_2d_graph, 3, -2)
|
||||
pytest.raises(TypeError, nx.grid_2d_graph, 3.3, 2)
|
||||
pytest.raises(TypeError, nx.grid_2d_graph, 3, 2.2)
|
||||
|
||||
def test_node_input(self):
|
||||
G = nx.grid_2d_graph(4, 2, periodic=True)
|
||||
H = nx.grid_2d_graph(range(4), range(2), periodic=True)
|
||||
assert nx.is_isomorphic(H, G)
|
||||
H = nx.grid_2d_graph("abcd", "ef", periodic=True)
|
||||
assert nx.is_isomorphic(H, G)
|
||||
G = nx.grid_2d_graph(5, 6)
|
||||
H = nx.grid_2d_graph(range(5), range(6))
|
||||
assert edges_equal(H, G)
|
||||
|
||||
|
||||
class TestGridGraph:
|
||||
"""Unit tests for :func:`networkx.generators.lattice.grid_graph`"""
|
||||
|
||||
def test_grid_graph(self):
|
||||
"""grid_graph([n,m]) is a connected simple graph with the
|
||||
following properties:
|
||||
number_of_nodes = n*m
|
||||
degree_histogram = [0,0,4,2*(n+m)-8,(n-2)*(m-2)]
|
||||
"""
|
||||
for n, m in [(3, 5), (5, 3), (4, 5), (5, 4)]:
|
||||
dim = [n, m]
|
||||
g = nx.grid_graph(dim)
|
||||
assert len(g) == n * m
|
||||
assert nx.degree_histogram(g) == [
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
2 * (n + m) - 8,
|
||||
(n - 2) * (m - 2),
|
||||
]
|
||||
|
||||
for n, m in [(1, 5), (5, 1)]:
|
||||
dim = [n, m]
|
||||
g = nx.grid_graph(dim)
|
||||
assert len(g) == n * m
|
||||
assert nx.is_isomorphic(g, nx.path_graph(5))
|
||||
|
||||
# mg = nx.grid_graph([n,m], create_using=MultiGraph())
|
||||
# assert_equal(mg.edges(), g.edges())
|
||||
|
||||
def test_node_input(self):
|
||||
G = nx.grid_graph([range(7, 9), range(3, 6)])
|
||||
assert len(G) == 2 * 3
|
||||
assert nx.is_isomorphic(G, nx.grid_graph([2, 3]))
|
||||
|
||||
def test_periodic_iterable(self):
|
||||
m, n, k = 3, 7, 5
|
||||
for a, b, c in product([0, 1], [0, 1], [0, 1]):
|
||||
G = nx.grid_graph([m, n, k], periodic=(a, b, c))
|
||||
num_e = (m + a - 1) * n * k + (n + b - 1) * m * k + (k + c - 1) * m * n
|
||||
assert G.number_of_nodes() == m * n * k
|
||||
assert G.number_of_edges() == num_e
|
||||
|
||||
|
||||
class TestHypercubeGraph:
|
||||
"""Unit tests for :func:`networkx.generators.lattice.hypercube_graph`"""
|
||||
|
||||
def test_special_cases(self):
|
||||
for n, H in [
|
||||
(0, nx.null_graph()),
|
||||
(1, nx.path_graph(2)),
|
||||
(2, nx.cycle_graph(4)),
|
||||
(3, nx.cubical_graph()),
|
||||
]:
|
||||
G = nx.hypercube_graph(n)
|
||||
assert nx.could_be_isomorphic(G, H)
|
||||
|
||||
def test_degree_distribution(self):
|
||||
for n in range(1, 10):
|
||||
G = nx.hypercube_graph(n)
|
||||
expected_histogram = [0] * n + [2**n]
|
||||
assert nx.degree_histogram(G) == expected_histogram
|
||||
|
||||
|
||||
class TestTriangularLatticeGraph:
|
||||
"Tests for :func:`networkx.generators.lattice.triangular_lattice_graph`"
|
||||
|
||||
def test_lattice_points(self):
|
||||
"""Tests that the graph is really a triangular lattice."""
|
||||
for m, n in [(2, 3), (2, 2), (2, 1), (3, 3), (3, 2), (3, 4)]:
|
||||
G = nx.triangular_lattice_graph(m, n)
|
||||
N = (n + 1) // 2
|
||||
assert len(G) == (m + 1) * (1 + N) - (n % 2) * ((m + 1) // 2)
|
||||
for i, j in G.nodes():
|
||||
nbrs = G[(i, j)]
|
||||
if i < N:
|
||||
assert (i + 1, j) in nbrs
|
||||
if j < m:
|
||||
assert (i, j + 1) in nbrs
|
||||
if j < m and (i > 0 or j % 2) and (i < N or (j + 1) % 2):
|
||||
assert (i + 1, j + 1) in nbrs or (i - 1, j + 1) in nbrs
|
||||
|
||||
def test_directed(self):
|
||||
"""Tests for creating a directed triangular lattice."""
|
||||
G = nx.triangular_lattice_graph(3, 4, create_using=nx.Graph())
|
||||
H = nx.triangular_lattice_graph(3, 4, create_using=nx.DiGraph())
|
||||
assert H.is_directed()
|
||||
for u, v in H.edges():
|
||||
assert v[1] >= u[1]
|
||||
if v[1] == u[1]:
|
||||
assert v[0] > u[0]
|
||||
|
||||
def test_multigraph(self):
|
||||
"""Tests for creating a triangular lattice multigraph."""
|
||||
G = nx.triangular_lattice_graph(3, 4, create_using=nx.Graph())
|
||||
H = nx.triangular_lattice_graph(3, 4, create_using=nx.MultiGraph())
|
||||
assert list(H.edges()) == list(G.edges())
|
||||
|
||||
def test_periodic(self):
|
||||
G = nx.triangular_lattice_graph(4, 6, periodic=True)
|
||||
assert len(G) == 12
|
||||
assert G.size() == 36
|
||||
# all degrees are 6
|
||||
assert len([n for n, d in G.degree() if d != 6]) == 0
|
||||
G = nx.triangular_lattice_graph(5, 7, periodic=True)
|
||||
TLG = nx.triangular_lattice_graph
|
||||
pytest.raises(nx.NetworkXError, TLG, 2, 4, periodic=True)
|
||||
pytest.raises(nx.NetworkXError, TLG, 4, 4, periodic=True)
|
||||
pytest.raises(nx.NetworkXError, TLG, 2, 6, periodic=True)
|
||||
|
||||
|
||||
class TestHexagonalLatticeGraph:
|
||||
"Tests for :func:`networkx.generators.lattice.hexagonal_lattice_graph`"
|
||||
|
||||
def test_lattice_points(self):
|
||||
"""Tests that the graph is really a hexagonal lattice."""
|
||||
for m, n in [(4, 5), (4, 4), (4, 3), (3, 2), (3, 3), (3, 5)]:
|
||||
G = nx.hexagonal_lattice_graph(m, n)
|
||||
assert len(G) == 2 * (m + 1) * (n + 1) - 2
|
||||
C_6 = nx.cycle_graph(6)
|
||||
hexagons = [
|
||||
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)],
|
||||
[(0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4)],
|
||||
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3)],
|
||||
[(2, 0), (2, 1), (2, 2), (3, 0), (3, 1), (3, 2)],
|
||||
[(2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4)],
|
||||
]
|
||||
for hexagon in hexagons:
|
||||
assert nx.is_isomorphic(G.subgraph(hexagon), C_6)
|
||||
|
||||
def test_directed(self):
|
||||
"""Tests for creating a directed hexagonal lattice."""
|
||||
G = nx.hexagonal_lattice_graph(3, 5, create_using=nx.Graph())
|
||||
H = nx.hexagonal_lattice_graph(3, 5, create_using=nx.DiGraph())
|
||||
assert H.is_directed()
|
||||
pos = nx.get_node_attributes(H, "pos")
|
||||
for u, v in H.edges():
|
||||
assert pos[v][1] >= pos[u][1]
|
||||
if pos[v][1] == pos[u][1]:
|
||||
assert pos[v][0] > pos[u][0]
|
||||
|
||||
def test_multigraph(self):
|
||||
"""Tests for creating a hexagonal lattice multigraph."""
|
||||
G = nx.hexagonal_lattice_graph(3, 5, create_using=nx.Graph())
|
||||
H = nx.hexagonal_lattice_graph(3, 5, create_using=nx.MultiGraph())
|
||||
assert list(H.edges()) == list(G.edges())
|
||||
|
||||
def test_periodic(self):
|
||||
G = nx.hexagonal_lattice_graph(4, 6, periodic=True)
|
||||
assert len(G) == 48
|
||||
assert G.size() == 72
|
||||
# all degrees are 3
|
||||
assert len([n for n, d in G.degree() if d != 3]) == 0
|
||||
G = nx.hexagonal_lattice_graph(5, 8, periodic=True)
|
||||
HLG = nx.hexagonal_lattice_graph
|
||||
pytest.raises(nx.NetworkXError, HLG, 2, 7, periodic=True)
|
||||
pytest.raises(nx.NetworkXError, HLG, 1, 4, periodic=True)
|
||||
pytest.raises(nx.NetworkXError, HLG, 2, 1, periodic=True)
|
||||
@@ -1,309 +0,0 @@
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.generators import line
|
||||
from networkx.utils import edges_equal
|
||||
|
||||
|
||||
class TestGeneratorLine:
|
||||
def test_star(self):
|
||||
G = nx.star_graph(5)
|
||||
L = nx.line_graph(G)
|
||||
assert nx.is_isomorphic(L, nx.complete_graph(5))
|
||||
|
||||
def test_path(self):
|
||||
G = nx.path_graph(5)
|
||||
L = nx.line_graph(G)
|
||||
assert nx.is_isomorphic(L, nx.path_graph(4))
|
||||
|
||||
def test_cycle(self):
|
||||
G = nx.cycle_graph(5)
|
||||
L = nx.line_graph(G)
|
||||
assert nx.is_isomorphic(L, G)
|
||||
|
||||
def test_digraph1(self):
|
||||
G = nx.DiGraph([(0, 1), (0, 2), (0, 3)])
|
||||
L = nx.line_graph(G)
|
||||
# no edge graph, but with nodes
|
||||
assert L.adj == {(0, 1): {}, (0, 2): {}, (0, 3): {}}
|
||||
|
||||
def test_multigraph1(self):
|
||||
G = nx.MultiGraph([(0, 1), (0, 1), (1, 0), (0, 2), (2, 0), (0, 3)])
|
||||
L = nx.line_graph(G)
|
||||
# no edge graph, but with nodes
|
||||
assert edges_equal(
|
||||
L.edges(),
|
||||
[
|
||||
((0, 3, 0), (0, 1, 0)),
|
||||
((0, 3, 0), (0, 2, 0)),
|
||||
((0, 3, 0), (0, 2, 1)),
|
||||
((0, 3, 0), (0, 1, 1)),
|
||||
((0, 3, 0), (0, 1, 2)),
|
||||
((0, 1, 0), (0, 1, 1)),
|
||||
((0, 1, 0), (0, 2, 0)),
|
||||
((0, 1, 0), (0, 1, 2)),
|
||||
((0, 1, 0), (0, 2, 1)),
|
||||
((0, 1, 1), (0, 1, 2)),
|
||||
((0, 1, 1), (0, 2, 0)),
|
||||
((0, 1, 1), (0, 2, 1)),
|
||||
((0, 1, 2), (0, 2, 0)),
|
||||
((0, 1, 2), (0, 2, 1)),
|
||||
((0, 2, 0), (0, 2, 1)),
|
||||
],
|
||||
)
|
||||
|
||||
def test_multigraph2(self):
|
||||
G = nx.MultiGraph([(1, 2), (2, 1)])
|
||||
L = nx.line_graph(G)
|
||||
assert edges_equal(L.edges(), [((1, 2, 0), (1, 2, 1))])
|
||||
|
||||
def test_multidigraph1(self):
|
||||
G = nx.MultiDiGraph([(1, 2), (2, 1)])
|
||||
L = nx.line_graph(G)
|
||||
assert edges_equal(L.edges(), [((1, 2, 0), (2, 1, 0)), ((2, 1, 0), (1, 2, 0))])
|
||||
|
||||
def test_multidigraph2(self):
|
||||
G = nx.MultiDiGraph([(0, 1), (0, 1), (0, 1), (1, 2)])
|
||||
L = nx.line_graph(G)
|
||||
assert edges_equal(
|
||||
L.edges(),
|
||||
[((0, 1, 0), (1, 2, 0)), ((0, 1, 1), (1, 2, 0)), ((0, 1, 2), (1, 2, 0))],
|
||||
)
|
||||
|
||||
def test_digraph2(self):
|
||||
G = nx.DiGraph([(0, 1), (1, 2), (2, 3)])
|
||||
L = nx.line_graph(G)
|
||||
assert edges_equal(L.edges(), [((0, 1), (1, 2)), ((1, 2), (2, 3))])
|
||||
|
||||
def test_create1(self):
|
||||
G = nx.DiGraph([(0, 1), (1, 2), (2, 3)])
|
||||
L = nx.line_graph(G, create_using=nx.Graph())
|
||||
assert edges_equal(L.edges(), [((0, 1), (1, 2)), ((1, 2), (2, 3))])
|
||||
|
||||
def test_create2(self):
|
||||
G = nx.Graph([(0, 1), (1, 2), (2, 3)])
|
||||
L = nx.line_graph(G, create_using=nx.DiGraph())
|
||||
assert edges_equal(L.edges(), [((0, 1), (1, 2)), ((1, 2), (2, 3))])
|
||||
|
||||
|
||||
class TestGeneratorInverseLine:
|
||||
def test_example(self):
|
||||
G = nx.Graph()
|
||||
G_edges = [
|
||||
[1, 2],
|
||||
[1, 3],
|
||||
[1, 4],
|
||||
[1, 5],
|
||||
[2, 3],
|
||||
[2, 5],
|
||||
[2, 6],
|
||||
[2, 7],
|
||||
[3, 4],
|
||||
[3, 5],
|
||||
[6, 7],
|
||||
[6, 8],
|
||||
[7, 8],
|
||||
]
|
||||
G.add_edges_from(G_edges)
|
||||
H = nx.inverse_line_graph(G)
|
||||
solution = nx.Graph()
|
||||
solution_edges = [
|
||||
("a", "b"),
|
||||
("a", "c"),
|
||||
("a", "d"),
|
||||
("a", "e"),
|
||||
("c", "d"),
|
||||
("e", "f"),
|
||||
("e", "g"),
|
||||
("f", "g"),
|
||||
]
|
||||
solution.add_edges_from(solution_edges)
|
||||
assert nx.is_isomorphic(H, solution)
|
||||
|
||||
def test_example_2(self):
|
||||
G = nx.Graph()
|
||||
G_edges = [[1, 2], [1, 3], [2, 3], [3, 4], [3, 5], [4, 5]]
|
||||
G.add_edges_from(G_edges)
|
||||
H = nx.inverse_line_graph(G)
|
||||
solution = nx.Graph()
|
||||
solution_edges = [("a", "c"), ("b", "c"), ("c", "d"), ("d", "e"), ("d", "f")]
|
||||
solution.add_edges_from(solution_edges)
|
||||
assert nx.is_isomorphic(H, solution)
|
||||
|
||||
def test_pair(self):
|
||||
G = nx.path_graph(2)
|
||||
H = nx.inverse_line_graph(G)
|
||||
solution = nx.path_graph(3)
|
||||
assert nx.is_isomorphic(H, solution)
|
||||
|
||||
def test_line(self):
|
||||
G = nx.path_graph(5)
|
||||
solution = nx.path_graph(6)
|
||||
H = nx.inverse_line_graph(G)
|
||||
assert nx.is_isomorphic(H, solution)
|
||||
|
||||
def test_triangle_graph(self):
|
||||
G = nx.complete_graph(3)
|
||||
H = nx.inverse_line_graph(G)
|
||||
alternative_solution = nx.Graph()
|
||||
alternative_solution.add_edges_from([[0, 1], [0, 2], [0, 3]])
|
||||
# there are two alternative inverse line graphs for this case
|
||||
# so long as we get one of them the test should pass
|
||||
assert nx.is_isomorphic(H, G) or nx.is_isomorphic(H, alternative_solution)
|
||||
|
||||
def test_cycle(self):
|
||||
G = nx.cycle_graph(5)
|
||||
H = nx.inverse_line_graph(G)
|
||||
assert nx.is_isomorphic(H, G)
|
||||
|
||||
def test_empty(self):
|
||||
G = nx.Graph()
|
||||
H = nx.inverse_line_graph(G)
|
||||
assert nx.is_isomorphic(H, nx.complete_graph(1))
|
||||
|
||||
def test_K1(self):
|
||||
G = nx.complete_graph(1)
|
||||
H = nx.inverse_line_graph(G)
|
||||
solution = nx.path_graph(2)
|
||||
assert nx.is_isomorphic(H, solution)
|
||||
|
||||
def test_edgeless_graph(self):
|
||||
G = nx.empty_graph(5)
|
||||
with pytest.raises(nx.NetworkXError, match="edgeless graph"):
|
||||
nx.inverse_line_graph(G)
|
||||
|
||||
def test_selfloops_error(self):
|
||||
G = nx.cycle_graph(4)
|
||||
G.add_edge(0, 0)
|
||||
pytest.raises(nx.NetworkXError, nx.inverse_line_graph, G)
|
||||
|
||||
def test_non_line_graphs(self):
|
||||
# Tests several known non-line graphs for impossibility
|
||||
# Adapted from L.W.Beineke, "Characterizations of derived graphs"
|
||||
|
||||
# claw graph
|
||||
claw = nx.star_graph(3)
|
||||
pytest.raises(nx.NetworkXError, nx.inverse_line_graph, claw)
|
||||
|
||||
# wheel graph with 6 nodes
|
||||
wheel = nx.wheel_graph(6)
|
||||
pytest.raises(nx.NetworkXError, nx.inverse_line_graph, wheel)
|
||||
|
||||
# K5 with one edge remove
|
||||
K5m = nx.complete_graph(5)
|
||||
K5m.remove_edge(0, 1)
|
||||
pytest.raises(nx.NetworkXError, nx.inverse_line_graph, K5m)
|
||||
|
||||
# graph without any odd triangles (contains claw as induced subgraph)
|
||||
G = nx.compose(nx.path_graph(2), nx.complete_bipartite_graph(2, 3))
|
||||
pytest.raises(nx.NetworkXError, nx.inverse_line_graph, G)
|
||||
|
||||
## Variations on a diamond graph
|
||||
|
||||
# Diamond + 2 edges (+ "roof")
|
||||
G = nx.diamond_graph()
|
||||
G.add_edges_from([(4, 0), (5, 3)])
|
||||
pytest.raises(nx.NetworkXError, nx.inverse_line_graph, G)
|
||||
G.add_edge(4, 5)
|
||||
pytest.raises(nx.NetworkXError, nx.inverse_line_graph, G)
|
||||
|
||||
# Diamond + 2 connected edges
|
||||
G = nx.diamond_graph()
|
||||
G.add_edges_from([(4, 0), (4, 3)])
|
||||
pytest.raises(nx.NetworkXError, nx.inverse_line_graph, G)
|
||||
|
||||
# Diamond + K3 + one edge (+ 2*K3)
|
||||
G = nx.diamond_graph()
|
||||
G.add_edges_from([(4, 0), (4, 1), (4, 2), (5, 3)])
|
||||
pytest.raises(nx.NetworkXError, nx.inverse_line_graph, G)
|
||||
G.add_edges_from([(5, 1), (5, 2)])
|
||||
pytest.raises(nx.NetworkXError, nx.inverse_line_graph, G)
|
||||
|
||||
# 4 triangles
|
||||
G = nx.diamond_graph()
|
||||
G.add_edges_from([(4, 0), (4, 1), (5, 2), (5, 3)])
|
||||
pytest.raises(nx.NetworkXError, nx.inverse_line_graph, G)
|
||||
|
||||
def test_wrong_graph_type(self):
|
||||
G = nx.DiGraph()
|
||||
G_edges = [[0, 1], [0, 2], [0, 3]]
|
||||
G.add_edges_from(G_edges)
|
||||
pytest.raises(nx.NetworkXNotImplemented, nx.inverse_line_graph, G)
|
||||
|
||||
G = nx.MultiGraph()
|
||||
G_edges = [[0, 1], [0, 2], [0, 3]]
|
||||
G.add_edges_from(G_edges)
|
||||
pytest.raises(nx.NetworkXNotImplemented, nx.inverse_line_graph, G)
|
||||
|
||||
def test_line_inverse_line_complete(self):
|
||||
G = nx.complete_graph(10)
|
||||
H = nx.line_graph(G)
|
||||
J = nx.inverse_line_graph(H)
|
||||
assert nx.is_isomorphic(G, J)
|
||||
|
||||
def test_line_inverse_line_path(self):
|
||||
G = nx.path_graph(10)
|
||||
H = nx.line_graph(G)
|
||||
J = nx.inverse_line_graph(H)
|
||||
assert nx.is_isomorphic(G, J)
|
||||
|
||||
def test_line_inverse_line_hypercube(self):
|
||||
G = nx.hypercube_graph(5)
|
||||
H = nx.line_graph(G)
|
||||
J = nx.inverse_line_graph(H)
|
||||
assert nx.is_isomorphic(G, J)
|
||||
|
||||
def test_line_inverse_line_cycle(self):
|
||||
G = nx.cycle_graph(10)
|
||||
H = nx.line_graph(G)
|
||||
J = nx.inverse_line_graph(H)
|
||||
assert nx.is_isomorphic(G, J)
|
||||
|
||||
def test_line_inverse_line_star(self):
|
||||
G = nx.star_graph(20)
|
||||
H = nx.line_graph(G)
|
||||
J = nx.inverse_line_graph(H)
|
||||
assert nx.is_isomorphic(G, J)
|
||||
|
||||
def test_line_inverse_line_multipartite(self):
|
||||
G = nx.complete_multipartite_graph(3, 4, 5)
|
||||
H = nx.line_graph(G)
|
||||
J = nx.inverse_line_graph(H)
|
||||
assert nx.is_isomorphic(G, J)
|
||||
|
||||
def test_line_inverse_line_dgm(self):
|
||||
G = nx.dorogovtsev_goltsev_mendes_graph(4)
|
||||
H = nx.line_graph(G)
|
||||
J = nx.inverse_line_graph(H)
|
||||
assert nx.is_isomorphic(G, J)
|
||||
|
||||
def test_line_different_node_types(self):
|
||||
G = nx.path_graph([1, 2, 3, "a", "b", "c"])
|
||||
H = nx.line_graph(G)
|
||||
J = nx.inverse_line_graph(H)
|
||||
assert nx.is_isomorphic(G, J)
|
||||
|
||||
|
||||
class TestGeneratorPrivateFunctions:
|
||||
def test_triangles_error(self):
|
||||
G = nx.diamond_graph()
|
||||
pytest.raises(nx.NetworkXError, line._triangles, G, (4, 0))
|
||||
pytest.raises(nx.NetworkXError, line._triangles, G, (0, 3))
|
||||
|
||||
def test_odd_triangles_error(self):
|
||||
G = nx.diamond_graph()
|
||||
pytest.raises(nx.NetworkXError, line._odd_triangle, G, (0, 1, 4))
|
||||
pytest.raises(nx.NetworkXError, line._odd_triangle, G, (0, 1, 3))
|
||||
|
||||
def test_select_starting_cell_error(self):
|
||||
G = nx.diamond_graph()
|
||||
pytest.raises(nx.NetworkXError, line._select_starting_cell, G, (4, 0))
|
||||
pytest.raises(nx.NetworkXError, line._select_starting_cell, G, (0, 3))
|
||||
|
||||
def test_diamond_graph(self):
|
||||
G = nx.diamond_graph()
|
||||
for edge in G.edges:
|
||||
cell = line._select_starting_cell(G, starting_edge=edge)
|
||||
# Starting cell should always be one of the two triangles
|
||||
assert len(cell) == 3
|
||||
assert all(v in G[u] for u in cell for v in cell if u != v)
|
||||
@@ -1,26 +0,0 @@
|
||||
"""Unit tests for the :mod:`networkx.generators.mycielski` module."""
|
||||
|
||||
import networkx as nx
|
||||
|
||||
|
||||
class TestMycielski:
|
||||
def test_construction(self):
|
||||
G = nx.path_graph(2)
|
||||
M = nx.mycielskian(G)
|
||||
assert nx.is_isomorphic(M, nx.cycle_graph(5))
|
||||
|
||||
def test_size(self):
|
||||
G = nx.path_graph(2)
|
||||
M = nx.mycielskian(G, 2)
|
||||
assert len(M) == 11
|
||||
assert M.size() == 20
|
||||
|
||||
def test_mycielski_graph_generator(self):
|
||||
G = nx.mycielski_graph(1)
|
||||
assert nx.is_isomorphic(G, nx.empty_graph(1))
|
||||
G = nx.mycielski_graph(2)
|
||||
assert nx.is_isomorphic(G, nx.path_graph(2))
|
||||
G = nx.mycielski_graph(3)
|
||||
assert nx.is_isomorphic(G, nx.cycle_graph(5))
|
||||
G = nx.mycielski_graph(4)
|
||||
assert nx.is_isomorphic(G, nx.mycielskian(nx.cycle_graph(5)))
|
||||
@@ -1,64 +0,0 @@
|
||||
"""
|
||||
====================
|
||||
Generators - Non Isomorphic Trees
|
||||
====================
|
||||
|
||||
Unit tests for WROM algorithm generator in generators/nonisomorphic_trees.py
|
||||
"""
|
||||
import networkx as nx
|
||||
from networkx.utils import edges_equal
|
||||
|
||||
|
||||
class TestGeneratorNonIsomorphicTrees:
|
||||
def test_tree_structure(self):
|
||||
# test for tree structure for nx.nonisomorphic_trees()
|
||||
def f(x):
|
||||
return list(nx.nonisomorphic_trees(x))
|
||||
|
||||
for i in f(6):
|
||||
assert nx.is_tree(i)
|
||||
for i in f(8):
|
||||
assert nx.is_tree(i)
|
||||
|
||||
def test_nonisomorphism(self):
|
||||
# test for nonisomorphism of trees for nx.nonisomorphic_trees()
|
||||
def f(x):
|
||||
return list(nx.nonisomorphic_trees(x))
|
||||
|
||||
trees = f(6)
|
||||
for i in range(len(trees)):
|
||||
for j in range(i + 1, len(trees)):
|
||||
assert not nx.is_isomorphic(trees[i], trees[j])
|
||||
trees = f(8)
|
||||
for i in range(len(trees)):
|
||||
for j in range(i + 1, len(trees)):
|
||||
assert not nx.is_isomorphic(trees[i], trees[j])
|
||||
|
||||
def test_number_of_nonisomorphic_trees(self):
|
||||
# http://oeis.org/A000055
|
||||
assert nx.number_of_nonisomorphic_trees(2) == 1
|
||||
assert nx.number_of_nonisomorphic_trees(3) == 1
|
||||
assert nx.number_of_nonisomorphic_trees(4) == 2
|
||||
assert nx.number_of_nonisomorphic_trees(5) == 3
|
||||
assert nx.number_of_nonisomorphic_trees(6) == 6
|
||||
assert nx.number_of_nonisomorphic_trees(7) == 11
|
||||
assert nx.number_of_nonisomorphic_trees(8) == 23
|
||||
|
||||
def test_nonisomorphic_trees(self):
|
||||
def f(x):
|
||||
return list(nx.nonisomorphic_trees(x))
|
||||
|
||||
assert edges_equal(f(3)[0].edges(), [(0, 1), (0, 2)])
|
||||
assert edges_equal(f(4)[0].edges(), [(0, 1), (0, 3), (1, 2)])
|
||||
assert edges_equal(f(4)[1].edges(), [(0, 1), (0, 2), (0, 3)])
|
||||
|
||||
def test_nonisomorphic_trees_matrix(self):
|
||||
trees_2 = [[[0, 1], [1, 0]]]
|
||||
assert list(nx.nonisomorphic_trees(2, create="matrix")) == trees_2
|
||||
trees_3 = [[[0, 1, 1], [1, 0, 0], [1, 0, 0]]]
|
||||
assert list(nx.nonisomorphic_trees(3, create="matrix")) == trees_3
|
||||
trees_4 = [
|
||||
[[0, 1, 0, 1], [1, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]],
|
||||
[[0, 1, 1, 1], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]],
|
||||
]
|
||||
assert list(nx.nonisomorphic_trees(4, create="matrix")) == trees_4
|
||||
@@ -1,34 +0,0 @@
|
||||
import pytest
|
||||
|
||||
import networkx
|
||||
|
||||
|
||||
class TestRandomClusteredGraph:
|
||||
def test_valid(self):
|
||||
node = [1, 1, 1, 2, 1, 2, 0, 0]
|
||||
tri = [0, 0, 0, 0, 0, 1, 1, 1]
|
||||
joint_degree_sequence = zip(node, tri)
|
||||
G = networkx.random_clustered_graph(joint_degree_sequence)
|
||||
assert G.number_of_nodes() == 8
|
||||
assert G.number_of_edges() == 7
|
||||
|
||||
def test_valid2(self):
|
||||
G = networkx.random_clustered_graph(
|
||||
[(1, 2), (2, 1), (1, 1), (1, 1), (1, 1), (2, 0)]
|
||||
)
|
||||
assert G.number_of_nodes() == 6
|
||||
assert G.number_of_edges() == 10
|
||||
|
||||
def test_invalid1(self):
|
||||
pytest.raises(
|
||||
(TypeError, networkx.NetworkXError),
|
||||
networkx.random_clustered_graph,
|
||||
[[1, 1], [2, 1], [0, 1]],
|
||||
)
|
||||
|
||||
def test_invalid2(self):
|
||||
pytest.raises(
|
||||
(TypeError, networkx.NetworkXError),
|
||||
networkx.random_clustered_graph,
|
||||
[[1, 1], [1, 2], [0, 1]],
|
||||
)
|
||||
@@ -1,335 +0,0 @@
|
||||
"""Unit tests for the :mod:`networkx.generators.random_graphs` module."""
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
|
||||
_gnp_generators = [
|
||||
nx.gnp_random_graph,
|
||||
nx.fast_gnp_random_graph,
|
||||
nx.binomial_graph,
|
||||
nx.erdos_renyi_graph,
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("generator", _gnp_generators)
|
||||
@pytest.mark.parametrize("directed", (True, False))
|
||||
def test_gnp_generators_negative_edge_probability(generator, directed):
|
||||
"""If the edge probability `p` is <=0, the resulting graph should have no edges."""
|
||||
G = generator(10, -1.1, directed=directed)
|
||||
assert len(G) == 10
|
||||
assert G.number_of_edges() == 0
|
||||
assert G.is_directed() == directed
|
||||
|
||||
|
||||
@pytest.mark.parametrize("generator", _gnp_generators)
|
||||
@pytest.mark.parametrize(
|
||||
("directed", "expected_num_edges"),
|
||||
[(False, 45), (True, 90)],
|
||||
)
|
||||
def test_gnp_generators_greater_than_1_edge_probability(
|
||||
generator, directed, expected_num_edges
|
||||
):
|
||||
"""If the edge probability `p` is >=1, the resulting graph should be complete."""
|
||||
G = generator(10, 1.1, directed=directed)
|
||||
assert len(G) == 10
|
||||
assert G.number_of_edges() == expected_num_edges
|
||||
assert G.is_directed() == directed
|
||||
|
||||
|
||||
@pytest.mark.parametrize("generator", _gnp_generators)
|
||||
@pytest.mark.parametrize("directed", (True, False))
|
||||
def test_gnp_generators_basic(generator, directed):
|
||||
"""If the edge probability `p` is >0 and <1, test only the basic properties."""
|
||||
G = generator(10, 0.1, directed=directed)
|
||||
assert len(G) == 10
|
||||
assert G.is_directed() == directed
|
||||
|
||||
|
||||
@pytest.mark.parametrize("generator", _gnp_generators)
|
||||
def test_gnp_generators_for_p_close_to_1(generator):
|
||||
"""If the edge probability `p` is close to 1, the resulting graph should have all edges."""
|
||||
runs = 100
|
||||
edges = sum(
|
||||
generator(10, 0.99999, directed=True).number_of_edges() for _ in range(runs)
|
||||
)
|
||||
assert abs(edges / float(runs) - 90) <= runs * 2.0 / 100
|
||||
|
||||
|
||||
@pytest.mark.parametrize("generator", _gnp_generators)
|
||||
@pytest.mark.parametrize("p", (0.2, 0.8))
|
||||
@pytest.mark.parametrize("directed", (True, False))
|
||||
def test_gnp_generators_edge_probability(generator, p, directed):
|
||||
"""Test that gnp generators generate edges according to the their probability `p`."""
|
||||
runs = 5000
|
||||
n = 5
|
||||
edge_counts = [[0] * n for _ in range(n)]
|
||||
for i in range(runs):
|
||||
G = generator(n, p, directed=directed)
|
||||
for v, w in G.edges:
|
||||
edge_counts[v][w] += 1
|
||||
if not directed:
|
||||
edge_counts[w][v] += 1
|
||||
for v in range(n):
|
||||
for w in range(n):
|
||||
if v == w:
|
||||
# There should be no loops
|
||||
assert edge_counts[v][w] == 0
|
||||
else:
|
||||
# Each edge should have been generated with probability close to p
|
||||
assert abs(edge_counts[v][w] / float(runs) - p) <= 0.03
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"generator", [nx.gnp_random_graph, nx.binomial_graph, nx.erdos_renyi_graph]
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
("seed", "directed", "expected_num_edges"),
|
||||
[(42, False, 1219), (42, True, 2454), (314, False, 1247), (314, True, 2476)],
|
||||
)
|
||||
def test_gnp_random_graph_aliases(generator, seed, directed, expected_num_edges):
|
||||
"""Test that aliases give the same result with the same seed."""
|
||||
G = generator(100, 0.25, seed=seed, directed=directed)
|
||||
assert len(G) == 100
|
||||
assert G.number_of_edges() == expected_num_edges
|
||||
assert G.is_directed() == directed
|
||||
|
||||
|
||||
class TestGeneratorsRandom:
|
||||
def test_random_graph(self):
|
||||
seed = 42
|
||||
G = nx.gnm_random_graph(100, 20, seed)
|
||||
G = nx.gnm_random_graph(100, 20, seed, directed=True)
|
||||
G = nx.dense_gnm_random_graph(100, 20, seed)
|
||||
|
||||
G = nx.watts_strogatz_graph(10, 2, 0.25, seed)
|
||||
assert len(G) == 10
|
||||
assert G.number_of_edges() == 10
|
||||
|
||||
G = nx.connected_watts_strogatz_graph(10, 2, 0.1, tries=10, seed=seed)
|
||||
assert len(G) == 10
|
||||
assert G.number_of_edges() == 10
|
||||
pytest.raises(
|
||||
nx.NetworkXError, nx.connected_watts_strogatz_graph, 10, 2, 0.1, tries=0
|
||||
)
|
||||
|
||||
G = nx.watts_strogatz_graph(10, 4, 0.25, seed)
|
||||
assert len(G) == 10
|
||||
assert G.number_of_edges() == 20
|
||||
|
||||
G = nx.newman_watts_strogatz_graph(10, 2, 0.0, seed)
|
||||
assert len(G) == 10
|
||||
assert G.number_of_edges() == 10
|
||||
|
||||
G = nx.newman_watts_strogatz_graph(10, 4, 0.25, seed)
|
||||
assert len(G) == 10
|
||||
assert G.number_of_edges() >= 20
|
||||
|
||||
G = nx.barabasi_albert_graph(100, 1, seed)
|
||||
G = nx.barabasi_albert_graph(100, 3, seed)
|
||||
assert G.number_of_edges() == (97 * 3)
|
||||
|
||||
G = nx.barabasi_albert_graph(100, 3, seed, nx.complete_graph(5))
|
||||
assert G.number_of_edges() == (10 + 95 * 3)
|
||||
|
||||
G = nx.extended_barabasi_albert_graph(100, 1, 0, 0, seed)
|
||||
assert G.number_of_edges() == 99
|
||||
G = nx.extended_barabasi_albert_graph(100, 3, 0, 0, seed)
|
||||
assert G.number_of_edges() == 97 * 3
|
||||
G = nx.extended_barabasi_albert_graph(100, 1, 0, 0.5, seed)
|
||||
assert G.number_of_edges() == 99
|
||||
G = nx.extended_barabasi_albert_graph(100, 2, 0.5, 0, seed)
|
||||
assert G.number_of_edges() > 100 * 3
|
||||
assert G.number_of_edges() < 100 * 4
|
||||
|
||||
G = nx.extended_barabasi_albert_graph(100, 2, 0.3, 0.3, seed)
|
||||
assert G.number_of_edges() > 100 * 2
|
||||
assert G.number_of_edges() < 100 * 4
|
||||
|
||||
G = nx.powerlaw_cluster_graph(100, 1, 1.0, seed)
|
||||
G = nx.powerlaw_cluster_graph(100, 3, 0.0, seed)
|
||||
assert G.number_of_edges() == (97 * 3)
|
||||
|
||||
G = nx.random_regular_graph(10, 20, seed)
|
||||
|
||||
pytest.raises(nx.NetworkXError, nx.random_regular_graph, 3, 21)
|
||||
pytest.raises(nx.NetworkXError, nx.random_regular_graph, 33, 21)
|
||||
|
||||
constructor = [(10, 20, 0.8), (20, 40, 0.8)]
|
||||
G = nx.random_shell_graph(constructor, seed)
|
||||
|
||||
def is_caterpillar(g):
|
||||
"""
|
||||
A tree is a caterpillar iff all nodes of degree >=3 are surrounded
|
||||
by at most two nodes of degree two or greater.
|
||||
ref: http://mathworld.wolfram.com/CaterpillarGraph.html
|
||||
"""
|
||||
deg_over_3 = [n for n in g if g.degree(n) >= 3]
|
||||
for n in deg_over_3:
|
||||
nbh_deg_over_2 = [nbh for nbh in g.neighbors(n) if g.degree(nbh) >= 2]
|
||||
if not len(nbh_deg_over_2) <= 2:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_lobster(g):
|
||||
"""
|
||||
A tree is a lobster if it has the property that the removal of leaf
|
||||
nodes leaves a caterpillar graph (Gallian 2007)
|
||||
ref: http://mathworld.wolfram.com/LobsterGraph.html
|
||||
"""
|
||||
non_leafs = [n for n in g if g.degree(n) > 1]
|
||||
return is_caterpillar(g.subgraph(non_leafs))
|
||||
|
||||
G = nx.random_lobster(10, 0.1, 0.5, seed)
|
||||
assert max(G.degree(n) for n in G.nodes()) > 3
|
||||
assert is_lobster(G)
|
||||
pytest.raises(nx.NetworkXError, nx.random_lobster, 10, 0.1, 1, seed)
|
||||
pytest.raises(nx.NetworkXError, nx.random_lobster, 10, 1, 1, seed)
|
||||
pytest.raises(nx.NetworkXError, nx.random_lobster, 10, 1, 0.5, seed)
|
||||
|
||||
# docstring says this should be a caterpillar
|
||||
G = nx.random_lobster(10, 0.1, 0.0, seed)
|
||||
assert is_caterpillar(G)
|
||||
|
||||
# difficult to find seed that requires few tries
|
||||
seq = nx.random_powerlaw_tree_sequence(10, 3, seed=14, tries=1)
|
||||
G = nx.random_powerlaw_tree(10, 3, seed=14, tries=1)
|
||||
|
||||
def test_dual_barabasi_albert(self, m1=1, m2=4, p=0.5):
|
||||
"""
|
||||
Tests that the dual BA random graph generated behaves consistently.
|
||||
|
||||
Tests the exceptions are raised as expected.
|
||||
|
||||
The graphs generation are repeated several times to prevent lucky shots
|
||||
|
||||
"""
|
||||
seeds = [42, 314, 2718]
|
||||
initial_graph = nx.complete_graph(10)
|
||||
|
||||
for seed in seeds:
|
||||
# This should be BA with m = m1
|
||||
BA1 = nx.barabasi_albert_graph(100, m1, seed)
|
||||
DBA1 = nx.dual_barabasi_albert_graph(100, m1, m2, 1, seed)
|
||||
assert BA1.edges() == DBA1.edges()
|
||||
|
||||
# This should be BA with m = m2
|
||||
BA2 = nx.barabasi_albert_graph(100, m2, seed)
|
||||
DBA2 = nx.dual_barabasi_albert_graph(100, m1, m2, 0, seed)
|
||||
assert BA2.edges() == DBA2.edges()
|
||||
|
||||
BA3 = nx.barabasi_albert_graph(100, m1, seed)
|
||||
DBA3 = nx.dual_barabasi_albert_graph(100, m1, m1, p, seed)
|
||||
# We can't compare edges here since randomness is "consumed" when drawing
|
||||
# between m1 and m2
|
||||
assert BA3.size() == DBA3.size()
|
||||
|
||||
DBA = nx.dual_barabasi_albert_graph(100, m1, m2, p, seed, initial_graph)
|
||||
BA1 = nx.barabasi_albert_graph(100, m1, seed, initial_graph)
|
||||
BA2 = nx.barabasi_albert_graph(100, m2, seed, initial_graph)
|
||||
assert (
|
||||
min(BA1.size(), BA2.size()) <= DBA.size() <= max(BA1.size(), BA2.size())
|
||||
)
|
||||
|
||||
# Testing exceptions
|
||||
dbag = nx.dual_barabasi_albert_graph
|
||||
pytest.raises(nx.NetworkXError, dbag, m1, m1, m2, 0)
|
||||
pytest.raises(nx.NetworkXError, dbag, m2, m1, m2, 0)
|
||||
pytest.raises(nx.NetworkXError, dbag, 100, m1, m2, -0.5)
|
||||
pytest.raises(nx.NetworkXError, dbag, 100, m1, m2, 1.5)
|
||||
initial = nx.complete_graph(max(m1, m2) - 1)
|
||||
pytest.raises(nx.NetworkXError, dbag, 100, m1, m2, p, initial_graph=initial)
|
||||
|
||||
def test_extended_barabasi_albert(self, m=2):
|
||||
"""
|
||||
Tests that the extended BA random graph generated behaves consistently.
|
||||
|
||||
Tests the exceptions are raised as expected.
|
||||
|
||||
The graphs generation are repeated several times to prevent lucky-shots
|
||||
|
||||
"""
|
||||
seeds = [42, 314, 2718]
|
||||
|
||||
for seed in seeds:
|
||||
BA_model = nx.barabasi_albert_graph(100, m, seed)
|
||||
BA_model_edges = BA_model.number_of_edges()
|
||||
|
||||
# This behaves just like BA, the number of edges must be the same
|
||||
G1 = nx.extended_barabasi_albert_graph(100, m, 0, 0, seed)
|
||||
assert G1.size() == BA_model_edges
|
||||
|
||||
# More than twice more edges should have been added
|
||||
G1 = nx.extended_barabasi_albert_graph(100, m, 0.8, 0, seed)
|
||||
assert G1.size() > BA_model_edges * 2
|
||||
|
||||
# Only edge rewiring, so the number of edges less than original
|
||||
G2 = nx.extended_barabasi_albert_graph(100, m, 0, 0.8, seed)
|
||||
assert G2.size() == BA_model_edges
|
||||
|
||||
# Mixed scenario: less edges than G1 and more edges than G2
|
||||
G3 = nx.extended_barabasi_albert_graph(100, m, 0.3, 0.3, seed)
|
||||
assert G3.size() > G2.size()
|
||||
assert G3.size() < G1.size()
|
||||
|
||||
# Testing exceptions
|
||||
ebag = nx.extended_barabasi_albert_graph
|
||||
pytest.raises(nx.NetworkXError, ebag, m, m, 0, 0)
|
||||
pytest.raises(nx.NetworkXError, ebag, 1, 0.5, 0, 0)
|
||||
pytest.raises(nx.NetworkXError, ebag, 100, 2, 0.5, 0.5)
|
||||
|
||||
def test_random_zero_regular_graph(self):
|
||||
"""Tests that a 0-regular graph has the correct number of nodes and
|
||||
edges.
|
||||
|
||||
"""
|
||||
seed = 42
|
||||
G = nx.random_regular_graph(0, 10, seed)
|
||||
assert len(G) == 10
|
||||
assert G.number_of_edges() == 0
|
||||
|
||||
def test_gnm(self):
|
||||
G = nx.gnm_random_graph(10, 3)
|
||||
assert len(G) == 10
|
||||
assert G.number_of_edges() == 3
|
||||
|
||||
G = nx.gnm_random_graph(10, 3, seed=42)
|
||||
assert len(G) == 10
|
||||
assert G.number_of_edges() == 3
|
||||
|
||||
G = nx.gnm_random_graph(10, 100)
|
||||
assert len(G) == 10
|
||||
assert G.number_of_edges() == 45
|
||||
|
||||
G = nx.gnm_random_graph(10, 100, directed=True)
|
||||
assert len(G) == 10
|
||||
assert G.number_of_edges() == 90
|
||||
|
||||
G = nx.gnm_random_graph(10, -1.1)
|
||||
assert len(G) == 10
|
||||
assert G.number_of_edges() == 0
|
||||
|
||||
def test_watts_strogatz_big_k(self):
|
||||
# Test to make sure than n <= k
|
||||
pytest.raises(nx.NetworkXError, nx.watts_strogatz_graph, 10, 11, 0.25)
|
||||
pytest.raises(nx.NetworkXError, nx.newman_watts_strogatz_graph, 10, 11, 0.25)
|
||||
|
||||
# could create an infinite loop, now doesn't
|
||||
# infinite loop used to occur when a node has degree n-1 and needs to rewire
|
||||
nx.watts_strogatz_graph(10, 9, 0.25, seed=0)
|
||||
nx.newman_watts_strogatz_graph(10, 9, 0.5, seed=0)
|
||||
|
||||
# Test k==n scenario
|
||||
nx.watts_strogatz_graph(10, 10, 0.25, seed=0)
|
||||
nx.newman_watts_strogatz_graph(10, 10, 0.25, seed=0)
|
||||
|
||||
def test_random_kernel_graph(self):
|
||||
def integral(u, w, z):
|
||||
return c * (z - w)
|
||||
|
||||
def root(u, w, r):
|
||||
return r / c + w
|
||||
|
||||
c = 1
|
||||
graph = nx.random_kernel_graph(1000, integral, root)
|
||||
graph = nx.random_kernel_graph(1000, integral, root, seed=42)
|
||||
assert len(graph) == 1000
|
||||
@@ -1,205 +0,0 @@
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.algorithms.isomorphism.isomorph import graph_could_be_isomorphic
|
||||
|
||||
is_isomorphic = graph_could_be_isomorphic
|
||||
|
||||
"""Generators - Small
|
||||
=====================
|
||||
|
||||
Some small graphs
|
||||
"""
|
||||
|
||||
null = nx.null_graph()
|
||||
|
||||
|
||||
class TestGeneratorsSmall:
|
||||
def test__LCF_graph(self):
|
||||
# If n<=0, then return the null_graph
|
||||
G = nx.LCF_graph(-10, [1, 2], 100)
|
||||
assert is_isomorphic(G, null)
|
||||
G = nx.LCF_graph(0, [1, 2], 3)
|
||||
assert is_isomorphic(G, null)
|
||||
G = nx.LCF_graph(0, [1, 2], 10)
|
||||
assert is_isomorphic(G, null)
|
||||
|
||||
# Test that LCF(n,[],0) == cycle_graph(n)
|
||||
for a, b, c in [(5, [], 0), (10, [], 0), (5, [], 1), (10, [], 10)]:
|
||||
G = nx.LCF_graph(a, b, c)
|
||||
assert is_isomorphic(G, nx.cycle_graph(a))
|
||||
|
||||
# Generate the utility graph K_{3,3}
|
||||
G = nx.LCF_graph(6, [3, -3], 3)
|
||||
utility_graph = nx.complete_bipartite_graph(3, 3)
|
||||
assert is_isomorphic(G, utility_graph)
|
||||
|
||||
def test_properties_named_small_graphs(self):
|
||||
G = nx.bull_graph()
|
||||
assert sorted(G) == list(range(5))
|
||||
assert G.number_of_edges() == 5
|
||||
assert sorted(d for n, d in G.degree()) == [1, 1, 2, 3, 3]
|
||||
assert nx.diameter(G) == 3
|
||||
assert nx.radius(G) == 2
|
||||
|
||||
G = nx.chvatal_graph()
|
||||
assert sorted(G) == list(range(12))
|
||||
assert G.number_of_edges() == 24
|
||||
assert [d for n, d in G.degree()] == 12 * [4]
|
||||
assert nx.diameter(G) == 2
|
||||
assert nx.radius(G) == 2
|
||||
|
||||
G = nx.cubical_graph()
|
||||
assert sorted(G) == list(range(8))
|
||||
assert G.number_of_edges() == 12
|
||||
assert [d for n, d in G.degree()] == 8 * [3]
|
||||
assert nx.diameter(G) == 3
|
||||
assert nx.radius(G) == 3
|
||||
|
||||
G = nx.desargues_graph()
|
||||
assert sorted(G) == list(range(20))
|
||||
assert G.number_of_edges() == 30
|
||||
assert [d for n, d in G.degree()] == 20 * [3]
|
||||
|
||||
G = nx.diamond_graph()
|
||||
assert sorted(G) == list(range(4))
|
||||
assert sorted(d for n, d in G.degree()) == [2, 2, 3, 3]
|
||||
assert nx.diameter(G) == 2
|
||||
assert nx.radius(G) == 1
|
||||
|
||||
G = nx.dodecahedral_graph()
|
||||
assert sorted(G) == list(range(20))
|
||||
assert G.number_of_edges() == 30
|
||||
assert [d for n, d in G.degree()] == 20 * [3]
|
||||
assert nx.diameter(G) == 5
|
||||
assert nx.radius(G) == 5
|
||||
|
||||
G = nx.frucht_graph()
|
||||
assert sorted(G) == list(range(12))
|
||||
assert G.number_of_edges() == 18
|
||||
assert [d for n, d in G.degree()] == 12 * [3]
|
||||
assert nx.diameter(G) == 4
|
||||
assert nx.radius(G) == 3
|
||||
|
||||
G = nx.heawood_graph()
|
||||
assert sorted(G) == list(range(14))
|
||||
assert G.number_of_edges() == 21
|
||||
assert [d for n, d in G.degree()] == 14 * [3]
|
||||
assert nx.diameter(G) == 3
|
||||
assert nx.radius(G) == 3
|
||||
|
||||
G = nx.hoffman_singleton_graph()
|
||||
assert sorted(G) == list(range(50))
|
||||
assert G.number_of_edges() == 175
|
||||
assert [d for n, d in G.degree()] == 50 * [7]
|
||||
assert nx.diameter(G) == 2
|
||||
assert nx.radius(G) == 2
|
||||
|
||||
G = nx.house_graph()
|
||||
assert sorted(G) == list(range(5))
|
||||
assert G.number_of_edges() == 6
|
||||
assert sorted(d for n, d in G.degree()) == [2, 2, 2, 3, 3]
|
||||
assert nx.diameter(G) == 2
|
||||
assert nx.radius(G) == 2
|
||||
|
||||
G = nx.house_x_graph()
|
||||
assert sorted(G) == list(range(5))
|
||||
assert G.number_of_edges() == 8
|
||||
assert sorted(d for n, d in G.degree()) == [2, 3, 3, 4, 4]
|
||||
assert nx.diameter(G) == 2
|
||||
assert nx.radius(G) == 1
|
||||
|
||||
G = nx.icosahedral_graph()
|
||||
assert sorted(G) == list(range(12))
|
||||
assert G.number_of_edges() == 30
|
||||
assert [d for n, d in G.degree()] == [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
|
||||
assert nx.diameter(G) == 3
|
||||
assert nx.radius(G) == 3
|
||||
|
||||
G = nx.krackhardt_kite_graph()
|
||||
assert sorted(G) == list(range(10))
|
||||
assert G.number_of_edges() == 18
|
||||
assert sorted(d for n, d in G.degree()) == [1, 2, 3, 3, 3, 4, 4, 5, 5, 6]
|
||||
|
||||
G = nx.moebius_kantor_graph()
|
||||
assert sorted(G) == list(range(16))
|
||||
assert G.number_of_edges() == 24
|
||||
assert [d for n, d in G.degree()] == 16 * [3]
|
||||
assert nx.diameter(G) == 4
|
||||
|
||||
G = nx.octahedral_graph()
|
||||
assert sorted(G) == list(range(6))
|
||||
assert G.number_of_edges() == 12
|
||||
assert [d for n, d in G.degree()] == 6 * [4]
|
||||
assert nx.diameter(G) == 2
|
||||
assert nx.radius(G) == 2
|
||||
|
||||
G = nx.pappus_graph()
|
||||
assert sorted(G) == list(range(18))
|
||||
assert G.number_of_edges() == 27
|
||||
assert [d for n, d in G.degree()] == 18 * [3]
|
||||
assert nx.diameter(G) == 4
|
||||
|
||||
G = nx.petersen_graph()
|
||||
assert sorted(G) == list(range(10))
|
||||
assert G.number_of_edges() == 15
|
||||
assert [d for n, d in G.degree()] == 10 * [3]
|
||||
assert nx.diameter(G) == 2
|
||||
assert nx.radius(G) == 2
|
||||
|
||||
G = nx.sedgewick_maze_graph()
|
||||
assert sorted(G) == list(range(8))
|
||||
assert G.number_of_edges() == 10
|
||||
assert sorted(d for n, d in G.degree()) == [1, 2, 2, 2, 3, 3, 3, 4]
|
||||
|
||||
G = nx.tetrahedral_graph()
|
||||
assert sorted(G) == list(range(4))
|
||||
assert G.number_of_edges() == 6
|
||||
assert [d for n, d in G.degree()] == [3, 3, 3, 3]
|
||||
assert nx.diameter(G) == 1
|
||||
assert nx.radius(G) == 1
|
||||
|
||||
G = nx.truncated_cube_graph()
|
||||
assert sorted(G) == list(range(24))
|
||||
assert G.number_of_edges() == 36
|
||||
assert [d for n, d in G.degree()] == 24 * [3]
|
||||
|
||||
G = nx.truncated_tetrahedron_graph()
|
||||
assert sorted(G) == list(range(12))
|
||||
assert G.number_of_edges() == 18
|
||||
assert [d for n, d in G.degree()] == 12 * [3]
|
||||
|
||||
G = nx.tutte_graph()
|
||||
assert sorted(G) == list(range(46))
|
||||
assert G.number_of_edges() == 69
|
||||
assert [d for n, d in G.degree()] == 46 * [3]
|
||||
|
||||
# Test create_using with directed or multigraphs on small graphs
|
||||
pytest.raises(nx.NetworkXError, nx.tutte_graph, create_using=nx.DiGraph)
|
||||
MG = nx.tutte_graph(create_using=nx.MultiGraph)
|
||||
assert sorted(MG.edges()) == sorted(G.edges())
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"fn",
|
||||
(
|
||||
nx.bull_graph,
|
||||
nx.chvatal_graph,
|
||||
nx.cubical_graph,
|
||||
nx.diamond_graph,
|
||||
nx.house_graph,
|
||||
nx.house_x_graph,
|
||||
nx.icosahedral_graph,
|
||||
nx.krackhardt_kite_graph,
|
||||
nx.octahedral_graph,
|
||||
nx.petersen_graph,
|
||||
nx.truncated_cube_graph,
|
||||
nx.tutte_graph,
|
||||
),
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"create_using", (nx.DiGraph, nx.MultiDiGraph, nx.DiGraph([(0, 1)]))
|
||||
)
|
||||
def tests_raises_with_directed_create_using(fn, create_using):
|
||||
with pytest.raises(nx.NetworkXError, match="Directed Graph not supported"):
|
||||
fn(create_using=create_using)
|
||||
@@ -1,49 +0,0 @@
|
||||
import pytest
|
||||
|
||||
pytest.importorskip("numpy")
|
||||
pytest.importorskip("scipy")
|
||||
|
||||
|
||||
from networkx import is_isomorphic
|
||||
from networkx.exception import NetworkXError
|
||||
from networkx.generators import karate_club_graph
|
||||
from networkx.generators.spectral_graph_forge import spectral_graph_forge
|
||||
from networkx.utils import nodes_equal
|
||||
|
||||
|
||||
def test_spectral_graph_forge():
|
||||
G = karate_club_graph()
|
||||
|
||||
seed = 54321
|
||||
|
||||
# common cases, just checking node number preserving and difference
|
||||
# between identity and modularity cases
|
||||
H = spectral_graph_forge(G, 0.1, transformation="identity", seed=seed)
|
||||
assert nodes_equal(G, H)
|
||||
|
||||
I = spectral_graph_forge(G, 0.1, transformation="identity", seed=seed)
|
||||
assert nodes_equal(G, H)
|
||||
assert is_isomorphic(I, H)
|
||||
|
||||
I = spectral_graph_forge(G, 0.1, transformation="modularity", seed=seed)
|
||||
assert nodes_equal(G, I)
|
||||
|
||||
assert not is_isomorphic(I, H)
|
||||
|
||||
# with all the eigenvectors, output graph is identical to the input one
|
||||
H = spectral_graph_forge(G, 1, transformation="modularity", seed=seed)
|
||||
assert nodes_equal(G, H)
|
||||
assert is_isomorphic(G, H)
|
||||
|
||||
# invalid alpha input value, it is silently truncated in [0,1]
|
||||
H = spectral_graph_forge(G, -1, transformation="identity", seed=seed)
|
||||
assert nodes_equal(G, H)
|
||||
|
||||
H = spectral_graph_forge(G, 10, transformation="identity", seed=seed)
|
||||
assert nodes_equal(G, H)
|
||||
assert is_isomorphic(G, H)
|
||||
|
||||
# invalid transformation mode, checking the error raising
|
||||
pytest.raises(
|
||||
NetworkXError, spectral_graph_forge, G, 0.1, transformation="unknown", seed=seed
|
||||
)
|
||||
@@ -1,71 +0,0 @@
|
||||
"""Unit tests for the :mod:`networkx.generators.stochastic` module."""
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
|
||||
|
||||
class TestStochasticGraph:
|
||||
"""Unit tests for the :func:`~networkx.stochastic_graph` function."""
|
||||
|
||||
def test_default_weights(self):
|
||||
G = nx.DiGraph()
|
||||
G.add_edge(0, 1)
|
||||
G.add_edge(0, 2)
|
||||
S = nx.stochastic_graph(G)
|
||||
assert nx.is_isomorphic(G, S)
|
||||
assert sorted(S.edges(data=True)) == [
|
||||
(0, 1, {"weight": 0.5}),
|
||||
(0, 2, {"weight": 0.5}),
|
||||
]
|
||||
|
||||
def test_in_place(self):
|
||||
"""Tests for an in-place reweighting of the edges of the graph."""
|
||||
G = nx.DiGraph()
|
||||
G.add_edge(0, 1, weight=1)
|
||||
G.add_edge(0, 2, weight=1)
|
||||
nx.stochastic_graph(G, copy=False)
|
||||
assert sorted(G.edges(data=True)) == [
|
||||
(0, 1, {"weight": 0.5}),
|
||||
(0, 2, {"weight": 0.5}),
|
||||
]
|
||||
|
||||
def test_arbitrary_weights(self):
|
||||
G = nx.DiGraph()
|
||||
G.add_edge(0, 1, weight=1)
|
||||
G.add_edge(0, 2, weight=1)
|
||||
S = nx.stochastic_graph(G)
|
||||
assert sorted(S.edges(data=True)) == [
|
||||
(0, 1, {"weight": 0.5}),
|
||||
(0, 2, {"weight": 0.5}),
|
||||
]
|
||||
|
||||
def test_multidigraph(self):
|
||||
G = nx.MultiDiGraph()
|
||||
G.add_edges_from([(0, 1), (0, 1), (0, 2), (0, 2)])
|
||||
S = nx.stochastic_graph(G)
|
||||
d = {"weight": 0.25}
|
||||
assert sorted(S.edges(data=True)) == [
|
||||
(0, 1, d),
|
||||
(0, 1, d),
|
||||
(0, 2, d),
|
||||
(0, 2, d),
|
||||
]
|
||||
|
||||
def test_zero_weights(self):
|
||||
"""Smoke test: ensure ZeroDivisionError is not raised."""
|
||||
G = nx.DiGraph()
|
||||
G.add_edge(0, 1, weight=0)
|
||||
G.add_edge(0, 2, weight=0)
|
||||
S = nx.stochastic_graph(G)
|
||||
assert sorted(S.edges(data=True)) == [
|
||||
(0, 1, {"weight": 0}),
|
||||
(0, 2, {"weight": 0}),
|
||||
]
|
||||
|
||||
def test_graph_disallowed(self):
|
||||
with pytest.raises(nx.NetworkXNotImplemented):
|
||||
nx.stochastic_graph(nx.Graph())
|
||||
|
||||
def test_multigraph_disallowed(self):
|
||||
with pytest.raises(nx.NetworkXNotImplemented):
|
||||
nx.stochastic_graph(nx.MultiGraph())
|
||||
@@ -1,92 +0,0 @@
|
||||
"""Unit tests for the :mod:`networkx.generators.sudoku_graph` module."""
|
||||
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
|
||||
|
||||
def test_sudoku_negative():
|
||||
"""Raise an error when generating a Sudoku graph of order -1."""
|
||||
pytest.raises(nx.NetworkXError, nx.sudoku_graph, n=-1)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("n", [0, 1, 2, 3, 4])
|
||||
def test_sudoku_generator(n):
|
||||
"""Generate Sudoku graphs of various sizes and verify their properties."""
|
||||
G = nx.sudoku_graph(n)
|
||||
expected_nodes = n**4
|
||||
expected_degree = (n - 1) * (3 * n + 1)
|
||||
expected_edges = expected_nodes * expected_degree // 2
|
||||
assert not G.is_directed()
|
||||
assert not G.is_multigraph()
|
||||
assert G.number_of_nodes() == expected_nodes
|
||||
assert G.number_of_edges() == expected_edges
|
||||
assert all(d == expected_degree for _, d in G.degree)
|
||||
|
||||
if n == 2:
|
||||
assert sorted(G.neighbors(6)) == [2, 3, 4, 5, 7, 10, 14]
|
||||
elif n == 3:
|
||||
assert sorted(G.neighbors(42)) == [
|
||||
6,
|
||||
15,
|
||||
24,
|
||||
33,
|
||||
34,
|
||||
35,
|
||||
36,
|
||||
37,
|
||||
38,
|
||||
39,
|
||||
40,
|
||||
41,
|
||||
43,
|
||||
44,
|
||||
51,
|
||||
52,
|
||||
53,
|
||||
60,
|
||||
69,
|
||||
78,
|
||||
]
|
||||
elif n == 4:
|
||||
assert sorted(G.neighbors(0)) == [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
32,
|
||||
33,
|
||||
34,
|
||||
35,
|
||||
48,
|
||||
49,
|
||||
50,
|
||||
51,
|
||||
64,
|
||||
80,
|
||||
96,
|
||||
112,
|
||||
128,
|
||||
144,
|
||||
160,
|
||||
176,
|
||||
192,
|
||||
208,
|
||||
224,
|
||||
240,
|
||||
]
|
||||
@@ -1,101 +0,0 @@
|
||||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.utils import arbitrary_element, graphs_equal
|
||||
|
||||
|
||||
@pytest.mark.parametrize("prefix_tree_fn", (nx.prefix_tree, nx.prefix_tree_recursive))
|
||||
def test_basic_prefix_tree(prefix_tree_fn):
|
||||
# This example is from the Wikipedia article "Trie"
|
||||
# <https://en.wikipedia.org/wiki/Trie>.
|
||||
strings = ["a", "to", "tea", "ted", "ten", "i", "in", "inn"]
|
||||
T = prefix_tree_fn(strings)
|
||||
root, NIL = 0, -1
|
||||
|
||||
def source_label(v):
|
||||
return T.nodes[v]["source"]
|
||||
|
||||
# First, we check that the tree has the expected
|
||||
# structure. Recall that each node that corresponds to one of
|
||||
# the input strings has an edge to the NIL node.
|
||||
#
|
||||
# Consider the three children at level 1 in the trie.
|
||||
a, i, t = sorted(T[root], key=source_label)
|
||||
# Check the 'a' branch.
|
||||
assert len(T[a]) == 1
|
||||
nil = arbitrary_element(T[a])
|
||||
assert len(T[nil]) == 0
|
||||
# Check the 'i' branch.
|
||||
assert len(T[i]) == 2
|
||||
nil, in_ = sorted(T[i], key=source_label)
|
||||
assert len(T[nil]) == 0
|
||||
assert len(T[in_]) == 2
|
||||
nil, inn = sorted(T[in_], key=source_label)
|
||||
assert len(T[nil]) == 0
|
||||
assert len(T[inn]) == 1
|
||||
nil = arbitrary_element(T[inn])
|
||||
assert len(T[nil]) == 0
|
||||
# Check the 't' branch.
|
||||
te, to = sorted(T[t], key=source_label)
|
||||
assert len(T[to]) == 1
|
||||
nil = arbitrary_element(T[to])
|
||||
assert len(T[nil]) == 0
|
||||
tea, ted, ten = sorted(T[te], key=source_label)
|
||||
assert len(T[tea]) == 1
|
||||
assert len(T[ted]) == 1
|
||||
assert len(T[ten]) == 1
|
||||
nil = arbitrary_element(T[tea])
|
||||
assert len(T[nil]) == 0
|
||||
nil = arbitrary_element(T[ted])
|
||||
assert len(T[nil]) == 0
|
||||
nil = arbitrary_element(T[ten])
|
||||
assert len(T[nil]) == 0
|
||||
|
||||
# Next, we check that the "sources" of each of the nodes is the
|
||||
# rightmost letter in the string corresponding to the path to
|
||||
# that node.
|
||||
assert source_label(root) is None
|
||||
assert source_label(a) == "a"
|
||||
assert source_label(i) == "i"
|
||||
assert source_label(t) == "t"
|
||||
assert source_label(in_) == "n"
|
||||
assert source_label(inn) == "n"
|
||||
assert source_label(to) == "o"
|
||||
assert source_label(te) == "e"
|
||||
assert source_label(tea) == "a"
|
||||
assert source_label(ted) == "d"
|
||||
assert source_label(ten) == "n"
|
||||
assert source_label(NIL) == "NIL"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"strings",
|
||||
(
|
||||
["a", "to", "tea", "ted", "ten", "i", "in", "inn"],
|
||||
["ab", "abs", "ad"],
|
||||
["ab", "abs", "ad", ""],
|
||||
["distant", "disparaging", "distant", "diamond", "ruby"],
|
||||
),
|
||||
)
|
||||
def test_implementations_consistent(strings):
|
||||
"""Ensure results are consistent between prefix_tree implementations."""
|
||||
assert graphs_equal(nx.prefix_tree(strings), nx.prefix_tree_recursive(strings))
|
||||
|
||||
|
||||
def test_random_tree():
|
||||
"""Tests that a random tree is in fact a tree."""
|
||||
T = nx.random_tree(10, seed=1234)
|
||||
assert nx.is_tree(T)
|
||||
|
||||
|
||||
def test_random_tree_n_zero():
|
||||
"""Tests if n = 0 then the NetworkXPointlessConcept exception is raised."""
|
||||
with pytest.raises(nx.NetworkXPointlessConcept):
|
||||
T = nx.random_tree(0, seed=1234)
|
||||
|
||||
|
||||
def test_random_tree_using_generator():
|
||||
"""Tests that creating a ramdom tree with a generator works"""
|
||||
G = nx.Graph()
|
||||
T = nx.random_tree(10, seed=1234, create_using=G)
|
||||
assert nx.is_tree(T)
|
||||
@@ -1,14 +0,0 @@
|
||||
"""Unit tests for the :mod:`networkx.generators.triads` module."""
|
||||
import pytest
|
||||
|
||||
from networkx import triad_graph
|
||||
|
||||
|
||||
def test_triad_graph():
|
||||
G = triad_graph("030T")
|
||||
assert [tuple(e) for e in ("ab", "ac", "cb")] == sorted(G.edges())
|
||||
|
||||
|
||||
def test_invalid_name():
|
||||
with pytest.raises(ValueError):
|
||||
triad_graph("bogus")
|
||||
Reference in New Issue
Block a user