260 lines
9.0 KiB
Python
260 lines
9.0 KiB
Python
#!/usr/bin/env python
|
|
from random import Random
|
|
|
|
import pytest
|
|
|
|
|
|
import networkx as nx
|
|
from networkx import convert_node_labels_to_integers as cnlti
|
|
|
|
|
|
class TestDistance:
|
|
def setup_method(self):
|
|
G = cnlti(nx.grid_2d_graph(4, 4), first_label=1, ordering="sorted")
|
|
self.G = G
|
|
|
|
def test_eccentricity(self):
|
|
assert nx.eccentricity(self.G, 1) == 6
|
|
e = nx.eccentricity(self.G)
|
|
assert e[1] == 6
|
|
|
|
sp = dict(nx.shortest_path_length(self.G))
|
|
e = nx.eccentricity(self.G, sp=sp)
|
|
assert e[1] == 6
|
|
|
|
e = nx.eccentricity(self.G, v=1)
|
|
assert e == 6
|
|
|
|
# This behavior changed in version 1.8 (ticket #739)
|
|
e = nx.eccentricity(self.G, v=[1, 1])
|
|
assert e[1] == 6
|
|
e = nx.eccentricity(self.G, v=[1, 2])
|
|
assert e[1] == 6
|
|
|
|
# test against graph with one node
|
|
G = nx.path_graph(1)
|
|
e = nx.eccentricity(G)
|
|
assert e[0] == 0
|
|
e = nx.eccentricity(G, v=0)
|
|
assert e == 0
|
|
pytest.raises(nx.NetworkXError, nx.eccentricity, G, 1)
|
|
|
|
# test against empty graph
|
|
G = nx.empty_graph()
|
|
e = nx.eccentricity(G)
|
|
assert e == {}
|
|
|
|
def test_diameter(self):
|
|
assert nx.diameter(self.G) == 6
|
|
|
|
def test_radius(self):
|
|
assert nx.radius(self.G) == 4
|
|
|
|
def test_periphery(self):
|
|
assert set(nx.periphery(self.G)) == set([1, 4, 13, 16])
|
|
|
|
def test_center(self):
|
|
assert set(nx.center(self.G)) == set([6, 7, 10, 11])
|
|
|
|
def test_bound_diameter(self):
|
|
assert nx.diameter(self.G, usebounds=True) == 6
|
|
|
|
def test_bound_radius(self):
|
|
assert nx.radius(self.G, usebounds=True) == 4
|
|
|
|
def test_bound_periphery(self):
|
|
result = set([1, 4, 13, 16])
|
|
assert set(nx.periphery(self.G, usebounds=True)) == result
|
|
|
|
def test_bound_center(self):
|
|
result = set([6, 7, 10, 11])
|
|
assert set(nx.center(self.G, usebounds=True)) == result
|
|
|
|
def test_radius_exception(self):
|
|
G = nx.Graph()
|
|
G.add_edge(1, 2)
|
|
G.add_edge(3, 4)
|
|
pytest.raises(nx.NetworkXError, nx.diameter, G)
|
|
|
|
def test_eccentricity_infinite(self):
|
|
with pytest.raises(nx.NetworkXError):
|
|
G = nx.Graph([(1, 2), (3, 4)])
|
|
e = nx.eccentricity(G)
|
|
|
|
def test_eccentricity_undirected_not_connected(self):
|
|
with pytest.raises(nx.NetworkXError):
|
|
G = nx.Graph([(1, 2), (3, 4)])
|
|
e = nx.eccentricity(G, sp=1)
|
|
|
|
def test_eccentricity_directed_weakly_connected(self):
|
|
with pytest.raises(nx.NetworkXError):
|
|
DG = nx.DiGraph([(1, 2), (1, 3)])
|
|
nx.eccentricity(DG)
|
|
|
|
|
|
class TestResistanceDistance:
|
|
@classmethod
|
|
def setup_class(cls):
|
|
global np
|
|
global sp_sparse
|
|
np = pytest.importorskip('numpy')
|
|
scipy = pytest.importorskip('scipy')
|
|
sp_sparse = pytest.importorskip('scipy.sparse')
|
|
|
|
def setup_method(self):
|
|
G = nx.Graph()
|
|
G.add_edge(1, 2, weight=2)
|
|
G.add_edge(2, 3, weight=4)
|
|
G.add_edge(3, 4, weight=1)
|
|
G.add_edge(1, 4, weight=3)
|
|
self.G = G
|
|
|
|
def test_laplacian_submatrix(self):
|
|
from networkx.algorithms.distance_measures import _laplacian_submatrix
|
|
M = sp_sparse.csr_matrix([[1, 2, 3],
|
|
[4, 5, 6],
|
|
[7, 8, 9]], dtype=np.float32)
|
|
N = sp_sparse.csr_matrix([[5, 6],
|
|
[8, 9]], dtype=np.float32)
|
|
Mn, Mn_nodelist = _laplacian_submatrix(1, M, [1, 2, 3])
|
|
assert Mn_nodelist == [2, 3]
|
|
assert np.allclose(Mn.toarray(), N.toarray())
|
|
|
|
def test_laplacian_submatrix_square(self):
|
|
with pytest.raises(nx.NetworkXError):
|
|
from networkx.algorithms.distance_measures import _laplacian_submatrix
|
|
M = sp_sparse.csr_matrix([[1, 2],
|
|
[4, 5],
|
|
[7, 8]], dtype=np.float32)
|
|
_laplacian_submatrix(1, M, [1, 2, 3])
|
|
|
|
def test_laplacian_submatrix_matrix_node_dim(self):
|
|
with pytest.raises(nx.NetworkXError):
|
|
from networkx.algorithms.distance_measures import _laplacian_submatrix
|
|
M = sp_sparse.csr_matrix([[1, 2, 3],
|
|
[4, 5, 6],
|
|
[7, 8, 9]], dtype=np.float32)
|
|
_laplacian_submatrix(1, M, [1, 2, 3, 4])
|
|
|
|
def test_resistance_distance(self):
|
|
rd = nx.resistance_distance(self.G, 1, 3, 'weight', True)
|
|
test_data = 1/(1/(2+4) + 1/(1+3))
|
|
assert round(rd, 5) == round(test_data, 5)
|
|
|
|
def test_resistance_distance_noinv(self):
|
|
rd = nx.resistance_distance(self.G, 1, 3, 'weight', False)
|
|
test_data = 1/(1/(1/2+1/4) + 1/(1/1+1/3))
|
|
assert round(rd, 5) == round(test_data, 5)
|
|
|
|
def test_resistance_distance_no_weight(self):
|
|
rd = nx.resistance_distance(self.G, 1, 3)
|
|
assert round(rd, 5) == 1
|
|
|
|
def test_resistance_distance_neg_weight(self):
|
|
self.G[2][3]['weight'] = -4
|
|
rd = nx.resistance_distance(self.G, 1, 3, 'weight', True)
|
|
test_data = 1/(1/(2+-4) + 1/(1+3))
|
|
assert round(rd, 5) == round(test_data, 5)
|
|
|
|
def test_multigraph(self):
|
|
G = nx.MultiGraph()
|
|
G.add_edge(1, 2, weight=2)
|
|
G.add_edge(2, 3, weight=4)
|
|
G.add_edge(3, 4, weight=1)
|
|
G.add_edge(1, 4, weight=3)
|
|
rd = nx.resistance_distance(G, 1, 3, 'weight', True)
|
|
assert np.isclose(rd, 1/(1/(2+4) + 1/(1+3)))
|
|
|
|
def test_resistance_distance_div0(self):
|
|
with pytest.raises(ZeroDivisionError):
|
|
self.G[1][2]['weight'] = 0
|
|
nx.resistance_distance(self.G, 1, 3, 'weight')
|
|
|
|
def test_resistance_distance_not_connected(self):
|
|
with pytest.raises(nx.NetworkXError):
|
|
self.G.add_node(5)
|
|
nx.resistance_distance(self.G, 1, 5)
|
|
|
|
def test_resistance_distance_same_node(self):
|
|
with pytest.raises(nx.NetworkXError):
|
|
nx.resistance_distance(self.G, 1, 1)
|
|
|
|
def test_resistance_distance_nodeA_not_in_graph(self):
|
|
with pytest.raises(nx.NetworkXError):
|
|
nx.resistance_distance(self.G, 9, 1)
|
|
|
|
def test_resistance_distance_nodeB_not_in_graph(self):
|
|
with pytest.raises(nx.NetworkXError):
|
|
nx.resistance_distance(self.G, 1, 9)
|
|
|
|
|
|
class TestBarycenter(object):
|
|
"""Test :func:`networkx.algorithms.distance_measures.barycenter`."""
|
|
def barycenter_as_subgraph(self, g, **kwargs):
|
|
"""Return the subgraph induced on the barycenter of g"""
|
|
b = nx.barycenter(g, **kwargs)
|
|
assert isinstance(b, list)
|
|
assert set(b) <= set(g)
|
|
return g.subgraph(b)
|
|
|
|
def test_must_be_connected(self):
|
|
pytest.raises(nx.NetworkXNoPath, nx.barycenter, nx.empty_graph(5))
|
|
|
|
def test_sp_kwarg(self):
|
|
# Complete graph K_5. Normally it works...
|
|
K_5 = nx.complete_graph(5)
|
|
sp = dict(nx.shortest_path_length(K_5))
|
|
assert nx.barycenter(K_5, sp=sp) == list(K_5)
|
|
|
|
# ...but not with the weight argument
|
|
for u, v, data in K_5.edges.data():
|
|
data['weight'] = 1
|
|
pytest.raises(ValueError, nx.barycenter, K_5, sp=sp, weight='weight')
|
|
|
|
# ...and a corrupted sp can make it seem like K_5 is disconnected
|
|
del sp[0][1]
|
|
pytest.raises(nx.NetworkXNoPath, nx.barycenter, K_5, sp=sp)
|
|
|
|
def test_trees(self):
|
|
"""The barycenter of a tree is a single vertex or an edge.
|
|
|
|
See [West01]_, p. 78.
|
|
"""
|
|
prng = Random(0xdeadbeef)
|
|
for i in range(50):
|
|
RT = nx.random_tree(prng.randint(1, 75), prng)
|
|
b = self.barycenter_as_subgraph(RT)
|
|
if len(b) == 2:
|
|
assert b.size() == 1
|
|
else:
|
|
assert len(b) == 1
|
|
assert b.size() == 0
|
|
|
|
def test_this_one_specific_tree(self):
|
|
"""Test the tree pictured at the bottom of [West01]_, p. 78."""
|
|
g = nx.Graph({
|
|
'a': ['b'],
|
|
'b': ['a', 'x'],
|
|
'x': ['b', 'y'],
|
|
'y': ['x', 'z'],
|
|
'z': ['y', 0, 1, 2, 3, 4],
|
|
0: ['z'], 1: ['z'], 2: ['z'], 3: ['z'], 4: ['z']})
|
|
b = self.barycenter_as_subgraph(g, attr='barycentricity')
|
|
assert list(b) == ['z']
|
|
assert not b.edges
|
|
expected_barycentricity = {0: 23, 1: 23, 2: 23, 3: 23, 4: 23,
|
|
'a': 35, 'b': 27, 'x': 21, 'y': 17, 'z': 15
|
|
}
|
|
for node, barycentricity in expected_barycentricity.items():
|
|
assert g.nodes[node]['barycentricity'] == barycentricity
|
|
|
|
# Doubling weights should do nothing but double the barycentricities
|
|
for edge in g.edges:
|
|
g.edges[edge]['weight'] = 2
|
|
b = self.barycenter_as_subgraph(g, weight='weight',
|
|
attr='barycentricity2')
|
|
assert list(b) == ['z']
|
|
assert not b.edges
|
|
for node, barycentricity in expected_barycentricity.items():
|
|
assert g.nodes[node]['barycentricity2'] == barycentricity*2
|