Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/distutils-precedence.pth +3 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/__pycache__/conftest.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/__pycache__/convert.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/__pycache__/exception.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/__pycache__/lazy_imports.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/__pycache__/relabel.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/asteroidal.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/cluster.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/distance_regular.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/hierarchy.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/planarity.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/polynomials.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/smetric.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/vitality.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/voronoi.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/__pycache__/__init__.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/__pycache__/centrality.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/__pycache__/matching.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/__pycache__/redundancy.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/__init__.py +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/__pycache__/__init__.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/__pycache__/test_basic.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/__pycache__/test_cluster.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/__pycache__/test_edgelist.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/__pycache__/test_project.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/test_basic.py +125 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/test_cluster.py +84 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/test_covering.py +33 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/test_extendability.py +326 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/test_generators.py +400 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/test_matching.py +326 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/test_matrix.py +79 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/test_redundancy.py +37 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/centrality/__pycache__/dispersion.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/centrality/__pycache__/trophic.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/community/__pycache__/__init__.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/community/tests/__pycache__/test_asyn_fluid.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/community/tests/test_lukes.py +152 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/community/tests/test_quality.py +138 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/components/__init__.py +6 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/components/__pycache__/connected.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/components/__pycache__/semiconnected.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/components/biconnected.py +393 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/components/tests/__init__.py +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/components/tests/__pycache__/test_semiconnected.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/components/tests/test_biconnected.py +248 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/components/tests/test_connected.py +117 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/isomorphism/__init__.py +7 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/isomorphism/__pycache__/__init__.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/isomorphism/__pycache__/ismags.cpython-311.pyc +0 -0
tuning-competition-baseline/.venv/lib/python3.11/site-packages/distutils-precedence.pth
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2638ce9e2500e572a5e0de7faed6661eb569d1b696fcba07b0dd223da5f5d224
|
| 3 |
+
size 151
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/__pycache__/conftest.cpython-311.pyc
ADDED
|
Binary file (9.32 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/__pycache__/convert.cpython-311.pyc
ADDED
|
Binary file (20.6 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/__pycache__/exception.cpython-311.pyc
ADDED
|
Binary file (6.09 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/__pycache__/lazy_imports.cpython-311.pyc
ADDED
|
Binary file (8.02 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/__pycache__/relabel.cpython-311.pyc
ADDED
|
Binary file (16.2 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/asteroidal.cpython-311.pyc
ADDED
|
Binary file (7.01 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/cluster.cpython-311.pyc
ADDED
|
Binary file (30.2 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/distance_regular.cpython-311.pyc
ADDED
|
Binary file (9.03 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/hierarchy.cpython-311.pyc
ADDED
|
Binary file (2.51 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/planarity.cpython-311.pyc
ADDED
|
Binary file (48.4 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/polynomials.cpython-311.pyc
ADDED
|
Binary file (13 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/smetric.cpython-311.pyc
ADDED
|
Binary file (2.41 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/vitality.cpython-311.pyc
ADDED
|
Binary file (3.04 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/voronoi.cpython-311.pyc
ADDED
|
Binary file (3.54 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (4.17 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/__pycache__/centrality.cpython-311.pyc
ADDED
|
Binary file (11.5 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/__pycache__/matching.cpython-311.pyc
ADDED
|
Binary file (21.7 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/__pycache__/redundancy.cpython-311.pyc
ADDED
|
Binary file (4.87 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/__init__.py
ADDED
|
File without changes
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (236 Bytes). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/__pycache__/test_basic.cpython-311.pyc
ADDED
|
Binary file (11.1 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/__pycache__/test_cluster.cpython-311.pyc
ADDED
|
Binary file (6.45 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/__pycache__/test_edgelist.cpython-311.pyc
ADDED
|
Binary file (17 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/__pycache__/test_project.cpython-311.pyc
ADDED
|
Binary file (30.1 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/test_basic.py
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pytest
|
| 2 |
+
|
| 3 |
+
import networkx as nx
|
| 4 |
+
from networkx.algorithms import bipartite
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class TestBipartiteBasic:
|
| 8 |
+
def test_is_bipartite(self):
|
| 9 |
+
assert bipartite.is_bipartite(nx.path_graph(4))
|
| 10 |
+
assert bipartite.is_bipartite(nx.DiGraph([(1, 0)]))
|
| 11 |
+
assert not bipartite.is_bipartite(nx.complete_graph(3))
|
| 12 |
+
|
| 13 |
+
def test_bipartite_color(self):
|
| 14 |
+
G = nx.path_graph(4)
|
| 15 |
+
c = bipartite.color(G)
|
| 16 |
+
assert c == {0: 1, 1: 0, 2: 1, 3: 0}
|
| 17 |
+
|
| 18 |
+
def test_not_bipartite_color(self):
|
| 19 |
+
with pytest.raises(nx.NetworkXError):
|
| 20 |
+
c = bipartite.color(nx.complete_graph(4))
|
| 21 |
+
|
| 22 |
+
def test_bipartite_directed(self):
|
| 23 |
+
G = bipartite.random_graph(10, 10, 0.1, directed=True)
|
| 24 |
+
assert bipartite.is_bipartite(G)
|
| 25 |
+
|
| 26 |
+
def test_bipartite_sets(self):
|
| 27 |
+
G = nx.path_graph(4)
|
| 28 |
+
X, Y = bipartite.sets(G)
|
| 29 |
+
assert X == {0, 2}
|
| 30 |
+
assert Y == {1, 3}
|
| 31 |
+
|
| 32 |
+
def test_bipartite_sets_directed(self):
|
| 33 |
+
G = nx.path_graph(4)
|
| 34 |
+
D = G.to_directed()
|
| 35 |
+
X, Y = bipartite.sets(D)
|
| 36 |
+
assert X == {0, 2}
|
| 37 |
+
assert Y == {1, 3}
|
| 38 |
+
|
| 39 |
+
def test_bipartite_sets_given_top_nodes(self):
|
| 40 |
+
G = nx.path_graph(4)
|
| 41 |
+
top_nodes = [0, 2]
|
| 42 |
+
X, Y = bipartite.sets(G, top_nodes)
|
| 43 |
+
assert X == {0, 2}
|
| 44 |
+
assert Y == {1, 3}
|
| 45 |
+
|
| 46 |
+
def test_bipartite_sets_disconnected(self):
|
| 47 |
+
with pytest.raises(nx.AmbiguousSolution):
|
| 48 |
+
G = nx.path_graph(4)
|
| 49 |
+
G.add_edges_from([(5, 6), (6, 7)])
|
| 50 |
+
X, Y = bipartite.sets(G)
|
| 51 |
+
|
| 52 |
+
def test_is_bipartite_node_set(self):
|
| 53 |
+
G = nx.path_graph(4)
|
| 54 |
+
|
| 55 |
+
with pytest.raises(nx.AmbiguousSolution):
|
| 56 |
+
bipartite.is_bipartite_node_set(G, [1, 1, 2, 3])
|
| 57 |
+
|
| 58 |
+
assert bipartite.is_bipartite_node_set(G, [0, 2])
|
| 59 |
+
assert bipartite.is_bipartite_node_set(G, [1, 3])
|
| 60 |
+
assert not bipartite.is_bipartite_node_set(G, [1, 2])
|
| 61 |
+
G.add_edge(10, 20)
|
| 62 |
+
assert bipartite.is_bipartite_node_set(G, [0, 2, 10])
|
| 63 |
+
assert bipartite.is_bipartite_node_set(G, [0, 2, 20])
|
| 64 |
+
assert bipartite.is_bipartite_node_set(G, [1, 3, 10])
|
| 65 |
+
assert bipartite.is_bipartite_node_set(G, [1, 3, 20])
|
| 66 |
+
|
| 67 |
+
def test_bipartite_density(self):
|
| 68 |
+
G = nx.path_graph(5)
|
| 69 |
+
X, Y = bipartite.sets(G)
|
| 70 |
+
density = len(list(G.edges())) / (len(X) * len(Y))
|
| 71 |
+
assert bipartite.density(G, X) == density
|
| 72 |
+
D = nx.DiGraph(G.edges())
|
| 73 |
+
assert bipartite.density(D, X) == density / 2.0
|
| 74 |
+
assert bipartite.density(nx.Graph(), {}) == 0.0
|
| 75 |
+
|
| 76 |
+
def test_bipartite_degrees(self):
|
| 77 |
+
G = nx.path_graph(5)
|
| 78 |
+
X = {1, 3}
|
| 79 |
+
Y = {0, 2, 4}
|
| 80 |
+
u, d = bipartite.degrees(G, Y)
|
| 81 |
+
assert dict(u) == {1: 2, 3: 2}
|
| 82 |
+
assert dict(d) == {0: 1, 2: 2, 4: 1}
|
| 83 |
+
|
| 84 |
+
def test_bipartite_weighted_degrees(self):
|
| 85 |
+
G = nx.path_graph(5)
|
| 86 |
+
G.add_edge(0, 1, weight=0.1, other=0.2)
|
| 87 |
+
X = {1, 3}
|
| 88 |
+
Y = {0, 2, 4}
|
| 89 |
+
u, d = bipartite.degrees(G, Y, weight="weight")
|
| 90 |
+
assert dict(u) == {1: 1.1, 3: 2}
|
| 91 |
+
assert dict(d) == {0: 0.1, 2: 2, 4: 1}
|
| 92 |
+
u, d = bipartite.degrees(G, Y, weight="other")
|
| 93 |
+
assert dict(u) == {1: 1.2, 3: 2}
|
| 94 |
+
assert dict(d) == {0: 0.2, 2: 2, 4: 1}
|
| 95 |
+
|
| 96 |
+
def test_biadjacency_matrix_weight(self):
|
| 97 |
+
pytest.importorskip("scipy")
|
| 98 |
+
G = nx.path_graph(5)
|
| 99 |
+
G.add_edge(0, 1, weight=2, other=4)
|
| 100 |
+
X = [1, 3]
|
| 101 |
+
Y = [0, 2, 4]
|
| 102 |
+
M = bipartite.biadjacency_matrix(G, X, weight="weight")
|
| 103 |
+
assert M[0, 0] == 2
|
| 104 |
+
M = bipartite.biadjacency_matrix(G, X, weight="other")
|
| 105 |
+
assert M[0, 0] == 4
|
| 106 |
+
|
| 107 |
+
def test_biadjacency_matrix(self):
|
| 108 |
+
pytest.importorskip("scipy")
|
| 109 |
+
tops = [2, 5, 10]
|
| 110 |
+
bots = [5, 10, 15]
|
| 111 |
+
for i in range(len(tops)):
|
| 112 |
+
G = bipartite.random_graph(tops[i], bots[i], 0.2)
|
| 113 |
+
top = [n for n, d in G.nodes(data=True) if d["bipartite"] == 0]
|
| 114 |
+
M = bipartite.biadjacency_matrix(G, top)
|
| 115 |
+
assert M.shape[0] == tops[i]
|
| 116 |
+
assert M.shape[1] == bots[i]
|
| 117 |
+
|
| 118 |
+
def test_biadjacency_matrix_order(self):
|
| 119 |
+
pytest.importorskip("scipy")
|
| 120 |
+
G = nx.path_graph(5)
|
| 121 |
+
G.add_edge(0, 1, weight=2)
|
| 122 |
+
X = [3, 1]
|
| 123 |
+
Y = [4, 2, 0]
|
| 124 |
+
M = bipartite.biadjacency_matrix(G, X, Y, weight="weight")
|
| 125 |
+
assert M[1, 2] == 2
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/test_cluster.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pytest
|
| 2 |
+
|
| 3 |
+
import networkx as nx
|
| 4 |
+
from networkx.algorithms import bipartite
|
| 5 |
+
from networkx.algorithms.bipartite.cluster import cc_dot, cc_max, cc_min
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def test_pairwise_bipartite_cc_functions():
|
| 9 |
+
# Test functions for different kinds of bipartite clustering coefficients
|
| 10 |
+
# between pairs of nodes using 3 example graphs from figure 5 p. 40
|
| 11 |
+
# Latapy et al (2008)
|
| 12 |
+
G1 = nx.Graph([(0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (1, 5), (1, 6), (1, 7)])
|
| 13 |
+
G2 = nx.Graph([(0, 2), (0, 3), (0, 4), (1, 3), (1, 4), (1, 5)])
|
| 14 |
+
G3 = nx.Graph(
|
| 15 |
+
[(0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (1, 5), (1, 6), (1, 7), (1, 8), (1, 9)]
|
| 16 |
+
)
|
| 17 |
+
result = {
|
| 18 |
+
0: [1 / 3.0, 2 / 3.0, 2 / 5.0],
|
| 19 |
+
1: [1 / 2.0, 2 / 3.0, 2 / 3.0],
|
| 20 |
+
2: [2 / 8.0, 2 / 5.0, 2 / 5.0],
|
| 21 |
+
}
|
| 22 |
+
for i, G in enumerate([G1, G2, G3]):
|
| 23 |
+
assert bipartite.is_bipartite(G)
|
| 24 |
+
assert cc_dot(set(G[0]), set(G[1])) == result[i][0]
|
| 25 |
+
assert cc_min(set(G[0]), set(G[1])) == result[i][1]
|
| 26 |
+
assert cc_max(set(G[0]), set(G[1])) == result[i][2]
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def test_star_graph():
|
| 30 |
+
G = nx.star_graph(3)
|
| 31 |
+
# all modes are the same
|
| 32 |
+
answer = {0: 0, 1: 1, 2: 1, 3: 1}
|
| 33 |
+
assert bipartite.clustering(G, mode="dot") == answer
|
| 34 |
+
assert bipartite.clustering(G, mode="min") == answer
|
| 35 |
+
assert bipartite.clustering(G, mode="max") == answer
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
def test_not_bipartite():
|
| 39 |
+
with pytest.raises(nx.NetworkXError):
|
| 40 |
+
bipartite.clustering(nx.complete_graph(4))
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
def test_bad_mode():
|
| 44 |
+
with pytest.raises(nx.NetworkXError):
|
| 45 |
+
bipartite.clustering(nx.path_graph(4), mode="foo")
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def test_path_graph():
|
| 49 |
+
G = nx.path_graph(4)
|
| 50 |
+
answer = {0: 0.5, 1: 0.5, 2: 0.5, 3: 0.5}
|
| 51 |
+
assert bipartite.clustering(G, mode="dot") == answer
|
| 52 |
+
assert bipartite.clustering(G, mode="max") == answer
|
| 53 |
+
answer = {0: 1, 1: 1, 2: 1, 3: 1}
|
| 54 |
+
assert bipartite.clustering(G, mode="min") == answer
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def test_average_path_graph():
|
| 58 |
+
G = nx.path_graph(4)
|
| 59 |
+
assert bipartite.average_clustering(G, mode="dot") == 0.5
|
| 60 |
+
assert bipartite.average_clustering(G, mode="max") == 0.5
|
| 61 |
+
assert bipartite.average_clustering(G, mode="min") == 1
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
def test_ra_clustering_davis():
|
| 65 |
+
G = nx.davis_southern_women_graph()
|
| 66 |
+
cc4 = round(bipartite.robins_alexander_clustering(G), 3)
|
| 67 |
+
assert cc4 == 0.468
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def test_ra_clustering_square():
|
| 71 |
+
G = nx.path_graph(4)
|
| 72 |
+
G.add_edge(0, 3)
|
| 73 |
+
assert bipartite.robins_alexander_clustering(G) == 1.0
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def test_ra_clustering_zero():
|
| 77 |
+
G = nx.Graph()
|
| 78 |
+
assert bipartite.robins_alexander_clustering(G) == 0
|
| 79 |
+
G.add_nodes_from(range(4))
|
| 80 |
+
assert bipartite.robins_alexander_clustering(G) == 0
|
| 81 |
+
G.add_edges_from([(0, 1), (2, 3), (3, 4)])
|
| 82 |
+
assert bipartite.robins_alexander_clustering(G) == 0
|
| 83 |
+
G.add_edge(1, 2)
|
| 84 |
+
assert bipartite.robins_alexander_clustering(G) == 0
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/test_covering.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import networkx as nx
|
| 2 |
+
from networkx.algorithms import bipartite
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class TestMinEdgeCover:
|
| 6 |
+
"""Tests for :func:`networkx.algorithms.bipartite.min_edge_cover`"""
|
| 7 |
+
|
| 8 |
+
def test_empty_graph(self):
|
| 9 |
+
G = nx.Graph()
|
| 10 |
+
assert bipartite.min_edge_cover(G) == set()
|
| 11 |
+
|
| 12 |
+
def test_graph_single_edge(self):
|
| 13 |
+
G = nx.Graph()
|
| 14 |
+
G.add_edge(0, 1)
|
| 15 |
+
assert bipartite.min_edge_cover(G) == {(0, 1), (1, 0)}
|
| 16 |
+
|
| 17 |
+
def test_bipartite_default(self):
|
| 18 |
+
G = nx.Graph()
|
| 19 |
+
G.add_nodes_from([1, 2, 3, 4], bipartite=0)
|
| 20 |
+
G.add_nodes_from(["a", "b", "c"], bipartite=1)
|
| 21 |
+
G.add_edges_from([(1, "a"), (1, "b"), (2, "b"), (2, "c"), (3, "c"), (4, "a")])
|
| 22 |
+
min_cover = bipartite.min_edge_cover(G)
|
| 23 |
+
assert nx.is_edge_cover(G, min_cover)
|
| 24 |
+
assert len(min_cover) == 8
|
| 25 |
+
|
| 26 |
+
def test_bipartite_explicit(self):
|
| 27 |
+
G = nx.Graph()
|
| 28 |
+
G.add_nodes_from([1, 2, 3, 4], bipartite=0)
|
| 29 |
+
G.add_nodes_from(["a", "b", "c"], bipartite=1)
|
| 30 |
+
G.add_edges_from([(1, "a"), (1, "b"), (2, "b"), (2, "c"), (3, "c"), (4, "a")])
|
| 31 |
+
min_cover = bipartite.min_edge_cover(G, bipartite.eppstein_matching)
|
| 32 |
+
assert nx.is_edge_cover(G, min_cover)
|
| 33 |
+
assert len(min_cover) == 8
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/test_extendability.py
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pytest
|
| 2 |
+
|
| 3 |
+
import networkx as nx
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def test_selfloops_raises():
|
| 7 |
+
G = nx.ladder_graph(3)
|
| 8 |
+
G.add_edge(0, 0)
|
| 9 |
+
with pytest.raises(nx.NetworkXError, match=".*not bipartite"):
|
| 10 |
+
nx.bipartite.maximal_extendability(G)
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def test_disconnected_raises():
|
| 14 |
+
G = nx.ladder_graph(3)
|
| 15 |
+
G.add_node("a")
|
| 16 |
+
with pytest.raises(nx.NetworkXError, match=".*not connected"):
|
| 17 |
+
nx.bipartite.maximal_extendability(G)
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def test_not_bipartite_raises():
|
| 21 |
+
G = nx.complete_graph(5)
|
| 22 |
+
with pytest.raises(nx.NetworkXError, match=".*not bipartite"):
|
| 23 |
+
nx.bipartite.maximal_extendability(G)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def test_no_perfect_matching_raises():
|
| 27 |
+
G = nx.Graph([(0, 1), (0, 2)])
|
| 28 |
+
with pytest.raises(nx.NetworkXError, match=".*not contain a perfect matching"):
|
| 29 |
+
nx.bipartite.maximal_extendability(G)
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def test_ladder_graph_is_1():
|
| 33 |
+
G = nx.ladder_graph(3)
|
| 34 |
+
assert nx.bipartite.maximal_extendability(G) == 1
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def test_cubical_graph_is_2():
|
| 38 |
+
G = nx.cubical_graph()
|
| 39 |
+
assert nx.bipartite.maximal_extendability(G) == 2
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def test_k_is_3():
|
| 43 |
+
G = nx.Graph(
|
| 44 |
+
[
|
| 45 |
+
(1, 6),
|
| 46 |
+
(1, 7),
|
| 47 |
+
(1, 8),
|
| 48 |
+
(1, 9),
|
| 49 |
+
(2, 6),
|
| 50 |
+
(2, 7),
|
| 51 |
+
(2, 8),
|
| 52 |
+
(2, 10),
|
| 53 |
+
(3, 6),
|
| 54 |
+
(3, 8),
|
| 55 |
+
(3, 9),
|
| 56 |
+
(3, 10),
|
| 57 |
+
(4, 7),
|
| 58 |
+
(4, 8),
|
| 59 |
+
(4, 9),
|
| 60 |
+
(4, 10),
|
| 61 |
+
(5, 6),
|
| 62 |
+
(5, 7),
|
| 63 |
+
(5, 9),
|
| 64 |
+
(5, 10),
|
| 65 |
+
]
|
| 66 |
+
)
|
| 67 |
+
assert nx.bipartite.maximal_extendability(G) == 3
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def test_k_is_4():
|
| 71 |
+
G = nx.Graph(
|
| 72 |
+
[
|
| 73 |
+
(8, 1),
|
| 74 |
+
(8, 2),
|
| 75 |
+
(8, 3),
|
| 76 |
+
(8, 4),
|
| 77 |
+
(8, 5),
|
| 78 |
+
(9, 1),
|
| 79 |
+
(9, 2),
|
| 80 |
+
(9, 3),
|
| 81 |
+
(9, 4),
|
| 82 |
+
(9, 7),
|
| 83 |
+
(10, 1),
|
| 84 |
+
(10, 2),
|
| 85 |
+
(10, 3),
|
| 86 |
+
(10, 4),
|
| 87 |
+
(10, 6),
|
| 88 |
+
(11, 1),
|
| 89 |
+
(11, 2),
|
| 90 |
+
(11, 5),
|
| 91 |
+
(11, 6),
|
| 92 |
+
(11, 7),
|
| 93 |
+
(12, 1),
|
| 94 |
+
(12, 3),
|
| 95 |
+
(12, 5),
|
| 96 |
+
(12, 6),
|
| 97 |
+
(12, 7),
|
| 98 |
+
(13, 2),
|
| 99 |
+
(13, 4),
|
| 100 |
+
(13, 5),
|
| 101 |
+
(13, 6),
|
| 102 |
+
(13, 7),
|
| 103 |
+
(14, 3),
|
| 104 |
+
(14, 4),
|
| 105 |
+
(14, 5),
|
| 106 |
+
(14, 6),
|
| 107 |
+
(14, 7),
|
| 108 |
+
]
|
| 109 |
+
)
|
| 110 |
+
assert nx.bipartite.maximal_extendability(G) == 4
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
def test_k_is_5():
|
| 114 |
+
G = nx.Graph(
|
| 115 |
+
[
|
| 116 |
+
(8, 1),
|
| 117 |
+
(8, 2),
|
| 118 |
+
(8, 3),
|
| 119 |
+
(8, 4),
|
| 120 |
+
(8, 5),
|
| 121 |
+
(8, 6),
|
| 122 |
+
(9, 1),
|
| 123 |
+
(9, 2),
|
| 124 |
+
(9, 3),
|
| 125 |
+
(9, 4),
|
| 126 |
+
(9, 5),
|
| 127 |
+
(9, 7),
|
| 128 |
+
(10, 1),
|
| 129 |
+
(10, 2),
|
| 130 |
+
(10, 3),
|
| 131 |
+
(10, 4),
|
| 132 |
+
(10, 6),
|
| 133 |
+
(10, 7),
|
| 134 |
+
(11, 1),
|
| 135 |
+
(11, 2),
|
| 136 |
+
(11, 3),
|
| 137 |
+
(11, 5),
|
| 138 |
+
(11, 6),
|
| 139 |
+
(11, 7),
|
| 140 |
+
(12, 1),
|
| 141 |
+
(12, 2),
|
| 142 |
+
(12, 4),
|
| 143 |
+
(12, 5),
|
| 144 |
+
(12, 6),
|
| 145 |
+
(12, 7),
|
| 146 |
+
(13, 1),
|
| 147 |
+
(13, 3),
|
| 148 |
+
(13, 4),
|
| 149 |
+
(13, 5),
|
| 150 |
+
(13, 6),
|
| 151 |
+
(13, 7),
|
| 152 |
+
(14, 2),
|
| 153 |
+
(14, 3),
|
| 154 |
+
(14, 4),
|
| 155 |
+
(14, 5),
|
| 156 |
+
(14, 6),
|
| 157 |
+
(14, 7),
|
| 158 |
+
]
|
| 159 |
+
)
|
| 160 |
+
assert nx.bipartite.maximal_extendability(G) == 5
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
def test_k_is_6():
|
| 164 |
+
G = nx.Graph(
|
| 165 |
+
[
|
| 166 |
+
(9, 1),
|
| 167 |
+
(9, 2),
|
| 168 |
+
(9, 3),
|
| 169 |
+
(9, 4),
|
| 170 |
+
(9, 5),
|
| 171 |
+
(9, 6),
|
| 172 |
+
(9, 7),
|
| 173 |
+
(10, 1),
|
| 174 |
+
(10, 2),
|
| 175 |
+
(10, 3),
|
| 176 |
+
(10, 4),
|
| 177 |
+
(10, 5),
|
| 178 |
+
(10, 6),
|
| 179 |
+
(10, 8),
|
| 180 |
+
(11, 1),
|
| 181 |
+
(11, 2),
|
| 182 |
+
(11, 3),
|
| 183 |
+
(11, 4),
|
| 184 |
+
(11, 5),
|
| 185 |
+
(11, 7),
|
| 186 |
+
(11, 8),
|
| 187 |
+
(12, 1),
|
| 188 |
+
(12, 2),
|
| 189 |
+
(12, 3),
|
| 190 |
+
(12, 4),
|
| 191 |
+
(12, 6),
|
| 192 |
+
(12, 7),
|
| 193 |
+
(12, 8),
|
| 194 |
+
(13, 1),
|
| 195 |
+
(13, 2),
|
| 196 |
+
(13, 3),
|
| 197 |
+
(13, 5),
|
| 198 |
+
(13, 6),
|
| 199 |
+
(13, 7),
|
| 200 |
+
(13, 8),
|
| 201 |
+
(14, 1),
|
| 202 |
+
(14, 2),
|
| 203 |
+
(14, 4),
|
| 204 |
+
(14, 5),
|
| 205 |
+
(14, 6),
|
| 206 |
+
(14, 7),
|
| 207 |
+
(14, 8),
|
| 208 |
+
(15, 1),
|
| 209 |
+
(15, 3),
|
| 210 |
+
(15, 4),
|
| 211 |
+
(15, 5),
|
| 212 |
+
(15, 6),
|
| 213 |
+
(15, 7),
|
| 214 |
+
(15, 8),
|
| 215 |
+
(16, 2),
|
| 216 |
+
(16, 3),
|
| 217 |
+
(16, 4),
|
| 218 |
+
(16, 5),
|
| 219 |
+
(16, 6),
|
| 220 |
+
(16, 7),
|
| 221 |
+
(16, 8),
|
| 222 |
+
]
|
| 223 |
+
)
|
| 224 |
+
assert nx.bipartite.maximal_extendability(G) == 6
|
| 225 |
+
|
| 226 |
+
|
| 227 |
+
def test_k_is_7():
|
| 228 |
+
G = nx.Graph(
|
| 229 |
+
[
|
| 230 |
+
(1, 11),
|
| 231 |
+
(1, 12),
|
| 232 |
+
(1, 13),
|
| 233 |
+
(1, 14),
|
| 234 |
+
(1, 15),
|
| 235 |
+
(1, 16),
|
| 236 |
+
(1, 17),
|
| 237 |
+
(1, 18),
|
| 238 |
+
(2, 11),
|
| 239 |
+
(2, 12),
|
| 240 |
+
(2, 13),
|
| 241 |
+
(2, 14),
|
| 242 |
+
(2, 15),
|
| 243 |
+
(2, 16),
|
| 244 |
+
(2, 17),
|
| 245 |
+
(2, 19),
|
| 246 |
+
(3, 11),
|
| 247 |
+
(3, 12),
|
| 248 |
+
(3, 13),
|
| 249 |
+
(3, 14),
|
| 250 |
+
(3, 15),
|
| 251 |
+
(3, 16),
|
| 252 |
+
(3, 17),
|
| 253 |
+
(3, 20),
|
| 254 |
+
(4, 11),
|
| 255 |
+
(4, 12),
|
| 256 |
+
(4, 13),
|
| 257 |
+
(4, 14),
|
| 258 |
+
(4, 15),
|
| 259 |
+
(4, 16),
|
| 260 |
+
(4, 17),
|
| 261 |
+
(4, 18),
|
| 262 |
+
(4, 19),
|
| 263 |
+
(4, 20),
|
| 264 |
+
(5, 11),
|
| 265 |
+
(5, 12),
|
| 266 |
+
(5, 13),
|
| 267 |
+
(5, 14),
|
| 268 |
+
(5, 15),
|
| 269 |
+
(5, 16),
|
| 270 |
+
(5, 17),
|
| 271 |
+
(5, 18),
|
| 272 |
+
(5, 19),
|
| 273 |
+
(5, 20),
|
| 274 |
+
(6, 11),
|
| 275 |
+
(6, 12),
|
| 276 |
+
(6, 13),
|
| 277 |
+
(6, 14),
|
| 278 |
+
(6, 15),
|
| 279 |
+
(6, 16),
|
| 280 |
+
(6, 17),
|
| 281 |
+
(6, 18),
|
| 282 |
+
(6, 19),
|
| 283 |
+
(6, 20),
|
| 284 |
+
(7, 11),
|
| 285 |
+
(7, 12),
|
| 286 |
+
(7, 13),
|
| 287 |
+
(7, 14),
|
| 288 |
+
(7, 15),
|
| 289 |
+
(7, 16),
|
| 290 |
+
(7, 17),
|
| 291 |
+
(7, 18),
|
| 292 |
+
(7, 19),
|
| 293 |
+
(7, 20),
|
| 294 |
+
(8, 11),
|
| 295 |
+
(8, 12),
|
| 296 |
+
(8, 13),
|
| 297 |
+
(8, 14),
|
| 298 |
+
(8, 15),
|
| 299 |
+
(8, 16),
|
| 300 |
+
(8, 17),
|
| 301 |
+
(8, 18),
|
| 302 |
+
(8, 19),
|
| 303 |
+
(8, 20),
|
| 304 |
+
(9, 11),
|
| 305 |
+
(9, 12),
|
| 306 |
+
(9, 13),
|
| 307 |
+
(9, 14),
|
| 308 |
+
(9, 15),
|
| 309 |
+
(9, 16),
|
| 310 |
+
(9, 17),
|
| 311 |
+
(9, 18),
|
| 312 |
+
(9, 19),
|
| 313 |
+
(9, 20),
|
| 314 |
+
(10, 11),
|
| 315 |
+
(10, 12),
|
| 316 |
+
(10, 13),
|
| 317 |
+
(10, 14),
|
| 318 |
+
(10, 15),
|
| 319 |
+
(10, 16),
|
| 320 |
+
(10, 17),
|
| 321 |
+
(10, 18),
|
| 322 |
+
(10, 19),
|
| 323 |
+
(10, 20),
|
| 324 |
+
]
|
| 325 |
+
)
|
| 326 |
+
assert nx.bipartite.maximal_extendability(G) == 7
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/test_generators.py
ADDED
|
@@ -0,0 +1,400 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numbers
|
| 2 |
+
|
| 3 |
+
import pytest
|
| 4 |
+
|
| 5 |
+
import networkx as nx
|
| 6 |
+
|
| 7 |
+
from ..generators import (
|
| 8 |
+
alternating_havel_hakimi_graph,
|
| 9 |
+
complete_bipartite_graph,
|
| 10 |
+
configuration_model,
|
| 11 |
+
gnmk_random_graph,
|
| 12 |
+
havel_hakimi_graph,
|
| 13 |
+
preferential_attachment_graph,
|
| 14 |
+
random_graph,
|
| 15 |
+
reverse_havel_hakimi_graph,
|
| 16 |
+
)
|
| 17 |
+
|
| 18 |
+
"""
|
| 19 |
+
Generators - Bipartite
|
| 20 |
+
----------------------
|
| 21 |
+
"""
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
class TestGeneratorsBipartite:
|
| 25 |
+
def test_complete_bipartite_graph(self):
|
| 26 |
+
G = complete_bipartite_graph(0, 0)
|
| 27 |
+
assert nx.is_isomorphic(G, nx.null_graph())
|
| 28 |
+
|
| 29 |
+
for i in [1, 5]:
|
| 30 |
+
G = complete_bipartite_graph(i, 0)
|
| 31 |
+
assert nx.is_isomorphic(G, nx.empty_graph(i))
|
| 32 |
+
G = complete_bipartite_graph(0, i)
|
| 33 |
+
assert nx.is_isomorphic(G, nx.empty_graph(i))
|
| 34 |
+
|
| 35 |
+
G = complete_bipartite_graph(2, 2)
|
| 36 |
+
assert nx.is_isomorphic(G, nx.cycle_graph(4))
|
| 37 |
+
|
| 38 |
+
G = complete_bipartite_graph(1, 5)
|
| 39 |
+
assert nx.is_isomorphic(G, nx.star_graph(5))
|
| 40 |
+
|
| 41 |
+
G = complete_bipartite_graph(5, 1)
|
| 42 |
+
assert nx.is_isomorphic(G, nx.star_graph(5))
|
| 43 |
+
|
| 44 |
+
# complete_bipartite_graph(m1,m2) is a connected graph with
|
| 45 |
+
# m1+m2 nodes and m1*m2 edges
|
| 46 |
+
for m1, m2 in [(5, 11), (7, 3)]:
|
| 47 |
+
G = complete_bipartite_graph(m1, m2)
|
| 48 |
+
assert nx.number_of_nodes(G) == m1 + m2
|
| 49 |
+
assert nx.number_of_edges(G) == m1 * m2
|
| 50 |
+
|
| 51 |
+
with pytest.raises(nx.NetworkXError):
|
| 52 |
+
complete_bipartite_graph(7, 3, create_using=nx.DiGraph)
|
| 53 |
+
with pytest.raises(nx.NetworkXError):
|
| 54 |
+
complete_bipartite_graph(7, 3, create_using=nx.MultiDiGraph)
|
| 55 |
+
|
| 56 |
+
mG = complete_bipartite_graph(7, 3, create_using=nx.MultiGraph)
|
| 57 |
+
assert mG.is_multigraph()
|
| 58 |
+
assert sorted(mG.edges()) == sorted(G.edges())
|
| 59 |
+
|
| 60 |
+
mG = complete_bipartite_graph(7, 3, create_using=nx.MultiGraph)
|
| 61 |
+
assert mG.is_multigraph()
|
| 62 |
+
assert sorted(mG.edges()) == sorted(G.edges())
|
| 63 |
+
|
| 64 |
+
mG = complete_bipartite_graph(7, 3) # default to Graph
|
| 65 |
+
assert sorted(mG.edges()) == sorted(G.edges())
|
| 66 |
+
assert not mG.is_multigraph()
|
| 67 |
+
assert not mG.is_directed()
|
| 68 |
+
|
| 69 |
+
# specify nodes rather than number of nodes
|
| 70 |
+
for n1, n2 in [([1, 2], "ab"), (3, 2), (3, "ab"), ("ab", 3)]:
|
| 71 |
+
G = complete_bipartite_graph(n1, n2)
|
| 72 |
+
if isinstance(n1, numbers.Integral):
|
| 73 |
+
if isinstance(n2, numbers.Integral):
|
| 74 |
+
n2 = range(n1, n1 + n2)
|
| 75 |
+
n1 = range(n1)
|
| 76 |
+
elif isinstance(n2, numbers.Integral):
|
| 77 |
+
n2 = range(n2)
|
| 78 |
+
edges = {(u, v) for u in n1 for v in n2}
|
| 79 |
+
assert edges == set(G.edges)
|
| 80 |
+
assert G.size() == len(edges)
|
| 81 |
+
|
| 82 |
+
# raise when node sets are not distinct
|
| 83 |
+
for n1, n2 in [([1, 2], 3), (3, [1, 2]), ("abc", "bcd")]:
|
| 84 |
+
pytest.raises(nx.NetworkXError, complete_bipartite_graph, n1, n2)
|
| 85 |
+
|
| 86 |
+
def test_configuration_model(self):
|
| 87 |
+
aseq = []
|
| 88 |
+
bseq = []
|
| 89 |
+
G = configuration_model(aseq, bseq)
|
| 90 |
+
assert len(G) == 0
|
| 91 |
+
|
| 92 |
+
aseq = [0, 0]
|
| 93 |
+
bseq = [0, 0]
|
| 94 |
+
G = configuration_model(aseq, bseq)
|
| 95 |
+
assert len(G) == 4
|
| 96 |
+
assert G.number_of_edges() == 0
|
| 97 |
+
|
| 98 |
+
aseq = [3, 3, 3, 3]
|
| 99 |
+
bseq = [2, 2, 2, 2, 2]
|
| 100 |
+
pytest.raises(nx.NetworkXError, configuration_model, aseq, bseq)
|
| 101 |
+
|
| 102 |
+
aseq = [3, 3, 3, 3]
|
| 103 |
+
bseq = [2, 2, 2, 2, 2, 2]
|
| 104 |
+
G = configuration_model(aseq, bseq)
|
| 105 |
+
assert sorted(d for n, d in G.degree()) == [2, 2, 2, 2, 2, 2, 3, 3, 3, 3]
|
| 106 |
+
|
| 107 |
+
aseq = [2, 2, 2, 2, 2, 2]
|
| 108 |
+
bseq = [3, 3, 3, 3]
|
| 109 |
+
G = configuration_model(aseq, bseq)
|
| 110 |
+
assert sorted(d for n, d in G.degree()) == [2, 2, 2, 2, 2, 2, 3, 3, 3, 3]
|
| 111 |
+
|
| 112 |
+
aseq = [2, 2, 2, 1, 1, 1]
|
| 113 |
+
bseq = [3, 3, 3]
|
| 114 |
+
G = configuration_model(aseq, bseq)
|
| 115 |
+
assert G.is_multigraph()
|
| 116 |
+
assert not G.is_directed()
|
| 117 |
+
assert sorted(d for n, d in G.degree()) == [1, 1, 1, 2, 2, 2, 3, 3, 3]
|
| 118 |
+
|
| 119 |
+
GU = nx.projected_graph(nx.Graph(G), range(len(aseq)))
|
| 120 |
+
assert GU.number_of_nodes() == 6
|
| 121 |
+
|
| 122 |
+
GD = nx.projected_graph(nx.Graph(G), range(len(aseq), len(aseq) + len(bseq)))
|
| 123 |
+
assert GD.number_of_nodes() == 3
|
| 124 |
+
|
| 125 |
+
G = reverse_havel_hakimi_graph(aseq, bseq, create_using=nx.Graph)
|
| 126 |
+
assert not G.is_multigraph()
|
| 127 |
+
assert not G.is_directed()
|
| 128 |
+
|
| 129 |
+
pytest.raises(
|
| 130 |
+
nx.NetworkXError, configuration_model, aseq, bseq, create_using=nx.DiGraph()
|
| 131 |
+
)
|
| 132 |
+
pytest.raises(
|
| 133 |
+
nx.NetworkXError, configuration_model, aseq, bseq, create_using=nx.DiGraph
|
| 134 |
+
)
|
| 135 |
+
pytest.raises(
|
| 136 |
+
nx.NetworkXError,
|
| 137 |
+
configuration_model,
|
| 138 |
+
aseq,
|
| 139 |
+
bseq,
|
| 140 |
+
create_using=nx.MultiDiGraph,
|
| 141 |
+
)
|
| 142 |
+
|
| 143 |
+
def test_havel_hakimi_graph(self):
|
| 144 |
+
aseq = []
|
| 145 |
+
bseq = []
|
| 146 |
+
G = havel_hakimi_graph(aseq, bseq)
|
| 147 |
+
assert len(G) == 0
|
| 148 |
+
|
| 149 |
+
aseq = [0, 0]
|
| 150 |
+
bseq = [0, 0]
|
| 151 |
+
G = havel_hakimi_graph(aseq, bseq)
|
| 152 |
+
assert len(G) == 4
|
| 153 |
+
assert G.number_of_edges() == 0
|
| 154 |
+
|
| 155 |
+
aseq = [3, 3, 3, 3]
|
| 156 |
+
bseq = [2, 2, 2, 2, 2]
|
| 157 |
+
pytest.raises(nx.NetworkXError, havel_hakimi_graph, aseq, bseq)
|
| 158 |
+
|
| 159 |
+
bseq = [2, 2, 2, 2, 2, 2]
|
| 160 |
+
G = havel_hakimi_graph(aseq, bseq)
|
| 161 |
+
assert sorted(d for n, d in G.degree()) == [2, 2, 2, 2, 2, 2, 3, 3, 3, 3]
|
| 162 |
+
|
| 163 |
+
aseq = [2, 2, 2, 2, 2, 2]
|
| 164 |
+
bseq = [3, 3, 3, 3]
|
| 165 |
+
G = havel_hakimi_graph(aseq, bseq)
|
| 166 |
+
assert G.is_multigraph()
|
| 167 |
+
assert not G.is_directed()
|
| 168 |
+
assert sorted(d for n, d in G.degree()) == [2, 2, 2, 2, 2, 2, 3, 3, 3, 3]
|
| 169 |
+
|
| 170 |
+
GU = nx.projected_graph(nx.Graph(G), range(len(aseq)))
|
| 171 |
+
assert GU.number_of_nodes() == 6
|
| 172 |
+
|
| 173 |
+
GD = nx.projected_graph(nx.Graph(G), range(len(aseq), len(aseq) + len(bseq)))
|
| 174 |
+
assert GD.number_of_nodes() == 4
|
| 175 |
+
|
| 176 |
+
G = reverse_havel_hakimi_graph(aseq, bseq, create_using=nx.Graph)
|
| 177 |
+
assert not G.is_multigraph()
|
| 178 |
+
assert not G.is_directed()
|
| 179 |
+
|
| 180 |
+
pytest.raises(
|
| 181 |
+
nx.NetworkXError, havel_hakimi_graph, aseq, bseq, create_using=nx.DiGraph
|
| 182 |
+
)
|
| 183 |
+
pytest.raises(
|
| 184 |
+
nx.NetworkXError, havel_hakimi_graph, aseq, bseq, create_using=nx.DiGraph
|
| 185 |
+
)
|
| 186 |
+
pytest.raises(
|
| 187 |
+
nx.NetworkXError,
|
| 188 |
+
havel_hakimi_graph,
|
| 189 |
+
aseq,
|
| 190 |
+
bseq,
|
| 191 |
+
create_using=nx.MultiDiGraph,
|
| 192 |
+
)
|
| 193 |
+
|
| 194 |
+
def test_reverse_havel_hakimi_graph(self):
|
| 195 |
+
aseq = []
|
| 196 |
+
bseq = []
|
| 197 |
+
G = reverse_havel_hakimi_graph(aseq, bseq)
|
| 198 |
+
assert len(G) == 0
|
| 199 |
+
|
| 200 |
+
aseq = [0, 0]
|
| 201 |
+
bseq = [0, 0]
|
| 202 |
+
G = reverse_havel_hakimi_graph(aseq, bseq)
|
| 203 |
+
assert len(G) == 4
|
| 204 |
+
assert G.number_of_edges() == 0
|
| 205 |
+
|
| 206 |
+
aseq = [3, 3, 3, 3]
|
| 207 |
+
bseq = [2, 2, 2, 2, 2]
|
| 208 |
+
pytest.raises(nx.NetworkXError, reverse_havel_hakimi_graph, aseq, bseq)
|
| 209 |
+
|
| 210 |
+
bseq = [2, 2, 2, 2, 2, 2]
|
| 211 |
+
G = reverse_havel_hakimi_graph(aseq, bseq)
|
| 212 |
+
assert sorted(d for n, d in G.degree()) == [2, 2, 2, 2, 2, 2, 3, 3, 3, 3]
|
| 213 |
+
|
| 214 |
+
aseq = [2, 2, 2, 2, 2, 2]
|
| 215 |
+
bseq = [3, 3, 3, 3]
|
| 216 |
+
G = reverse_havel_hakimi_graph(aseq, bseq)
|
| 217 |
+
assert sorted(d for n, d in G.degree()) == [2, 2, 2, 2, 2, 2, 3, 3, 3, 3]
|
| 218 |
+
|
| 219 |
+
aseq = [2, 2, 2, 1, 1, 1]
|
| 220 |
+
bseq = [3, 3, 3]
|
| 221 |
+
G = reverse_havel_hakimi_graph(aseq, bseq)
|
| 222 |
+
assert G.is_multigraph()
|
| 223 |
+
assert not G.is_directed()
|
| 224 |
+
assert sorted(d for n, d in G.degree()) == [1, 1, 1, 2, 2, 2, 3, 3, 3]
|
| 225 |
+
|
| 226 |
+
GU = nx.projected_graph(nx.Graph(G), range(len(aseq)))
|
| 227 |
+
assert GU.number_of_nodes() == 6
|
| 228 |
+
|
| 229 |
+
GD = nx.projected_graph(nx.Graph(G), range(len(aseq), len(aseq) + len(bseq)))
|
| 230 |
+
assert GD.number_of_nodes() == 3
|
| 231 |
+
|
| 232 |
+
G = reverse_havel_hakimi_graph(aseq, bseq, create_using=nx.Graph)
|
| 233 |
+
assert not G.is_multigraph()
|
| 234 |
+
assert not G.is_directed()
|
| 235 |
+
|
| 236 |
+
pytest.raises(
|
| 237 |
+
nx.NetworkXError,
|
| 238 |
+
reverse_havel_hakimi_graph,
|
| 239 |
+
aseq,
|
| 240 |
+
bseq,
|
| 241 |
+
create_using=nx.DiGraph,
|
| 242 |
+
)
|
| 243 |
+
pytest.raises(
|
| 244 |
+
nx.NetworkXError,
|
| 245 |
+
reverse_havel_hakimi_graph,
|
| 246 |
+
aseq,
|
| 247 |
+
bseq,
|
| 248 |
+
create_using=nx.DiGraph,
|
| 249 |
+
)
|
| 250 |
+
pytest.raises(
|
| 251 |
+
nx.NetworkXError,
|
| 252 |
+
reverse_havel_hakimi_graph,
|
| 253 |
+
aseq,
|
| 254 |
+
bseq,
|
| 255 |
+
create_using=nx.MultiDiGraph,
|
| 256 |
+
)
|
| 257 |
+
|
| 258 |
+
def test_alternating_havel_hakimi_graph(self):
|
| 259 |
+
aseq = []
|
| 260 |
+
bseq = []
|
| 261 |
+
G = alternating_havel_hakimi_graph(aseq, bseq)
|
| 262 |
+
assert len(G) == 0
|
| 263 |
+
|
| 264 |
+
aseq = [0, 0]
|
| 265 |
+
bseq = [0, 0]
|
| 266 |
+
G = alternating_havel_hakimi_graph(aseq, bseq)
|
| 267 |
+
assert len(G) == 4
|
| 268 |
+
assert G.number_of_edges() == 0
|
| 269 |
+
|
| 270 |
+
aseq = [3, 3, 3, 3]
|
| 271 |
+
bseq = [2, 2, 2, 2, 2]
|
| 272 |
+
pytest.raises(nx.NetworkXError, alternating_havel_hakimi_graph, aseq, bseq)
|
| 273 |
+
|
| 274 |
+
bseq = [2, 2, 2, 2, 2, 2]
|
| 275 |
+
G = alternating_havel_hakimi_graph(aseq, bseq)
|
| 276 |
+
assert sorted(d for n, d in G.degree()) == [2, 2, 2, 2, 2, 2, 3, 3, 3, 3]
|
| 277 |
+
|
| 278 |
+
aseq = [2, 2, 2, 2, 2, 2]
|
| 279 |
+
bseq = [3, 3, 3, 3]
|
| 280 |
+
G = alternating_havel_hakimi_graph(aseq, bseq)
|
| 281 |
+
assert sorted(d for n, d in G.degree()) == [2, 2, 2, 2, 2, 2, 3, 3, 3, 3]
|
| 282 |
+
|
| 283 |
+
aseq = [2, 2, 2, 1, 1, 1]
|
| 284 |
+
bseq = [3, 3, 3]
|
| 285 |
+
G = alternating_havel_hakimi_graph(aseq, bseq)
|
| 286 |
+
assert G.is_multigraph()
|
| 287 |
+
assert not G.is_directed()
|
| 288 |
+
assert sorted(d for n, d in G.degree()) == [1, 1, 1, 2, 2, 2, 3, 3, 3]
|
| 289 |
+
|
| 290 |
+
GU = nx.projected_graph(nx.Graph(G), range(len(aseq)))
|
| 291 |
+
assert GU.number_of_nodes() == 6
|
| 292 |
+
|
| 293 |
+
GD = nx.projected_graph(nx.Graph(G), range(len(aseq), len(aseq) + len(bseq)))
|
| 294 |
+
assert GD.number_of_nodes() == 3
|
| 295 |
+
|
| 296 |
+
G = reverse_havel_hakimi_graph(aseq, bseq, create_using=nx.Graph)
|
| 297 |
+
assert not G.is_multigraph()
|
| 298 |
+
assert not G.is_directed()
|
| 299 |
+
|
| 300 |
+
pytest.raises(
|
| 301 |
+
nx.NetworkXError,
|
| 302 |
+
alternating_havel_hakimi_graph,
|
| 303 |
+
aseq,
|
| 304 |
+
bseq,
|
| 305 |
+
create_using=nx.DiGraph,
|
| 306 |
+
)
|
| 307 |
+
pytest.raises(
|
| 308 |
+
nx.NetworkXError,
|
| 309 |
+
alternating_havel_hakimi_graph,
|
| 310 |
+
aseq,
|
| 311 |
+
bseq,
|
| 312 |
+
create_using=nx.DiGraph,
|
| 313 |
+
)
|
| 314 |
+
pytest.raises(
|
| 315 |
+
nx.NetworkXError,
|
| 316 |
+
alternating_havel_hakimi_graph,
|
| 317 |
+
aseq,
|
| 318 |
+
bseq,
|
| 319 |
+
create_using=nx.MultiDiGraph,
|
| 320 |
+
)
|
| 321 |
+
|
| 322 |
+
def test_preferential_attachment(self):
|
| 323 |
+
aseq = [3, 2, 1, 1]
|
| 324 |
+
G = preferential_attachment_graph(aseq, 0.5)
|
| 325 |
+
assert G.is_multigraph()
|
| 326 |
+
assert not G.is_directed()
|
| 327 |
+
|
| 328 |
+
G = preferential_attachment_graph(aseq, 0.5, create_using=nx.Graph)
|
| 329 |
+
assert not G.is_multigraph()
|
| 330 |
+
assert not G.is_directed()
|
| 331 |
+
|
| 332 |
+
pytest.raises(
|
| 333 |
+
nx.NetworkXError,
|
| 334 |
+
preferential_attachment_graph,
|
| 335 |
+
aseq,
|
| 336 |
+
0.5,
|
| 337 |
+
create_using=nx.DiGraph(),
|
| 338 |
+
)
|
| 339 |
+
pytest.raises(
|
| 340 |
+
nx.NetworkXError,
|
| 341 |
+
preferential_attachment_graph,
|
| 342 |
+
aseq,
|
| 343 |
+
0.5,
|
| 344 |
+
create_using=nx.DiGraph(),
|
| 345 |
+
)
|
| 346 |
+
pytest.raises(
|
| 347 |
+
nx.NetworkXError,
|
| 348 |
+
preferential_attachment_graph,
|
| 349 |
+
aseq,
|
| 350 |
+
0.5,
|
| 351 |
+
create_using=nx.DiGraph(),
|
| 352 |
+
)
|
| 353 |
+
|
| 354 |
+
def test_random_graph(self):
|
| 355 |
+
n = 10
|
| 356 |
+
m = 20
|
| 357 |
+
G = random_graph(n, m, 0.9)
|
| 358 |
+
assert len(G) == 30
|
| 359 |
+
assert nx.is_bipartite(G)
|
| 360 |
+
X, Y = nx.algorithms.bipartite.sets(G)
|
| 361 |
+
assert set(range(n)) == X
|
| 362 |
+
assert set(range(n, n + m)) == Y
|
| 363 |
+
|
| 364 |
+
def test_random_digraph(self):
|
| 365 |
+
n = 10
|
| 366 |
+
m = 20
|
| 367 |
+
G = random_graph(n, m, 0.9, directed=True)
|
| 368 |
+
assert len(G) == 30
|
| 369 |
+
assert nx.is_bipartite(G)
|
| 370 |
+
X, Y = nx.algorithms.bipartite.sets(G)
|
| 371 |
+
assert set(range(n)) == X
|
| 372 |
+
assert set(range(n, n + m)) == Y
|
| 373 |
+
|
| 374 |
+
def test_gnmk_random_graph(self):
|
| 375 |
+
n = 10
|
| 376 |
+
m = 20
|
| 377 |
+
edges = 100
|
| 378 |
+
# set seed because sometimes it is not connected
|
| 379 |
+
# which raises an error in bipartite.sets(G) below.
|
| 380 |
+
G = gnmk_random_graph(n, m, edges, seed=1234)
|
| 381 |
+
assert len(G) == n + m
|
| 382 |
+
assert nx.is_bipartite(G)
|
| 383 |
+
X, Y = nx.algorithms.bipartite.sets(G)
|
| 384 |
+
# print(X)
|
| 385 |
+
assert set(range(n)) == X
|
| 386 |
+
assert set(range(n, n + m)) == Y
|
| 387 |
+
assert edges == len(list(G.edges()))
|
| 388 |
+
|
| 389 |
+
def test_gnmk_random_graph_complete(self):
|
| 390 |
+
n = 10
|
| 391 |
+
m = 20
|
| 392 |
+
edges = 200
|
| 393 |
+
G = gnmk_random_graph(n, m, edges)
|
| 394 |
+
assert len(G) == n + m
|
| 395 |
+
assert nx.is_bipartite(G)
|
| 396 |
+
X, Y = nx.algorithms.bipartite.sets(G)
|
| 397 |
+
# print(X)
|
| 398 |
+
assert set(range(n)) == X
|
| 399 |
+
assert set(range(n, n + m)) == Y
|
| 400 |
+
assert edges == len(list(G.edges()))
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/test_matching.py
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Unit tests for the :mod:`networkx.algorithms.bipartite.matching` module."""
|
| 2 |
+
import itertools
|
| 3 |
+
|
| 4 |
+
import pytest
|
| 5 |
+
|
| 6 |
+
import networkx as nx
|
| 7 |
+
from networkx.algorithms.bipartite.matching import (
|
| 8 |
+
eppstein_matching,
|
| 9 |
+
hopcroft_karp_matching,
|
| 10 |
+
maximum_matching,
|
| 11 |
+
minimum_weight_full_matching,
|
| 12 |
+
to_vertex_cover,
|
| 13 |
+
)
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class TestMatching:
|
| 17 |
+
"""Tests for bipartite matching algorithms."""
|
| 18 |
+
|
| 19 |
+
def setup_method(self):
|
| 20 |
+
"""Creates a bipartite graph for use in testing matching algorithms.
|
| 21 |
+
|
| 22 |
+
The bipartite graph has a maximum cardinality matching that leaves
|
| 23 |
+
vertex 1 and vertex 10 unmatched. The first six numbers are the left
|
| 24 |
+
vertices and the next six numbers are the right vertices.
|
| 25 |
+
|
| 26 |
+
"""
|
| 27 |
+
self.simple_graph = nx.complete_bipartite_graph(2, 3)
|
| 28 |
+
self.simple_solution = {0: 2, 1: 3, 2: 0, 3: 1}
|
| 29 |
+
|
| 30 |
+
edges = [(0, 7), (0, 8), (2, 6), (2, 9), (3, 8), (4, 8), (4, 9), (5, 11)]
|
| 31 |
+
self.top_nodes = set(range(6))
|
| 32 |
+
self.graph = nx.Graph()
|
| 33 |
+
self.graph.add_nodes_from(range(12))
|
| 34 |
+
self.graph.add_edges_from(edges)
|
| 35 |
+
|
| 36 |
+
# Example bipartite graph from issue 2127
|
| 37 |
+
G = nx.Graph()
|
| 38 |
+
G.add_nodes_from(
|
| 39 |
+
[
|
| 40 |
+
(1, "C"),
|
| 41 |
+
(1, "B"),
|
| 42 |
+
(0, "G"),
|
| 43 |
+
(1, "F"),
|
| 44 |
+
(1, "E"),
|
| 45 |
+
(0, "C"),
|
| 46 |
+
(1, "D"),
|
| 47 |
+
(1, "I"),
|
| 48 |
+
(0, "A"),
|
| 49 |
+
(0, "D"),
|
| 50 |
+
(0, "F"),
|
| 51 |
+
(0, "E"),
|
| 52 |
+
(0, "H"),
|
| 53 |
+
(1, "G"),
|
| 54 |
+
(1, "A"),
|
| 55 |
+
(0, "I"),
|
| 56 |
+
(0, "B"),
|
| 57 |
+
(1, "H"),
|
| 58 |
+
]
|
| 59 |
+
)
|
| 60 |
+
G.add_edge((1, "C"), (0, "A"))
|
| 61 |
+
G.add_edge((1, "B"), (0, "A"))
|
| 62 |
+
G.add_edge((0, "G"), (1, "I"))
|
| 63 |
+
G.add_edge((0, "G"), (1, "H"))
|
| 64 |
+
G.add_edge((1, "F"), (0, "A"))
|
| 65 |
+
G.add_edge((1, "F"), (0, "C"))
|
| 66 |
+
G.add_edge((1, "F"), (0, "E"))
|
| 67 |
+
G.add_edge((1, "E"), (0, "A"))
|
| 68 |
+
G.add_edge((1, "E"), (0, "C"))
|
| 69 |
+
G.add_edge((0, "C"), (1, "D"))
|
| 70 |
+
G.add_edge((0, "C"), (1, "I"))
|
| 71 |
+
G.add_edge((0, "C"), (1, "G"))
|
| 72 |
+
G.add_edge((0, "C"), (1, "H"))
|
| 73 |
+
G.add_edge((1, "D"), (0, "A"))
|
| 74 |
+
G.add_edge((1, "I"), (0, "A"))
|
| 75 |
+
G.add_edge((1, "I"), (0, "E"))
|
| 76 |
+
G.add_edge((0, "A"), (1, "G"))
|
| 77 |
+
G.add_edge((0, "A"), (1, "H"))
|
| 78 |
+
G.add_edge((0, "E"), (1, "G"))
|
| 79 |
+
G.add_edge((0, "E"), (1, "H"))
|
| 80 |
+
self.disconnected_graph = G
|
| 81 |
+
|
| 82 |
+
def check_match(self, matching):
|
| 83 |
+
"""Asserts that the matching is what we expect from the bipartite graph
|
| 84 |
+
constructed in the :meth:`setup` fixture.
|
| 85 |
+
|
| 86 |
+
"""
|
| 87 |
+
# For the sake of brevity, rename `matching` to `M`.
|
| 88 |
+
M = matching
|
| 89 |
+
matched_vertices = frozenset(itertools.chain(*M.items()))
|
| 90 |
+
# Assert that the maximum number of vertices (10) is matched.
|
| 91 |
+
assert matched_vertices == frozenset(range(12)) - {1, 10}
|
| 92 |
+
# Assert that no vertex appears in two edges, or in other words, that
|
| 93 |
+
# the matching (u, v) and (v, u) both appear in the matching
|
| 94 |
+
# dictionary.
|
| 95 |
+
assert all(u == M[M[u]] for u in range(12) if u in M)
|
| 96 |
+
|
| 97 |
+
def check_vertex_cover(self, vertices):
|
| 98 |
+
"""Asserts that the given set of vertices is the vertex cover we
|
| 99 |
+
expected from the bipartite graph constructed in the :meth:`setup`
|
| 100 |
+
fixture.
|
| 101 |
+
|
| 102 |
+
"""
|
| 103 |
+
# By Konig's theorem, the number of edges in a maximum matching equals
|
| 104 |
+
# the number of vertices in a minimum vertex cover.
|
| 105 |
+
assert len(vertices) == 5
|
| 106 |
+
# Assert that the set is truly a vertex cover.
|
| 107 |
+
for u, v in self.graph.edges():
|
| 108 |
+
assert u in vertices or v in vertices
|
| 109 |
+
# TODO Assert that the vertices are the correct ones.
|
| 110 |
+
|
| 111 |
+
def test_eppstein_matching(self):
|
| 112 |
+
"""Tests that David Eppstein's implementation of the Hopcroft--Karp
|
| 113 |
+
algorithm produces a maximum cardinality matching.
|
| 114 |
+
|
| 115 |
+
"""
|
| 116 |
+
self.check_match(eppstein_matching(self.graph, self.top_nodes))
|
| 117 |
+
|
| 118 |
+
def test_hopcroft_karp_matching(self):
|
| 119 |
+
"""Tests that the Hopcroft--Karp algorithm produces a maximum
|
| 120 |
+
cardinality matching in a bipartite graph.
|
| 121 |
+
|
| 122 |
+
"""
|
| 123 |
+
self.check_match(hopcroft_karp_matching(self.graph, self.top_nodes))
|
| 124 |
+
|
| 125 |
+
def test_to_vertex_cover(self):
|
| 126 |
+
"""Test for converting a maximum matching to a minimum vertex cover."""
|
| 127 |
+
matching = maximum_matching(self.graph, self.top_nodes)
|
| 128 |
+
vertex_cover = to_vertex_cover(self.graph, matching, self.top_nodes)
|
| 129 |
+
self.check_vertex_cover(vertex_cover)
|
| 130 |
+
|
| 131 |
+
def test_eppstein_matching_simple(self):
|
| 132 |
+
match = eppstein_matching(self.simple_graph)
|
| 133 |
+
assert match == self.simple_solution
|
| 134 |
+
|
| 135 |
+
def test_hopcroft_karp_matching_simple(self):
|
| 136 |
+
match = hopcroft_karp_matching(self.simple_graph)
|
| 137 |
+
assert match == self.simple_solution
|
| 138 |
+
|
| 139 |
+
def test_eppstein_matching_disconnected(self):
|
| 140 |
+
with pytest.raises(nx.AmbiguousSolution):
|
| 141 |
+
match = eppstein_matching(self.disconnected_graph)
|
| 142 |
+
|
| 143 |
+
def test_hopcroft_karp_matching_disconnected(self):
|
| 144 |
+
with pytest.raises(nx.AmbiguousSolution):
|
| 145 |
+
match = hopcroft_karp_matching(self.disconnected_graph)
|
| 146 |
+
|
| 147 |
+
def test_issue_2127(self):
|
| 148 |
+
"""Test from issue 2127"""
|
| 149 |
+
# Build the example DAG
|
| 150 |
+
G = nx.DiGraph()
|
| 151 |
+
G.add_edge("A", "C")
|
| 152 |
+
G.add_edge("A", "B")
|
| 153 |
+
G.add_edge("C", "E")
|
| 154 |
+
G.add_edge("C", "D")
|
| 155 |
+
G.add_edge("E", "G")
|
| 156 |
+
G.add_edge("E", "F")
|
| 157 |
+
G.add_edge("G", "I")
|
| 158 |
+
G.add_edge("G", "H")
|
| 159 |
+
|
| 160 |
+
tc = nx.transitive_closure(G)
|
| 161 |
+
btc = nx.Graph()
|
| 162 |
+
|
| 163 |
+
# Create a bipartite graph based on the transitive closure of G
|
| 164 |
+
for v in tc.nodes():
|
| 165 |
+
btc.add_node((0, v))
|
| 166 |
+
btc.add_node((1, v))
|
| 167 |
+
|
| 168 |
+
for u, v in tc.edges():
|
| 169 |
+
btc.add_edge((0, u), (1, v))
|
| 170 |
+
|
| 171 |
+
top_nodes = {n for n in btc if n[0] == 0}
|
| 172 |
+
matching = hopcroft_karp_matching(btc, top_nodes)
|
| 173 |
+
vertex_cover = to_vertex_cover(btc, matching, top_nodes)
|
| 174 |
+
independent_set = set(G) - {v for _, v in vertex_cover}
|
| 175 |
+
assert {"B", "D", "F", "I", "H"} == independent_set
|
| 176 |
+
|
| 177 |
+
def test_vertex_cover_issue_2384(self):
|
| 178 |
+
G = nx.Graph([(0, 3), (1, 3), (1, 4), (2, 3)])
|
| 179 |
+
matching = maximum_matching(G)
|
| 180 |
+
vertex_cover = to_vertex_cover(G, matching)
|
| 181 |
+
for u, v in G.edges():
|
| 182 |
+
assert u in vertex_cover or v in vertex_cover
|
| 183 |
+
|
| 184 |
+
def test_vertex_cover_issue_3306(self):
|
| 185 |
+
G = nx.Graph()
|
| 186 |
+
edges = [(0, 2), (1, 0), (1, 1), (1, 2), (2, 2)]
|
| 187 |
+
G.add_edges_from([((i, "L"), (j, "R")) for i, j in edges])
|
| 188 |
+
|
| 189 |
+
matching = maximum_matching(G)
|
| 190 |
+
vertex_cover = to_vertex_cover(G, matching)
|
| 191 |
+
for u, v in G.edges():
|
| 192 |
+
assert u in vertex_cover or v in vertex_cover
|
| 193 |
+
|
| 194 |
+
def test_unorderable_nodes(self):
|
| 195 |
+
a = object()
|
| 196 |
+
b = object()
|
| 197 |
+
c = object()
|
| 198 |
+
d = object()
|
| 199 |
+
e = object()
|
| 200 |
+
G = nx.Graph([(a, d), (b, d), (b, e), (c, d)])
|
| 201 |
+
matching = maximum_matching(G)
|
| 202 |
+
vertex_cover = to_vertex_cover(G, matching)
|
| 203 |
+
for u, v in G.edges():
|
| 204 |
+
assert u in vertex_cover or v in vertex_cover
|
| 205 |
+
|
| 206 |
+
|
| 207 |
+
def test_eppstein_matching():
|
| 208 |
+
"""Test in accordance to issue #1927"""
|
| 209 |
+
G = nx.Graph()
|
| 210 |
+
G.add_nodes_from(["a", 2, 3, 4], bipartite=0)
|
| 211 |
+
G.add_nodes_from([1, "b", "c"], bipartite=1)
|
| 212 |
+
G.add_edges_from([("a", 1), ("a", "b"), (2, "b"), (2, "c"), (3, "c"), (4, 1)])
|
| 213 |
+
matching = eppstein_matching(G)
|
| 214 |
+
assert len(matching) == len(maximum_matching(G))
|
| 215 |
+
assert all(x in set(matching.keys()) for x in set(matching.values()))
|
| 216 |
+
|
| 217 |
+
|
| 218 |
+
class TestMinimumWeightFullMatching:
|
| 219 |
+
@classmethod
|
| 220 |
+
def setup_class(cls):
|
| 221 |
+
pytest.importorskip("scipy")
|
| 222 |
+
|
| 223 |
+
def test_minimum_weight_full_matching_incomplete_graph(self):
|
| 224 |
+
B = nx.Graph()
|
| 225 |
+
B.add_nodes_from([1, 2], bipartite=0)
|
| 226 |
+
B.add_nodes_from([3, 4], bipartite=1)
|
| 227 |
+
B.add_edge(1, 4, weight=100)
|
| 228 |
+
B.add_edge(2, 3, weight=100)
|
| 229 |
+
B.add_edge(2, 4, weight=50)
|
| 230 |
+
matching = minimum_weight_full_matching(B)
|
| 231 |
+
assert matching == {1: 4, 2: 3, 4: 1, 3: 2}
|
| 232 |
+
|
| 233 |
+
def test_minimum_weight_full_matching_with_no_full_matching(self):
|
| 234 |
+
B = nx.Graph()
|
| 235 |
+
B.add_nodes_from([1, 2, 3], bipartite=0)
|
| 236 |
+
B.add_nodes_from([4, 5, 6], bipartite=1)
|
| 237 |
+
B.add_edge(1, 4, weight=100)
|
| 238 |
+
B.add_edge(2, 4, weight=100)
|
| 239 |
+
B.add_edge(3, 4, weight=50)
|
| 240 |
+
B.add_edge(3, 5, weight=50)
|
| 241 |
+
B.add_edge(3, 6, weight=50)
|
| 242 |
+
with pytest.raises(ValueError):
|
| 243 |
+
minimum_weight_full_matching(B)
|
| 244 |
+
|
| 245 |
+
def test_minimum_weight_full_matching_square(self):
|
| 246 |
+
G = nx.complete_bipartite_graph(3, 3)
|
| 247 |
+
G.add_edge(0, 3, weight=400)
|
| 248 |
+
G.add_edge(0, 4, weight=150)
|
| 249 |
+
G.add_edge(0, 5, weight=400)
|
| 250 |
+
G.add_edge(1, 3, weight=400)
|
| 251 |
+
G.add_edge(1, 4, weight=450)
|
| 252 |
+
G.add_edge(1, 5, weight=600)
|
| 253 |
+
G.add_edge(2, 3, weight=300)
|
| 254 |
+
G.add_edge(2, 4, weight=225)
|
| 255 |
+
G.add_edge(2, 5, weight=300)
|
| 256 |
+
matching = minimum_weight_full_matching(G)
|
| 257 |
+
assert matching == {0: 4, 1: 3, 2: 5, 4: 0, 3: 1, 5: 2}
|
| 258 |
+
|
| 259 |
+
def test_minimum_weight_full_matching_smaller_left(self):
|
| 260 |
+
G = nx.complete_bipartite_graph(3, 4)
|
| 261 |
+
G.add_edge(0, 3, weight=400)
|
| 262 |
+
G.add_edge(0, 4, weight=150)
|
| 263 |
+
G.add_edge(0, 5, weight=400)
|
| 264 |
+
G.add_edge(0, 6, weight=1)
|
| 265 |
+
G.add_edge(1, 3, weight=400)
|
| 266 |
+
G.add_edge(1, 4, weight=450)
|
| 267 |
+
G.add_edge(1, 5, weight=600)
|
| 268 |
+
G.add_edge(1, 6, weight=2)
|
| 269 |
+
G.add_edge(2, 3, weight=300)
|
| 270 |
+
G.add_edge(2, 4, weight=225)
|
| 271 |
+
G.add_edge(2, 5, weight=290)
|
| 272 |
+
G.add_edge(2, 6, weight=3)
|
| 273 |
+
matching = minimum_weight_full_matching(G)
|
| 274 |
+
assert matching == {0: 4, 1: 6, 2: 5, 4: 0, 5: 2, 6: 1}
|
| 275 |
+
|
| 276 |
+
def test_minimum_weight_full_matching_smaller_top_nodes_right(self):
|
| 277 |
+
G = nx.complete_bipartite_graph(3, 4)
|
| 278 |
+
G.add_edge(0, 3, weight=400)
|
| 279 |
+
G.add_edge(0, 4, weight=150)
|
| 280 |
+
G.add_edge(0, 5, weight=400)
|
| 281 |
+
G.add_edge(0, 6, weight=1)
|
| 282 |
+
G.add_edge(1, 3, weight=400)
|
| 283 |
+
G.add_edge(1, 4, weight=450)
|
| 284 |
+
G.add_edge(1, 5, weight=600)
|
| 285 |
+
G.add_edge(1, 6, weight=2)
|
| 286 |
+
G.add_edge(2, 3, weight=300)
|
| 287 |
+
G.add_edge(2, 4, weight=225)
|
| 288 |
+
G.add_edge(2, 5, weight=290)
|
| 289 |
+
G.add_edge(2, 6, weight=3)
|
| 290 |
+
matching = minimum_weight_full_matching(G, top_nodes=[3, 4, 5, 6])
|
| 291 |
+
assert matching == {0: 4, 1: 6, 2: 5, 4: 0, 5: 2, 6: 1}
|
| 292 |
+
|
| 293 |
+
def test_minimum_weight_full_matching_smaller_right(self):
|
| 294 |
+
G = nx.complete_bipartite_graph(4, 3)
|
| 295 |
+
G.add_edge(0, 4, weight=400)
|
| 296 |
+
G.add_edge(0, 5, weight=400)
|
| 297 |
+
G.add_edge(0, 6, weight=300)
|
| 298 |
+
G.add_edge(1, 4, weight=150)
|
| 299 |
+
G.add_edge(1, 5, weight=450)
|
| 300 |
+
G.add_edge(1, 6, weight=225)
|
| 301 |
+
G.add_edge(2, 4, weight=400)
|
| 302 |
+
G.add_edge(2, 5, weight=600)
|
| 303 |
+
G.add_edge(2, 6, weight=290)
|
| 304 |
+
G.add_edge(3, 4, weight=1)
|
| 305 |
+
G.add_edge(3, 5, weight=2)
|
| 306 |
+
G.add_edge(3, 6, weight=3)
|
| 307 |
+
matching = minimum_weight_full_matching(G)
|
| 308 |
+
assert matching == {1: 4, 2: 6, 3: 5, 4: 1, 5: 3, 6: 2}
|
| 309 |
+
|
| 310 |
+
def test_minimum_weight_full_matching_negative_weights(self):
|
| 311 |
+
G = nx.complete_bipartite_graph(2, 2)
|
| 312 |
+
G.add_edge(0, 2, weight=-2)
|
| 313 |
+
G.add_edge(0, 3, weight=0.2)
|
| 314 |
+
G.add_edge(1, 2, weight=-2)
|
| 315 |
+
G.add_edge(1, 3, weight=0.3)
|
| 316 |
+
matching = minimum_weight_full_matching(G)
|
| 317 |
+
assert matching == {0: 3, 1: 2, 2: 1, 3: 0}
|
| 318 |
+
|
| 319 |
+
def test_minimum_weight_full_matching_different_weight_key(self):
|
| 320 |
+
G = nx.complete_bipartite_graph(2, 2)
|
| 321 |
+
G.add_edge(0, 2, mass=2)
|
| 322 |
+
G.add_edge(0, 3, mass=0.2)
|
| 323 |
+
G.add_edge(1, 2, mass=1)
|
| 324 |
+
G.add_edge(1, 3, mass=2)
|
| 325 |
+
matching = minimum_weight_full_matching(G, weight="mass")
|
| 326 |
+
assert matching == {0: 3, 1: 2, 2: 1, 3: 0}
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/test_matrix.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pytest
|
| 2 |
+
|
| 3 |
+
np = pytest.importorskip("numpy")
|
| 4 |
+
sp = pytest.importorskip("scipy")
|
| 5 |
+
sparse = pytest.importorskip("scipy.sparse")
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
import networkx as nx
|
| 9 |
+
from networkx.algorithms import bipartite
|
| 10 |
+
from networkx.utils import edges_equal
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class TestBiadjacencyMatrix:
|
| 14 |
+
def test_biadjacency_matrix_weight(self):
|
| 15 |
+
G = nx.path_graph(5)
|
| 16 |
+
G.add_edge(0, 1, weight=2, other=4)
|
| 17 |
+
X = [1, 3]
|
| 18 |
+
Y = [0, 2, 4]
|
| 19 |
+
M = bipartite.biadjacency_matrix(G, X, weight="weight")
|
| 20 |
+
assert M[0, 0] == 2
|
| 21 |
+
M = bipartite.biadjacency_matrix(G, X, weight="other")
|
| 22 |
+
assert M[0, 0] == 4
|
| 23 |
+
|
| 24 |
+
def test_biadjacency_matrix(self):
|
| 25 |
+
tops = [2, 5, 10]
|
| 26 |
+
bots = [5, 10, 15]
|
| 27 |
+
for i in range(len(tops)):
|
| 28 |
+
G = bipartite.random_graph(tops[i], bots[i], 0.2)
|
| 29 |
+
top = [n for n, d in G.nodes(data=True) if d["bipartite"] == 0]
|
| 30 |
+
M = bipartite.biadjacency_matrix(G, top)
|
| 31 |
+
assert M.shape[0] == tops[i]
|
| 32 |
+
assert M.shape[1] == bots[i]
|
| 33 |
+
|
| 34 |
+
def test_biadjacency_matrix_order(self):
|
| 35 |
+
G = nx.path_graph(5)
|
| 36 |
+
G.add_edge(0, 1, weight=2)
|
| 37 |
+
X = [3, 1]
|
| 38 |
+
Y = [4, 2, 0]
|
| 39 |
+
M = bipartite.biadjacency_matrix(G, X, Y, weight="weight")
|
| 40 |
+
assert M[1, 2] == 2
|
| 41 |
+
|
| 42 |
+
def test_null_graph(self):
|
| 43 |
+
with pytest.raises(nx.NetworkXError):
|
| 44 |
+
bipartite.biadjacency_matrix(nx.Graph(), [])
|
| 45 |
+
|
| 46 |
+
def test_empty_graph(self):
|
| 47 |
+
with pytest.raises(nx.NetworkXError):
|
| 48 |
+
bipartite.biadjacency_matrix(nx.Graph([(1, 0)]), [])
|
| 49 |
+
|
| 50 |
+
def test_duplicate_row(self):
|
| 51 |
+
with pytest.raises(nx.NetworkXError):
|
| 52 |
+
bipartite.biadjacency_matrix(nx.Graph([(1, 0)]), [1, 1])
|
| 53 |
+
|
| 54 |
+
def test_duplicate_col(self):
|
| 55 |
+
with pytest.raises(nx.NetworkXError):
|
| 56 |
+
bipartite.biadjacency_matrix(nx.Graph([(1, 0)]), [0], [1, 1])
|
| 57 |
+
|
| 58 |
+
def test_format_keyword(self):
|
| 59 |
+
with pytest.raises(nx.NetworkXError):
|
| 60 |
+
bipartite.biadjacency_matrix(nx.Graph([(1, 0)]), [0], format="foo")
|
| 61 |
+
|
| 62 |
+
def test_from_biadjacency_roundtrip(self):
|
| 63 |
+
B1 = nx.path_graph(5)
|
| 64 |
+
M = bipartite.biadjacency_matrix(B1, [0, 2, 4])
|
| 65 |
+
B2 = bipartite.from_biadjacency_matrix(M)
|
| 66 |
+
assert nx.is_isomorphic(B1, B2)
|
| 67 |
+
|
| 68 |
+
def test_from_biadjacency_weight(self):
|
| 69 |
+
M = sparse.csc_matrix([[1, 2], [0, 3]])
|
| 70 |
+
B = bipartite.from_biadjacency_matrix(M)
|
| 71 |
+
assert edges_equal(B.edges(), [(0, 2), (0, 3), (1, 3)])
|
| 72 |
+
B = bipartite.from_biadjacency_matrix(M, edge_attribute="weight")
|
| 73 |
+
e = [(0, 2, {"weight": 1}), (0, 3, {"weight": 2}), (1, 3, {"weight": 3})]
|
| 74 |
+
assert edges_equal(B.edges(data=True), e)
|
| 75 |
+
|
| 76 |
+
def test_from_biadjacency_multigraph(self):
|
| 77 |
+
M = sparse.csc_matrix([[1, 2], [0, 3]])
|
| 78 |
+
B = bipartite.from_biadjacency_matrix(M, create_using=nx.MultiGraph())
|
| 79 |
+
assert edges_equal(B.edges(), [(0, 2), (0, 3), (0, 3), (1, 3), (1, 3), (1, 3)])
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/tests/test_redundancy.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Unit tests for the :mod:`networkx.algorithms.bipartite.redundancy` module.
|
| 2 |
+
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
import pytest
|
| 6 |
+
|
| 7 |
+
from networkx import NetworkXError, cycle_graph
|
| 8 |
+
from networkx.algorithms.bipartite import complete_bipartite_graph, node_redundancy
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def test_no_redundant_nodes():
|
| 12 |
+
G = complete_bipartite_graph(2, 2)
|
| 13 |
+
|
| 14 |
+
# when nodes is None
|
| 15 |
+
rc = node_redundancy(G)
|
| 16 |
+
assert all(redundancy == 1 for redundancy in rc.values())
|
| 17 |
+
|
| 18 |
+
# when set of nodes is specified
|
| 19 |
+
rc = node_redundancy(G, (2, 3))
|
| 20 |
+
assert rc == {2: 1.0, 3: 1.0}
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def test_redundant_nodes():
|
| 24 |
+
G = cycle_graph(6)
|
| 25 |
+
edge = {0, 3}
|
| 26 |
+
G.add_edge(*edge)
|
| 27 |
+
redundancy = node_redundancy(G)
|
| 28 |
+
for v in edge:
|
| 29 |
+
assert redundancy[v] == 2 / 3
|
| 30 |
+
for v in set(G) - edge:
|
| 31 |
+
assert redundancy[v] == 1
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def test_not_enough_neighbors():
|
| 35 |
+
with pytest.raises(NetworkXError):
|
| 36 |
+
G = complete_bipartite_graph(1, 2)
|
| 37 |
+
node_redundancy(G)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/centrality/__pycache__/dispersion.cpython-311.pyc
ADDED
|
Binary file (4.41 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/centrality/__pycache__/trophic.cpython-311.pyc
ADDED
|
Binary file (6.2 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/community/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (1.45 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/community/tests/__pycache__/test_asyn_fluid.cpython-311.pyc
ADDED
|
Binary file (6.75 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/community/tests/test_lukes.py
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from itertools import product
|
| 2 |
+
|
| 3 |
+
import pytest
|
| 4 |
+
|
| 5 |
+
import networkx as nx
|
| 6 |
+
|
| 7 |
+
EWL = "e_weight"
|
| 8 |
+
NWL = "n_weight"
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
# first test from the Lukes original paper
|
| 12 |
+
def paper_1_case(float_edge_wt=False, explicit_node_wt=True, directed=False):
|
| 13 |
+
# problem-specific constants
|
| 14 |
+
limit = 3
|
| 15 |
+
|
| 16 |
+
# configuration
|
| 17 |
+
if float_edge_wt:
|
| 18 |
+
shift = 0.001
|
| 19 |
+
else:
|
| 20 |
+
shift = 0
|
| 21 |
+
|
| 22 |
+
if directed:
|
| 23 |
+
example_1 = nx.DiGraph()
|
| 24 |
+
else:
|
| 25 |
+
example_1 = nx.Graph()
|
| 26 |
+
|
| 27 |
+
# graph creation
|
| 28 |
+
example_1.add_edge(1, 2, **{EWL: 3 + shift})
|
| 29 |
+
example_1.add_edge(1, 4, **{EWL: 2 + shift})
|
| 30 |
+
example_1.add_edge(2, 3, **{EWL: 4 + shift})
|
| 31 |
+
example_1.add_edge(2, 5, **{EWL: 6 + shift})
|
| 32 |
+
|
| 33 |
+
# node weights
|
| 34 |
+
if explicit_node_wt:
|
| 35 |
+
nx.set_node_attributes(example_1, 1, NWL)
|
| 36 |
+
wtu = NWL
|
| 37 |
+
else:
|
| 38 |
+
wtu = None
|
| 39 |
+
|
| 40 |
+
# partitioning
|
| 41 |
+
clusters_1 = {
|
| 42 |
+
frozenset(x)
|
| 43 |
+
for x in nx.community.lukes_partitioning(
|
| 44 |
+
example_1, limit, node_weight=wtu, edge_weight=EWL
|
| 45 |
+
)
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
return clusters_1
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
# second test from the Lukes original paper
|
| 52 |
+
def paper_2_case(explicit_edge_wt=True, directed=False):
|
| 53 |
+
# problem specific constants
|
| 54 |
+
byte_block_size = 32
|
| 55 |
+
|
| 56 |
+
# configuration
|
| 57 |
+
if directed:
|
| 58 |
+
example_2 = nx.DiGraph()
|
| 59 |
+
else:
|
| 60 |
+
example_2 = nx.Graph()
|
| 61 |
+
|
| 62 |
+
if explicit_edge_wt:
|
| 63 |
+
edic = {EWL: 1}
|
| 64 |
+
wtu = EWL
|
| 65 |
+
else:
|
| 66 |
+
edic = {}
|
| 67 |
+
wtu = None
|
| 68 |
+
|
| 69 |
+
# graph creation
|
| 70 |
+
example_2.add_edge("name", "home_address", **edic)
|
| 71 |
+
example_2.add_edge("name", "education", **edic)
|
| 72 |
+
example_2.add_edge("education", "bs", **edic)
|
| 73 |
+
example_2.add_edge("education", "ms", **edic)
|
| 74 |
+
example_2.add_edge("education", "phd", **edic)
|
| 75 |
+
example_2.add_edge("name", "telephone", **edic)
|
| 76 |
+
example_2.add_edge("telephone", "home", **edic)
|
| 77 |
+
example_2.add_edge("telephone", "office", **edic)
|
| 78 |
+
example_2.add_edge("office", "no1", **edic)
|
| 79 |
+
example_2.add_edge("office", "no2", **edic)
|
| 80 |
+
|
| 81 |
+
example_2.nodes["name"][NWL] = 20
|
| 82 |
+
example_2.nodes["education"][NWL] = 10
|
| 83 |
+
example_2.nodes["bs"][NWL] = 1
|
| 84 |
+
example_2.nodes["ms"][NWL] = 1
|
| 85 |
+
example_2.nodes["phd"][NWL] = 1
|
| 86 |
+
example_2.nodes["home_address"][NWL] = 8
|
| 87 |
+
example_2.nodes["telephone"][NWL] = 8
|
| 88 |
+
example_2.nodes["home"][NWL] = 8
|
| 89 |
+
example_2.nodes["office"][NWL] = 4
|
| 90 |
+
example_2.nodes["no1"][NWL] = 1
|
| 91 |
+
example_2.nodes["no2"][NWL] = 1
|
| 92 |
+
|
| 93 |
+
# partitioning
|
| 94 |
+
clusters_2 = {
|
| 95 |
+
frozenset(x)
|
| 96 |
+
for x in nx.community.lukes_partitioning(
|
| 97 |
+
example_2, byte_block_size, node_weight=NWL, edge_weight=wtu
|
| 98 |
+
)
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
return clusters_2
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
def test_paper_1_case():
|
| 105 |
+
ground_truth = {frozenset([1, 4]), frozenset([2, 3, 5])}
|
| 106 |
+
|
| 107 |
+
tf = (True, False)
|
| 108 |
+
for flt, nwt, drc in product(tf, tf, tf):
|
| 109 |
+
part = paper_1_case(flt, nwt, drc)
|
| 110 |
+
assert part == ground_truth
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
def test_paper_2_case():
|
| 114 |
+
ground_truth = {
|
| 115 |
+
frozenset(["education", "bs", "ms", "phd"]),
|
| 116 |
+
frozenset(["name", "home_address"]),
|
| 117 |
+
frozenset(["telephone", "home", "office", "no1", "no2"]),
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
tf = (True, False)
|
| 121 |
+
for ewt, drc in product(tf, tf):
|
| 122 |
+
part = paper_2_case(ewt, drc)
|
| 123 |
+
assert part == ground_truth
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
def test_mandatory_tree():
|
| 127 |
+
not_a_tree = nx.complete_graph(4)
|
| 128 |
+
|
| 129 |
+
with pytest.raises(nx.NotATree):
|
| 130 |
+
nx.community.lukes_partitioning(not_a_tree, 5)
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
def test_mandatory_integrality():
|
| 134 |
+
byte_block_size = 32
|
| 135 |
+
|
| 136 |
+
ex_1_broken = nx.DiGraph()
|
| 137 |
+
|
| 138 |
+
ex_1_broken.add_edge(1, 2, **{EWL: 3.2})
|
| 139 |
+
ex_1_broken.add_edge(1, 4, **{EWL: 2.4})
|
| 140 |
+
ex_1_broken.add_edge(2, 3, **{EWL: 4.0})
|
| 141 |
+
ex_1_broken.add_edge(2, 5, **{EWL: 6.3})
|
| 142 |
+
|
| 143 |
+
ex_1_broken.nodes[1][NWL] = 1.2 # !
|
| 144 |
+
ex_1_broken.nodes[2][NWL] = 1
|
| 145 |
+
ex_1_broken.nodes[3][NWL] = 1
|
| 146 |
+
ex_1_broken.nodes[4][NWL] = 1
|
| 147 |
+
ex_1_broken.nodes[5][NWL] = 2
|
| 148 |
+
|
| 149 |
+
with pytest.raises(TypeError):
|
| 150 |
+
nx.community.lukes_partitioning(
|
| 151 |
+
ex_1_broken, byte_block_size, node_weight=NWL, edge_weight=EWL
|
| 152 |
+
)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/community/tests/test_quality.py
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Unit tests for the :mod:`networkx.algorithms.community.quality`
|
| 2 |
+
module.
|
| 3 |
+
|
| 4 |
+
"""
|
| 5 |
+
import pytest
|
| 6 |
+
|
| 7 |
+
import networkx as nx
|
| 8 |
+
from networkx import barbell_graph
|
| 9 |
+
from networkx.algorithms.community import modularity, partition_quality
|
| 10 |
+
from networkx.algorithms.community.quality import inter_community_edges
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class TestPerformance:
|
| 14 |
+
"""Unit tests for the :func:`performance` function."""
|
| 15 |
+
|
| 16 |
+
def test_bad_partition(self):
|
| 17 |
+
"""Tests that a poor partition has a low performance measure."""
|
| 18 |
+
G = barbell_graph(3, 0)
|
| 19 |
+
partition = [{0, 1, 4}, {2, 3, 5}]
|
| 20 |
+
assert 8 / 15 == pytest.approx(partition_quality(G, partition)[1], abs=1e-7)
|
| 21 |
+
|
| 22 |
+
def test_good_partition(self):
|
| 23 |
+
"""Tests that a good partition has a high performance measure."""
|
| 24 |
+
G = barbell_graph(3, 0)
|
| 25 |
+
partition = [{0, 1, 2}, {3, 4, 5}]
|
| 26 |
+
assert 14 / 15 == pytest.approx(partition_quality(G, partition)[1], abs=1e-7)
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
class TestCoverage:
|
| 30 |
+
"""Unit tests for the :func:`coverage` function."""
|
| 31 |
+
|
| 32 |
+
def test_bad_partition(self):
|
| 33 |
+
"""Tests that a poor partition has a low coverage measure."""
|
| 34 |
+
G = barbell_graph(3, 0)
|
| 35 |
+
partition = [{0, 1, 4}, {2, 3, 5}]
|
| 36 |
+
assert 3 / 7 == pytest.approx(partition_quality(G, partition)[0], abs=1e-7)
|
| 37 |
+
|
| 38 |
+
def test_good_partition(self):
|
| 39 |
+
"""Tests that a good partition has a high coverage measure."""
|
| 40 |
+
G = barbell_graph(3, 0)
|
| 41 |
+
partition = [{0, 1, 2}, {3, 4, 5}]
|
| 42 |
+
assert 6 / 7 == pytest.approx(partition_quality(G, partition)[0], abs=1e-7)
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def test_modularity():
|
| 46 |
+
G = nx.barbell_graph(3, 0)
|
| 47 |
+
C = [{0, 1, 4}, {2, 3, 5}]
|
| 48 |
+
assert (-16 / (14**2)) == pytest.approx(modularity(G, C), abs=1e-7)
|
| 49 |
+
C = [{0, 1, 2}, {3, 4, 5}]
|
| 50 |
+
assert (35 * 2) / (14**2) == pytest.approx(modularity(G, C), abs=1e-7)
|
| 51 |
+
|
| 52 |
+
n = 1000
|
| 53 |
+
G = nx.erdos_renyi_graph(n, 0.09, seed=42, directed=True)
|
| 54 |
+
C = [set(range(n // 2)), set(range(n // 2, n))]
|
| 55 |
+
assert 0.00017154251389292754 == pytest.approx(modularity(G, C), abs=1e-7)
|
| 56 |
+
|
| 57 |
+
G = nx.margulis_gabber_galil_graph(10)
|
| 58 |
+
mid_value = G.number_of_nodes() // 2
|
| 59 |
+
nodes = list(G.nodes)
|
| 60 |
+
C = [set(nodes[:mid_value]), set(nodes[mid_value:])]
|
| 61 |
+
assert 0.13 == pytest.approx(modularity(G, C), abs=1e-7)
|
| 62 |
+
|
| 63 |
+
G = nx.DiGraph()
|
| 64 |
+
G.add_edges_from([(2, 1), (2, 3), (3, 4)])
|
| 65 |
+
C = [{1, 2}, {3, 4}]
|
| 66 |
+
assert 2 / 9 == pytest.approx(modularity(G, C), abs=1e-7)
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def test_modularity_resolution():
|
| 70 |
+
G = nx.barbell_graph(3, 0)
|
| 71 |
+
C = [{0, 1, 4}, {2, 3, 5}]
|
| 72 |
+
assert modularity(G, C) == pytest.approx(3 / 7 - 100 / 14**2)
|
| 73 |
+
gamma = 2
|
| 74 |
+
result = modularity(G, C, resolution=gamma)
|
| 75 |
+
assert result == pytest.approx(3 / 7 - gamma * 100 / 14**2)
|
| 76 |
+
gamma = 0.2
|
| 77 |
+
result = modularity(G, C, resolution=gamma)
|
| 78 |
+
assert result == pytest.approx(3 / 7 - gamma * 100 / 14**2)
|
| 79 |
+
|
| 80 |
+
C = [{0, 1, 2}, {3, 4, 5}]
|
| 81 |
+
assert modularity(G, C) == pytest.approx(6 / 7 - 98 / 14**2)
|
| 82 |
+
gamma = 2
|
| 83 |
+
result = modularity(G, C, resolution=gamma)
|
| 84 |
+
assert result == pytest.approx(6 / 7 - gamma * 98 / 14**2)
|
| 85 |
+
gamma = 0.2
|
| 86 |
+
result = modularity(G, C, resolution=gamma)
|
| 87 |
+
assert result == pytest.approx(6 / 7 - gamma * 98 / 14**2)
|
| 88 |
+
|
| 89 |
+
G = nx.barbell_graph(5, 3)
|
| 90 |
+
C = [frozenset(range(5)), frozenset(range(8, 13)), frozenset(range(5, 8))]
|
| 91 |
+
gamma = 1
|
| 92 |
+
result = modularity(G, C, resolution=gamma)
|
| 93 |
+
# This C is maximal for gamma=1: modularity = 0.518229
|
| 94 |
+
assert result == pytest.approx((22 / 24) - gamma * (918 / (48**2)))
|
| 95 |
+
gamma = 2
|
| 96 |
+
result = modularity(G, C, resolution=gamma)
|
| 97 |
+
assert result == pytest.approx((22 / 24) - gamma * (918 / (48**2)))
|
| 98 |
+
gamma = 0.2
|
| 99 |
+
result = modularity(G, C, resolution=gamma)
|
| 100 |
+
assert result == pytest.approx((22 / 24) - gamma * (918 / (48**2)))
|
| 101 |
+
|
| 102 |
+
C = [{0, 1, 2, 3}, {9, 10, 11, 12}, {5, 6, 7}, {4}, {8}]
|
| 103 |
+
gamma = 1
|
| 104 |
+
result = modularity(G, C, resolution=gamma)
|
| 105 |
+
assert result == pytest.approx((14 / 24) - gamma * (598 / (48**2)))
|
| 106 |
+
gamma = 2.5
|
| 107 |
+
result = modularity(G, C, resolution=gamma)
|
| 108 |
+
# This C is maximal for gamma=2.5: modularity = -0.06553819
|
| 109 |
+
assert result == pytest.approx((14 / 24) - gamma * (598 / (48**2)))
|
| 110 |
+
gamma = 0.2
|
| 111 |
+
result = modularity(G, C, resolution=gamma)
|
| 112 |
+
assert result == pytest.approx((14 / 24) - gamma * (598 / (48**2)))
|
| 113 |
+
|
| 114 |
+
C = [frozenset(range(8)), frozenset(range(8, 13))]
|
| 115 |
+
gamma = 1
|
| 116 |
+
result = modularity(G, C, resolution=gamma)
|
| 117 |
+
assert result == pytest.approx((23 / 24) - gamma * (1170 / (48**2)))
|
| 118 |
+
gamma = 2
|
| 119 |
+
result = modularity(G, C, resolution=gamma)
|
| 120 |
+
assert result == pytest.approx((23 / 24) - gamma * (1170 / (48**2)))
|
| 121 |
+
gamma = 0.3
|
| 122 |
+
result = modularity(G, C, resolution=gamma)
|
| 123 |
+
# This C is maximal for gamma=0.3: modularity = 0.805990
|
| 124 |
+
assert result == pytest.approx((23 / 24) - gamma * (1170 / (48**2)))
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
def test_inter_community_edges_with_digraphs():
|
| 128 |
+
G = nx.complete_graph(2, create_using=nx.DiGraph())
|
| 129 |
+
partition = [{0}, {1}]
|
| 130 |
+
assert inter_community_edges(G, partition) == 2
|
| 131 |
+
|
| 132 |
+
G = nx.complete_graph(10, create_using=nx.DiGraph())
|
| 133 |
+
partition = [{0}, {1, 2}, {3, 4, 5}, {6, 7, 8, 9}]
|
| 134 |
+
assert inter_community_edges(G, partition) == 70
|
| 135 |
+
|
| 136 |
+
G = nx.cycle_graph(4, create_using=nx.DiGraph())
|
| 137 |
+
partition = [{0, 1}, {2, 3}]
|
| 138 |
+
assert inter_community_edges(G, partition) == 2
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/components/__init__.py
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .connected import *
|
| 2 |
+
from .strongly_connected import *
|
| 3 |
+
from .weakly_connected import *
|
| 4 |
+
from .attracting import *
|
| 5 |
+
from .biconnected import *
|
| 6 |
+
from .semiconnected import *
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/components/__pycache__/connected.cpython-311.pyc
ADDED
|
Binary file (6.07 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/components/__pycache__/semiconnected.cpython-311.pyc
ADDED
|
Binary file (3.02 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/components/biconnected.py
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Biconnected components and articulation points."""
|
| 2 |
+
from itertools import chain
|
| 3 |
+
|
| 4 |
+
import networkx as nx
|
| 5 |
+
from networkx.utils.decorators import not_implemented_for
|
| 6 |
+
|
| 7 |
+
__all__ = [
|
| 8 |
+
"biconnected_components",
|
| 9 |
+
"biconnected_component_edges",
|
| 10 |
+
"is_biconnected",
|
| 11 |
+
"articulation_points",
|
| 12 |
+
]
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
@not_implemented_for("directed")
|
| 16 |
+
@nx._dispatch
|
| 17 |
+
def is_biconnected(G):
|
| 18 |
+
"""Returns True if the graph is biconnected, False otherwise.
|
| 19 |
+
|
| 20 |
+
A graph is biconnected if, and only if, it cannot be disconnected by
|
| 21 |
+
removing only one node (and all edges incident on that node). If
|
| 22 |
+
removing a node increases the number of disconnected components
|
| 23 |
+
in the graph, that node is called an articulation point, or cut
|
| 24 |
+
vertex. A biconnected graph has no articulation points.
|
| 25 |
+
|
| 26 |
+
Parameters
|
| 27 |
+
----------
|
| 28 |
+
G : NetworkX Graph
|
| 29 |
+
An undirected graph.
|
| 30 |
+
|
| 31 |
+
Returns
|
| 32 |
+
-------
|
| 33 |
+
biconnected : bool
|
| 34 |
+
True if the graph is biconnected, False otherwise.
|
| 35 |
+
|
| 36 |
+
Raises
|
| 37 |
+
------
|
| 38 |
+
NetworkXNotImplemented
|
| 39 |
+
If the input graph is not undirected.
|
| 40 |
+
|
| 41 |
+
Examples
|
| 42 |
+
--------
|
| 43 |
+
>>> G = nx.path_graph(4)
|
| 44 |
+
>>> print(nx.is_biconnected(G))
|
| 45 |
+
False
|
| 46 |
+
>>> G.add_edge(0, 3)
|
| 47 |
+
>>> print(nx.is_biconnected(G))
|
| 48 |
+
True
|
| 49 |
+
|
| 50 |
+
See Also
|
| 51 |
+
--------
|
| 52 |
+
biconnected_components
|
| 53 |
+
articulation_points
|
| 54 |
+
biconnected_component_edges
|
| 55 |
+
is_strongly_connected
|
| 56 |
+
is_weakly_connected
|
| 57 |
+
is_connected
|
| 58 |
+
is_semiconnected
|
| 59 |
+
|
| 60 |
+
Notes
|
| 61 |
+
-----
|
| 62 |
+
The algorithm to find articulation points and biconnected
|
| 63 |
+
components is implemented using a non-recursive depth-first-search
|
| 64 |
+
(DFS) that keeps track of the highest level that back edges reach
|
| 65 |
+
in the DFS tree. A node `n` is an articulation point if, and only
|
| 66 |
+
if, there exists a subtree rooted at `n` such that there is no
|
| 67 |
+
back edge from any successor of `n` that links to a predecessor of
|
| 68 |
+
`n` in the DFS tree. By keeping track of all the edges traversed
|
| 69 |
+
by the DFS we can obtain the biconnected components because all
|
| 70 |
+
edges of a bicomponent will be traversed consecutively between
|
| 71 |
+
articulation points.
|
| 72 |
+
|
| 73 |
+
References
|
| 74 |
+
----------
|
| 75 |
+
.. [1] Hopcroft, J.; Tarjan, R. (1973).
|
| 76 |
+
"Efficient algorithms for graph manipulation".
|
| 77 |
+
Communications of the ACM 16: 372–378. doi:10.1145/362248.362272
|
| 78 |
+
|
| 79 |
+
"""
|
| 80 |
+
bccs = biconnected_components(G)
|
| 81 |
+
try:
|
| 82 |
+
bcc = next(bccs)
|
| 83 |
+
except StopIteration:
|
| 84 |
+
# No bicomponents (empty graph?)
|
| 85 |
+
return False
|
| 86 |
+
try:
|
| 87 |
+
next(bccs)
|
| 88 |
+
except StopIteration:
|
| 89 |
+
# Only one bicomponent
|
| 90 |
+
return len(bcc) == len(G)
|
| 91 |
+
else:
|
| 92 |
+
# Multiple bicomponents
|
| 93 |
+
return False
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
@not_implemented_for("directed")
|
| 97 |
+
@nx._dispatch
|
| 98 |
+
def biconnected_component_edges(G):
|
| 99 |
+
"""Returns a generator of lists of edges, one list for each biconnected
|
| 100 |
+
component of the input graph.
|
| 101 |
+
|
| 102 |
+
Biconnected components are maximal subgraphs such that the removal of a
|
| 103 |
+
node (and all edges incident on that node) will not disconnect the
|
| 104 |
+
subgraph. Note that nodes may be part of more than one biconnected
|
| 105 |
+
component. Those nodes are articulation points, or cut vertices.
|
| 106 |
+
However, each edge belongs to one, and only one, biconnected component.
|
| 107 |
+
|
| 108 |
+
Notice that by convention a dyad is considered a biconnected component.
|
| 109 |
+
|
| 110 |
+
Parameters
|
| 111 |
+
----------
|
| 112 |
+
G : NetworkX Graph
|
| 113 |
+
An undirected graph.
|
| 114 |
+
|
| 115 |
+
Returns
|
| 116 |
+
-------
|
| 117 |
+
edges : generator of lists
|
| 118 |
+
Generator of lists of edges, one list for each bicomponent.
|
| 119 |
+
|
| 120 |
+
Raises
|
| 121 |
+
------
|
| 122 |
+
NetworkXNotImplemented
|
| 123 |
+
If the input graph is not undirected.
|
| 124 |
+
|
| 125 |
+
Examples
|
| 126 |
+
--------
|
| 127 |
+
>>> G = nx.barbell_graph(4, 2)
|
| 128 |
+
>>> print(nx.is_biconnected(G))
|
| 129 |
+
False
|
| 130 |
+
>>> bicomponents_edges = list(nx.biconnected_component_edges(G))
|
| 131 |
+
>>> len(bicomponents_edges)
|
| 132 |
+
5
|
| 133 |
+
>>> G.add_edge(2, 8)
|
| 134 |
+
>>> print(nx.is_biconnected(G))
|
| 135 |
+
True
|
| 136 |
+
>>> bicomponents_edges = list(nx.biconnected_component_edges(G))
|
| 137 |
+
>>> len(bicomponents_edges)
|
| 138 |
+
1
|
| 139 |
+
|
| 140 |
+
See Also
|
| 141 |
+
--------
|
| 142 |
+
is_biconnected,
|
| 143 |
+
biconnected_components,
|
| 144 |
+
articulation_points,
|
| 145 |
+
|
| 146 |
+
Notes
|
| 147 |
+
-----
|
| 148 |
+
The algorithm to find articulation points and biconnected
|
| 149 |
+
components is implemented using a non-recursive depth-first-search
|
| 150 |
+
(DFS) that keeps track of the highest level that back edges reach
|
| 151 |
+
in the DFS tree. A node `n` is an articulation point if, and only
|
| 152 |
+
if, there exists a subtree rooted at `n` such that there is no
|
| 153 |
+
back edge from any successor of `n` that links to a predecessor of
|
| 154 |
+
`n` in the DFS tree. By keeping track of all the edges traversed
|
| 155 |
+
by the DFS we can obtain the biconnected components because all
|
| 156 |
+
edges of a bicomponent will be traversed consecutively between
|
| 157 |
+
articulation points.
|
| 158 |
+
|
| 159 |
+
References
|
| 160 |
+
----------
|
| 161 |
+
.. [1] Hopcroft, J.; Tarjan, R. (1973).
|
| 162 |
+
"Efficient algorithms for graph manipulation".
|
| 163 |
+
Communications of the ACM 16: 372–378. doi:10.1145/362248.362272
|
| 164 |
+
|
| 165 |
+
"""
|
| 166 |
+
yield from _biconnected_dfs(G, components=True)
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
@not_implemented_for("directed")
|
| 170 |
+
@nx._dispatch
|
| 171 |
+
def biconnected_components(G):
|
| 172 |
+
"""Returns a generator of sets of nodes, one set for each biconnected
|
| 173 |
+
component of the graph
|
| 174 |
+
|
| 175 |
+
Biconnected components are maximal subgraphs such that the removal of a
|
| 176 |
+
node (and all edges incident on that node) will not disconnect the
|
| 177 |
+
subgraph. Note that nodes may be part of more than one biconnected
|
| 178 |
+
component. Those nodes are articulation points, or cut vertices. The
|
| 179 |
+
removal of articulation points will increase the number of connected
|
| 180 |
+
components of the graph.
|
| 181 |
+
|
| 182 |
+
Notice that by convention a dyad is considered a biconnected component.
|
| 183 |
+
|
| 184 |
+
Parameters
|
| 185 |
+
----------
|
| 186 |
+
G : NetworkX Graph
|
| 187 |
+
An undirected graph.
|
| 188 |
+
|
| 189 |
+
Returns
|
| 190 |
+
-------
|
| 191 |
+
nodes : generator
|
| 192 |
+
Generator of sets of nodes, one set for each biconnected component.
|
| 193 |
+
|
| 194 |
+
Raises
|
| 195 |
+
------
|
| 196 |
+
NetworkXNotImplemented
|
| 197 |
+
If the input graph is not undirected.
|
| 198 |
+
|
| 199 |
+
Examples
|
| 200 |
+
--------
|
| 201 |
+
>>> G = nx.lollipop_graph(5, 1)
|
| 202 |
+
>>> print(nx.is_biconnected(G))
|
| 203 |
+
False
|
| 204 |
+
>>> bicomponents = list(nx.biconnected_components(G))
|
| 205 |
+
>>> len(bicomponents)
|
| 206 |
+
2
|
| 207 |
+
>>> G.add_edge(0, 5)
|
| 208 |
+
>>> print(nx.is_biconnected(G))
|
| 209 |
+
True
|
| 210 |
+
>>> bicomponents = list(nx.biconnected_components(G))
|
| 211 |
+
>>> len(bicomponents)
|
| 212 |
+
1
|
| 213 |
+
|
| 214 |
+
You can generate a sorted list of biconnected components, largest
|
| 215 |
+
first, using sort.
|
| 216 |
+
|
| 217 |
+
>>> G.remove_edge(0, 5)
|
| 218 |
+
>>> [len(c) for c in sorted(nx.biconnected_components(G), key=len, reverse=True)]
|
| 219 |
+
[5, 2]
|
| 220 |
+
|
| 221 |
+
If you only want the largest connected component, it's more
|
| 222 |
+
efficient to use max instead of sort.
|
| 223 |
+
|
| 224 |
+
>>> Gc = max(nx.biconnected_components(G), key=len)
|
| 225 |
+
|
| 226 |
+
To create the components as subgraphs use:
|
| 227 |
+
``(G.subgraph(c).copy() for c in biconnected_components(G))``
|
| 228 |
+
|
| 229 |
+
See Also
|
| 230 |
+
--------
|
| 231 |
+
is_biconnected
|
| 232 |
+
articulation_points
|
| 233 |
+
biconnected_component_edges
|
| 234 |
+
k_components : this function is a special case where k=2
|
| 235 |
+
bridge_components : similar to this function, but is defined using
|
| 236 |
+
2-edge-connectivity instead of 2-node-connectivity.
|
| 237 |
+
|
| 238 |
+
Notes
|
| 239 |
+
-----
|
| 240 |
+
The algorithm to find articulation points and biconnected
|
| 241 |
+
components is implemented using a non-recursive depth-first-search
|
| 242 |
+
(DFS) that keeps track of the highest level that back edges reach
|
| 243 |
+
in the DFS tree. A node `n` is an articulation point if, and only
|
| 244 |
+
if, there exists a subtree rooted at `n` such that there is no
|
| 245 |
+
back edge from any successor of `n` that links to a predecessor of
|
| 246 |
+
`n` in the DFS tree. By keeping track of all the edges traversed
|
| 247 |
+
by the DFS we can obtain the biconnected components because all
|
| 248 |
+
edges of a bicomponent will be traversed consecutively between
|
| 249 |
+
articulation points.
|
| 250 |
+
|
| 251 |
+
References
|
| 252 |
+
----------
|
| 253 |
+
.. [1] Hopcroft, J.; Tarjan, R. (1973).
|
| 254 |
+
"Efficient algorithms for graph manipulation".
|
| 255 |
+
Communications of the ACM 16: 372–378. doi:10.1145/362248.362272
|
| 256 |
+
|
| 257 |
+
"""
|
| 258 |
+
for comp in _biconnected_dfs(G, components=True):
|
| 259 |
+
yield set(chain.from_iterable(comp))
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
@not_implemented_for("directed")
|
| 263 |
+
@nx._dispatch
|
| 264 |
+
def articulation_points(G):
|
| 265 |
+
"""Yield the articulation points, or cut vertices, of a graph.
|
| 266 |
+
|
| 267 |
+
An articulation point or cut vertex is any node whose removal (along with
|
| 268 |
+
all its incident edges) increases the number of connected components of
|
| 269 |
+
a graph. An undirected connected graph without articulation points is
|
| 270 |
+
biconnected. Articulation points belong to more than one biconnected
|
| 271 |
+
component of a graph.
|
| 272 |
+
|
| 273 |
+
Notice that by convention a dyad is considered a biconnected component.
|
| 274 |
+
|
| 275 |
+
Parameters
|
| 276 |
+
----------
|
| 277 |
+
G : NetworkX Graph
|
| 278 |
+
An undirected graph.
|
| 279 |
+
|
| 280 |
+
Yields
|
| 281 |
+
------
|
| 282 |
+
node
|
| 283 |
+
An articulation point in the graph.
|
| 284 |
+
|
| 285 |
+
Raises
|
| 286 |
+
------
|
| 287 |
+
NetworkXNotImplemented
|
| 288 |
+
If the input graph is not undirected.
|
| 289 |
+
|
| 290 |
+
Examples
|
| 291 |
+
--------
|
| 292 |
+
|
| 293 |
+
>>> G = nx.barbell_graph(4, 2)
|
| 294 |
+
>>> print(nx.is_biconnected(G))
|
| 295 |
+
False
|
| 296 |
+
>>> len(list(nx.articulation_points(G)))
|
| 297 |
+
4
|
| 298 |
+
>>> G.add_edge(2, 8)
|
| 299 |
+
>>> print(nx.is_biconnected(G))
|
| 300 |
+
True
|
| 301 |
+
>>> len(list(nx.articulation_points(G)))
|
| 302 |
+
0
|
| 303 |
+
|
| 304 |
+
See Also
|
| 305 |
+
--------
|
| 306 |
+
is_biconnected
|
| 307 |
+
biconnected_components
|
| 308 |
+
biconnected_component_edges
|
| 309 |
+
|
| 310 |
+
Notes
|
| 311 |
+
-----
|
| 312 |
+
The algorithm to find articulation points and biconnected
|
| 313 |
+
components is implemented using a non-recursive depth-first-search
|
| 314 |
+
(DFS) that keeps track of the highest level that back edges reach
|
| 315 |
+
in the DFS tree. A node `n` is an articulation point if, and only
|
| 316 |
+
if, there exists a subtree rooted at `n` such that there is no
|
| 317 |
+
back edge from any successor of `n` that links to a predecessor of
|
| 318 |
+
`n` in the DFS tree. By keeping track of all the edges traversed
|
| 319 |
+
by the DFS we can obtain the biconnected components because all
|
| 320 |
+
edges of a bicomponent will be traversed consecutively between
|
| 321 |
+
articulation points.
|
| 322 |
+
|
| 323 |
+
References
|
| 324 |
+
----------
|
| 325 |
+
.. [1] Hopcroft, J.; Tarjan, R. (1973).
|
| 326 |
+
"Efficient algorithms for graph manipulation".
|
| 327 |
+
Communications of the ACM 16: 372–378. doi:10.1145/362248.362272
|
| 328 |
+
|
| 329 |
+
"""
|
| 330 |
+
seen = set()
|
| 331 |
+
for articulation in _biconnected_dfs(G, components=False):
|
| 332 |
+
if articulation not in seen:
|
| 333 |
+
seen.add(articulation)
|
| 334 |
+
yield articulation
|
| 335 |
+
|
| 336 |
+
|
| 337 |
+
@not_implemented_for("directed")
|
| 338 |
+
def _biconnected_dfs(G, components=True):
|
| 339 |
+
# depth-first search algorithm to generate articulation points
|
| 340 |
+
# and biconnected components
|
| 341 |
+
visited = set()
|
| 342 |
+
for start in G:
|
| 343 |
+
if start in visited:
|
| 344 |
+
continue
|
| 345 |
+
discovery = {start: 0} # time of first discovery of node during search
|
| 346 |
+
low = {start: 0}
|
| 347 |
+
root_children = 0
|
| 348 |
+
visited.add(start)
|
| 349 |
+
edge_stack = []
|
| 350 |
+
stack = [(start, start, iter(G[start]))]
|
| 351 |
+
edge_index = {}
|
| 352 |
+
while stack:
|
| 353 |
+
grandparent, parent, children = stack[-1]
|
| 354 |
+
try:
|
| 355 |
+
child = next(children)
|
| 356 |
+
if grandparent == child:
|
| 357 |
+
continue
|
| 358 |
+
if child in visited:
|
| 359 |
+
if discovery[child] <= discovery[parent]: # back edge
|
| 360 |
+
low[parent] = min(low[parent], discovery[child])
|
| 361 |
+
if components:
|
| 362 |
+
edge_index[parent, child] = len(edge_stack)
|
| 363 |
+
edge_stack.append((parent, child))
|
| 364 |
+
else:
|
| 365 |
+
low[child] = discovery[child] = len(discovery)
|
| 366 |
+
visited.add(child)
|
| 367 |
+
stack.append((parent, child, iter(G[child])))
|
| 368 |
+
if components:
|
| 369 |
+
edge_index[parent, child] = len(edge_stack)
|
| 370 |
+
edge_stack.append((parent, child))
|
| 371 |
+
|
| 372 |
+
except StopIteration:
|
| 373 |
+
stack.pop()
|
| 374 |
+
if len(stack) > 1:
|
| 375 |
+
if low[parent] >= discovery[grandparent]:
|
| 376 |
+
if components:
|
| 377 |
+
ind = edge_index[grandparent, parent]
|
| 378 |
+
yield edge_stack[ind:]
|
| 379 |
+
del edge_stack[ind:]
|
| 380 |
+
|
| 381 |
+
else:
|
| 382 |
+
yield grandparent
|
| 383 |
+
low[grandparent] = min(low[parent], low[grandparent])
|
| 384 |
+
elif stack: # length 1 so grandparent is root
|
| 385 |
+
root_children += 1
|
| 386 |
+
if components:
|
| 387 |
+
ind = edge_index[grandparent, parent]
|
| 388 |
+
yield edge_stack[ind:]
|
| 389 |
+
del edge_stack[ind:]
|
| 390 |
+
if not components:
|
| 391 |
+
# root node is articulation point if it has more than 1 child
|
| 392 |
+
if root_children > 1:
|
| 393 |
+
yield start
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/components/tests/__init__.py
ADDED
|
File without changes
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/components/tests/__pycache__/test_semiconnected.cpython-311.pyc
ADDED
|
Binary file (5.53 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/components/tests/test_biconnected.py
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pytest
|
| 2 |
+
|
| 3 |
+
import networkx as nx
|
| 4 |
+
from networkx import NetworkXNotImplemented
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
def assert_components_edges_equal(x, y):
|
| 8 |
+
sx = {frozenset(frozenset(e) for e in c) for c in x}
|
| 9 |
+
sy = {frozenset(frozenset(e) for e in c) for c in y}
|
| 10 |
+
assert sx == sy
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def assert_components_equal(x, y):
|
| 14 |
+
sx = {frozenset(c) for c in x}
|
| 15 |
+
sy = {frozenset(c) for c in y}
|
| 16 |
+
assert sx == sy
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def test_barbell():
|
| 20 |
+
G = nx.barbell_graph(8, 4)
|
| 21 |
+
nx.add_path(G, [7, 20, 21, 22])
|
| 22 |
+
nx.add_cycle(G, [22, 23, 24, 25])
|
| 23 |
+
pts = set(nx.articulation_points(G))
|
| 24 |
+
assert pts == {7, 8, 9, 10, 11, 12, 20, 21, 22}
|
| 25 |
+
|
| 26 |
+
answer = [
|
| 27 |
+
{12, 13, 14, 15, 16, 17, 18, 19},
|
| 28 |
+
{0, 1, 2, 3, 4, 5, 6, 7},
|
| 29 |
+
{22, 23, 24, 25},
|
| 30 |
+
{11, 12},
|
| 31 |
+
{10, 11},
|
| 32 |
+
{9, 10},
|
| 33 |
+
{8, 9},
|
| 34 |
+
{7, 8},
|
| 35 |
+
{21, 22},
|
| 36 |
+
{20, 21},
|
| 37 |
+
{7, 20},
|
| 38 |
+
]
|
| 39 |
+
assert_components_equal(list(nx.biconnected_components(G)), answer)
|
| 40 |
+
|
| 41 |
+
G.add_edge(2, 17)
|
| 42 |
+
pts = set(nx.articulation_points(G))
|
| 43 |
+
assert pts == {7, 20, 21, 22}
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def test_articulation_points_repetitions():
|
| 47 |
+
G = nx.Graph()
|
| 48 |
+
G.add_edges_from([(0, 1), (1, 2), (1, 3)])
|
| 49 |
+
assert list(nx.articulation_points(G)) == [1]
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def test_articulation_points_cycle():
|
| 53 |
+
G = nx.cycle_graph(3)
|
| 54 |
+
nx.add_cycle(G, [1, 3, 4])
|
| 55 |
+
pts = set(nx.articulation_points(G))
|
| 56 |
+
assert pts == {1}
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
def test_is_biconnected():
|
| 60 |
+
G = nx.cycle_graph(3)
|
| 61 |
+
assert nx.is_biconnected(G)
|
| 62 |
+
nx.add_cycle(G, [1, 3, 4])
|
| 63 |
+
assert not nx.is_biconnected(G)
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
def test_empty_is_biconnected():
|
| 67 |
+
G = nx.empty_graph(5)
|
| 68 |
+
assert not nx.is_biconnected(G)
|
| 69 |
+
G.add_edge(0, 1)
|
| 70 |
+
assert not nx.is_biconnected(G)
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
def test_biconnected_components_cycle():
|
| 74 |
+
G = nx.cycle_graph(3)
|
| 75 |
+
nx.add_cycle(G, [1, 3, 4])
|
| 76 |
+
answer = [{0, 1, 2}, {1, 3, 4}]
|
| 77 |
+
assert_components_equal(list(nx.biconnected_components(G)), answer)
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def test_biconnected_components1():
|
| 81 |
+
# graph example from
|
| 82 |
+
# https://web.archive.org/web/20121229123447/http://www.ibluemojo.com/school/articul_algorithm.html
|
| 83 |
+
edges = [
|
| 84 |
+
(0, 1),
|
| 85 |
+
(0, 5),
|
| 86 |
+
(0, 6),
|
| 87 |
+
(0, 14),
|
| 88 |
+
(1, 5),
|
| 89 |
+
(1, 6),
|
| 90 |
+
(1, 14),
|
| 91 |
+
(2, 4),
|
| 92 |
+
(2, 10),
|
| 93 |
+
(3, 4),
|
| 94 |
+
(3, 15),
|
| 95 |
+
(4, 6),
|
| 96 |
+
(4, 7),
|
| 97 |
+
(4, 10),
|
| 98 |
+
(5, 14),
|
| 99 |
+
(6, 14),
|
| 100 |
+
(7, 9),
|
| 101 |
+
(8, 9),
|
| 102 |
+
(8, 12),
|
| 103 |
+
(8, 13),
|
| 104 |
+
(10, 15),
|
| 105 |
+
(11, 12),
|
| 106 |
+
(11, 13),
|
| 107 |
+
(12, 13),
|
| 108 |
+
]
|
| 109 |
+
G = nx.Graph(edges)
|
| 110 |
+
pts = set(nx.articulation_points(G))
|
| 111 |
+
assert pts == {4, 6, 7, 8, 9}
|
| 112 |
+
comps = list(nx.biconnected_component_edges(G))
|
| 113 |
+
answer = [
|
| 114 |
+
[(3, 4), (15, 3), (10, 15), (10, 4), (2, 10), (4, 2)],
|
| 115 |
+
[(13, 12), (13, 8), (11, 13), (12, 11), (8, 12)],
|
| 116 |
+
[(9, 8)],
|
| 117 |
+
[(7, 9)],
|
| 118 |
+
[(4, 7)],
|
| 119 |
+
[(6, 4)],
|
| 120 |
+
[(14, 0), (5, 1), (5, 0), (14, 5), (14, 1), (6, 14), (6, 0), (1, 6), (0, 1)],
|
| 121 |
+
]
|
| 122 |
+
assert_components_edges_equal(comps, answer)
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
def test_biconnected_components2():
|
| 126 |
+
G = nx.Graph()
|
| 127 |
+
nx.add_cycle(G, "ABC")
|
| 128 |
+
nx.add_cycle(G, "CDE")
|
| 129 |
+
nx.add_cycle(G, "FIJHG")
|
| 130 |
+
nx.add_cycle(G, "GIJ")
|
| 131 |
+
G.add_edge("E", "G")
|
| 132 |
+
comps = list(nx.biconnected_component_edges(G))
|
| 133 |
+
answer = [
|
| 134 |
+
[
|
| 135 |
+
tuple("GF"),
|
| 136 |
+
tuple("FI"),
|
| 137 |
+
tuple("IG"),
|
| 138 |
+
tuple("IJ"),
|
| 139 |
+
tuple("JG"),
|
| 140 |
+
tuple("JH"),
|
| 141 |
+
tuple("HG"),
|
| 142 |
+
],
|
| 143 |
+
[tuple("EG")],
|
| 144 |
+
[tuple("CD"), tuple("DE"), tuple("CE")],
|
| 145 |
+
[tuple("AB"), tuple("BC"), tuple("AC")],
|
| 146 |
+
]
|
| 147 |
+
assert_components_edges_equal(comps, answer)
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
def test_biconnected_davis():
|
| 151 |
+
D = nx.davis_southern_women_graph()
|
| 152 |
+
bcc = list(nx.biconnected_components(D))[0]
|
| 153 |
+
assert set(D) == bcc # All nodes in a giant bicomponent
|
| 154 |
+
# So no articulation points
|
| 155 |
+
assert len(list(nx.articulation_points(D))) == 0
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
def test_biconnected_karate():
|
| 159 |
+
K = nx.karate_club_graph()
|
| 160 |
+
answer = [
|
| 161 |
+
{
|
| 162 |
+
0,
|
| 163 |
+
1,
|
| 164 |
+
2,
|
| 165 |
+
3,
|
| 166 |
+
7,
|
| 167 |
+
8,
|
| 168 |
+
9,
|
| 169 |
+
12,
|
| 170 |
+
13,
|
| 171 |
+
14,
|
| 172 |
+
15,
|
| 173 |
+
17,
|
| 174 |
+
18,
|
| 175 |
+
19,
|
| 176 |
+
20,
|
| 177 |
+
21,
|
| 178 |
+
22,
|
| 179 |
+
23,
|
| 180 |
+
24,
|
| 181 |
+
25,
|
| 182 |
+
26,
|
| 183 |
+
27,
|
| 184 |
+
28,
|
| 185 |
+
29,
|
| 186 |
+
30,
|
| 187 |
+
31,
|
| 188 |
+
32,
|
| 189 |
+
33,
|
| 190 |
+
},
|
| 191 |
+
{0, 4, 5, 6, 10, 16},
|
| 192 |
+
{0, 11},
|
| 193 |
+
]
|
| 194 |
+
bcc = list(nx.biconnected_components(K))
|
| 195 |
+
assert_components_equal(bcc, answer)
|
| 196 |
+
assert set(nx.articulation_points(K)) == {0}
|
| 197 |
+
|
| 198 |
+
|
| 199 |
+
def test_biconnected_eppstein():
|
| 200 |
+
# tests from http://www.ics.uci.edu/~eppstein/PADS/Biconnectivity.py
|
| 201 |
+
G1 = nx.Graph(
|
| 202 |
+
{
|
| 203 |
+
0: [1, 2, 5],
|
| 204 |
+
1: [0, 5],
|
| 205 |
+
2: [0, 3, 4],
|
| 206 |
+
3: [2, 4, 5, 6],
|
| 207 |
+
4: [2, 3, 5, 6],
|
| 208 |
+
5: [0, 1, 3, 4],
|
| 209 |
+
6: [3, 4],
|
| 210 |
+
}
|
| 211 |
+
)
|
| 212 |
+
G2 = nx.Graph(
|
| 213 |
+
{
|
| 214 |
+
0: [2, 5],
|
| 215 |
+
1: [3, 8],
|
| 216 |
+
2: [0, 3, 5],
|
| 217 |
+
3: [1, 2, 6, 8],
|
| 218 |
+
4: [7],
|
| 219 |
+
5: [0, 2],
|
| 220 |
+
6: [3, 8],
|
| 221 |
+
7: [4],
|
| 222 |
+
8: [1, 3, 6],
|
| 223 |
+
}
|
| 224 |
+
)
|
| 225 |
+
assert nx.is_biconnected(G1)
|
| 226 |
+
assert not nx.is_biconnected(G2)
|
| 227 |
+
answer_G2 = [{1, 3, 6, 8}, {0, 2, 5}, {2, 3}, {4, 7}]
|
| 228 |
+
bcc = list(nx.biconnected_components(G2))
|
| 229 |
+
assert_components_equal(bcc, answer_G2)
|
| 230 |
+
|
| 231 |
+
|
| 232 |
+
def test_null_graph():
|
| 233 |
+
G = nx.Graph()
|
| 234 |
+
assert not nx.is_biconnected(G)
|
| 235 |
+
assert list(nx.biconnected_components(G)) == []
|
| 236 |
+
assert list(nx.biconnected_component_edges(G)) == []
|
| 237 |
+
assert list(nx.articulation_points(G)) == []
|
| 238 |
+
|
| 239 |
+
|
| 240 |
+
def test_connected_raise():
|
| 241 |
+
DG = nx.DiGraph()
|
| 242 |
+
with pytest.raises(NetworkXNotImplemented):
|
| 243 |
+
next(nx.biconnected_components(DG))
|
| 244 |
+
with pytest.raises(NetworkXNotImplemented):
|
| 245 |
+
next(nx.biconnected_component_edges(DG))
|
| 246 |
+
with pytest.raises(NetworkXNotImplemented):
|
| 247 |
+
next(nx.articulation_points(DG))
|
| 248 |
+
pytest.raises(NetworkXNotImplemented, nx.is_biconnected, DG)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/components/tests/test_connected.py
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pytest
|
| 2 |
+
|
| 3 |
+
import networkx as nx
|
| 4 |
+
from networkx import NetworkXNotImplemented
|
| 5 |
+
from networkx import convert_node_labels_to_integers as cnlti
|
| 6 |
+
from networkx.classes.tests import dispatch_interface
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class TestConnected:
|
| 10 |
+
@classmethod
|
| 11 |
+
def setup_class(cls):
|
| 12 |
+
G1 = cnlti(nx.grid_2d_graph(2, 2), first_label=0, ordering="sorted")
|
| 13 |
+
G2 = cnlti(nx.lollipop_graph(3, 3), first_label=4, ordering="sorted")
|
| 14 |
+
G3 = cnlti(nx.house_graph(), first_label=10, ordering="sorted")
|
| 15 |
+
cls.G = nx.union(G1, G2)
|
| 16 |
+
cls.G = nx.union(cls.G, G3)
|
| 17 |
+
cls.DG = nx.DiGraph([(1, 2), (1, 3), (2, 3)])
|
| 18 |
+
cls.grid = cnlti(nx.grid_2d_graph(4, 4), first_label=1)
|
| 19 |
+
|
| 20 |
+
cls.gc = []
|
| 21 |
+
G = nx.DiGraph()
|
| 22 |
+
G.add_edges_from(
|
| 23 |
+
[
|
| 24 |
+
(1, 2),
|
| 25 |
+
(2, 3),
|
| 26 |
+
(2, 8),
|
| 27 |
+
(3, 4),
|
| 28 |
+
(3, 7),
|
| 29 |
+
(4, 5),
|
| 30 |
+
(5, 3),
|
| 31 |
+
(5, 6),
|
| 32 |
+
(7, 4),
|
| 33 |
+
(7, 6),
|
| 34 |
+
(8, 1),
|
| 35 |
+
(8, 7),
|
| 36 |
+
]
|
| 37 |
+
)
|
| 38 |
+
C = [[3, 4, 5, 7], [1, 2, 8], [6]]
|
| 39 |
+
cls.gc.append((G, C))
|
| 40 |
+
|
| 41 |
+
G = nx.DiGraph()
|
| 42 |
+
G.add_edges_from([(1, 2), (1, 3), (1, 4), (4, 2), (3, 4), (2, 3)])
|
| 43 |
+
C = [[2, 3, 4], [1]]
|
| 44 |
+
cls.gc.append((G, C))
|
| 45 |
+
|
| 46 |
+
G = nx.DiGraph()
|
| 47 |
+
G.add_edges_from([(1, 2), (2, 3), (3, 2), (2, 1)])
|
| 48 |
+
C = [[1, 2, 3]]
|
| 49 |
+
cls.gc.append((G, C))
|
| 50 |
+
|
| 51 |
+
# Eppstein's tests
|
| 52 |
+
G = nx.DiGraph({0: [1], 1: [2, 3], 2: [4, 5], 3: [4, 5], 4: [6], 5: [], 6: []})
|
| 53 |
+
C = [[0], [1], [2], [3], [4], [5], [6]]
|
| 54 |
+
cls.gc.append((G, C))
|
| 55 |
+
|
| 56 |
+
G = nx.DiGraph({0: [1], 1: [2, 3, 4], 2: [0, 3], 3: [4], 4: [3]})
|
| 57 |
+
C = [[0, 1, 2], [3, 4]]
|
| 58 |
+
cls.gc.append((G, C))
|
| 59 |
+
|
| 60 |
+
G = nx.DiGraph()
|
| 61 |
+
C = []
|
| 62 |
+
cls.gc.append((G, C))
|
| 63 |
+
|
| 64 |
+
# This additionally tests the @nx._dispatch mechanism, treating
|
| 65 |
+
# nx.connected_components as if it were a re-implementation from another package
|
| 66 |
+
@pytest.mark.parametrize("wrapper", [lambda x: x, dispatch_interface.convert])
|
| 67 |
+
def test_connected_components(self, wrapper):
|
| 68 |
+
cc = nx.connected_components
|
| 69 |
+
G = wrapper(self.G)
|
| 70 |
+
C = {
|
| 71 |
+
frozenset([0, 1, 2, 3]),
|
| 72 |
+
frozenset([4, 5, 6, 7, 8, 9]),
|
| 73 |
+
frozenset([10, 11, 12, 13, 14]),
|
| 74 |
+
}
|
| 75 |
+
assert {frozenset(g) for g in cc(G)} == C
|
| 76 |
+
|
| 77 |
+
def test_number_connected_components(self):
|
| 78 |
+
ncc = nx.number_connected_components
|
| 79 |
+
assert ncc(self.G) == 3
|
| 80 |
+
|
| 81 |
+
def test_number_connected_components2(self):
|
| 82 |
+
ncc = nx.number_connected_components
|
| 83 |
+
assert ncc(self.grid) == 1
|
| 84 |
+
|
| 85 |
+
def test_connected_components2(self):
|
| 86 |
+
cc = nx.connected_components
|
| 87 |
+
G = self.grid
|
| 88 |
+
C = {frozenset([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])}
|
| 89 |
+
assert {frozenset(g) for g in cc(G)} == C
|
| 90 |
+
|
| 91 |
+
def test_node_connected_components(self):
|
| 92 |
+
ncc = nx.node_connected_component
|
| 93 |
+
G = self.grid
|
| 94 |
+
C = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
|
| 95 |
+
assert ncc(G, 1) == C
|
| 96 |
+
|
| 97 |
+
def test_is_connected(self):
|
| 98 |
+
assert nx.is_connected(self.grid)
|
| 99 |
+
G = nx.Graph()
|
| 100 |
+
G.add_nodes_from([1, 2])
|
| 101 |
+
assert not nx.is_connected(G)
|
| 102 |
+
|
| 103 |
+
def test_connected_raise(self):
|
| 104 |
+
with pytest.raises(NetworkXNotImplemented):
|
| 105 |
+
next(nx.connected_components(self.DG))
|
| 106 |
+
pytest.raises(NetworkXNotImplemented, nx.number_connected_components, self.DG)
|
| 107 |
+
pytest.raises(NetworkXNotImplemented, nx.node_connected_component, self.DG, 1)
|
| 108 |
+
pytest.raises(NetworkXNotImplemented, nx.is_connected, self.DG)
|
| 109 |
+
pytest.raises(nx.NetworkXPointlessConcept, nx.is_connected, nx.Graph())
|
| 110 |
+
|
| 111 |
+
def test_connected_mutability(self):
|
| 112 |
+
G = self.grid
|
| 113 |
+
seen = set()
|
| 114 |
+
for component in nx.connected_components(G):
|
| 115 |
+
assert len(seen & component) == 0
|
| 116 |
+
seen.update(component)
|
| 117 |
+
component.clear()
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/isomorphism/__init__.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from networkx.algorithms.isomorphism.isomorph import *
|
| 2 |
+
from networkx.algorithms.isomorphism.vf2userfunc import *
|
| 3 |
+
from networkx.algorithms.isomorphism.matchhelpers import *
|
| 4 |
+
from networkx.algorithms.isomorphism.temporalisomorphvf2 import *
|
| 5 |
+
from networkx.algorithms.isomorphism.ismags import *
|
| 6 |
+
from networkx.algorithms.isomorphism.tree_isomorphism import *
|
| 7 |
+
from networkx.algorithms.isomorphism.vf2pp import *
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/isomorphism/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (690 Bytes). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/isomorphism/__pycache__/ismags.cpython-311.pyc
ADDED
|
Binary file (51 kB). View file
|
|
|