Fixed database typo and removed unnecessary class identifier.
This commit is contained in:
parent
00ad49a143
commit
45fb349a7d
5098 changed files with 952558 additions and 85 deletions
0
venv/Lib/site-packages/networkx/linalg/tests/__init__.py
Normal file
0
venv/Lib/site-packages/networkx/linalg/tests/__init__.py
Normal file
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.
|
@ -0,0 +1,365 @@
|
|||
from math import sqrt
|
||||
|
||||
import pytest
|
||||
|
||||
numpy = pytest.importorskip("numpy")
|
||||
numpy.linalg = pytest.importorskip("numpy.linalg")
|
||||
scipy = pytest.importorskip("scipy")
|
||||
scipy.sparse = pytest.importorskip("scipy.sparse")
|
||||
|
||||
|
||||
import networkx as nx
|
||||
from networkx.testing import almost_equal
|
||||
|
||||
try:
|
||||
from scikits.sparse.cholmod import cholesky
|
||||
|
||||
_cholesky = cholesky
|
||||
except ImportError:
|
||||
_cholesky = None
|
||||
|
||||
if _cholesky is None:
|
||||
methods = ("tracemin_pcg", "tracemin_lu", "lanczos", "lobpcg")
|
||||
else:
|
||||
methods = ("tracemin_pcg", "tracemin_chol", "tracemin_lu", "lanczos", "lobpcg")
|
||||
|
||||
|
||||
def check_eigenvector(A, l, x):
|
||||
nx = numpy.linalg.norm(x)
|
||||
# Check zeroness.
|
||||
assert not almost_equal(nx, 0)
|
||||
y = A * x
|
||||
ny = numpy.linalg.norm(y)
|
||||
# Check collinearity.
|
||||
assert almost_equal(numpy.dot(x, y), nx * ny)
|
||||
# Check eigenvalue.
|
||||
assert almost_equal(ny, l * nx)
|
||||
|
||||
|
||||
class TestAlgebraicConnectivity:
|
||||
@pytest.mark.parametrize("method", methods)
|
||||
def test_directed(self, method):
|
||||
G = nx.DiGraph()
|
||||
pytest.raises(
|
||||
nx.NetworkXNotImplemented, nx.algebraic_connectivity, G, method=method
|
||||
)
|
||||
pytest.raises(nx.NetworkXNotImplemented, nx.fiedler_vector, G, method=method)
|
||||
|
||||
@pytest.mark.parametrize("method", methods)
|
||||
def test_null_and_singleton(self, method):
|
||||
G = nx.Graph()
|
||||
pytest.raises(nx.NetworkXError, nx.algebraic_connectivity, G, method=method)
|
||||
pytest.raises(nx.NetworkXError, nx.fiedler_vector, G, method=method)
|
||||
G.add_edge(0, 0)
|
||||
pytest.raises(nx.NetworkXError, nx.algebraic_connectivity, G, method=method)
|
||||
pytest.raises(nx.NetworkXError, nx.fiedler_vector, G, method=method)
|
||||
|
||||
@pytest.mark.parametrize("method", methods)
|
||||
def test_disconnected(self, method):
|
||||
G = nx.Graph()
|
||||
G.add_nodes_from(range(2))
|
||||
assert nx.algebraic_connectivity(G) == 0
|
||||
pytest.raises(nx.NetworkXError, nx.fiedler_vector, G, method=method)
|
||||
G.add_edge(0, 1, weight=0)
|
||||
assert nx.algebraic_connectivity(G) == 0
|
||||
pytest.raises(nx.NetworkXError, nx.fiedler_vector, G, method=method)
|
||||
|
||||
def test_unrecognized_method(self):
|
||||
G = nx.path_graph(4)
|
||||
pytest.raises(nx.NetworkXError, nx.algebraic_connectivity, G, method="unknown")
|
||||
pytest.raises(nx.NetworkXError, nx.fiedler_vector, G, method="unknown")
|
||||
|
||||
@pytest.mark.parametrize("method", methods)
|
||||
def test_two_nodes(self, method):
|
||||
G = nx.Graph()
|
||||
G.add_edge(0, 1, weight=1)
|
||||
A = nx.laplacian_matrix(G)
|
||||
assert almost_equal(nx.algebraic_connectivity(G, tol=1e-12, method=method), 2)
|
||||
x = nx.fiedler_vector(G, tol=1e-12, method=method)
|
||||
check_eigenvector(A, 2, x)
|
||||
|
||||
@pytest.mark.parametrize("method", methods)
|
||||
def test_two_nodes_multigraph(self, method):
|
||||
G = nx.MultiGraph()
|
||||
G.add_edge(0, 0, spam=1e8)
|
||||
G.add_edge(0, 1, spam=1)
|
||||
G.add_edge(0, 1, spam=-2)
|
||||
A = -3 * nx.laplacian_matrix(G, weight="spam")
|
||||
assert almost_equal(
|
||||
nx.algebraic_connectivity(G, weight="spam", tol=1e-12, method=method), 6
|
||||
)
|
||||
x = nx.fiedler_vector(G, weight="spam", tol=1e-12, method=method)
|
||||
check_eigenvector(A, 6, x)
|
||||
|
||||
def test_abbreviation_of_method(self):
|
||||
G = nx.path_graph(8)
|
||||
A = nx.laplacian_matrix(G)
|
||||
sigma = 2 - sqrt(2 + sqrt(2))
|
||||
ac = nx.algebraic_connectivity(G, tol=1e-12, method="tracemin")
|
||||
assert almost_equal(ac, sigma)
|
||||
x = nx.fiedler_vector(G, tol=1e-12, method="tracemin")
|
||||
check_eigenvector(A, sigma, x)
|
||||
|
||||
@pytest.mark.parametrize("method", methods)
|
||||
def test_path(self, method):
|
||||
G = nx.path_graph(8)
|
||||
A = nx.laplacian_matrix(G)
|
||||
sigma = 2 - sqrt(2 + sqrt(2))
|
||||
ac = nx.algebraic_connectivity(G, tol=1e-12, method=method)
|
||||
assert almost_equal(ac, sigma)
|
||||
x = nx.fiedler_vector(G, tol=1e-12, method=method)
|
||||
check_eigenvector(A, sigma, x)
|
||||
|
||||
@pytest.mark.parametrize("method", methods)
|
||||
def test_problematic_graph_issue_2381(self, method):
|
||||
G = nx.path_graph(4)
|
||||
G.add_edges_from([(4, 2), (5, 1)])
|
||||
A = nx.laplacian_matrix(G)
|
||||
sigma = 0.438447187191
|
||||
ac = nx.algebraic_connectivity(G, tol=1e-12, method=method)
|
||||
assert almost_equal(ac, sigma)
|
||||
x = nx.fiedler_vector(G, tol=1e-12, method=method)
|
||||
check_eigenvector(A, sigma, x)
|
||||
|
||||
@pytest.mark.parametrize("method", methods)
|
||||
def test_cycle(self, method):
|
||||
G = nx.cycle_graph(8)
|
||||
A = nx.laplacian_matrix(G)
|
||||
sigma = 2 - sqrt(2)
|
||||
ac = nx.algebraic_connectivity(G, tol=1e-12, method=method)
|
||||
assert almost_equal(ac, sigma)
|
||||
x = nx.fiedler_vector(G, tol=1e-12, method=method)
|
||||
check_eigenvector(A, sigma, x)
|
||||
|
||||
@pytest.mark.parametrize("method", methods)
|
||||
def test_seed_argument(self, method):
|
||||
G = nx.cycle_graph(8)
|
||||
A = nx.laplacian_matrix(G)
|
||||
sigma = 2 - sqrt(2)
|
||||
ac = nx.algebraic_connectivity(G, tol=1e-12, method=method, seed=1)
|
||||
assert almost_equal(ac, sigma)
|
||||
x = nx.fiedler_vector(G, tol=1e-12, method=method, seed=1)
|
||||
check_eigenvector(A, sigma, x)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("normalized", "sigma", "laplacian_fn"),
|
||||
(
|
||||
(False, 0.2434017461399311, nx.laplacian_matrix),
|
||||
(True, 0.08113391537997749, nx.normalized_laplacian_matrix),
|
||||
),
|
||||
)
|
||||
@pytest.mark.parametrize("method", methods)
|
||||
def test_buckminsterfullerene(self, normalized, sigma, laplacian_fn, method):
|
||||
G = nx.Graph(
|
||||
[
|
||||
(1, 10),
|
||||
(1, 41),
|
||||
(1, 59),
|
||||
(2, 12),
|
||||
(2, 42),
|
||||
(2, 60),
|
||||
(3, 6),
|
||||
(3, 43),
|
||||
(3, 57),
|
||||
(4, 8),
|
||||
(4, 44),
|
||||
(4, 58),
|
||||
(5, 13),
|
||||
(5, 56),
|
||||
(5, 57),
|
||||
(6, 10),
|
||||
(6, 31),
|
||||
(7, 14),
|
||||
(7, 56),
|
||||
(7, 58),
|
||||
(8, 12),
|
||||
(8, 32),
|
||||
(9, 23),
|
||||
(9, 53),
|
||||
(9, 59),
|
||||
(10, 15),
|
||||
(11, 24),
|
||||
(11, 53),
|
||||
(11, 60),
|
||||
(12, 16),
|
||||
(13, 14),
|
||||
(13, 25),
|
||||
(14, 26),
|
||||
(15, 27),
|
||||
(15, 49),
|
||||
(16, 28),
|
||||
(16, 50),
|
||||
(17, 18),
|
||||
(17, 19),
|
||||
(17, 54),
|
||||
(18, 20),
|
||||
(18, 55),
|
||||
(19, 23),
|
||||
(19, 41),
|
||||
(20, 24),
|
||||
(20, 42),
|
||||
(21, 31),
|
||||
(21, 33),
|
||||
(21, 57),
|
||||
(22, 32),
|
||||
(22, 34),
|
||||
(22, 58),
|
||||
(23, 24),
|
||||
(25, 35),
|
||||
(25, 43),
|
||||
(26, 36),
|
||||
(26, 44),
|
||||
(27, 51),
|
||||
(27, 59),
|
||||
(28, 52),
|
||||
(28, 60),
|
||||
(29, 33),
|
||||
(29, 34),
|
||||
(29, 56),
|
||||
(30, 51),
|
||||
(30, 52),
|
||||
(30, 53),
|
||||
(31, 47),
|
||||
(32, 48),
|
||||
(33, 45),
|
||||
(34, 46),
|
||||
(35, 36),
|
||||
(35, 37),
|
||||
(36, 38),
|
||||
(37, 39),
|
||||
(37, 49),
|
||||
(38, 40),
|
||||
(38, 50),
|
||||
(39, 40),
|
||||
(39, 51),
|
||||
(40, 52),
|
||||
(41, 47),
|
||||
(42, 48),
|
||||
(43, 49),
|
||||
(44, 50),
|
||||
(45, 46),
|
||||
(45, 54),
|
||||
(46, 55),
|
||||
(47, 54),
|
||||
(48, 55),
|
||||
]
|
||||
)
|
||||
A = laplacian_fn(G)
|
||||
try:
|
||||
assert almost_equal(
|
||||
nx.algebraic_connectivity(
|
||||
G, normalized=normalized, tol=1e-12, method=method
|
||||
),
|
||||
sigma,
|
||||
)
|
||||
x = nx.fiedler_vector(G, normalized=normalized, tol=1e-12, method=method)
|
||||
check_eigenvector(A, sigma, x)
|
||||
except nx.NetworkXError as e:
|
||||
if e.args not in (
|
||||
("Cholesky solver unavailable.",),
|
||||
("LU solver unavailable.",),
|
||||
):
|
||||
raise
|
||||
|
||||
|
||||
class TestSpectralOrdering:
|
||||
_graphs = (nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph)
|
||||
|
||||
@pytest.mark.parametrize("graph", _graphs)
|
||||
def test_nullgraph(self, graph):
|
||||
G = graph()
|
||||
pytest.raises(nx.NetworkXError, nx.spectral_ordering, G)
|
||||
|
||||
@pytest.mark.parametrize("graph", _graphs)
|
||||
def test_singleton(self, graph):
|
||||
G = graph()
|
||||
G.add_node("x")
|
||||
assert nx.spectral_ordering(G) == ["x"]
|
||||
G.add_edge("x", "x", weight=33)
|
||||
G.add_edge("x", "x", weight=33)
|
||||
assert nx.spectral_ordering(G) == ["x"]
|
||||
|
||||
def test_unrecognized_method(self):
|
||||
G = nx.path_graph(4)
|
||||
pytest.raises(nx.NetworkXError, nx.spectral_ordering, G, method="unknown")
|
||||
|
||||
@pytest.mark.parametrize("method", methods)
|
||||
def test_three_nodes(self, method):
|
||||
G = nx.Graph()
|
||||
G.add_weighted_edges_from([(1, 2, 1), (1, 3, 2), (2, 3, 1)], weight="spam")
|
||||
order = nx.spectral_ordering(G, weight="spam", method=method)
|
||||
assert set(order) == set(G)
|
||||
assert {1, 3} in (set(order[:-1]), set(order[1:]))
|
||||
|
||||
@pytest.mark.parametrize("method", methods)
|
||||
def test_three_nodes_multigraph(self, method):
|
||||
G = nx.MultiDiGraph()
|
||||
G.add_weighted_edges_from([(1, 2, 1), (1, 3, 2), (2, 3, 1), (2, 3, 2)])
|
||||
order = nx.spectral_ordering(G, method=method)
|
||||
assert set(order) == set(G)
|
||||
assert {2, 3} in (set(order[:-1]), set(order[1:]))
|
||||
|
||||
@pytest.mark.parametrize("method", methods)
|
||||
def test_path(self, method):
|
||||
# based on setup_class numpy is installed if we get here
|
||||
from numpy.random import shuffle
|
||||
|
||||
path = list(range(10))
|
||||
shuffle(path)
|
||||
G = nx.Graph()
|
||||
nx.add_path(G, path)
|
||||
order = nx.spectral_ordering(G, method=method)
|
||||
assert order in [path, list(reversed(path))]
|
||||
|
||||
@pytest.mark.parametrize("method", methods)
|
||||
def test_seed_argument(self, method):
|
||||
# based on setup_class numpy is installed if we get here
|
||||
from numpy.random import shuffle
|
||||
|
||||
path = list(range(10))
|
||||
shuffle(path)
|
||||
G = nx.Graph()
|
||||
nx.add_path(G, path)
|
||||
order = nx.spectral_ordering(G, method=method, seed=1)
|
||||
assert order in [path, list(reversed(path))]
|
||||
|
||||
@pytest.mark.parametrize("method", methods)
|
||||
def test_disconnected(self, method):
|
||||
G = nx.Graph()
|
||||
nx.add_path(G, range(0, 10, 2))
|
||||
nx.add_path(G, range(1, 10, 2))
|
||||
order = nx.spectral_ordering(G, method=method)
|
||||
assert set(order) == set(G)
|
||||
seqs = [
|
||||
list(range(0, 10, 2)),
|
||||
list(range(8, -1, -2)),
|
||||
list(range(1, 10, 2)),
|
||||
list(range(9, -1, -2)),
|
||||
]
|
||||
assert order[:5] in seqs
|
||||
assert order[5:] in seqs
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("normalized", "expected_order"),
|
||||
(
|
||||
(False, [[1, 2, 0, 3, 4, 5, 6, 9, 7, 8], [8, 7, 9, 6, 5, 4, 3, 0, 2, 1]]),
|
||||
(True, [[1, 2, 3, 0, 4, 5, 9, 6, 7, 8], [8, 7, 6, 9, 5, 4, 0, 3, 2, 1]]),
|
||||
),
|
||||
)
|
||||
@pytest.mark.parametrize("method", methods)
|
||||
def test_cycle(self, normalized, expected_order, method):
|
||||
path = list(range(10))
|
||||
G = nx.Graph()
|
||||
nx.add_path(G, path, weight=5)
|
||||
G.add_edge(path[-1], path[0], weight=1)
|
||||
A = nx.laplacian_matrix(G).todense()
|
||||
try:
|
||||
order = nx.spectral_ordering(G, normalized=normalized, method=method)
|
||||
except nx.NetworkXError as e:
|
||||
if e.args not in (
|
||||
("Cholesky solver unavailable.",),
|
||||
("LU solver unavailable.",),
|
||||
):
|
||||
raise
|
||||
else:
|
||||
assert order in expected_order
|
108
venv/Lib/site-packages/networkx/linalg/tests/test_attrmatrix.py
Normal file
108
venv/Lib/site-packages/networkx/linalg/tests/test_attrmatrix.py
Normal file
|
@ -0,0 +1,108 @@
|
|||
import pytest
|
||||
|
||||
np = pytest.importorskip("numpy")
|
||||
import numpy.testing as npt
|
||||
|
||||
import networkx as nx
|
||||
|
||||
|
||||
def test_attr_matrix():
|
||||
G = nx.Graph()
|
||||
G.add_edge(0, 1, thickness=1, weight=3)
|
||||
G.add_edge(0, 1, thickness=1, weight=3)
|
||||
G.add_edge(0, 2, thickness=2)
|
||||
G.add_edge(1, 2, thickness=3)
|
||||
|
||||
def node_attr(u):
|
||||
return G.nodes[u].get("size", 0.5) * 3
|
||||
|
||||
def edge_attr(u, v):
|
||||
return G[u][v].get("thickness", 0.5)
|
||||
|
||||
M = nx.attr_matrix(G, edge_attr=edge_attr, node_attr=node_attr)
|
||||
npt.assert_equal(M[0], np.array([[6.0]]))
|
||||
assert M[1] == [1.5]
|
||||
|
||||
|
||||
def test_attr_matrix_directed():
|
||||
G = nx.DiGraph()
|
||||
G.add_edge(0, 1, thickness=1, weight=3)
|
||||
G.add_edge(0, 1, thickness=1, weight=3)
|
||||
G.add_edge(0, 2, thickness=2)
|
||||
G.add_edge(1, 2, thickness=3)
|
||||
M = nx.attr_matrix(G, rc_order=[0, 1, 2])
|
||||
# fmt: off
|
||||
data = np.array(
|
||||
[[0., 1., 1.],
|
||||
[0., 0., 1.],
|
||||
[0., 0., 0.]]
|
||||
)
|
||||
# fmt: on
|
||||
npt.assert_equal(M, np.array(data))
|
||||
|
||||
|
||||
def test_attr_matrix_multigraph():
|
||||
G = nx.MultiGraph()
|
||||
G.add_edge(0, 1, thickness=1, weight=3)
|
||||
G.add_edge(0, 1, thickness=1, weight=3)
|
||||
G.add_edge(0, 1, thickness=1, weight=3)
|
||||
G.add_edge(0, 2, thickness=2)
|
||||
G.add_edge(1, 2, thickness=3)
|
||||
M = nx.attr_matrix(G, rc_order=[0, 1, 2])
|
||||
# fmt: off
|
||||
data = np.array(
|
||||
[[0., 3., 1.],
|
||||
[3., 0., 1.],
|
||||
[1., 1., 0.]]
|
||||
)
|
||||
# fmt: on
|
||||
npt.assert_equal(M, np.array(data))
|
||||
M = nx.attr_matrix(G, edge_attr="weight", rc_order=[0, 1, 2])
|
||||
# fmt: off
|
||||
data = np.array(
|
||||
[[0., 9., 1.],
|
||||
[9., 0., 1.],
|
||||
[1., 1., 0.]]
|
||||
)
|
||||
# fmt: on
|
||||
npt.assert_equal(M, np.array(data))
|
||||
M = nx.attr_matrix(G, edge_attr="thickness", rc_order=[0, 1, 2])
|
||||
# fmt: off
|
||||
data = np.array(
|
||||
[[0., 3., 2.],
|
||||
[3., 0., 3.],
|
||||
[2., 3., 0.]]
|
||||
)
|
||||
# fmt: on
|
||||
npt.assert_equal(M, np.array(data))
|
||||
|
||||
|
||||
def test_attr_sparse_matrix():
|
||||
pytest.importorskip("scipy")
|
||||
G = nx.Graph()
|
||||
G.add_edge(0, 1, thickness=1, weight=3)
|
||||
G.add_edge(0, 2, thickness=2)
|
||||
G.add_edge(1, 2, thickness=3)
|
||||
M = nx.attr_sparse_matrix(G)
|
||||
mtx = M[0]
|
||||
data = np.ones((3, 3), float)
|
||||
np.fill_diagonal(data, 0)
|
||||
npt.assert_equal(mtx.todense(), np.array(data))
|
||||
assert M[1] == [0, 1, 2]
|
||||
|
||||
|
||||
def test_attr_sparse_matrix_directed():
|
||||
G = nx.DiGraph()
|
||||
G.add_edge(0, 1, thickness=1, weight=3)
|
||||
G.add_edge(0, 1, thickness=1, weight=3)
|
||||
G.add_edge(0, 2, thickness=2)
|
||||
G.add_edge(1, 2, thickness=3)
|
||||
M = nx.attr_sparse_matrix(G, rc_order=[0, 1, 2])
|
||||
# fmt: off
|
||||
data = np.array(
|
||||
[[0., 1., 1.],
|
||||
[0., 0., 1.],
|
||||
[0., 0., 0.]]
|
||||
)
|
||||
# fmt: on
|
||||
npt.assert_equal(M.todense(), np.array(data))
|
|
@ -0,0 +1,42 @@
|
|||
import pytest
|
||||
|
||||
np = pytest.importorskip("numpy")
|
||||
npt = pytest.importorskip("numpy.testing")
|
||||
sp = pytest.importorskip("scipy")
|
||||
|
||||
import networkx as nx
|
||||
from networkx.generators.degree_seq import havel_hakimi_graph
|
||||
|
||||
|
||||
class TestBetheHessian:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
deg = [3, 2, 2, 1, 0]
|
||||
cls.G = havel_hakimi_graph(deg)
|
||||
cls.P = nx.path_graph(3)
|
||||
|
||||
def test_bethe_hessian(self):
|
||||
"Bethe Hessian matrix"
|
||||
# fmt: off
|
||||
H = np.array([[4, -2, 0],
|
||||
[-2, 5, -2],
|
||||
[0, -2, 4]])
|
||||
# fmt: on
|
||||
permutation = [2, 0, 1]
|
||||
# Bethe Hessian gives expected form
|
||||
npt.assert_equal(nx.bethe_hessian_matrix(self.P, r=2).todense(), H)
|
||||
# nodelist is correctly implemented
|
||||
npt.assert_equal(
|
||||
nx.bethe_hessian_matrix(self.P, r=2, nodelist=permutation).todense(),
|
||||
H[np.ix_(permutation, permutation)],
|
||||
)
|
||||
# Equal to Laplacian matrix when r=1
|
||||
npt.assert_equal(
|
||||
nx.bethe_hessian_matrix(self.G, r=1).todense(),
|
||||
nx.laplacian_matrix(self.G).todense(),
|
||||
)
|
||||
# Correct default for the regularizer r
|
||||
npt.assert_equal(
|
||||
nx.bethe_hessian_matrix(self.G).todense(),
|
||||
nx.bethe_hessian_matrix(self.G, r=1.25).todense(),
|
||||
)
|
293
venv/Lib/site-packages/networkx/linalg/tests/test_graphmatrix.py
Normal file
293
venv/Lib/site-packages/networkx/linalg/tests/test_graphmatrix.py
Normal file
|
@ -0,0 +1,293 @@
|
|||
import pytest
|
||||
|
||||
np = pytest.importorskip("numpy")
|
||||
npt = pytest.importorskip("numpy.testing")
|
||||
scipy = pytest.importorskip("scipy")
|
||||
|
||||
import networkx as nx
|
||||
from networkx.generators.degree_seq import havel_hakimi_graph
|
||||
from networkx.exception import NetworkXError
|
||||
|
||||
|
||||
def test_incidence_matrix_simple():
|
||||
deg = [3, 2, 2, 1, 0]
|
||||
G = havel_hakimi_graph(deg)
|
||||
deg = [(1, 0), (1, 0), (1, 0), (2, 0), (1, 0), (2, 1), (0, 1), (0, 1)]
|
||||
MG = nx.random_clustered_graph(deg, seed=42)
|
||||
|
||||
I = nx.incidence_matrix(G).todense().astype(int)
|
||||
# fmt: off
|
||||
expected = np.array(
|
||||
[[1, 1, 1, 0],
|
||||
[0, 1, 0, 1],
|
||||
[1, 0, 0, 1],
|
||||
[0, 0, 1, 0],
|
||||
[0, 0, 0, 0]]
|
||||
)
|
||||
# fmt: on
|
||||
npt.assert_equal(I, expected)
|
||||
|
||||
I = nx.incidence_matrix(MG).todense().astype(int)
|
||||
# fmt: off
|
||||
expected = np.array(
|
||||
[[1, 0, 0, 0, 0, 0, 0],
|
||||
[1, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 1, 1, 0],
|
||||
[0, 0, 0, 0, 0, 1, 1],
|
||||
[0, 0, 0, 0, 1, 0, 1]]
|
||||
)
|
||||
# fmt: on
|
||||
npt.assert_equal(I, expected)
|
||||
|
||||
with pytest.raises(NetworkXError):
|
||||
nx.incidence_matrix(G, nodelist=[0, 1])
|
||||
|
||||
|
||||
class TestGraphMatrix:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
deg = [3, 2, 2, 1, 0]
|
||||
cls.G = havel_hakimi_graph(deg)
|
||||
# fmt: off
|
||||
cls.OI = np.array(
|
||||
[[-1, -1, -1, 0],
|
||||
[1, 0, 0, -1],
|
||||
[0, 1, 0, 1],
|
||||
[0, 0, 1, 0],
|
||||
[0, 0, 0, 0]]
|
||||
)
|
||||
cls.A = np.array(
|
||||
[[0, 1, 1, 1, 0],
|
||||
[1, 0, 1, 0, 0],
|
||||
[1, 1, 0, 0, 0],
|
||||
[1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0]]
|
||||
)
|
||||
# fmt: on
|
||||
cls.WG = havel_hakimi_graph(deg)
|
||||
cls.WG.add_edges_from(
|
||||
(u, v, {"weight": 0.5, "other": 0.3}) for (u, v) in cls.G.edges()
|
||||
)
|
||||
# fmt: off
|
||||
cls.WA = np.array(
|
||||
[[0, 0.5, 0.5, 0.5, 0],
|
||||
[0.5, 0, 0.5, 0, 0],
|
||||
[0.5, 0.5, 0, 0, 0],
|
||||
[0.5, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0]]
|
||||
)
|
||||
# fmt: on
|
||||
cls.MG = nx.MultiGraph(cls.G)
|
||||
cls.MG2 = cls.MG.copy()
|
||||
cls.MG2.add_edge(0, 1)
|
||||
# fmt: off
|
||||
cls.MG2A = np.array(
|
||||
[[0, 2, 1, 1, 0],
|
||||
[2, 0, 1, 0, 0],
|
||||
[1, 1, 0, 0, 0],
|
||||
[1, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0]]
|
||||
)
|
||||
cls.MGOI = np.array(
|
||||
[[-1, -1, -1, -1, 0],
|
||||
[1, 1, 0, 0, -1],
|
||||
[0, 0, 1, 0, 1],
|
||||
[0, 0, 0, 1, 0],
|
||||
[0, 0, 0, 0, 0]]
|
||||
)
|
||||
# fmt: on
|
||||
cls.no_edges_G = nx.Graph([(1, 2), (3, 2, {"weight": 8})])
|
||||
cls.no_edges_A = np.array([[0, 0], [0, 0]])
|
||||
|
||||
def test_incidence_matrix(self):
|
||||
"Conversion to incidence matrix"
|
||||
I = (
|
||||
nx.incidence_matrix(
|
||||
self.G,
|
||||
nodelist=sorted(self.G),
|
||||
edgelist=sorted(self.G.edges()),
|
||||
oriented=True,
|
||||
)
|
||||
.todense()
|
||||
.astype(int)
|
||||
)
|
||||
npt.assert_equal(I, self.OI)
|
||||
|
||||
I = (
|
||||
nx.incidence_matrix(
|
||||
self.G,
|
||||
nodelist=sorted(self.G),
|
||||
edgelist=sorted(self.G.edges()),
|
||||
oriented=False,
|
||||
)
|
||||
.todense()
|
||||
.astype(int)
|
||||
)
|
||||
npt.assert_equal(I, np.abs(self.OI))
|
||||
|
||||
I = (
|
||||
nx.incidence_matrix(
|
||||
self.MG,
|
||||
nodelist=sorted(self.MG),
|
||||
edgelist=sorted(self.MG.edges()),
|
||||
oriented=True,
|
||||
)
|
||||
.todense()
|
||||
.astype(int)
|
||||
)
|
||||
npt.assert_equal(I, self.OI)
|
||||
|
||||
I = (
|
||||
nx.incidence_matrix(
|
||||
self.MG,
|
||||
nodelist=sorted(self.MG),
|
||||
edgelist=sorted(self.MG.edges()),
|
||||
oriented=False,
|
||||
)
|
||||
.todense()
|
||||
.astype(int)
|
||||
)
|
||||
npt.assert_equal(I, np.abs(self.OI))
|
||||
|
||||
I = (
|
||||
nx.incidence_matrix(
|
||||
self.MG2,
|
||||
nodelist=sorted(self.MG2),
|
||||
edgelist=sorted(self.MG2.edges()),
|
||||
oriented=True,
|
||||
)
|
||||
.todense()
|
||||
.astype(int)
|
||||
)
|
||||
npt.assert_equal(I, self.MGOI)
|
||||
|
||||
I = (
|
||||
nx.incidence_matrix(
|
||||
self.MG2,
|
||||
nodelist=sorted(self.MG),
|
||||
edgelist=sorted(self.MG2.edges()),
|
||||
oriented=False,
|
||||
)
|
||||
.todense()
|
||||
.astype(int)
|
||||
)
|
||||
npt.assert_equal(I, np.abs(self.MGOI))
|
||||
|
||||
def test_weighted_incidence_matrix(self):
|
||||
I = (
|
||||
nx.incidence_matrix(
|
||||
self.WG,
|
||||
nodelist=sorted(self.WG),
|
||||
edgelist=sorted(self.WG.edges()),
|
||||
oriented=True,
|
||||
)
|
||||
.todense()
|
||||
.astype(int)
|
||||
)
|
||||
npt.assert_equal(I, self.OI)
|
||||
|
||||
I = (
|
||||
nx.incidence_matrix(
|
||||
self.WG,
|
||||
nodelist=sorted(self.WG),
|
||||
edgelist=sorted(self.WG.edges()),
|
||||
oriented=False,
|
||||
)
|
||||
.todense()
|
||||
.astype(int)
|
||||
)
|
||||
npt.assert_equal(I, np.abs(self.OI))
|
||||
|
||||
# npt.assert_equal(nx.incidence_matrix(self.WG,oriented=True,
|
||||
# weight='weight').todense(),0.5*self.OI)
|
||||
# npt.assert_equal(nx.incidence_matrix(self.WG,weight='weight').todense(),
|
||||
# np.abs(0.5*self.OI))
|
||||
# npt.assert_equal(nx.incidence_matrix(self.WG,oriented=True,weight='other').todense(),
|
||||
# 0.3*self.OI)
|
||||
|
||||
I = nx.incidence_matrix(
|
||||
self.WG,
|
||||
nodelist=sorted(self.WG),
|
||||
edgelist=sorted(self.WG.edges()),
|
||||
oriented=True,
|
||||
weight="weight",
|
||||
).todense()
|
||||
npt.assert_equal(I, 0.5 * self.OI)
|
||||
|
||||
I = nx.incidence_matrix(
|
||||
self.WG,
|
||||
nodelist=sorted(self.WG),
|
||||
edgelist=sorted(self.WG.edges()),
|
||||
oriented=False,
|
||||
weight="weight",
|
||||
).todense()
|
||||
npt.assert_equal(I, np.abs(0.5 * self.OI))
|
||||
|
||||
I = nx.incidence_matrix(
|
||||
self.WG,
|
||||
nodelist=sorted(self.WG),
|
||||
edgelist=sorted(self.WG.edges()),
|
||||
oriented=True,
|
||||
weight="other",
|
||||
).todense()
|
||||
npt.assert_equal(I, 0.3 * self.OI)
|
||||
|
||||
# WMG=nx.MultiGraph(self.WG)
|
||||
# WMG.add_edge(0,1,weight=0.5,other=0.3)
|
||||
# npt.assert_equal(nx.incidence_matrix(WMG,weight='weight').todense(),
|
||||
# np.abs(0.5*self.MGOI))
|
||||
# npt.assert_equal(nx.incidence_matrix(WMG,weight='weight',oriented=True).todense(),
|
||||
# 0.5*self.MGOI)
|
||||
# npt.assert_equal(nx.incidence_matrix(WMG,weight='other',oriented=True).todense(),
|
||||
# 0.3*self.MGOI)
|
||||
|
||||
WMG = nx.MultiGraph(self.WG)
|
||||
WMG.add_edge(0, 1, weight=0.5, other=0.3)
|
||||
|
||||
I = nx.incidence_matrix(
|
||||
WMG,
|
||||
nodelist=sorted(WMG),
|
||||
edgelist=sorted(WMG.edges(keys=True)),
|
||||
oriented=True,
|
||||
weight="weight",
|
||||
).todense()
|
||||
npt.assert_equal(I, 0.5 * self.MGOI)
|
||||
|
||||
I = nx.incidence_matrix(
|
||||
WMG,
|
||||
nodelist=sorted(WMG),
|
||||
edgelist=sorted(WMG.edges(keys=True)),
|
||||
oriented=False,
|
||||
weight="weight",
|
||||
).todense()
|
||||
npt.assert_equal(I, np.abs(0.5 * self.MGOI))
|
||||
|
||||
I = nx.incidence_matrix(
|
||||
WMG,
|
||||
nodelist=sorted(WMG),
|
||||
edgelist=sorted(WMG.edges(keys=True)),
|
||||
oriented=True,
|
||||
weight="other",
|
||||
).todense()
|
||||
npt.assert_equal(I, 0.3 * self.MGOI)
|
||||
|
||||
def test_adjacency_matrix(self):
|
||||
"Conversion to adjacency matrix"
|
||||
npt.assert_equal(nx.adj_matrix(self.G).todense(), self.A)
|
||||
npt.assert_equal(nx.adj_matrix(self.MG).todense(), self.A)
|
||||
npt.assert_equal(nx.adj_matrix(self.MG2).todense(), self.MG2A)
|
||||
npt.assert_equal(
|
||||
nx.adj_matrix(self.G, nodelist=[0, 1]).todense(), self.A[:2, :2]
|
||||
)
|
||||
npt.assert_equal(nx.adj_matrix(self.WG).todense(), self.WA)
|
||||
npt.assert_equal(nx.adj_matrix(self.WG, weight=None).todense(), self.A)
|
||||
npt.assert_equal(nx.adj_matrix(self.MG2, weight=None).todense(), self.MG2A)
|
||||
npt.assert_equal(
|
||||
nx.adj_matrix(self.WG, weight="other").todense(), 0.6 * self.WA
|
||||
)
|
||||
npt.assert_equal(
|
||||
nx.adj_matrix(self.no_edges_G, nodelist=[1, 3]).todense(), self.no_edges_A
|
||||
)
|
231
venv/Lib/site-packages/networkx/linalg/tests/test_laplacian.py
Normal file
231
venv/Lib/site-packages/networkx/linalg/tests/test_laplacian.py
Normal file
|
@ -0,0 +1,231 @@
|
|||
import pytest
|
||||
|
||||
np = pytest.importorskip("numpy")
|
||||
npt = pytest.importorskip("numpy.testing")
|
||||
pytest.importorskip("scipy")
|
||||
|
||||
import networkx as nx
|
||||
from networkx.generators.degree_seq import havel_hakimi_graph
|
||||
from networkx.generators.expanders import margulis_gabber_galil_graph
|
||||
|
||||
|
||||
class TestLaplacian:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
deg = [3, 2, 2, 1, 0]
|
||||
cls.G = havel_hakimi_graph(deg)
|
||||
cls.WG = nx.Graph(
|
||||
(u, v, {"weight": 0.5, "other": 0.3}) for (u, v) in cls.G.edges()
|
||||
)
|
||||
cls.WG.add_node(4)
|
||||
cls.MG = nx.MultiGraph(cls.G)
|
||||
|
||||
# Graph with clsloops
|
||||
cls.Gsl = cls.G.copy()
|
||||
for node in cls.Gsl.nodes():
|
||||
cls.Gsl.add_edge(node, node)
|
||||
|
||||
def test_laplacian(self):
|
||||
"Graph Laplacian"
|
||||
# fmt: off
|
||||
NL = np.array([[3, -1, -1, -1, 0],
|
||||
[-1, 2, -1, 0, 0],
|
||||
[-1, -1, 2, 0, 0],
|
||||
[-1, 0, 0, 1, 0],
|
||||
[0, 0, 0, 0, 0]])
|
||||
# fmt: on
|
||||
WL = 0.5 * NL
|
||||
OL = 0.3 * NL
|
||||
npt.assert_equal(nx.laplacian_matrix(self.G).todense(), NL)
|
||||
npt.assert_equal(nx.laplacian_matrix(self.MG).todense(), NL)
|
||||
npt.assert_equal(
|
||||
nx.laplacian_matrix(self.G, nodelist=[0, 1]).todense(),
|
||||
np.array([[1, -1], [-1, 1]]),
|
||||
)
|
||||
npt.assert_equal(nx.laplacian_matrix(self.WG).todense(), WL)
|
||||
npt.assert_equal(nx.laplacian_matrix(self.WG, weight=None).todense(), NL)
|
||||
npt.assert_equal(nx.laplacian_matrix(self.WG, weight="other").todense(), OL)
|
||||
|
||||
def test_normalized_laplacian(self):
|
||||
"Generalized Graph Laplacian"
|
||||
# fmt: off
|
||||
G = np.array([[ 1. , -0.408, -0.408, -0.577, 0.],
|
||||
[-0.408, 1. , -0.5 , 0. , 0.],
|
||||
[-0.408, -0.5 , 1. , 0. , 0.],
|
||||
[-0.577, 0. , 0. , 1. , 0.],
|
||||
[ 0. , 0. , 0. , 0. , 0.]])
|
||||
GL = np.array([[1.00, -0.408, -0.408, -0.577, 0.00],
|
||||
[-0.408, 1.00, -0.50, 0.00, 0.00],
|
||||
[-0.408, -0.50, 1.00, 0.00, 0.00],
|
||||
[-0.577, 0.00, 0.00, 1.00, 0.00],
|
||||
[0.00, 0.00, 0.00, 0.00, 0.00]])
|
||||
Lsl = np.array([[0.75, -0.2887, -0.2887, -0.3536, 0.],
|
||||
[-0.2887, 0.6667, -0.3333, 0., 0.],
|
||||
[-0.2887, -0.3333, 0.6667, 0., 0.],
|
||||
[-0.3536, 0., 0., 0.5, 0.],
|
||||
[0., 0., 0., 0., 0.]])
|
||||
# fmt: on
|
||||
|
||||
npt.assert_almost_equal(
|
||||
nx.normalized_laplacian_matrix(self.G, nodelist=range(5)).todense(),
|
||||
G,
|
||||
decimal=3,
|
||||
)
|
||||
npt.assert_almost_equal(
|
||||
nx.normalized_laplacian_matrix(self.G).todense(), GL, decimal=3
|
||||
)
|
||||
npt.assert_almost_equal(
|
||||
nx.normalized_laplacian_matrix(self.MG).todense(), GL, decimal=3
|
||||
)
|
||||
npt.assert_almost_equal(
|
||||
nx.normalized_laplacian_matrix(self.WG).todense(), GL, decimal=3
|
||||
)
|
||||
npt.assert_almost_equal(
|
||||
nx.normalized_laplacian_matrix(self.WG, weight="other").todense(),
|
||||
GL,
|
||||
decimal=3,
|
||||
)
|
||||
npt.assert_almost_equal(
|
||||
nx.normalized_laplacian_matrix(self.Gsl).todense(), Lsl, decimal=3
|
||||
)
|
||||
|
||||
def test_directed_laplacian(self):
|
||||
"Directed Laplacian"
|
||||
# Graph used as an example in Sec. 4.1 of Langville and Meyer,
|
||||
# "Google's PageRank and Beyond". The graph contains dangling nodes, so
|
||||
# the pagerank random walk is selected by directed_laplacian
|
||||
G = nx.DiGraph()
|
||||
G.add_edges_from(
|
||||
(
|
||||
(1, 2),
|
||||
(1, 3),
|
||||
(3, 1),
|
||||
(3, 2),
|
||||
(3, 5),
|
||||
(4, 5),
|
||||
(4, 6),
|
||||
(5, 4),
|
||||
(5, 6),
|
||||
(6, 4),
|
||||
)
|
||||
)
|
||||
# fmt: off
|
||||
GL = np.array([[0.9833, -0.2941, -0.3882, -0.0291, -0.0231, -0.0261],
|
||||
[-0.2941, 0.8333, -0.2339, -0.0536, -0.0589, -0.0554],
|
||||
[-0.3882, -0.2339, 0.9833, -0.0278, -0.0896, -0.0251],
|
||||
[-0.0291, -0.0536, -0.0278, 0.9833, -0.4878, -0.6675],
|
||||
[-0.0231, -0.0589, -0.0896, -0.4878, 0.9833, -0.2078],
|
||||
[-0.0261, -0.0554, -0.0251, -0.6675, -0.2078, 0.9833]])
|
||||
# fmt: on
|
||||
L = nx.directed_laplacian_matrix(G, alpha=0.9, nodelist=sorted(G))
|
||||
npt.assert_almost_equal(L, GL, decimal=3)
|
||||
|
||||
# Make the graph strongly connected, so we can use a random and lazy walk
|
||||
G.add_edges_from(((2, 5), (6, 1)))
|
||||
# fmt: off
|
||||
GL = np.array([[1., -0.3062, -0.4714, 0., 0., -0.3227],
|
||||
[-0.3062, 1., -0.1443, 0., -0.3162, 0.],
|
||||
[-0.4714, -0.1443, 1., 0., -0.0913, 0.],
|
||||
[0., 0., 0., 1., -0.5, -0.5],
|
||||
[0., -0.3162, -0.0913, -0.5, 1., -0.25],
|
||||
[-0.3227, 0., 0., -0.5, -0.25, 1.]])
|
||||
# fmt: on
|
||||
L = nx.directed_laplacian_matrix(
|
||||
G, alpha=0.9, nodelist=sorted(G), walk_type="random"
|
||||
)
|
||||
npt.assert_almost_equal(L, GL, decimal=3)
|
||||
|
||||
# fmt: off
|
||||
GL = np.array([[0.5, -0.1531, -0.2357, 0., 0., -0.1614],
|
||||
[-0.1531, 0.5, -0.0722, 0., -0.1581, 0.],
|
||||
[-0.2357, -0.0722, 0.5, 0., -0.0456, 0.],
|
||||
[0., 0., 0., 0.5, -0.25, -0.25],
|
||||
[0., -0.1581, -0.0456, -0.25, 0.5, -0.125],
|
||||
[-0.1614, 0., 0., -0.25, -0.125, 0.5]])
|
||||
# fmt: on
|
||||
L = nx.directed_laplacian_matrix(
|
||||
G, alpha=0.9, nodelist=sorted(G), walk_type="lazy"
|
||||
)
|
||||
npt.assert_almost_equal(L, GL, decimal=3)
|
||||
|
||||
def test_directed_combinatorial_laplacian(self):
|
||||
"Directed combinatorial Laplacian"
|
||||
# Graph used as an example in Sec. 4.1 of Langville and Meyer,
|
||||
# "Google's PageRank and Beyond". The graph contains dangling nodes, so
|
||||
# the pagerank random walk is selected by directed_laplacian
|
||||
G = nx.DiGraph()
|
||||
G.add_edges_from(
|
||||
(
|
||||
(1, 2),
|
||||
(1, 3),
|
||||
(3, 1),
|
||||
(3, 2),
|
||||
(3, 5),
|
||||
(4, 5),
|
||||
(4, 6),
|
||||
(5, 4),
|
||||
(5, 6),
|
||||
(6, 4),
|
||||
)
|
||||
)
|
||||
# fmt: off
|
||||
GL = np.array([[0.0366, -0.0132, -0.0153, -0.0034, -0.0020, -0.0027],
|
||||
[-0.0132, 0.0450, -0.0111, -0.0076, -0.0062, -0.0069],
|
||||
[-0.0153, -0.0111, 0.0408, -0.0035, -0.0083, -0.0027],
|
||||
[-0.0034, -0.0076, -0.0035, 0.3688, -0.1356, -0.2187],
|
||||
[-0.0020, -0.0062, -0.0083, -0.1356, 0.2026, -0.0505],
|
||||
[-0.0027, -0.0069, -0.0027, -0.2187, -0.0505, 0.2815]])
|
||||
# fmt: on
|
||||
|
||||
L = nx.directed_combinatorial_laplacian_matrix(G, alpha=0.9, nodelist=sorted(G))
|
||||
npt.assert_almost_equal(L, GL, decimal=3)
|
||||
|
||||
# Make the graph strongly connected, so we can use a random and lazy walk
|
||||
G.add_edges_from(((2, 5), (6, 1)))
|
||||
|
||||
# fmt: off
|
||||
GL = np.array([[0.1395, -0.0349, -0.0465, 0, 0, -0.0581],
|
||||
[-0.0349, 0.0930, -0.0116, 0, -0.0465, 0],
|
||||
[-0.0465, -0.0116, 0.0698, 0, -0.0116, 0],
|
||||
[0, 0, 0, 0.2326, -0.1163, -0.1163],
|
||||
[0, -0.0465, -0.0116, -0.1163, 0.2326, -0.0581],
|
||||
[-0.0581, 0, 0, -0.1163, -0.0581, 0.2326]])
|
||||
# fmt: on
|
||||
|
||||
L = nx.directed_combinatorial_laplacian_matrix(
|
||||
G, alpha=0.9, nodelist=sorted(G), walk_type="random"
|
||||
)
|
||||
npt.assert_almost_equal(L, GL, decimal=3)
|
||||
|
||||
# fmt: off
|
||||
GL = np.array([[0.0698, -0.0174, -0.0233, 0, 0, -0.0291],
|
||||
[-0.0174, 0.0465, -0.0058, 0, -0.0233, 0],
|
||||
[-0.0233, -0.0058, 0.0349, 0, -0.0058, 0],
|
||||
[0, 0, 0, 0.1163, -0.0581, -0.0581],
|
||||
[0, -0.0233, -0.0058, -0.0581, 0.1163, -0.0291],
|
||||
[-0.0291, 0, 0, -0.0581, -0.0291, 0.1163]])
|
||||
# fmt: on
|
||||
|
||||
L = nx.directed_combinatorial_laplacian_matrix(
|
||||
G, alpha=0.9, nodelist=sorted(G), walk_type="lazy"
|
||||
)
|
||||
npt.assert_almost_equal(L, GL, decimal=3)
|
||||
|
||||
E = nx.DiGraph(margulis_gabber_galil_graph(2))
|
||||
L = nx.directed_combinatorial_laplacian_matrix(E)
|
||||
# fmt: off
|
||||
expected = np.array(
|
||||
[[ 0.16666667, -0.08333333, -0.08333333, 0. ],
|
||||
[-0.08333333, 0.16666667, 0. , -0.08333333],
|
||||
[-0.08333333, 0. , 0.16666667, -0.08333333],
|
||||
[ 0. , -0.08333333, -0.08333333, 0.16666667]]
|
||||
)
|
||||
# fmt: on
|
||||
npt.assert_almost_equal(L, expected, decimal=6)
|
||||
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
nx.directed_combinatorial_laplacian_matrix(
|
||||
G, walk_type="pagerank", alpha=100
|
||||
)
|
||||
with pytest.raises(nx.NetworkXError):
|
||||
nx.directed_combinatorial_laplacian_matrix(G, walk_type="silly")
|
|
@ -0,0 +1,86 @@
|
|||
import pytest
|
||||
|
||||
np = pytest.importorskip("numpy")
|
||||
npt = pytest.importorskip("numpy.testing")
|
||||
scipy = pytest.importorskip("scipy")
|
||||
|
||||
import networkx as nx
|
||||
from networkx.generators.degree_seq import havel_hakimi_graph
|
||||
|
||||
|
||||
class TestModularity:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
deg = [3, 2, 2, 1, 0]
|
||||
cls.G = havel_hakimi_graph(deg)
|
||||
# Graph used as an example in Sec. 4.1 of Langville and Meyer,
|
||||
# "Google's PageRank and Beyond". (Used for test_directed_laplacian)
|
||||
cls.DG = nx.DiGraph()
|
||||
cls.DG.add_edges_from(
|
||||
(
|
||||
(1, 2),
|
||||
(1, 3),
|
||||
(3, 1),
|
||||
(3, 2),
|
||||
(3, 5),
|
||||
(4, 5),
|
||||
(4, 6),
|
||||
(5, 4),
|
||||
(5, 6),
|
||||
(6, 4),
|
||||
)
|
||||
)
|
||||
|
||||
def test_modularity(self):
|
||||
"Modularity matrix"
|
||||
# fmt: off
|
||||
B = np.array([[-1.125, 0.25, 0.25, 0.625, 0.],
|
||||
[0.25, -0.5, 0.5, -0.25, 0.],
|
||||
[0.25, 0.5, -0.5, -0.25, 0.],
|
||||
[0.625, -0.25, -0.25, -0.125, 0.],
|
||||
[0., 0., 0., 0., 0.]])
|
||||
# fmt: on
|
||||
|
||||
permutation = [4, 0, 1, 2, 3]
|
||||
npt.assert_equal(nx.modularity_matrix(self.G), B)
|
||||
npt.assert_equal(
|
||||
nx.modularity_matrix(self.G, nodelist=permutation),
|
||||
B[np.ix_(permutation, permutation)],
|
||||
)
|
||||
|
||||
def test_modularity_weight(self):
|
||||
"Modularity matrix with weights"
|
||||
# fmt: off
|
||||
B = np.array([[-1.125, 0.25, 0.25, 0.625, 0.],
|
||||
[0.25, -0.5, 0.5, -0.25, 0.],
|
||||
[0.25, 0.5, -0.5, -0.25, 0.],
|
||||
[0.625, -0.25, -0.25, -0.125, 0.],
|
||||
[0., 0., 0., 0., 0.]])
|
||||
# fmt: on
|
||||
|
||||
G_weighted = self.G.copy()
|
||||
for n1, n2 in G_weighted.edges():
|
||||
G_weighted.edges[n1, n2]["weight"] = 0.5
|
||||
# The following test would fail in networkx 1.1
|
||||
npt.assert_equal(nx.modularity_matrix(G_weighted), B)
|
||||
# The following test that the modularity matrix get rescaled accordingly
|
||||
npt.assert_equal(nx.modularity_matrix(G_weighted, weight="weight"), 0.5 * B)
|
||||
|
||||
def test_directed_modularity(self):
|
||||
"Directed Modularity matrix"
|
||||
# fmt: off
|
||||
B = np.array([[-0.2, 0.6, 0.8, -0.4, -0.4, -0.4],
|
||||
[0., 0., 0., 0., 0., 0.],
|
||||
[0.7, 0.4, -0.3, -0.6, 0.4, -0.6],
|
||||
[-0.2, -0.4, -0.2, -0.4, 0.6, 0.6],
|
||||
[-0.2, -0.4, -0.2, 0.6, -0.4, 0.6],
|
||||
[-0.1, -0.2, -0.1, 0.8, -0.2, -0.2]])
|
||||
# fmt: on
|
||||
node_permutation = [5, 1, 2, 3, 4, 6]
|
||||
idx_permutation = [4, 0, 1, 2, 3, 5]
|
||||
mm = nx.directed_modularity_matrix(self.DG, nodelist=sorted(self.DG))
|
||||
npt.assert_equal(mm, B)
|
||||
npt.assert_equal(
|
||||
nx.directed_modularity_matrix(self.DG, nodelist=node_permutation),
|
||||
B[np.ix_(idx_permutation, idx_permutation)],
|
||||
)
|
|
@ -0,0 +1,72 @@
|
|||
import pytest
|
||||
|
||||
np = pytest.importorskip("numpy")
|
||||
npt = pytest.importorskip("numpy.testing")
|
||||
scipy = pytest.importorskip("scipy")
|
||||
|
||||
import networkx as nx
|
||||
from networkx.generators.degree_seq import havel_hakimi_graph
|
||||
|
||||
|
||||
class TestSpectrum:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
deg = [3, 2, 2, 1, 0]
|
||||
cls.G = havel_hakimi_graph(deg)
|
||||
cls.P = nx.path_graph(3)
|
||||
cls.WG = nx.Graph(
|
||||
(u, v, {"weight": 0.5, "other": 0.3}) for (u, v) in cls.G.edges()
|
||||
)
|
||||
cls.WG.add_node(4)
|
||||
cls.DG = nx.DiGraph()
|
||||
nx.add_path(cls.DG, [0, 1, 2])
|
||||
|
||||
def test_laplacian_spectrum(self):
|
||||
"Laplacian eigenvalues"
|
||||
evals = np.array([0, 0, 1, 3, 4])
|
||||
e = sorted(nx.laplacian_spectrum(self.G))
|
||||
npt.assert_almost_equal(e, evals)
|
||||
e = sorted(nx.laplacian_spectrum(self.WG, weight=None))
|
||||
npt.assert_almost_equal(e, evals)
|
||||
e = sorted(nx.laplacian_spectrum(self.WG))
|
||||
npt.assert_almost_equal(e, 0.5 * evals)
|
||||
e = sorted(nx.laplacian_spectrum(self.WG, weight="other"))
|
||||
npt.assert_almost_equal(e, 0.3 * evals)
|
||||
|
||||
def test_normalized_laplacian_spectrum(self):
|
||||
"Normalized Laplacian eigenvalues"
|
||||
evals = np.array([0, 0, 0.7712864461218, 1.5, 1.7287135538781])
|
||||
e = sorted(nx.normalized_laplacian_spectrum(self.G))
|
||||
npt.assert_almost_equal(e, evals)
|
||||
e = sorted(nx.normalized_laplacian_spectrum(self.WG, weight=None))
|
||||
npt.assert_almost_equal(e, evals)
|
||||
e = sorted(nx.normalized_laplacian_spectrum(self.WG))
|
||||
npt.assert_almost_equal(e, evals)
|
||||
e = sorted(nx.normalized_laplacian_spectrum(self.WG, weight="other"))
|
||||
npt.assert_almost_equal(e, evals)
|
||||
|
||||
def test_adjacency_spectrum(self):
|
||||
"Adjacency eigenvalues"
|
||||
evals = np.array([-np.sqrt(2), 0, np.sqrt(2)])
|
||||
e = sorted(nx.adjacency_spectrum(self.P))
|
||||
npt.assert_almost_equal(e, evals)
|
||||
|
||||
def test_modularity_spectrum(self):
|
||||
"Modularity eigenvalues"
|
||||
evals = np.array([-1.5, 0.0, 0.0])
|
||||
e = sorted(nx.modularity_spectrum(self.P))
|
||||
npt.assert_almost_equal(e, evals)
|
||||
# Directed modularity eigenvalues
|
||||
evals = np.array([-0.5, 0.0, 0.0])
|
||||
e = sorted(nx.modularity_spectrum(self.DG))
|
||||
npt.assert_almost_equal(e, evals)
|
||||
|
||||
def test_bethe_hessian_spectrum(self):
|
||||
"Bethe Hessian eigenvalues"
|
||||
evals = np.array([0.5 * (9 - np.sqrt(33)), 4, 0.5 * (9 + np.sqrt(33))])
|
||||
e = sorted(nx.bethe_hessian_spectrum(self.P, r=2))
|
||||
npt.assert_almost_equal(e, evals)
|
||||
# Collapses back to Laplacian:
|
||||
e1 = sorted(nx.bethe_hessian_spectrum(self.P, r=1))
|
||||
e2 = sorted(nx.laplacian_spectrum(self.P))
|
||||
npt.assert_almost_equal(e1, e2)
|
Loading…
Add table
Add a link
Reference in a new issue