rm CondaPkg environment

This commit is contained in:
ton
2023-04-06 13:53:47 +07:00
parent 0a57ed7884
commit c43d949309
3329 changed files with 5725 additions and 447022 deletions

View File

@@ -2,7 +2,6 @@ import networkx as nx
def test_is_at_free():
is_at_free = nx.asteroidal.is_at_free
cycle = nx.cycle_graph(6)

View File

@@ -89,22 +89,22 @@ class TestMCS:
frozenset([2, 3, 4]),
frozenset([3, 4, 5, 6]),
}
assert {c for c in nx.chordal_graph_cliques(self.chordal_G)} == cliques
assert set(nx.chordal_graph_cliques(self.chordal_G)) == cliques
with pytest.raises(nx.NetworkXError, match="Input graph is not chordal"):
{c for c in nx.chordal_graph_cliques(self.non_chordal_G)}
set(nx.chordal_graph_cliques(self.non_chordal_G))
with pytest.raises(nx.NetworkXError, match="Input graph is not chordal"):
{c for c in nx.chordal_graph_cliques(self.self_loop_G)}
set(nx.chordal_graph_cliques(self.self_loop_G))
def test_chordal_find_cliques_path(self):
G = nx.path_graph(10)
cliqueset = nx.chordal_graph_cliques(G)
for (u, v) in G.edges():
for u, v in G.edges():
assert frozenset([u, v]) in cliqueset or frozenset([v, u]) in cliqueset
def test_chordal_find_cliquesCC(self):
cliques = {frozenset([1, 2, 3]), frozenset([2, 3, 4]), frozenset([3, 4, 5, 6])}
cgc = nx.chordal_graph_cliques
assert {c for c in cgc(self.connected_chordal_G)} == cliques
assert set(cgc(self.connected_chordal_G)) == cliques
def test_complete_to_chordal_graph(self):
fgrg = nx.fast_gnp_random_graph

View File

@@ -69,80 +69,96 @@ class TestCliques:
def test_clique_number(self):
G = self.G
assert nx.graph_clique_number(G) == 4
assert nx.graph_clique_number(G, cliques=self.cl) == 4
with pytest.deprecated_call():
assert nx.graph_clique_number(G) == 4
with pytest.deprecated_call():
assert nx.graph_clique_number(G, cliques=self.cl) == 4
def test_clique_number2(self):
G = nx.Graph()
G.add_nodes_from([1, 2, 3])
assert nx.graph_clique_number(G) == 1
with pytest.deprecated_call():
assert nx.graph_clique_number(G) == 1
def test_clique_number3(self):
G = nx.Graph()
assert nx.graph_clique_number(G) == 0
with pytest.deprecated_call():
assert nx.graph_clique_number(G) == 0
def test_number_of_cliques(self):
G = self.G
assert nx.graph_number_of_cliques(G) == 5
assert nx.graph_number_of_cliques(G, cliques=self.cl) == 5
assert nx.number_of_cliques(G, 1) == 1
assert list(nx.number_of_cliques(G, [1]).values()) == [1]
assert list(nx.number_of_cliques(G, [1, 2]).values()) == [1, 2]
assert nx.number_of_cliques(G, [1, 2]) == {1: 1, 2: 2}
assert nx.number_of_cliques(G, 2) == 2
assert nx.number_of_cliques(G) == {
1: 1,
2: 2,
3: 1,
4: 2,
5: 1,
6: 2,
7: 1,
8: 1,
9: 1,
10: 1,
11: 1,
}
assert nx.number_of_cliques(G, nodes=list(G)) == {
1: 1,
2: 2,
3: 1,
4: 2,
5: 1,
6: 2,
7: 1,
8: 1,
9: 1,
10: 1,
11: 1,
}
assert nx.number_of_cliques(G, nodes=[2, 3, 4]) == {2: 2, 3: 1, 4: 2}
assert nx.number_of_cliques(G, cliques=self.cl) == {
1: 1,
2: 2,
3: 1,
4: 2,
5: 1,
6: 2,
7: 1,
8: 1,
9: 1,
10: 1,
11: 1,
}
assert nx.number_of_cliques(G, list(G), cliques=self.cl) == {
1: 1,
2: 2,
3: 1,
4: 2,
5: 1,
6: 2,
7: 1,
8: 1,
9: 1,
10: 1,
11: 1,
}
with pytest.deprecated_call():
assert nx.graph_number_of_cliques(G) == 5
with pytest.deprecated_call():
assert nx.graph_number_of_cliques(G, cliques=self.cl) == 5
with pytest.deprecated_call():
assert nx.number_of_cliques(G, 1) == 1
with pytest.deprecated_call():
assert list(nx.number_of_cliques(G, [1]).values()) == [1]
with pytest.deprecated_call():
assert list(nx.number_of_cliques(G, [1, 2]).values()) == [1, 2]
with pytest.deprecated_call():
assert nx.number_of_cliques(G, [1, 2]) == {1: 1, 2: 2}
with pytest.deprecated_call():
assert nx.number_of_cliques(G, 2) == 2
with pytest.deprecated_call():
assert nx.number_of_cliques(G) == {
1: 1,
2: 2,
3: 1,
4: 2,
5: 1,
6: 2,
7: 1,
8: 1,
9: 1,
10: 1,
11: 1,
}
with pytest.deprecated_call():
assert nx.number_of_cliques(G, nodes=list(G)) == {
1: 1,
2: 2,
3: 1,
4: 2,
5: 1,
6: 2,
7: 1,
8: 1,
9: 1,
10: 1,
11: 1,
}
with pytest.deprecated_call():
assert nx.number_of_cliques(G, nodes=[2, 3, 4]) == {2: 2, 3: 1, 4: 2}
with pytest.deprecated_call():
assert nx.number_of_cliques(G, cliques=self.cl) == {
1: 1,
2: 2,
3: 1,
4: 2,
5: 1,
6: 2,
7: 1,
8: 1,
9: 1,
10: 1,
11: 1,
}
with pytest.deprecated_call():
assert nx.number_of_cliques(G, list(G), cliques=self.cl) == {
1: 1,
2: 2,
3: 1,
4: 2,
5: 1,
6: 2,
7: 1,
8: 1,
9: 1,
10: 1,
11: 1,
}
def test_node_clique_number(self):
G = self.G
@@ -182,23 +198,31 @@ class TestCliques:
def test_cliques_containing_node(self):
G = self.G
assert nx.cliques_containing_node(G, 1) == [[2, 6, 1, 3]]
assert list(nx.cliques_containing_node(G, [1]).values()) == [[[2, 6, 1, 3]]]
assert [
sorted(c) for c in list(nx.cliques_containing_node(G, [1, 2]).values())
] == [[[2, 6, 1, 3]], [[2, 6, 1, 3], [2, 6, 4]]]
result = nx.cliques_containing_node(G, [1, 2])
with pytest.deprecated_call():
assert nx.cliques_containing_node(G, 1) == [[2, 6, 1, 3]]
with pytest.deprecated_call():
assert list(nx.cliques_containing_node(G, [1]).values()) == [[[2, 6, 1, 3]]]
with pytest.deprecated_call():
assert [
sorted(c) for c in list(nx.cliques_containing_node(G, [1, 2]).values())
] == [[[2, 6, 1, 3]], [[2, 6, 1, 3], [2, 6, 4]]]
with pytest.deprecated_call():
result = nx.cliques_containing_node(G, [1, 2])
for k, v in result.items():
result[k] = sorted(v)
assert result == {1: [[2, 6, 1, 3]], 2: [[2, 6, 1, 3], [2, 6, 4]]}
assert nx.cliques_containing_node(G, 1) == [[2, 6, 1, 3]]
with pytest.deprecated_call():
assert nx.cliques_containing_node(G, 1) == [[2, 6, 1, 3]]
expected = [{2, 6, 1, 3}, {2, 6, 4}]
answer = [set(c) for c in nx.cliques_containing_node(G, 2)]
with pytest.deprecated_call():
answer = [set(c) for c in nx.cliques_containing_node(G, 2)]
assert answer in (expected, list(reversed(expected)))
answer = [set(c) for c in nx.cliques_containing_node(G, 2, cliques=self.cl)]
with pytest.deprecated_call():
answer = [set(c) for c in nx.cliques_containing_node(G, 2, cliques=self.cl)]
assert answer in (expected, list(reversed(expected)))
assert len(nx.cliques_containing_node(G)) == 11
with pytest.deprecated_call():
assert len(nx.cliques_containing_node(G)) == 11
def test_make_clique_bipartite(self):
G = self.G
@@ -233,6 +257,17 @@ class TestCliques:
with pytest.raises(nx.NetworkXNotImplemented):
next(nx.find_cliques(nx.DiGraph()))
def test_find_cliques_trivial(self):
G = nx.Graph()
assert sorted(nx.find_cliques(G)) == []
assert sorted(nx.find_cliques_recursive(G)) == []
def test_make_max_clique_graph_create_using(self):
G = nx.Graph([(1, 2), (3, 1), (4, 1), (5, 6)])
E = nx.Graph([(0, 1), (0, 2), (1, 2)])
E.add_node(3)
assert nx.is_isomorphic(nx.make_max_clique_graph(G, create_using=nx.Graph), E)
class TestEnumerateAllCliques:
def test_paper_figure_4(self):

View File

@@ -26,7 +26,6 @@ class TestCommunicability:
assert answer[k1][k2] == pytest.approx(result[k1][k2], abs=1e-7)
def test_communicability2(self):
answer_orig = {
("1", "1"): 1.6445956054135658,
("1", "Albert"): 0.7430186221096251,

View File

@@ -1,3 +1,6 @@
from itertools import chain, islice, tee
from random import shuffle
import pytest
import networkx
@@ -68,16 +71,13 @@ class TestCycles:
for c in cc:
assert any(self.is_cyclic_permutation(c, rc) for rc in ca)
def test_simple_cycles_graph(self):
with pytest.raises(nx.NetworkXNotImplemented):
G = nx.Graph()
c = sorted(nx.simple_cycles(G))
def test_unsortable(self):
# TODO What does this test do? das 6/2013
# this test ensures that graphs whose nodes without an intrinsic
# ordering do not cause issues
G = nx.DiGraph()
nx.add_cycle(G, ["a", 1])
c = list(nx.simple_cycles(G))
assert len(c) == 1
def test_simple_cycles_small(self):
G = nx.DiGraph()
@@ -96,13 +96,6 @@ class TestCycles:
G = nx.DiGraph()
assert list(nx.simple_cycles(G)) == []
def test_complete_directed_graph(self):
# see table 2 in Johnson's paper
ncircuits = [1, 5, 20, 84, 409, 2365, 16064]
for n, c in zip(range(2, 9), ncircuits):
G = nx.DiGraph(nx.complete_graph(n))
assert len(list(nx.simple_cycles(G))) == c
def worst_case_graph(self, k):
# see figure 1 in Johnson's paper
# this graph has exactly 3k simple cycles
@@ -169,6 +162,522 @@ class TestCycles:
assert any(self.is_cyclic_permutation(rc, c) for c in cc)
def pairwise(iterable):
a, b = tee(iterable)
next(b, None)
return zip(a, b)
def cycle_edges(c):
return pairwise(chain(c, islice(c, 1)))
def directed_cycle_edgeset(c):
return frozenset(cycle_edges(c))
def undirected_cycle_edgeset(c):
if len(c) == 1:
return frozenset(cycle_edges(c))
return frozenset(map(frozenset, cycle_edges(c)))
def multigraph_cycle_edgeset(c):
if len(c) <= 2:
return frozenset(cycle_edges(c))
else:
return frozenset(map(frozenset, cycle_edges(c)))
class TestCycleEnumeration:
@staticmethod
def K(n):
return nx.complete_graph(n)
@staticmethod
def D(n):
return nx.complete_graph(n).to_directed()
@staticmethod
def edgeset_function(g):
if g.is_directed():
return directed_cycle_edgeset
elif g.is_multigraph():
return multigraph_cycle_edgeset
else:
return undirected_cycle_edgeset
def check_cycle(self, g, c, es, cache, source, original_c, length_bound, chordless):
if length_bound is not None and len(c) > length_bound:
raise RuntimeError(
f"computed cycle {original_c} exceeds length bound {length_bound}"
)
if source == "computed":
if es in cache:
raise RuntimeError(
f"computed cycle {original_c} has already been found!"
)
else:
cache[es] = tuple(original_c)
else:
if es in cache:
cache.pop(es)
else:
raise RuntimeError(f"expected cycle {original_c} was not computed")
if not all(g.has_edge(*e) for e in es):
raise RuntimeError(
f"{source} claimed cycle {original_c} is not a cycle of g"
)
if chordless and len(g.subgraph(c).edges) > len(c):
raise RuntimeError(f"{source} cycle {original_c} is not chordless")
def check_cycle_algorithm(
self,
g,
expected_cycles,
length_bound=None,
chordless=False,
algorithm=None,
):
if algorithm is None:
algorithm = nx.chordless_cycles if chordless else nx.simple_cycles
# note: we shuffle the labels of g to rule out accidentally-correct
# behavior which occurred during the development of chordless cycle
# enumeration algorithms
relabel = list(range(len(g)))
shuffle(relabel)
label = dict(zip(g, relabel))
unlabel = dict(zip(relabel, g))
h = nx.relabel_nodes(g, label, copy=True)
edgeset = self.edgeset_function(h)
params = {}
if length_bound is not None:
params["length_bound"] = length_bound
cycle_cache = {}
for c in algorithm(h, **params):
original_c = [unlabel[x] for x in c]
es = edgeset(c)
self.check_cycle(
h, c, es, cycle_cache, "computed", original_c, length_bound, chordless
)
if isinstance(expected_cycles, int):
if len(cycle_cache) != expected_cycles:
raise RuntimeError(
f"expected {expected_cycles} cycles, got {len(cycle_cache)}"
)
return
for original_c in expected_cycles:
c = [label[x] for x in original_c]
es = edgeset(c)
self.check_cycle(
h, c, es, cycle_cache, "expected", original_c, length_bound, chordless
)
if len(cycle_cache):
for c in cycle_cache.values():
raise RuntimeError(
f"computed cycle {c} is valid but not in the expected cycle set!"
)
def check_cycle_enumeration_integer_sequence(
self,
g_family,
cycle_counts,
length_bound=None,
chordless=False,
algorithm=None,
):
for g, num_cycles in zip(g_family, cycle_counts):
self.check_cycle_algorithm(
g,
num_cycles,
length_bound=length_bound,
chordless=chordless,
algorithm=algorithm,
)
def test_directed_chordless_cycle_digons(self):
g = nx.DiGraph()
nx.add_cycle(g, range(5))
nx.add_cycle(g, range(5)[::-1])
g.add_edge(0, 0)
expected_cycles = [(0,), (1, 2), (2, 3), (3, 4)]
self.check_cycle_algorithm(g, expected_cycles, chordless=True)
self.check_cycle_algorithm(g, expected_cycles, chordless=True, length_bound=2)
expected_cycles = [c for c in expected_cycles if len(c) < 2]
self.check_cycle_algorithm(g, expected_cycles, chordless=True, length_bound=1)
def test_directed_chordless_cycle_undirected(self):
g = nx.DiGraph([(1, 2), (2, 3), (3, 4), (4, 5), (5, 0), (5, 1), (0, 2)])
expected_cycles = [(0, 2, 3, 4, 5), (1, 2, 3, 4, 5)]
self.check_cycle_algorithm(g, expected_cycles, chordless=True)
g = nx.DiGraph()
nx.add_cycle(g, range(5))
nx.add_cycle(g, range(4, 9))
g.add_edge(7, 3)
expected_cycles = [(0, 1, 2, 3, 4), (3, 4, 5, 6, 7), (4, 5, 6, 7, 8)]
self.check_cycle_algorithm(g, expected_cycles, chordless=True)
g.add_edge(3, 7)
expected_cycles = [(0, 1, 2, 3, 4), (3, 7), (4, 5, 6, 7, 8)]
self.check_cycle_algorithm(g, expected_cycles, chordless=True)
expected_cycles = [(3, 7)]
self.check_cycle_algorithm(g, expected_cycles, chordless=True, length_bound=4)
g.remove_edge(7, 3)
expected_cycles = [(0, 1, 2, 3, 4), (4, 5, 6, 7, 8)]
self.check_cycle_algorithm(g, expected_cycles, chordless=True)
g = nx.DiGraph((i, j) for i in range(10) for j in range(i))
expected_cycles = []
self.check_cycle_algorithm(g, expected_cycles, chordless=True)
def test_chordless_cycles_directed(self):
G = nx.DiGraph()
nx.add_cycle(G, range(5))
nx.add_cycle(G, range(4, 12))
expected = [[*range(5)], [*range(4, 12)]]
self.check_cycle_algorithm(G, expected, chordless=True)
self.check_cycle_algorithm(
G, [c for c in expected if len(c) <= 5], length_bound=5, chordless=True
)
G.add_edge(7, 3)
expected.append([*range(3, 8)])
self.check_cycle_algorithm(G, expected, chordless=True)
self.check_cycle_algorithm(
G, [c for c in expected if len(c) <= 5], length_bound=5, chordless=True
)
G.add_edge(3, 7)
expected[-1] = [7, 3]
self.check_cycle_algorithm(G, expected, chordless=True)
self.check_cycle_algorithm(
G, [c for c in expected if len(c) <= 5], length_bound=5, chordless=True
)
expected.pop()
G.remove_edge(7, 3)
self.check_cycle_algorithm(G, expected, chordless=True)
self.check_cycle_algorithm(
G, [c for c in expected if len(c) <= 5], length_bound=5, chordless=True
)
def test_directed_chordless_cycle_diclique(self):
g_family = [self.D(n) for n in range(10)]
expected_cycles = [(n * n - n) // 2 for n in range(10)]
self.check_cycle_enumeration_integer_sequence(
g_family, expected_cycles, chordless=True
)
expected_cycles = [(n * n - n) // 2 for n in range(10)]
self.check_cycle_enumeration_integer_sequence(
g_family, expected_cycles, length_bound=2
)
def test_directed_chordless_loop_blockade(self):
g = nx.DiGraph((i, i) for i in range(10))
nx.add_cycle(g, range(10))
expected_cycles = [(i,) for i in range(10)]
self.check_cycle_algorithm(g, expected_cycles, chordless=True)
self.check_cycle_algorithm(g, expected_cycles, length_bound=1)
g = nx.MultiDiGraph(g)
g.add_edges_from((i, i) for i in range(0, 10, 2))
expected_cycles = [(i,) for i in range(1, 10, 2)]
self.check_cycle_algorithm(g, expected_cycles, chordless=True)
def test_simple_cycles_notable_clique_sequences(self):
# A000292: Number of labeled graphs on n+3 nodes that are triangles.
g_family = [self.K(n) for n in range(2, 12)]
expected = [0, 1, 4, 10, 20, 35, 56, 84, 120, 165, 220]
self.check_cycle_enumeration_integer_sequence(
g_family, expected, length_bound=3
)
def triangles(g, **kwargs):
yield from (c for c in nx.simple_cycles(g, **kwargs) if len(c) == 3)
# directed complete graphs have twice as many triangles thanks to reversal
g_family = [self.D(n) for n in range(2, 12)]
expected = [2 * e for e in expected]
self.check_cycle_enumeration_integer_sequence(
g_family, expected, length_bound=3, algorithm=triangles
)
def four_cycles(g, **kwargs):
yield from (c for c in nx.simple_cycles(g, **kwargs) if len(c) == 4)
# A050534: the number of 4-cycles in the complete graph K_{n+1}
expected = [0, 0, 0, 3, 15, 45, 105, 210, 378, 630, 990]
g_family = [self.K(n) for n in range(1, 12)]
self.check_cycle_enumeration_integer_sequence(
g_family, expected, length_bound=4, algorithm=four_cycles
)
# directed complete graphs have twice as many 4-cycles thanks to reversal
expected = [2 * e for e in expected]
g_family = [self.D(n) for n in range(1, 15)]
self.check_cycle_enumeration_integer_sequence(
g_family, expected, length_bound=4, algorithm=four_cycles
)
# A006231: the number of elementary circuits in a complete directed graph with n nodes
expected = [0, 1, 5, 20, 84, 409, 2365]
g_family = [self.D(n) for n in range(1, 8)]
self.check_cycle_enumeration_integer_sequence(g_family, expected)
# A002807: Number of cycles in the complete graph on n nodes K_{n}.
expected = [0, 0, 0, 1, 7, 37, 197, 1172]
g_family = [self.K(n) for n in range(8)]
self.check_cycle_enumeration_integer_sequence(g_family, expected)
def test_directed_chordless_cycle_parallel_multiedges(self):
g = nx.MultiGraph()
nx.add_cycle(g, range(5))
expected = [[*range(5)]]
self.check_cycle_algorithm(g, expected, chordless=True)
nx.add_cycle(g, range(5))
expected = [*cycle_edges(range(5))]
self.check_cycle_algorithm(g, expected, chordless=True)
nx.add_cycle(g, range(5))
expected = []
self.check_cycle_algorithm(g, expected, chordless=True)
g = nx.MultiDiGraph()
nx.add_cycle(g, range(5))
expected = [[*range(5)]]
self.check_cycle_algorithm(g, expected, chordless=True)
nx.add_cycle(g, range(5))
self.check_cycle_algorithm(g, [], chordless=True)
nx.add_cycle(g, range(5))
self.check_cycle_algorithm(g, [], chordless=True)
g = nx.MultiDiGraph()
nx.add_cycle(g, range(5))
nx.add_cycle(g, range(5)[::-1])
expected = [*cycle_edges(range(5))]
self.check_cycle_algorithm(g, expected, chordless=True)
nx.add_cycle(g, range(5))
self.check_cycle_algorithm(g, [], chordless=True)
def test_chordless_cycles_graph(self):
G = nx.Graph()
nx.add_cycle(G, range(5))
nx.add_cycle(G, range(4, 12))
expected = [[*range(5)], [*range(4, 12)]]
self.check_cycle_algorithm(G, expected, chordless=True)
self.check_cycle_algorithm(
G, [c for c in expected if len(c) <= 5], length_bound=5, chordless=True
)
G.add_edge(7, 3)
expected.append([*range(3, 8)])
expected.append([4, 3, 7, 8, 9, 10, 11])
self.check_cycle_algorithm(G, expected, chordless=True)
self.check_cycle_algorithm(
G, [c for c in expected if len(c) <= 5], length_bound=5, chordless=True
)
def test_chordless_cycles_giant_hamiltonian(self):
# ... o - e - o - e - o ... # o = odd, e = even
# ... ---/ \-----/ \--- ... # <-- "long" edges
#
# each long edge belongs to exactly one triangle, and one giant cycle
# of length n/2. The remaining edges each belong to a triangle
n = 1000
assert n % 2 == 0
G = nx.Graph()
for v in range(n):
if not v % 2:
G.add_edge(v, (v + 2) % n)
G.add_edge(v, (v + 1) % n)
expected = [[*range(0, n, 2)]] + [
[x % n for x in range(i, i + 3)] for i in range(0, n, 2)
]
self.check_cycle_algorithm(G, expected, chordless=True)
self.check_cycle_algorithm(
G, [c for c in expected if len(c) <= 3], length_bound=3, chordless=True
)
# ... o -> e -> o -> e -> o ... # o = odd, e = even
# ... <---/ \---<---/ \---< ... # <-- "long" edges
#
# this time, we orient the short and long edges in opposition
# the cycle structure of this graph is the same, but we need to reverse
# the long one in our representation. Also, we need to drop the size
# because our partitioning algorithm uses strongly connected components
# instead of separating graphs by their strong articulation points
n = 100
assert n % 2 == 0
G = nx.DiGraph()
for v in range(n):
G.add_edge(v, (v + 1) % n)
if not v % 2:
G.add_edge((v + 2) % n, v)
expected = [[*range(n - 2, -2, -2)]] + [
[x % n for x in range(i, i + 3)] for i in range(0, n, 2)
]
self.check_cycle_algorithm(G, expected, chordless=True)
self.check_cycle_algorithm(
G, [c for c in expected if len(c) <= 3], length_bound=3, chordless=True
)
def test_simple_cycles_acyclic_tournament(self):
n = 10
G = nx.DiGraph((x, y) for x in range(n) for y in range(x))
self.check_cycle_algorithm(G, [])
self.check_cycle_algorithm(G, [], chordless=True)
for k in range(n + 1):
self.check_cycle_algorithm(G, [], length_bound=k)
self.check_cycle_algorithm(G, [], length_bound=k, chordless=True)
def test_simple_cycles_graph(self):
testG = nx.cycle_graph(8)
cyc1 = tuple(range(8))
self.check_cycle_algorithm(testG, [cyc1])
testG.add_edge(4, -1)
nx.add_path(testG, [3, -2, -3, -4])
self.check_cycle_algorithm(testG, [cyc1])
testG.update(nx.cycle_graph(range(8, 16)))
cyc2 = tuple(range(8, 16))
self.check_cycle_algorithm(testG, [cyc1, cyc2])
testG.update(nx.cycle_graph(range(4, 12)))
cyc3 = tuple(range(4, 12))
expected = {
(0, 1, 2, 3, 4, 5, 6, 7), # cyc1
(8, 9, 10, 11, 12, 13, 14, 15), # cyc2
(4, 5, 6, 7, 8, 9, 10, 11), # cyc3
(4, 5, 6, 7, 8, 15, 14, 13, 12, 11), # cyc2 + cyc3
(0, 1, 2, 3, 4, 11, 10, 9, 8, 7), # cyc1 + cyc3
(0, 1, 2, 3, 4, 11, 12, 13, 14, 15, 8, 7), # cyc1 + cyc2 + cyc3
}
self.check_cycle_algorithm(testG, expected)
assert len(expected) == (2**3 - 1) - 1 # 1 disjoint comb: cyc1 + cyc2
# Basis size = 5 (2 loops overlapping gives 5 small loops
# E
# / \ Note: A-F = 10-15
# 1-2-3-4-5
# / | | \ cyc1=012DAB -- left
# 0 D F 6 cyc2=234E -- top
# \ | | / cyc3=45678F -- right
# B-A-9-8-7 cyc4=89AC -- bottom
# \ / cyc5=234F89AD -- middle
# C
#
# combinations of 5 basis elements: 2^5 - 1 (one includes no cycles)
#
# disjoint combs: (11 total) not simple cycles
# Any pair not including cyc5 => choose(4, 2) = 6
# Any triple not including cyc5 => choose(4, 3) = 4
# Any quad not including cyc5 => choose(4, 4) = 1
#
# we expect 31 - 11 = 20 simple cycles
#
testG = nx.cycle_graph(12)
testG.update(nx.cycle_graph([12, 10, 13, 2, 14, 4, 15, 8]).edges)
expected = (2**5 - 1) - 11 # 11 disjoint combinations
self.check_cycle_algorithm(testG, expected)
def test_simple_cycles_bounded(self):
# iteratively construct a cluster of nested cycles running in the same direction
# there should be one cycle of every length
d = nx.DiGraph()
expected = []
for n in range(10):
nx.add_cycle(d, range(n))
expected.append(n)
for k, e in enumerate(expected):
self.check_cycle_algorithm(d, e, length_bound=k)
# iteratively construct a path of undirected cycles, connected at articulation
# points. there should be one cycle of every length except 2: no digons
g = nx.Graph()
top = 0
expected = []
for n in range(10):
expected.append(n if n < 2 else n - 1)
if n == 2:
# no digons in undirected graphs
continue
nx.add_cycle(g, range(top, top + n))
top += n
for k, e in enumerate(expected):
self.check_cycle_algorithm(g, e, length_bound=k)
def test_simple_cycles_bound_corner_cases(self):
G = nx.cycle_graph(4)
DG = nx.cycle_graph(4, create_using=nx.DiGraph)
assert list(nx.simple_cycles(G, length_bound=0)) == []
assert list(nx.simple_cycles(DG, length_bound=0)) == []
assert list(nx.chordless_cycles(G, length_bound=0)) == []
assert list(nx.chordless_cycles(DG, length_bound=0)) == []
def test_simple_cycles_bound_error(self):
with pytest.raises(ValueError):
G = nx.DiGraph()
for c in nx.simple_cycles(G, -1):
assert False
with pytest.raises(ValueError):
G = nx.Graph()
for c in nx.simple_cycles(G, -1):
assert False
with pytest.raises(ValueError):
G = nx.Graph()
for c in nx.chordless_cycles(G, -1):
assert False
with pytest.raises(ValueError):
G = nx.DiGraph()
for c in nx.chordless_cycles(G, -1):
assert False
def test_chordless_cycles_clique(self):
g_family = [self.K(n) for n in range(2, 15)]
expected = [0, 1, 4, 10, 20, 35, 56, 84, 120, 165, 220, 286, 364]
self.check_cycle_enumeration_integer_sequence(
g_family, expected, chordless=True
)
# directed cliques have as many digons as undirected graphs have edges
expected = [(n * n - n) // 2 for n in range(15)]
g_family = [self.D(n) for n in range(15)]
self.check_cycle_enumeration_integer_sequence(
g_family, expected, chordless=True
)
# These tests might fail with hash randomization since they depend on
# edge_dfs. For more information, see the comments in:
# networkx/algorithms/traversal/tests/test_edgedfs.py
@@ -349,7 +858,7 @@ class TestMinimumCycles:
def test_complete_graph(self):
cg = nx.complete_graph(5)
mcb = minimum_cycle_basis(cg)
assert all([len(cycle) == 3 for cycle in mcb])
assert all(len(cycle) == 3 for cycle in mcb)
def test_tree_graph(self):
tg = nx.balanced_tree(3, 3)

View File

@@ -119,7 +119,7 @@ class TestDominanceFrontiers:
# Software Practice & Experience, 4:110, 2001.
edges = [(1, 2), (2, 1), (3, 2), (4, 1), (5, 3), (5, 4)]
G = nx.DiGraph(edges)
assert {u: df for u, df in nx.dominance_frontiers(G, 5).items()} == {
assert dict(nx.dominance_frontiers(G, 5).items()) == {
1: {2},
2: {1},
3: {2},

View File

@@ -42,7 +42,7 @@ class TestAtlas:
@classmethod
def setup_class(cls):
global atlas
import networkx.generators.atlas as atlas
from networkx.generators import atlas
cls.GAG = atlas.graph_atlas_g()

View File

@@ -48,7 +48,7 @@ class TestTreeLCA:
@staticmethod
def assert_has_same_pairs(d1, d2):
for (a, b) in ((min(pair), max(pair)) for pair in chain(d1, d2)):
for a, b in ((min(pair), max(pair)) for pair in chain(d1, d2)):
assert get_pair(d1, a, b) == get_pair(d2, a, b)
def test_tree_all_pairs_lca_default_root(self):

View File

@@ -71,7 +71,7 @@ class TestHarmonicFunction:
for i in label_removed:
del G.nodes[i][label_name]
predicted = node_classification.harmonic_function(G, label_name=label_name)
label_not_removed = set(list(range(len(G)))) - label_removed
label_not_removed = set(range(len(G))) - label_removed
for i in label_not_removed:
assert predicted[i] == G.nodes[i][label_name]

View File

@@ -231,7 +231,7 @@ class Vector:
return self.x * other.y < self.y * other.x
def __ne__(self, other):
return not self == other
return self != other
def __le__(self, other):
return not other < self

View File

@@ -4,7 +4,6 @@ import networkx as nx
class TestReciprocity:
# test overall reicprocity by passing whole graph
def test_reciprocity_digraph(self):
DG = nx.DiGraph([(1, 2), (2, 1)])

View File

@@ -238,9 +238,9 @@ def test_hamiltonian_path():
def test_cutoff_zero():
G = nx.complete_graph(4)
paths = nx.all_simple_paths(G, 0, 3, cutoff=0)
assert list(list(p) for p in paths) == []
assert [list(p) for p in paths] == []
paths = nx.all_simple_paths(nx.MultiGraph(G), 0, 3, cutoff=0)
assert list(list(p) for p in paths) == []
assert [list(p) for p in paths] == []
def test_source_missing():
@@ -422,15 +422,15 @@ def test_hamiltonian__edge_path():
G = nx.complete_graph(4)
paths = hamiltonian_edge_path(G, 0)
exact = [list(pairwise([0] + list(p))) for p in permutations([1, 2, 3], 3)]
assert sorted(exact) == [p for p in sorted(paths)]
assert sorted(exact) == sorted(paths)
def test_edge_cutoff_zero():
G = nx.complete_graph(4)
paths = nx.all_simple_edge_paths(G, 0, 3, cutoff=0)
assert list(list(p) for p in paths) == []
assert [list(p) for p in paths] == []
paths = nx.all_simple_edge_paths(nx.MultiGraph(G), 0, 3, cutoff=0)
assert list(list(p) for p in paths) == []
assert [list(p) for p in paths] == []
def test_edge_source_missing():
@@ -461,10 +461,10 @@ def test_shortest_simple_paths():
def test_shortest_simple_paths_directed():
G = nx.cycle_graph(7, create_using=nx.DiGraph())
paths = nx.shortest_simple_paths(G, 0, 3)
assert [path for path in paths] == [[0, 1, 2, 3]]
assert list(paths) == [[0, 1, 2, 3]]
def test_shortest_simple_paths_directed_with_weight_fucntion():
def test_shortest_simple_paths_directed_with_weight_function():
def cost(u, v, x):
return 1
@@ -477,13 +477,13 @@ def test_shortest_simple_paths_directed_with_weight_fucntion():
] == sorted(len(path) for path in nx.all_simple_paths(G, 1, 12))
def test_shortest_simple_paths_with_weight_fucntion():
def test_shortest_simple_paths_with_weight_function():
def cost(u, v, x):
return 1
G = nx.cycle_graph(7, create_using=nx.DiGraph())
paths = nx.shortest_simple_paths(G, 0, 3, weight=cost)
assert [path for path in paths] == [[0, 1, 2, 3]]
assert list(paths) == [[0, 1, 2, 3]]
def test_Greg_Bernstein():
@@ -721,7 +721,7 @@ def test_bidirectional_dijksta_restricted():
"s",
"v",
11,
*_bidirectional_dijkstra(XG, "s", "v", ignore_edges=[("s", "x")])
*_bidirectional_dijkstra(XG, "s", "v", ignore_edges=[("s", "x")]),
)
pytest.raises(
nx.NetworkXNoPath,

View File

@@ -4,6 +4,7 @@ import math
import pytest
import networkx as nx
from networkx.classes.tests import dispatch_interface
class TestStructuralHoles:
@@ -51,8 +52,11 @@ class TestStructuralHoles:
("G", "C"): 10,
}
def test_constraint_directed(self):
constraint = nx.constraint(self.D)
# This additionally tests the @nx._dispatch mechanism, treating
# nx.mutual_weight as if it were a re-implementation from another package
@pytest.mark.parametrize("wrapper", [lambda x: x, dispatch_interface.convert])
def test_constraint_directed(self, wrapper):
constraint = nx.constraint(wrapper(self.D))
assert constraint[0] == pytest.approx(1.003, abs=1e-3)
assert constraint[1] == pytest.approx(1.003, abs=1e-3)
assert constraint[2] == pytest.approx(1.389, abs=1e-3)

View File

@@ -253,7 +253,7 @@ class AbstractSNAP:
node_labels = sorted(node_labels, key=lambda n: sorted(G.nodes[n]["group"])[0])
node_labels.sort()
label_mapping = dict()
label_mapping = {}
for index, node in enumerate(node_labels):
label = "Supernode-%s" % index
label_mapping[node] = label
@@ -277,18 +277,18 @@ class TestSNAPNoEdgeTypes(AbstractSNAP):
def build_original_graph(self):
nodes = {
"A": dict(color="Red"),
"B": dict(color="Red"),
"C": dict(color="Red"),
"D": dict(color="Red"),
"E": dict(color="Blue"),
"F": dict(color="Blue"),
"G": dict(color="Blue"),
"H": dict(color="Blue"),
"I": dict(color="Yellow"),
"J": dict(color="Yellow"),
"K": dict(color="Yellow"),
"L": dict(color="Yellow"),
"A": {"color": "Red"},
"B": {"color": "Red"},
"C": {"color": "Red"},
"D": {"color": "Red"},
"E": {"color": "Blue"},
"F": {"color": "Blue"},
"G": {"color": "Blue"},
"H": {"color": "Blue"},
"I": {"color": "Yellow"},
"J": {"color": "Yellow"},
"K": {"color": "Yellow"},
"L": {"color": "Yellow"},
}
edges = [
("A", "B"),
@@ -316,12 +316,12 @@ class TestSNAPNoEdgeTypes(AbstractSNAP):
def build_summary_graph(self):
nodes = {
"Supernode-0": dict(color="Red"),
"Supernode-1": dict(color="Red"),
"Supernode-2": dict(color="Blue"),
"Supernode-3": dict(color="Blue"),
"Supernode-4": dict(color="Yellow"),
"Supernode-5": dict(color="Yellow"),
"Supernode-0": {"color": "Red"},
"Supernode-1": {"color": "Red"},
"Supernode-2": {"color": "Blue"},
"Supernode-3": {"color": "Blue"},
"Supernode-4": {"color": "Yellow"},
"Supernode-5": {"color": "Yellow"},
}
edges = [
("Supernode-0", "Supernode-0"),
@@ -355,18 +355,18 @@ class TestSNAPNoEdgeTypes(AbstractSNAP):
class TestSNAPUndirected(AbstractSNAP):
def build_original_graph(self):
nodes = {
"A": dict(color="Red"),
"B": dict(color="Red"),
"C": dict(color="Red"),
"D": dict(color="Red"),
"E": dict(color="Blue"),
"F": dict(color="Blue"),
"G": dict(color="Blue"),
"H": dict(color="Blue"),
"I": dict(color="Yellow"),
"J": dict(color="Yellow"),
"K": dict(color="Yellow"),
"L": dict(color="Yellow"),
"A": {"color": "Red"},
"B": {"color": "Red"},
"C": {"color": "Red"},
"D": {"color": "Red"},
"E": {"color": "Blue"},
"F": {"color": "Blue"},
"G": {"color": "Blue"},
"H": {"color": "Blue"},
"I": {"color": "Yellow"},
"J": {"color": "Yellow"},
"K": {"color": "Yellow"},
"L": {"color": "Yellow"},
}
edges = [
("A", "B", "Strong"),
@@ -394,12 +394,12 @@ class TestSNAPUndirected(AbstractSNAP):
def build_summary_graph(self):
nodes = {
"Supernode-0": dict(color="Red"),
"Supernode-1": dict(color="Red"),
"Supernode-2": dict(color="Blue"),
"Supernode-3": dict(color="Blue"),
"Supernode-4": dict(color="Yellow"),
"Supernode-5": dict(color="Yellow"),
"Supernode-0": {"color": "Red"},
"Supernode-1": {"color": "Red"},
"Supernode-2": {"color": "Blue"},
"Supernode-3": {"color": "Blue"},
"Supernode-4": {"color": "Yellow"},
"Supernode-5": {"color": "Yellow"},
}
edges = [
("Supernode-0", "Supernode-0", "Strong"),
@@ -416,7 +416,7 @@ class TestSNAPUndirected(AbstractSNAP):
G.add_node(node, **attributes)
for source, target, type in edges:
G.add_edge(source, target, types=[dict(type=type)])
G.add_edge(source, target, types=[{"type": type}])
supernodes = {
"Supernode-0": {"A", "B"},
@@ -433,14 +433,14 @@ class TestSNAPUndirected(AbstractSNAP):
class TestSNAPDirected(AbstractSNAP):
def build_original_graph(self):
nodes = {
"A": dict(color="Red"),
"B": dict(color="Red"),
"C": dict(color="Green"),
"D": dict(color="Green"),
"E": dict(color="Blue"),
"F": dict(color="Blue"),
"G": dict(color="Yellow"),
"H": dict(color="Yellow"),
"A": {"color": "Red"},
"B": {"color": "Red"},
"C": {"color": "Green"},
"D": {"color": "Green"},
"E": {"color": "Blue"},
"F": {"color": "Blue"},
"G": {"color": "Yellow"},
"H": {"color": "Yellow"},
}
edges = [
("A", "C", "Strong"),
@@ -468,10 +468,10 @@ class TestSNAPDirected(AbstractSNAP):
def build_summary_graph(self):
nodes = {
"Supernode-0": dict(color="Red"),
"Supernode-1": dict(color="Green"),
"Supernode-2": dict(color="Blue"),
"Supernode-3": dict(color="Yellow"),
"Supernode-0": {"color": "Red"},
"Supernode-1": {"color": "Green"},
"Supernode-2": {"color": "Blue"},
"Supernode-3": {"color": "Yellow"},
}
edges = [
("Supernode-0", "Supernode-1", [{"type": "Strong"}]),
@@ -503,15 +503,15 @@ class TestSNAPDirected(AbstractSNAP):
class TestSNAPUndirectedMulti(AbstractSNAP):
def build_original_graph(self):
nodes = {
"A": dict(color="Red"),
"B": dict(color="Red"),
"C": dict(color="Red"),
"D": dict(color="Blue"),
"E": dict(color="Blue"),
"F": dict(color="Blue"),
"G": dict(color="Yellow"),
"H": dict(color="Yellow"),
"I": dict(color="Yellow"),
"A": {"color": "Red"},
"B": {"color": "Red"},
"C": {"color": "Red"},
"D": {"color": "Blue"},
"E": {"color": "Blue"},
"F": {"color": "Blue"},
"G": {"color": "Yellow"},
"H": {"color": "Yellow"},
"I": {"color": "Yellow"},
}
edges = [
("A", "D", ["Weak", "Strong"]),
@@ -536,12 +536,12 @@ class TestSNAPUndirectedMulti(AbstractSNAP):
def build_summary_graph(self):
nodes = {
"Supernode-0": dict(color="Red"),
"Supernode-1": dict(color="Blue"),
"Supernode-2": dict(color="Yellow"),
"Supernode-3": dict(color="Blue"),
"Supernode-4": dict(color="Yellow"),
"Supernode-5": dict(color="Red"),
"Supernode-0": {"color": "Red"},
"Supernode-1": {"color": "Blue"},
"Supernode-2": {"color": "Yellow"},
"Supernode-3": {"color": "Blue"},
"Supernode-4": {"color": "Yellow"},
"Supernode-5": {"color": "Red"},
}
edges = [
("Supernode-1", "Supernode-2", [{"type": "Weak"}]),
@@ -574,14 +574,14 @@ class TestSNAPUndirectedMulti(AbstractSNAP):
class TestSNAPDirectedMulti(AbstractSNAP):
def build_original_graph(self):
nodes = {
"A": dict(color="Red"),
"B": dict(color="Red"),
"C": dict(color="Green"),
"D": dict(color="Green"),
"E": dict(color="Blue"),
"F": dict(color="Blue"),
"G": dict(color="Yellow"),
"H": dict(color="Yellow"),
"A": {"color": "Red"},
"B": {"color": "Red"},
"C": {"color": "Green"},
"D": {"color": "Green"},
"E": {"color": "Blue"},
"F": {"color": "Blue"},
"G": {"color": "Yellow"},
"H": {"color": "Yellow"},
}
edges = [
("A", "C", ["Weak", "Strong"]),
@@ -610,10 +610,10 @@ class TestSNAPDirectedMulti(AbstractSNAP):
def build_summary_graph(self):
nodes = {
"Supernode-0": dict(color="Red"),
"Supernode-1": dict(color="Blue"),
"Supernode-2": dict(color="Yellow"),
"Supernode-3": dict(color="Blue"),
"Supernode-0": {"color": "Red"},
"Supernode-1": {"color": "Blue"},
"Supernode-2": {"color": "Yellow"},
"Supernode-3": {"color": "Blue"},
}
edges = [
("Supernode-0", "Supernode-1", ["Weak", "Strong"]),

View File

@@ -16,11 +16,11 @@ class TestGeneratorThreshold:
def test_threshold_sequence_graph_test(self):
G = nx.star_graph(10)
assert nxt.is_threshold_graph(G)
assert nxt.is_threshold_sequence(list(d for n, d in G.degree()))
assert nxt.is_threshold_sequence([d for n, d in G.degree()])
G = nx.complete_graph(10)
assert nxt.is_threshold_graph(G)
assert nxt.is_threshold_sequence(list(d for n, d in G.degree()))
assert nxt.is_threshold_sequence([d for n, d in G.degree()])
deg = [3, 2, 2, 1, 1, 1]
assert not nxt.is_threshold_sequence(deg)

View File

@@ -56,8 +56,8 @@ def test_all_triplets():
for k in range(j + 1, 7)
]
expected = [set(x.split(",")) for x in expected]
actual = list(set(x) for x in nx.all_triplets(G))
assert all([any([s1 == s2 for s1 in expected]) for s2 in actual])
actual = [set(x) for x in nx.all_triplets(G)]
assert all(any(s1 == s2 for s1 in expected) for s2 in actual)
def test_all_triads():
@@ -72,7 +72,7 @@ def test_all_triads():
]
expected = [G.subgraph(x.split(",")) for x in expected]
actual = list(nx.all_triads(G))
assert all(any([nx.is_isomorphic(G1, G2) for G1 in expected]) for G2 in actual)
assert all(any(nx.is_isomorphic(G1, G2) for G1 in expected) for G2 in actual)
def test_triad_type():