191 lines
6.4 KiB
Python
191 lines
6.4 KiB
Python
|
from unittest import TestCase
|
||
|
import collections
|
||
|
|
||
|
import pytest
|
||
|
|
||
|
import networkx as nx
|
||
|
|
||
|
|
||
|
class TestIsEulerian(TestCase):
|
||
|
def test_is_eulerian(self):
|
||
|
assert nx.is_eulerian(nx.complete_graph(5))
|
||
|
assert nx.is_eulerian(nx.complete_graph(7))
|
||
|
assert nx.is_eulerian(nx.hypercube_graph(4))
|
||
|
assert nx.is_eulerian(nx.hypercube_graph(6))
|
||
|
|
||
|
assert not nx.is_eulerian(nx.complete_graph(4))
|
||
|
assert not nx.is_eulerian(nx.complete_graph(6))
|
||
|
assert not nx.is_eulerian(nx.hypercube_graph(3))
|
||
|
assert not nx.is_eulerian(nx.hypercube_graph(5))
|
||
|
|
||
|
assert not nx.is_eulerian(nx.petersen_graph())
|
||
|
assert not nx.is_eulerian(nx.path_graph(4))
|
||
|
|
||
|
def test_is_eulerian2(self):
|
||
|
# not connected
|
||
|
G = nx.Graph()
|
||
|
G.add_nodes_from([1, 2, 3])
|
||
|
assert not nx.is_eulerian(G)
|
||
|
# not strongly connected
|
||
|
G = nx.DiGraph()
|
||
|
G.add_nodes_from([1, 2, 3])
|
||
|
assert not nx.is_eulerian(G)
|
||
|
G = nx.MultiDiGraph()
|
||
|
G.add_edge(1, 2)
|
||
|
G.add_edge(2, 3)
|
||
|
G.add_edge(2, 3)
|
||
|
G.add_edge(3, 1)
|
||
|
assert not nx.is_eulerian(G)
|
||
|
|
||
|
|
||
|
class TestEulerianCircuit(TestCase):
|
||
|
def test_eulerian_circuit_cycle(self):
|
||
|
G = nx.cycle_graph(4)
|
||
|
|
||
|
edges = list(nx.eulerian_circuit(G, source=0))
|
||
|
nodes = [u for u, v in edges]
|
||
|
assert nodes == [0, 3, 2, 1]
|
||
|
assert edges == [(0, 3), (3, 2), (2, 1), (1, 0)]
|
||
|
|
||
|
edges = list(nx.eulerian_circuit(G, source=1))
|
||
|
nodes = [u for u, v in edges]
|
||
|
assert nodes == [1, 2, 3, 0]
|
||
|
assert edges == [(1, 2), (2, 3), (3, 0), (0, 1)]
|
||
|
|
||
|
G = nx.complete_graph(3)
|
||
|
|
||
|
edges = list(nx.eulerian_circuit(G, source=0))
|
||
|
nodes = [u for u, v in edges]
|
||
|
assert nodes == [0, 2, 1]
|
||
|
assert edges == [(0, 2), (2, 1), (1, 0)]
|
||
|
|
||
|
edges = list(nx.eulerian_circuit(G, source=1))
|
||
|
nodes = [u for u, v in edges]
|
||
|
assert nodes == [1, 2, 0]
|
||
|
assert edges == [(1, 2), (2, 0), (0, 1)]
|
||
|
|
||
|
def test_eulerian_circuit_digraph(self):
|
||
|
G = nx.DiGraph()
|
||
|
nx.add_cycle(G, [0, 1, 2, 3])
|
||
|
|
||
|
edges = list(nx.eulerian_circuit(G, source=0))
|
||
|
nodes = [u for u, v in edges]
|
||
|
assert nodes == [0, 1, 2, 3]
|
||
|
assert edges == [(0, 1), (1, 2), (2, 3), (3, 0)]
|
||
|
|
||
|
edges = list(nx.eulerian_circuit(G, source=1))
|
||
|
nodes = [u for u, v in edges]
|
||
|
assert nodes == [1, 2, 3, 0]
|
||
|
assert edges == [(1, 2), (2, 3), (3, 0), (0, 1)]
|
||
|
|
||
|
def test_multigraph(self):
|
||
|
G = nx.MultiGraph()
|
||
|
nx.add_cycle(G, [0, 1, 2, 3])
|
||
|
G.add_edge(1, 2)
|
||
|
G.add_edge(1, 2)
|
||
|
edges = list(nx.eulerian_circuit(G, source=0))
|
||
|
nodes = [u for u, v in edges]
|
||
|
assert nodes == [0, 3, 2, 1, 2, 1]
|
||
|
assert edges == [(0, 3), (3, 2), (2, 1), (1, 2), (2, 1), (1, 0)]
|
||
|
|
||
|
def test_multigraph_with_keys(self):
|
||
|
G = nx.MultiGraph()
|
||
|
nx.add_cycle(G, [0, 1, 2, 3])
|
||
|
G.add_edge(1, 2)
|
||
|
G.add_edge(1, 2)
|
||
|
edges = list(nx.eulerian_circuit(G, source=0, keys=True))
|
||
|
nodes = [u for u, v, k in edges]
|
||
|
assert nodes == [0, 3, 2, 1, 2, 1]
|
||
|
assert edges[:2] == [(0, 3, 0), (3, 2, 0)]
|
||
|
assert collections.Counter(edges[2:5]) == collections.Counter([(2, 1, 0), (1, 2, 1), (2, 1, 2)])
|
||
|
assert edges[5:] == [(1, 0, 0)]
|
||
|
|
||
|
def test_not_eulerian(self):
|
||
|
with pytest.raises(nx.NetworkXError):
|
||
|
f = list(nx.eulerian_circuit(nx.complete_graph(4)))
|
||
|
|
||
|
|
||
|
class TestIsSemiEulerian(TestCase):
|
||
|
def test_is_semieulerian(self):
|
||
|
# Test graphs with Eulerian paths but no cycles return True.
|
||
|
assert nx.is_semieulerian(nx.path_graph(4))
|
||
|
G = nx.path_graph(6, create_using=nx.DiGraph)
|
||
|
assert nx.is_semieulerian(G)
|
||
|
|
||
|
# Test graphs with Eulerian cycles return False.
|
||
|
assert not nx.is_semieulerian(nx.complete_graph(5))
|
||
|
assert not nx.is_semieulerian(nx.complete_graph(7))
|
||
|
assert not nx.is_semieulerian(nx.hypercube_graph(4))
|
||
|
assert not nx.is_semieulerian(nx.hypercube_graph(6))
|
||
|
|
||
|
|
||
|
class TestHasEulerianPath(TestCase):
|
||
|
def test_has_eulerian_path_cyclic(self):
|
||
|
# Test graphs with Eulerian cycles return True.
|
||
|
assert nx.has_eulerian_path(nx.complete_graph(5))
|
||
|
assert nx.has_eulerian_path(nx.complete_graph(7))
|
||
|
assert nx.has_eulerian_path(nx.hypercube_graph(4))
|
||
|
assert nx.has_eulerian_path(nx.hypercube_graph(6))
|
||
|
|
||
|
def test_has_eulerian_path_non_cyclic(self):
|
||
|
# Test graphs with Eulerian paths but no cycles return True.
|
||
|
assert nx.has_eulerian_path(nx.path_graph(4))
|
||
|
G = nx.path_graph(6, create_using=nx.DiGraph)
|
||
|
assert nx.has_eulerian_path(G)
|
||
|
|
||
|
|
||
|
class TestFindPathStart(TestCase):
|
||
|
def testfind_path_start(self):
|
||
|
find_path_start = nx.algorithms.euler._find_path_start
|
||
|
# Test digraphs return correct starting node.
|
||
|
G = nx.path_graph(6, create_using=nx.DiGraph)
|
||
|
assert find_path_start(G) == 0
|
||
|
edges = [(0, 1), (1, 2), (2, 0), (4, 0)]
|
||
|
assert find_path_start(nx.DiGraph(edges)) == 4
|
||
|
|
||
|
# Test graph with no Eulerian path return None.
|
||
|
edges = [(0, 1), (1, 2), (2, 3), (2, 4)]
|
||
|
assert find_path_start(nx.DiGraph(edges)) == None
|
||
|
|
||
|
|
||
|
class TestEulerianPath(TestCase):
|
||
|
def test_eulerian_path(self):
|
||
|
x = [(4, 0), (0, 1), (1, 2), (2, 0)]
|
||
|
for e1, e2 in zip(x, nx.eulerian_path(nx.DiGraph(x))):
|
||
|
assert e1 == e2
|
||
|
|
||
|
|
||
|
class TestEulerize(TestCase):
|
||
|
def test_disconnected(self):
|
||
|
with pytest.raises(nx.NetworkXError):
|
||
|
G = nx.from_edgelist([(0, 1), (2, 3)])
|
||
|
nx.eulerize(G)
|
||
|
|
||
|
def test_null_graph(self):
|
||
|
with pytest.raises(nx.NetworkXPointlessConcept):
|
||
|
nx.eulerize(nx.Graph())
|
||
|
|
||
|
def test_null_multigraph(self):
|
||
|
with pytest.raises(nx.NetworkXPointlessConcept):
|
||
|
nx.eulerize(nx.MultiGraph())
|
||
|
|
||
|
def test_on_empty_graph(self):
|
||
|
with pytest.raises(nx.NetworkXError):
|
||
|
nx.eulerize(nx.empty_graph(3))
|
||
|
|
||
|
def test_on_eulerian(self):
|
||
|
G = nx.cycle_graph(3)
|
||
|
H = nx.eulerize(G)
|
||
|
assert nx.is_isomorphic(G, H)
|
||
|
|
||
|
def test_on_eulerian_multigraph(self):
|
||
|
G = nx.MultiGraph(nx.cycle_graph(3))
|
||
|
G.add_edge(0, 1)
|
||
|
H = nx.eulerize(G)
|
||
|
assert nx.is_eulerian(H)
|
||
|
|
||
|
def test_on_complete_graph(self):
|
||
|
G = nx.complete_graph(4)
|
||
|
assert nx.is_eulerian(nx.eulerize(G))
|
||
|
assert nx.is_eulerian(nx.eulerize(nx.MultiGraph(G)))
|