koichi12 commited on
Commit
7833ca4
·
verified ·
1 Parent(s): 1cd5f2c

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. tuning-competition-baseline/.venv/lib/python3.11/site-packages/Jinja2-3.1.3.dist-info/top_level.txt +1 -0
  2. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/__init__.py +49 -0
  3. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/__init__.py +5 -0
  4. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/__pycache__/__init__.cpython-311.pyc +0 -0
  5. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/__pycache__/correlation.cpython-311.pyc +0 -0
  6. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/__pycache__/neighbor_degree.cpython-311.pyc +0 -0
  7. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/connectivity.py +122 -0
  8. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/correlation.py +302 -0
  9. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/mixing.py +250 -0
  10. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/pairs.py +118 -0
  11. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/tests/__pycache__/__init__.cpython-311.pyc +0 -0
  12. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/tests/__pycache__/base_test.cpython-311.pyc +0 -0
  13. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/tests/__pycache__/test_connectivity.cpython-311.pyc +0 -0
  14. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/tests/__pycache__/test_mixing.cpython-311.pyc +0 -0
  15. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/tests/__pycache__/test_neighbor_degree.cpython-311.pyc +0 -0
  16. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/tests/__pycache__/test_pairs.cpython-311.pyc +0 -0
  17. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/tests/test_connectivity.py +143 -0
  18. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/tests/test_pairs.py +87 -0
  19. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/coloring/__init__.py +4 -0
  20. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/coloring/__pycache__/equitable_coloring.cpython-311.pyc +0 -0
  21. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/coloring/greedy_coloring.py +572 -0
  22. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/__pycache__/__init__.cpython-311.pyc +0 -0
  23. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/__pycache__/kcutsets.cpython-311.pyc +0 -0
  24. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/__init__.py +0 -0
  25. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/__pycache__/__init__.cpython-311.pyc +0 -0
  26. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/__pycache__/test_connectivity.cpython-311.pyc +0 -0
  27. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/__pycache__/test_cuts.cpython-311.pyc +0 -0
  28. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/__pycache__/test_kcutsets.cpython-311.pyc +0 -0
  29. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/__pycache__/test_stoer_wagner.cpython-311.pyc +0 -0
  30. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/test_connectivity.py +421 -0
  31. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/test_cuts.py +309 -0
  32. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/test_edge_augmentation.py +502 -0
  33. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/test_edge_kcomponents.py +488 -0
  34. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/test_kcomponents.py +296 -0
  35. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/test_kcutsets.py +266 -0
  36. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/__init__.py +5 -0
  37. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/__pycache__/__init__.cpython-311.pyc +0 -0
  38. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/__pycache__/astar.cpython-311.pyc +0 -0
  39. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/__pycache__/dense.cpython-311.pyc +0 -0
  40. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/__pycache__/generic.cpython-311.pyc +0 -0
  41. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/__pycache__/weighted.cpython-311.pyc +0 -0
  42. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/astar.py +214 -0
  43. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/dense.py +256 -0
  44. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/tests/__pycache__/test_dense.cpython-311.pyc +0 -0
  45. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/tests/__pycache__/test_generic.cpython-311.pyc +0 -0
  46. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/tests/__pycache__/test_unweighted.cpython-311.pyc +0 -0
  47. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/tests/__pycache__/test_weighted.cpython-311.pyc +0 -0
  48. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/tests/test_astar.py +210 -0
  49. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/tests/test_dense_numpy.py +89 -0
  50. tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/tests/test_unweighted.py +149 -0
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Jinja2-3.1.3.dist-info/top_level.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ jinja2
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/__init__.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ NetworkX
3
+ ========
4
+
5
+ NetworkX is a Python package for the creation, manipulation, and study of the
6
+ structure, dynamics, and functions of complex networks.
7
+
8
+ See https://networkx.org for complete documentation.
9
+ """
10
+
11
+ __version__ = "3.2.1"
12
+
13
+
14
+ # These are imported in order as listed
15
+ from networkx.lazy_imports import _lazy_import
16
+
17
+ from networkx.exception import *
18
+
19
+ from networkx import utils
20
+ from networkx.utils.backends import _dispatch
21
+
22
+ from networkx import classes
23
+ from networkx.classes import filters
24
+ from networkx.classes import *
25
+
26
+ from networkx import convert
27
+ from networkx.convert import *
28
+
29
+ from networkx import convert_matrix
30
+ from networkx.convert_matrix import *
31
+
32
+ from networkx import relabel
33
+ from networkx.relabel import *
34
+
35
+ from networkx import generators
36
+ from networkx.generators import *
37
+
38
+ from networkx import readwrite
39
+ from networkx.readwrite import *
40
+
41
+ # Need to test with SciPy, when available
42
+ from networkx import algorithms
43
+ from networkx.algorithms import *
44
+
45
+ from networkx import linalg
46
+ from networkx.linalg import *
47
+
48
+ from networkx import drawing
49
+ from networkx.drawing import *
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/__init__.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ from networkx.algorithms.assortativity.connectivity import *
2
+ from networkx.algorithms.assortativity.correlation import *
3
+ from networkx.algorithms.assortativity.mixing import *
4
+ from networkx.algorithms.assortativity.neighbor_degree import *
5
+ from networkx.algorithms.assortativity.pairs import *
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (566 Bytes). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/__pycache__/correlation.cpython-311.pyc ADDED
Binary file (12.3 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/__pycache__/neighbor_degree.cpython-311.pyc ADDED
Binary file (6.62 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/connectivity.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections import defaultdict
2
+
3
+ import networkx as nx
4
+
5
+ __all__ = ["average_degree_connectivity"]
6
+
7
+
8
+ @nx._dispatch(edge_attrs="weight")
9
+ def average_degree_connectivity(
10
+ G, source="in+out", target="in+out", nodes=None, weight=None
11
+ ):
12
+ r"""Compute the average degree connectivity of graph.
13
+
14
+ The average degree connectivity is the average nearest neighbor degree of
15
+ nodes with degree k. For weighted graphs, an analogous measure can
16
+ be computed using the weighted average neighbors degree defined in
17
+ [1]_, for a node `i`, as
18
+
19
+ .. math::
20
+
21
+ k_{nn,i}^{w} = \frac{1}{s_i} \sum_{j \in N(i)} w_{ij} k_j
22
+
23
+ where `s_i` is the weighted degree of node `i`,
24
+ `w_{ij}` is the weight of the edge that links `i` and `j`,
25
+ and `N(i)` are the neighbors of node `i`.
26
+
27
+ Parameters
28
+ ----------
29
+ G : NetworkX graph
30
+
31
+ source : "in"|"out"|"in+out" (default:"in+out")
32
+ Directed graphs only. Use "in"- or "out"-degree for source node.
33
+
34
+ target : "in"|"out"|"in+out" (default:"in+out"
35
+ Directed graphs only. Use "in"- or "out"-degree for target node.
36
+
37
+ nodes : list or iterable (optional)
38
+ Compute neighbor connectivity for these nodes. The default is all
39
+ nodes.
40
+
41
+ weight : string or None, optional (default=None)
42
+ The edge attribute that holds the numerical value used as a weight.
43
+ If None, then each edge has weight 1.
44
+
45
+ Returns
46
+ -------
47
+ d : dict
48
+ A dictionary keyed by degree k with the value of average connectivity.
49
+
50
+ Raises
51
+ ------
52
+ NetworkXError
53
+ If either `source` or `target` are not one of 'in',
54
+ 'out', or 'in+out'.
55
+ If either `source` or `target` is passed for an undirected graph.
56
+
57
+ Examples
58
+ --------
59
+ >>> G = nx.path_graph(4)
60
+ >>> G.edges[1, 2]["weight"] = 3
61
+ >>> nx.average_degree_connectivity(G)
62
+ {1: 2.0, 2: 1.5}
63
+ >>> nx.average_degree_connectivity(G, weight="weight")
64
+ {1: 2.0, 2: 1.75}
65
+
66
+ See Also
67
+ --------
68
+ average_neighbor_degree
69
+
70
+ References
71
+ ----------
72
+ .. [1] A. Barrat, M. Barthélemy, R. Pastor-Satorras, and A. Vespignani,
73
+ "The architecture of complex weighted networks".
74
+ PNAS 101 (11): 3747–3752 (2004).
75
+ """
76
+ # First, determine the type of neighbors and the type of degree to use.
77
+ if G.is_directed():
78
+ if source not in ("in", "out", "in+out"):
79
+ raise nx.NetworkXError('source must be one of "in", "out", or "in+out"')
80
+ if target not in ("in", "out", "in+out"):
81
+ raise nx.NetworkXError('target must be one of "in", "out", or "in+out"')
82
+ direction = {"out": G.out_degree, "in": G.in_degree, "in+out": G.degree}
83
+ neighbor_funcs = {
84
+ "out": G.successors,
85
+ "in": G.predecessors,
86
+ "in+out": G.neighbors,
87
+ }
88
+ source_degree = direction[source]
89
+ target_degree = direction[target]
90
+ neighbors = neighbor_funcs[source]
91
+ # `reverse` indicates whether to look at the in-edge when
92
+ # computing the weight of an edge.
93
+ reverse = source == "in"
94
+ else:
95
+ if source != "in+out" or target != "in+out":
96
+ raise nx.NetworkXError(
97
+ f"source and target arguments are only supported for directed graphs"
98
+ )
99
+ source_degree = G.degree
100
+ target_degree = G.degree
101
+ neighbors = G.neighbors
102
+ reverse = False
103
+ dsum = defaultdict(int)
104
+ dnorm = defaultdict(int)
105
+ # Check if `source_nodes` is actually a single node in the graph.
106
+ source_nodes = source_degree(nodes)
107
+ if nodes in G:
108
+ source_nodes = [(nodes, source_degree(nodes))]
109
+ for n, k in source_nodes:
110
+ nbrdeg = target_degree(neighbors(n))
111
+ if weight is None:
112
+ s = sum(d for n, d in nbrdeg)
113
+ else: # weight nbr degree by weight of (n,nbr) edge
114
+ if reverse:
115
+ s = sum(G[nbr][n].get(weight, 1) * d for nbr, d in nbrdeg)
116
+ else:
117
+ s = sum(G[n][nbr].get(weight, 1) * d for nbr, d in nbrdeg)
118
+ dnorm[k] += source_degree(n, weight=weight)
119
+ dsum[k] += s
120
+
121
+ # normalize
122
+ return {k: avg if dnorm[k] == 0 else avg / dnorm[k] for k, avg in dsum.items()}
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/correlation.py ADDED
@@ -0,0 +1,302 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Node assortativity coefficients and correlation measures.
2
+ """
3
+ import networkx as nx
4
+ from networkx.algorithms.assortativity.mixing import (
5
+ attribute_mixing_matrix,
6
+ degree_mixing_matrix,
7
+ )
8
+ from networkx.algorithms.assortativity.pairs import node_degree_xy
9
+
10
+ __all__ = [
11
+ "degree_pearson_correlation_coefficient",
12
+ "degree_assortativity_coefficient",
13
+ "attribute_assortativity_coefficient",
14
+ "numeric_assortativity_coefficient",
15
+ ]
16
+
17
+
18
+ @nx._dispatch(edge_attrs="weight")
19
+ def degree_assortativity_coefficient(G, x="out", y="in", weight=None, nodes=None):
20
+ """Compute degree assortativity of graph.
21
+
22
+ Assortativity measures the similarity of connections
23
+ in the graph with respect to the node degree.
24
+
25
+ Parameters
26
+ ----------
27
+ G : NetworkX graph
28
+
29
+ x: string ('in','out')
30
+ The degree type for source node (directed graphs only).
31
+
32
+ y: string ('in','out')
33
+ The degree type for target node (directed graphs only).
34
+
35
+ weight: string or None, optional (default=None)
36
+ The edge attribute that holds the numerical value used
37
+ as a weight. If None, then each edge has weight 1.
38
+ The degree is the sum of the edge weights adjacent to the node.
39
+
40
+ nodes: list or iterable (optional)
41
+ Compute degree assortativity only for nodes in container.
42
+ The default is all nodes.
43
+
44
+ Returns
45
+ -------
46
+ r : float
47
+ Assortativity of graph by degree.
48
+
49
+ Examples
50
+ --------
51
+ >>> G = nx.path_graph(4)
52
+ >>> r = nx.degree_assortativity_coefficient(G)
53
+ >>> print(f"{r:3.1f}")
54
+ -0.5
55
+
56
+ See Also
57
+ --------
58
+ attribute_assortativity_coefficient
59
+ numeric_assortativity_coefficient
60
+ degree_mixing_dict
61
+ degree_mixing_matrix
62
+
63
+ Notes
64
+ -----
65
+ This computes Eq. (21) in Ref. [1]_ , where e is the joint
66
+ probability distribution (mixing matrix) of the degrees. If G is
67
+ directed than the matrix e is the joint probability of the
68
+ user-specified degree type for the source and target.
69
+
70
+ References
71
+ ----------
72
+ .. [1] M. E. J. Newman, Mixing patterns in networks,
73
+ Physical Review E, 67 026126, 2003
74
+ .. [2] Foster, J.G., Foster, D.V., Grassberger, P. & Paczuski, M.
75
+ Edge direction and the structure of networks, PNAS 107, 10815-20 (2010).
76
+ """
77
+ if nodes is None:
78
+ nodes = G.nodes
79
+
80
+ degrees = None
81
+
82
+ if G.is_directed():
83
+ indeg = (
84
+ {d for _, d in G.in_degree(nodes, weight=weight)}
85
+ if "in" in (x, y)
86
+ else set()
87
+ )
88
+ outdeg = (
89
+ {d for _, d in G.out_degree(nodes, weight=weight)}
90
+ if "out" in (x, y)
91
+ else set()
92
+ )
93
+ degrees = set.union(indeg, outdeg)
94
+ else:
95
+ degrees = {d for _, d in G.degree(nodes, weight=weight)}
96
+
97
+ mapping = {d: i for i, d, in enumerate(degrees)}
98
+ M = degree_mixing_matrix(G, x=x, y=y, nodes=nodes, weight=weight, mapping=mapping)
99
+
100
+ return _numeric_ac(M, mapping=mapping)
101
+
102
+
103
+ @nx._dispatch(edge_attrs="weight")
104
+ def degree_pearson_correlation_coefficient(G, x="out", y="in", weight=None, nodes=None):
105
+ """Compute degree assortativity of graph.
106
+
107
+ Assortativity measures the similarity of connections
108
+ in the graph with respect to the node degree.
109
+
110
+ This is the same as degree_assortativity_coefficient but uses the
111
+ potentially faster scipy.stats.pearsonr function.
112
+
113
+ Parameters
114
+ ----------
115
+ G : NetworkX graph
116
+
117
+ x: string ('in','out')
118
+ The degree type for source node (directed graphs only).
119
+
120
+ y: string ('in','out')
121
+ The degree type for target node (directed graphs only).
122
+
123
+ weight: string or None, optional (default=None)
124
+ The edge attribute that holds the numerical value used
125
+ as a weight. If None, then each edge has weight 1.
126
+ The degree is the sum of the edge weights adjacent to the node.
127
+
128
+ nodes: list or iterable (optional)
129
+ Compute pearson correlation of degrees only for specified nodes.
130
+ The default is all nodes.
131
+
132
+ Returns
133
+ -------
134
+ r : float
135
+ Assortativity of graph by degree.
136
+
137
+ Examples
138
+ --------
139
+ >>> G = nx.path_graph(4)
140
+ >>> r = nx.degree_pearson_correlation_coefficient(G)
141
+ >>> print(f"{r:3.1f}")
142
+ -0.5
143
+
144
+ Notes
145
+ -----
146
+ This calls scipy.stats.pearsonr.
147
+
148
+ References
149
+ ----------
150
+ .. [1] M. E. J. Newman, Mixing patterns in networks
151
+ Physical Review E, 67 026126, 2003
152
+ .. [2] Foster, J.G., Foster, D.V., Grassberger, P. & Paczuski, M.
153
+ Edge direction and the structure of networks, PNAS 107, 10815-20 (2010).
154
+ """
155
+ import scipy as sp
156
+
157
+ xy = node_degree_xy(G, x=x, y=y, nodes=nodes, weight=weight)
158
+ x, y = zip(*xy)
159
+ return sp.stats.pearsonr(x, y)[0]
160
+
161
+
162
+ @nx._dispatch(node_attrs="attribute")
163
+ def attribute_assortativity_coefficient(G, attribute, nodes=None):
164
+ """Compute assortativity for node attributes.
165
+
166
+ Assortativity measures the similarity of connections
167
+ in the graph with respect to the given attribute.
168
+
169
+ Parameters
170
+ ----------
171
+ G : NetworkX graph
172
+
173
+ attribute : string
174
+ Node attribute key
175
+
176
+ nodes: list or iterable (optional)
177
+ Compute attribute assortativity for nodes in container.
178
+ The default is all nodes.
179
+
180
+ Returns
181
+ -------
182
+ r: float
183
+ Assortativity of graph for given attribute
184
+
185
+ Examples
186
+ --------
187
+ >>> G = nx.Graph()
188
+ >>> G.add_nodes_from([0, 1], color="red")
189
+ >>> G.add_nodes_from([2, 3], color="blue")
190
+ >>> G.add_edges_from([(0, 1), (2, 3)])
191
+ >>> print(nx.attribute_assortativity_coefficient(G, "color"))
192
+ 1.0
193
+
194
+ Notes
195
+ -----
196
+ This computes Eq. (2) in Ref. [1]_ , (trace(M)-sum(M^2))/(1-sum(M^2)),
197
+ where M is the joint probability distribution (mixing matrix)
198
+ of the specified attribute.
199
+
200
+ References
201
+ ----------
202
+ .. [1] M. E. J. Newman, Mixing patterns in networks,
203
+ Physical Review E, 67 026126, 2003
204
+ """
205
+ M = attribute_mixing_matrix(G, attribute, nodes)
206
+ return attribute_ac(M)
207
+
208
+
209
+ @nx._dispatch(node_attrs="attribute")
210
+ def numeric_assortativity_coefficient(G, attribute, nodes=None):
211
+ """Compute assortativity for numerical node attributes.
212
+
213
+ Assortativity measures the similarity of connections
214
+ in the graph with respect to the given numeric attribute.
215
+
216
+ Parameters
217
+ ----------
218
+ G : NetworkX graph
219
+
220
+ attribute : string
221
+ Node attribute key.
222
+
223
+ nodes: list or iterable (optional)
224
+ Compute numeric assortativity only for attributes of nodes in
225
+ container. The default is all nodes.
226
+
227
+ Returns
228
+ -------
229
+ r: float
230
+ Assortativity of graph for given attribute
231
+
232
+ Examples
233
+ --------
234
+ >>> G = nx.Graph()
235
+ >>> G.add_nodes_from([0, 1], size=2)
236
+ >>> G.add_nodes_from([2, 3], size=3)
237
+ >>> G.add_edges_from([(0, 1), (2, 3)])
238
+ >>> print(nx.numeric_assortativity_coefficient(G, "size"))
239
+ 1.0
240
+
241
+ Notes
242
+ -----
243
+ This computes Eq. (21) in Ref. [1]_ , which is the Pearson correlation
244
+ coefficient of the specified (scalar valued) attribute across edges.
245
+
246
+ References
247
+ ----------
248
+ .. [1] M. E. J. Newman, Mixing patterns in networks
249
+ Physical Review E, 67 026126, 2003
250
+ """
251
+ if nodes is None:
252
+ nodes = G.nodes
253
+ vals = {G.nodes[n][attribute] for n in nodes}
254
+ mapping = {d: i for i, d, in enumerate(vals)}
255
+ M = attribute_mixing_matrix(G, attribute, nodes, mapping)
256
+ return _numeric_ac(M, mapping)
257
+
258
+
259
+ def attribute_ac(M):
260
+ """Compute assortativity for attribute matrix M.
261
+
262
+ Parameters
263
+ ----------
264
+ M : numpy.ndarray
265
+ 2D ndarray representing the attribute mixing matrix.
266
+
267
+ Notes
268
+ -----
269
+ This computes Eq. (2) in Ref. [1]_ , (trace(e)-sum(e^2))/(1-sum(e^2)),
270
+ where e is the joint probability distribution (mixing matrix)
271
+ of the specified attribute.
272
+
273
+ References
274
+ ----------
275
+ .. [1] M. E. J. Newman, Mixing patterns in networks,
276
+ Physical Review E, 67 026126, 2003
277
+ """
278
+ if M.sum() != 1.0:
279
+ M = M / M.sum()
280
+ s = (M @ M).sum()
281
+ t = M.trace()
282
+ r = (t - s) / (1 - s)
283
+ return r
284
+
285
+
286
+ def _numeric_ac(M, mapping):
287
+ # M is a 2D numpy array
288
+ # numeric assortativity coefficient, pearsonr
289
+ import numpy as np
290
+
291
+ if M.sum() != 1.0:
292
+ M = M / M.sum()
293
+ x = np.array(list(mapping.keys()))
294
+ y = x # x and y have the same support
295
+ idx = list(mapping.values())
296
+ a = M.sum(axis=0)
297
+ b = M.sum(axis=1)
298
+ vara = (a[idx] * x**2).sum() - ((a[idx] * x).sum()) ** 2
299
+ varb = (b[idx] * y**2).sum() - ((b[idx] * y).sum()) ** 2
300
+ xy = np.outer(x, y)
301
+ ab = np.outer(a[idx], b[idx])
302
+ return (xy * (M - ab)).sum() / np.sqrt(vara * varb)
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/mixing.py ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Mixing matrices for node attributes and degree.
3
+ """
4
+ import networkx as nx
5
+ from networkx.algorithms.assortativity.pairs import node_attribute_xy, node_degree_xy
6
+ from networkx.utils import dict_to_numpy_array
7
+
8
+ __all__ = [
9
+ "attribute_mixing_matrix",
10
+ "attribute_mixing_dict",
11
+ "degree_mixing_matrix",
12
+ "degree_mixing_dict",
13
+ "mixing_dict",
14
+ ]
15
+
16
+
17
+ @nx._dispatch(node_attrs="attribute")
18
+ def attribute_mixing_dict(G, attribute, nodes=None, normalized=False):
19
+ """Returns dictionary representation of mixing matrix for attribute.
20
+
21
+ Parameters
22
+ ----------
23
+ G : graph
24
+ NetworkX graph object.
25
+
26
+ attribute : string
27
+ Node attribute key.
28
+
29
+ nodes: list or iterable (optional)
30
+ Unse nodes in container to build the dict. The default is all nodes.
31
+
32
+ normalized : bool (default=False)
33
+ Return counts if False or probabilities if True.
34
+
35
+ Examples
36
+ --------
37
+ >>> G = nx.Graph()
38
+ >>> G.add_nodes_from([0, 1], color="red")
39
+ >>> G.add_nodes_from([2, 3], color="blue")
40
+ >>> G.add_edge(1, 3)
41
+ >>> d = nx.attribute_mixing_dict(G, "color")
42
+ >>> print(d["red"]["blue"])
43
+ 1
44
+ >>> print(d["blue"]["red"]) # d symmetric for undirected graphs
45
+ 1
46
+
47
+ Returns
48
+ -------
49
+ d : dictionary
50
+ Counts or joint probability of occurrence of attribute pairs.
51
+ """
52
+ xy_iter = node_attribute_xy(G, attribute, nodes)
53
+ return mixing_dict(xy_iter, normalized=normalized)
54
+
55
+
56
+ @nx._dispatch(node_attrs="attribute")
57
+ def attribute_mixing_matrix(G, attribute, nodes=None, mapping=None, normalized=True):
58
+ """Returns mixing matrix for attribute.
59
+
60
+ Parameters
61
+ ----------
62
+ G : graph
63
+ NetworkX graph object.
64
+
65
+ attribute : string
66
+ Node attribute key.
67
+
68
+ nodes: list or iterable (optional)
69
+ Use only nodes in container to build the matrix. The default is
70
+ all nodes.
71
+
72
+ mapping : dictionary, optional
73
+ Mapping from node attribute to integer index in matrix.
74
+ If not specified, an arbitrary ordering will be used.
75
+
76
+ normalized : bool (default=True)
77
+ Return counts if False or probabilities if True.
78
+
79
+ Returns
80
+ -------
81
+ m: numpy array
82
+ Counts or joint probability of occurrence of attribute pairs.
83
+
84
+ Notes
85
+ -----
86
+ If each node has a unique attribute value, the unnormalized mixing matrix
87
+ will be equal to the adjacency matrix. To get a denser mixing matrix,
88
+ the rounding can be performed to form groups of nodes with equal values.
89
+ For example, the exact height of persons in cm (180.79155222, 163.9080892,
90
+ 163.30095355, 167.99016217, 168.21590163, ...) can be rounded to (180, 163,
91
+ 163, 168, 168, ...).
92
+
93
+ Definitions of attribute mixing matrix vary on whether the matrix
94
+ should include rows for attribute values that don't arise. Here we
95
+ do not include such empty-rows. But you can force them to appear
96
+ by inputting a `mapping` that includes those values.
97
+
98
+ Examples
99
+ --------
100
+ >>> G = nx.path_graph(3)
101
+ >>> gender = {0: 'male', 1: 'female', 2: 'female'}
102
+ >>> nx.set_node_attributes(G, gender, 'gender')
103
+ >>> mapping = {'male': 0, 'female': 1}
104
+ >>> mix_mat = nx.attribute_mixing_matrix(G, 'gender', mapping=mapping)
105
+ >>> # mixing from male nodes to female nodes
106
+ >>> mix_mat[mapping['male'], mapping['female']]
107
+ 0.25
108
+ """
109
+ d = attribute_mixing_dict(G, attribute, nodes)
110
+ a = dict_to_numpy_array(d, mapping=mapping)
111
+ if normalized:
112
+ a = a / a.sum()
113
+ return a
114
+
115
+
116
+ @nx._dispatch(edge_attrs="weight")
117
+ def degree_mixing_dict(G, x="out", y="in", weight=None, nodes=None, normalized=False):
118
+ """Returns dictionary representation of mixing matrix for degree.
119
+
120
+ Parameters
121
+ ----------
122
+ G : graph
123
+ NetworkX graph object.
124
+
125
+ x: string ('in','out')
126
+ The degree type for source node (directed graphs only).
127
+
128
+ y: string ('in','out')
129
+ The degree type for target node (directed graphs only).
130
+
131
+ weight: string or None, optional (default=None)
132
+ The edge attribute that holds the numerical value used
133
+ as a weight. If None, then each edge has weight 1.
134
+ The degree is the sum of the edge weights adjacent to the node.
135
+
136
+ normalized : bool (default=False)
137
+ Return counts if False or probabilities if True.
138
+
139
+ Returns
140
+ -------
141
+ d: dictionary
142
+ Counts or joint probability of occurrence of degree pairs.
143
+ """
144
+ xy_iter = node_degree_xy(G, x=x, y=y, nodes=nodes, weight=weight)
145
+ return mixing_dict(xy_iter, normalized=normalized)
146
+
147
+
148
+ @nx._dispatch(edge_attrs="weight")
149
+ def degree_mixing_matrix(
150
+ G, x="out", y="in", weight=None, nodes=None, normalized=True, mapping=None
151
+ ):
152
+ """Returns mixing matrix for attribute.
153
+
154
+ Parameters
155
+ ----------
156
+ G : graph
157
+ NetworkX graph object.
158
+
159
+ x: string ('in','out')
160
+ The degree type for source node (directed graphs only).
161
+
162
+ y: string ('in','out')
163
+ The degree type for target node (directed graphs only).
164
+
165
+ nodes: list or iterable (optional)
166
+ Build the matrix using only nodes in container.
167
+ The default is all nodes.
168
+
169
+ weight: string or None, optional (default=None)
170
+ The edge attribute that holds the numerical value used
171
+ as a weight. If None, then each edge has weight 1.
172
+ The degree is the sum of the edge weights adjacent to the node.
173
+
174
+ normalized : bool (default=True)
175
+ Return counts if False or probabilities if True.
176
+
177
+ mapping : dictionary, optional
178
+ Mapping from node degree to integer index in matrix.
179
+ If not specified, an arbitrary ordering will be used.
180
+
181
+ Returns
182
+ -------
183
+ m: numpy array
184
+ Counts, or joint probability, of occurrence of node degree.
185
+
186
+ Notes
187
+ -----
188
+ Definitions of degree mixing matrix vary on whether the matrix
189
+ should include rows for degree values that don't arise. Here we
190
+ do not include such empty-rows. But you can force them to appear
191
+ by inputting a `mapping` that includes those values. See examples.
192
+
193
+ Examples
194
+ --------
195
+ >>> G = nx.star_graph(3)
196
+ >>> mix_mat = nx.degree_mixing_matrix(G)
197
+ >>> mix_mat[0, 1] # mixing from node degree 1 to node degree 3
198
+ 0.5
199
+
200
+ If you want every possible degree to appear as a row, even if no nodes
201
+ have that degree, use `mapping` as follows,
202
+
203
+ >>> max_degree = max(deg for n, deg in G.degree)
204
+ >>> mapping = {x: x for x in range(max_degree + 1)} # identity mapping
205
+ >>> mix_mat = nx.degree_mixing_matrix(G, mapping=mapping)
206
+ >>> mix_mat[3, 1] # mixing from node degree 3 to node degree 1
207
+ 0.5
208
+ """
209
+ d = degree_mixing_dict(G, x=x, y=y, nodes=nodes, weight=weight)
210
+ a = dict_to_numpy_array(d, mapping=mapping)
211
+ if normalized:
212
+ a = a / a.sum()
213
+ return a
214
+
215
+
216
+ def mixing_dict(xy, normalized=False):
217
+ """Returns a dictionary representation of mixing matrix.
218
+
219
+ Parameters
220
+ ----------
221
+ xy : list or container of two-tuples
222
+ Pairs of (x,y) items.
223
+
224
+ attribute : string
225
+ Node attribute key
226
+
227
+ normalized : bool (default=False)
228
+ Return counts if False or probabilities if True.
229
+
230
+ Returns
231
+ -------
232
+ d: dictionary
233
+ Counts or Joint probability of occurrence of values in xy.
234
+ """
235
+ d = {}
236
+ psum = 0.0
237
+ for x, y in xy:
238
+ if x not in d:
239
+ d[x] = {}
240
+ if y not in d:
241
+ d[y] = {}
242
+ v = d[x].get(y, 0)
243
+ d[x][y] = v + 1
244
+ psum += 1
245
+
246
+ if normalized:
247
+ for _, jdict in d.items():
248
+ for j in jdict:
249
+ jdict[j] /= psum
250
+ return d
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/pairs.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Generators of x-y pairs of node data."""
2
+ import networkx as nx
3
+
4
+ __all__ = ["node_attribute_xy", "node_degree_xy"]
5
+
6
+
7
+ @nx._dispatch(node_attrs="attribute")
8
+ def node_attribute_xy(G, attribute, nodes=None):
9
+ """Returns iterator of node-attribute pairs for all edges in G.
10
+
11
+ Parameters
12
+ ----------
13
+ G: NetworkX graph
14
+
15
+ attribute: key
16
+ The node attribute key.
17
+
18
+ nodes: list or iterable (optional)
19
+ Use only edges that are incident to specified nodes.
20
+ The default is all nodes.
21
+
22
+ Returns
23
+ -------
24
+ (x, y): 2-tuple
25
+ Generates 2-tuple of (attribute, attribute) values.
26
+
27
+ Examples
28
+ --------
29
+ >>> G = nx.DiGraph()
30
+ >>> G.add_node(1, color="red")
31
+ >>> G.add_node(2, color="blue")
32
+ >>> G.add_edge(1, 2)
33
+ >>> list(nx.node_attribute_xy(G, "color"))
34
+ [('red', 'blue')]
35
+
36
+ Notes
37
+ -----
38
+ For undirected graphs each edge is produced twice, once for each edge
39
+ representation (u, v) and (v, u), with the exception of self-loop edges
40
+ which only appear once.
41
+ """
42
+ if nodes is None:
43
+ nodes = set(G)
44
+ else:
45
+ nodes = set(nodes)
46
+ Gnodes = G.nodes
47
+ for u, nbrsdict in G.adjacency():
48
+ if u not in nodes:
49
+ continue
50
+ uattr = Gnodes[u].get(attribute, None)
51
+ if G.is_multigraph():
52
+ for v, keys in nbrsdict.items():
53
+ vattr = Gnodes[v].get(attribute, None)
54
+ for _ in keys:
55
+ yield (uattr, vattr)
56
+ else:
57
+ for v in nbrsdict:
58
+ vattr = Gnodes[v].get(attribute, None)
59
+ yield (uattr, vattr)
60
+
61
+
62
+ @nx._dispatch(edge_attrs="weight")
63
+ def node_degree_xy(G, x="out", y="in", weight=None, nodes=None):
64
+ """Generate node degree-degree pairs for edges in G.
65
+
66
+ Parameters
67
+ ----------
68
+ G: NetworkX graph
69
+
70
+ x: string ('in','out')
71
+ The degree type for source node (directed graphs only).
72
+
73
+ y: string ('in','out')
74
+ The degree type for target node (directed graphs only).
75
+
76
+ weight: string or None, optional (default=None)
77
+ The edge attribute that holds the numerical value used
78
+ as a weight. If None, then each edge has weight 1.
79
+ The degree is the sum of the edge weights adjacent to the node.
80
+
81
+ nodes: list or iterable (optional)
82
+ Use only edges that are adjacency to specified nodes.
83
+ The default is all nodes.
84
+
85
+ Returns
86
+ -------
87
+ (x, y): 2-tuple
88
+ Generates 2-tuple of (degree, degree) values.
89
+
90
+
91
+ Examples
92
+ --------
93
+ >>> G = nx.DiGraph()
94
+ >>> G.add_edge(1, 2)
95
+ >>> list(nx.node_degree_xy(G, x="out", y="in"))
96
+ [(1, 1)]
97
+ >>> list(nx.node_degree_xy(G, x="in", y="out"))
98
+ [(0, 0)]
99
+
100
+ Notes
101
+ -----
102
+ For undirected graphs each edge is produced twice, once for each edge
103
+ representation (u, v) and (v, u), with the exception of self-loop edges
104
+ which only appear once.
105
+ """
106
+ nodes = set(G) if nodes is None else set(nodes)
107
+ if G.is_directed():
108
+ direction = {"out": G.out_degree, "in": G.in_degree}
109
+ xdeg = direction[x]
110
+ ydeg = direction[y]
111
+ else:
112
+ xdeg = ydeg = G.degree
113
+
114
+ for u, degu in xdeg(nodes, weight=weight):
115
+ # use G.edges to treat multigraphs correctly
116
+ neighbors = (nbr for _, nbr in G.edges(u) if nbr in nodes)
117
+ for _, degv in ydeg(neighbors, weight=weight):
118
+ yield degu, degv
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/tests/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (240 Bytes). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/tests/__pycache__/base_test.cpython-311.pyc ADDED
Binary file (6.09 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/tests/__pycache__/test_connectivity.cpython-311.pyc ADDED
Binary file (8.9 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/tests/__pycache__/test_mixing.cpython-311.pyc ADDED
Binary file (13.2 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/tests/__pycache__/test_neighbor_degree.cpython-311.pyc ADDED
Binary file (7.57 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/tests/__pycache__/test_pairs.cpython-311.pyc ADDED
Binary file (5.93 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/tests/test_connectivity.py ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from itertools import permutations
2
+
3
+ import pytest
4
+
5
+ import networkx as nx
6
+
7
+
8
+ class TestNeighborConnectivity:
9
+ def test_degree_p4(self):
10
+ G = nx.path_graph(4)
11
+ answer = {1: 2.0, 2: 1.5}
12
+ nd = nx.average_degree_connectivity(G)
13
+ assert nd == answer
14
+
15
+ D = G.to_directed()
16
+ answer = {2: 2.0, 4: 1.5}
17
+ nd = nx.average_degree_connectivity(D)
18
+ assert nd == answer
19
+
20
+ answer = {1: 2.0, 2: 1.5}
21
+ D = G.to_directed()
22
+ nd = nx.average_degree_connectivity(D, source="in", target="in")
23
+ assert nd == answer
24
+
25
+ D = G.to_directed()
26
+ nd = nx.average_degree_connectivity(D, source="in", target="in")
27
+ assert nd == answer
28
+
29
+ def test_degree_p4_weighted(self):
30
+ G = nx.path_graph(4)
31
+ G[1][2]["weight"] = 4
32
+ answer = {1: 2.0, 2: 1.8}
33
+ nd = nx.average_degree_connectivity(G, weight="weight")
34
+ assert nd == answer
35
+ answer = {1: 2.0, 2: 1.5}
36
+ nd = nx.average_degree_connectivity(G)
37
+ assert nd == answer
38
+
39
+ D = G.to_directed()
40
+ answer = {2: 2.0, 4: 1.8}
41
+ nd = nx.average_degree_connectivity(D, weight="weight")
42
+ assert nd == answer
43
+
44
+ answer = {1: 2.0, 2: 1.8}
45
+ D = G.to_directed()
46
+ nd = nx.average_degree_connectivity(
47
+ D, weight="weight", source="in", target="in"
48
+ )
49
+ assert nd == answer
50
+
51
+ D = G.to_directed()
52
+ nd = nx.average_degree_connectivity(
53
+ D, source="in", target="out", weight="weight"
54
+ )
55
+ assert nd == answer
56
+
57
+ def test_weight_keyword(self):
58
+ G = nx.path_graph(4)
59
+ G[1][2]["other"] = 4
60
+ answer = {1: 2.0, 2: 1.8}
61
+ nd = nx.average_degree_connectivity(G, weight="other")
62
+ assert nd == answer
63
+ answer = {1: 2.0, 2: 1.5}
64
+ nd = nx.average_degree_connectivity(G, weight=None)
65
+ assert nd == answer
66
+
67
+ D = G.to_directed()
68
+ answer = {2: 2.0, 4: 1.8}
69
+ nd = nx.average_degree_connectivity(D, weight="other")
70
+ assert nd == answer
71
+
72
+ answer = {1: 2.0, 2: 1.8}
73
+ D = G.to_directed()
74
+ nd = nx.average_degree_connectivity(D, weight="other", source="in", target="in")
75
+ assert nd == answer
76
+
77
+ D = G.to_directed()
78
+ nd = nx.average_degree_connectivity(D, weight="other", source="in", target="in")
79
+ assert nd == answer
80
+
81
+ def test_degree_barrat(self):
82
+ G = nx.star_graph(5)
83
+ G.add_edges_from([(5, 6), (5, 7), (5, 8), (5, 9)])
84
+ G[0][5]["weight"] = 5
85
+ nd = nx.average_degree_connectivity(G)[5]
86
+ assert nd == 1.8
87
+ nd = nx.average_degree_connectivity(G, weight="weight")[5]
88
+ assert nd == pytest.approx(3.222222, abs=1e-5)
89
+
90
+ def test_zero_deg(self):
91
+ G = nx.DiGraph()
92
+ G.add_edge(1, 2)
93
+ G.add_edge(1, 3)
94
+ G.add_edge(1, 4)
95
+ c = nx.average_degree_connectivity(G)
96
+ assert c == {1: 0, 3: 1}
97
+ c = nx.average_degree_connectivity(G, source="in", target="in")
98
+ assert c == {0: 0, 1: 0}
99
+ c = nx.average_degree_connectivity(G, source="in", target="out")
100
+ assert c == {0: 0, 1: 3}
101
+ c = nx.average_degree_connectivity(G, source="in", target="in+out")
102
+ assert c == {0: 0, 1: 3}
103
+ c = nx.average_degree_connectivity(G, source="out", target="out")
104
+ assert c == {0: 0, 3: 0}
105
+ c = nx.average_degree_connectivity(G, source="out", target="in")
106
+ assert c == {0: 0, 3: 1}
107
+ c = nx.average_degree_connectivity(G, source="out", target="in+out")
108
+ assert c == {0: 0, 3: 1}
109
+
110
+ def test_in_out_weight(self):
111
+ G = nx.DiGraph()
112
+ G.add_edge(1, 2, weight=1)
113
+ G.add_edge(1, 3, weight=1)
114
+ G.add_edge(3, 1, weight=1)
115
+ for s, t in permutations(["in", "out", "in+out"], 2):
116
+ c = nx.average_degree_connectivity(G, source=s, target=t)
117
+ cw = nx.average_degree_connectivity(G, source=s, target=t, weight="weight")
118
+ assert c == cw
119
+
120
+ def test_invalid_source(self):
121
+ with pytest.raises(nx.NetworkXError):
122
+ G = nx.DiGraph()
123
+ nx.average_degree_connectivity(G, source="bogus")
124
+
125
+ def test_invalid_target(self):
126
+ with pytest.raises(nx.NetworkXError):
127
+ G = nx.DiGraph()
128
+ nx.average_degree_connectivity(G, target="bogus")
129
+
130
+ def test_invalid_undirected_graph(self):
131
+ G = nx.Graph()
132
+ with pytest.raises(nx.NetworkXError):
133
+ nx.average_degree_connectivity(G, target="bogus")
134
+ with pytest.raises(nx.NetworkXError):
135
+ nx.average_degree_connectivity(G, source="bogus")
136
+
137
+ def test_single_node(self):
138
+ # TODO Is this really the intended behavior for providing a
139
+ # single node as the argument `nodes`? Shouldn't the function
140
+ # just return the connectivity value itself?
141
+ G = nx.trivial_graph()
142
+ conn = nx.average_degree_connectivity(G, nodes=0)
143
+ assert conn == {0: 0}
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/assortativity/tests/test_pairs.py ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import networkx as nx
2
+
3
+ from .base_test import BaseTestAttributeMixing, BaseTestDegreeMixing
4
+
5
+
6
+ class TestAttributeMixingXY(BaseTestAttributeMixing):
7
+ def test_node_attribute_xy_undirected(self):
8
+ attrxy = sorted(nx.node_attribute_xy(self.G, "fish"))
9
+ attrxy_result = sorted(
10
+ [
11
+ ("one", "one"),
12
+ ("one", "one"),
13
+ ("two", "two"),
14
+ ("two", "two"),
15
+ ("one", "red"),
16
+ ("red", "one"),
17
+ ("blue", "two"),
18
+ ("two", "blue"),
19
+ ]
20
+ )
21
+ assert attrxy == attrxy_result
22
+
23
+ def test_node_attribute_xy_undirected_nodes(self):
24
+ attrxy = sorted(nx.node_attribute_xy(self.G, "fish", nodes=["one", "yellow"]))
25
+ attrxy_result = sorted([])
26
+ assert attrxy == attrxy_result
27
+
28
+ def test_node_attribute_xy_directed(self):
29
+ attrxy = sorted(nx.node_attribute_xy(self.D, "fish"))
30
+ attrxy_result = sorted(
31
+ [("one", "one"), ("two", "two"), ("one", "red"), ("two", "blue")]
32
+ )
33
+ assert attrxy == attrxy_result
34
+
35
+ def test_node_attribute_xy_multigraph(self):
36
+ attrxy = sorted(nx.node_attribute_xy(self.M, "fish"))
37
+ attrxy_result = [
38
+ ("one", "one"),
39
+ ("one", "one"),
40
+ ("one", "one"),
41
+ ("one", "one"),
42
+ ("two", "two"),
43
+ ("two", "two"),
44
+ ]
45
+ assert attrxy == attrxy_result
46
+
47
+ def test_node_attribute_xy_selfloop(self):
48
+ attrxy = sorted(nx.node_attribute_xy(self.S, "fish"))
49
+ attrxy_result = [("one", "one"), ("two", "two")]
50
+ assert attrxy == attrxy_result
51
+
52
+
53
+ class TestDegreeMixingXY(BaseTestDegreeMixing):
54
+ def test_node_degree_xy_undirected(self):
55
+ xy = sorted(nx.node_degree_xy(self.P4))
56
+ xy_result = sorted([(1, 2), (2, 1), (2, 2), (2, 2), (1, 2), (2, 1)])
57
+ assert xy == xy_result
58
+
59
+ def test_node_degree_xy_undirected_nodes(self):
60
+ xy = sorted(nx.node_degree_xy(self.P4, nodes=[0, 1, -1]))
61
+ xy_result = sorted([(1, 2), (2, 1)])
62
+ assert xy == xy_result
63
+
64
+ def test_node_degree_xy_directed(self):
65
+ xy = sorted(nx.node_degree_xy(self.D))
66
+ xy_result = sorted([(2, 1), (2, 3), (1, 3), (1, 3)])
67
+ assert xy == xy_result
68
+
69
+ def test_node_degree_xy_multigraph(self):
70
+ xy = sorted(nx.node_degree_xy(self.M))
71
+ xy_result = sorted(
72
+ [(2, 3), (2, 3), (3, 2), (3, 2), (2, 3), (3, 2), (1, 2), (2, 1)]
73
+ )
74
+ assert xy == xy_result
75
+
76
+ def test_node_degree_xy_selfloop(self):
77
+ xy = sorted(nx.node_degree_xy(self.S))
78
+ xy_result = sorted([(2, 2), (2, 2)])
79
+ assert xy == xy_result
80
+
81
+ def test_node_degree_xy_weighted(self):
82
+ G = nx.Graph()
83
+ G.add_edge(1, 2, weight=7)
84
+ G.add_edge(2, 3, weight=10)
85
+ xy = sorted(nx.node_degree_xy(G, weight="weight"))
86
+ xy_result = sorted([(7, 17), (17, 10), (17, 7), (10, 17)])
87
+ assert xy == xy_result
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/coloring/__init__.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ from networkx.algorithms.coloring.greedy_coloring import *
2
+ from networkx.algorithms.coloring.equitable_coloring import equitable_color
3
+
4
+ __all__ = ["greedy_color", "equitable_color"]
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/coloring/__pycache__/equitable_coloring.cpython-311.pyc ADDED
Binary file (19 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/coloring/greedy_coloring.py ADDED
@@ -0,0 +1,572 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Greedy graph coloring using various strategies.
3
+ """
4
+ import itertools
5
+ from collections import defaultdict, deque
6
+
7
+ import networkx as nx
8
+ from networkx.utils import arbitrary_element, py_random_state
9
+
10
+ __all__ = [
11
+ "greedy_color",
12
+ "strategy_connected_sequential",
13
+ "strategy_connected_sequential_bfs",
14
+ "strategy_connected_sequential_dfs",
15
+ "strategy_independent_set",
16
+ "strategy_largest_first",
17
+ "strategy_random_sequential",
18
+ "strategy_saturation_largest_first",
19
+ "strategy_smallest_last",
20
+ ]
21
+
22
+
23
+ @nx._dispatch
24
+ def strategy_largest_first(G, colors):
25
+ """Returns a list of the nodes of ``G`` in decreasing order by
26
+ degree.
27
+
28
+ ``G`` is a NetworkX graph. ``colors`` is ignored.
29
+
30
+ """
31
+ return sorted(G, key=G.degree, reverse=True)
32
+
33
+
34
+ @py_random_state(2)
35
+ @nx._dispatch
36
+ def strategy_random_sequential(G, colors, seed=None):
37
+ """Returns a random permutation of the nodes of ``G`` as a list.
38
+
39
+ ``G`` is a NetworkX graph. ``colors`` is ignored.
40
+
41
+ seed : integer, random_state, or None (default)
42
+ Indicator of random number generation state.
43
+ See :ref:`Randomness<randomness>`.
44
+ """
45
+ nodes = list(G)
46
+ seed.shuffle(nodes)
47
+ return nodes
48
+
49
+
50
+ @nx._dispatch
51
+ def strategy_smallest_last(G, colors):
52
+ """Returns a deque of the nodes of ``G``, "smallest" last.
53
+
54
+ Specifically, the degrees of each node are tracked in a bucket queue.
55
+ From this, the node of minimum degree is repeatedly popped from the
56
+ graph, updating its neighbors' degrees.
57
+
58
+ ``G`` is a NetworkX graph. ``colors`` is ignored.
59
+
60
+ This implementation of the strategy runs in $O(n + m)$ time
61
+ (ignoring polylogarithmic factors), where $n$ is the number of nodes
62
+ and $m$ is the number of edges.
63
+
64
+ This strategy is related to :func:`strategy_independent_set`: if we
65
+ interpret each node removed as an independent set of size one, then
66
+ this strategy chooses an independent set of size one instead of a
67
+ maximal independent set.
68
+
69
+ """
70
+ H = G.copy()
71
+ result = deque()
72
+
73
+ # Build initial degree list (i.e. the bucket queue data structure)
74
+ degrees = defaultdict(set) # set(), for fast random-access removals
75
+ lbound = float("inf")
76
+ for node, d in H.degree():
77
+ degrees[d].add(node)
78
+ lbound = min(lbound, d) # Lower bound on min-degree.
79
+
80
+ def find_min_degree():
81
+ # Save time by starting the iterator at `lbound`, not 0.
82
+ # The value that we find will be our new `lbound`, which we set later.
83
+ return next(d for d in itertools.count(lbound) if d in degrees)
84
+
85
+ for _ in G:
86
+ # Pop a min-degree node and add it to the list.
87
+ min_degree = find_min_degree()
88
+ u = degrees[min_degree].pop()
89
+ if not degrees[min_degree]: # Clean up the degree list.
90
+ del degrees[min_degree]
91
+ result.appendleft(u)
92
+
93
+ # Update degrees of removed node's neighbors.
94
+ for v in H[u]:
95
+ degree = H.degree(v)
96
+ degrees[degree].remove(v)
97
+ if not degrees[degree]: # Clean up the degree list.
98
+ del degrees[degree]
99
+ degrees[degree - 1].add(v)
100
+
101
+ # Finally, remove the node.
102
+ H.remove_node(u)
103
+ lbound = min_degree - 1 # Subtract 1 in case of tied neighbors.
104
+
105
+ return result
106
+
107
+
108
+ def _maximal_independent_set(G):
109
+ """Returns a maximal independent set of nodes in ``G`` by repeatedly
110
+ choosing an independent node of minimum degree (with respect to the
111
+ subgraph of unchosen nodes).
112
+
113
+ """
114
+ result = set()
115
+ remaining = set(G)
116
+ while remaining:
117
+ G = G.subgraph(remaining)
118
+ v = min(remaining, key=G.degree)
119
+ result.add(v)
120
+ remaining -= set(G[v]) | {v}
121
+ return result
122
+
123
+
124
+ @nx._dispatch
125
+ def strategy_independent_set(G, colors):
126
+ """Uses a greedy independent set removal strategy to determine the
127
+ colors.
128
+
129
+ This function updates ``colors`` **in-place** and return ``None``,
130
+ unlike the other strategy functions in this module.
131
+
132
+ This algorithm repeatedly finds and removes a maximal independent
133
+ set, assigning each node in the set an unused color.
134
+
135
+ ``G`` is a NetworkX graph.
136
+
137
+ This strategy is related to :func:`strategy_smallest_last`: in that
138
+ strategy, an independent set of size one is chosen at each step
139
+ instead of a maximal independent set.
140
+
141
+ """
142
+ remaining_nodes = set(G)
143
+ while len(remaining_nodes) > 0:
144
+ nodes = _maximal_independent_set(G.subgraph(remaining_nodes))
145
+ remaining_nodes -= nodes
146
+ yield from nodes
147
+
148
+
149
+ @nx._dispatch
150
+ def strategy_connected_sequential_bfs(G, colors):
151
+ """Returns an iterable over nodes in ``G`` in the order given by a
152
+ breadth-first traversal.
153
+
154
+ The generated sequence has the property that for each node except
155
+ the first, at least one neighbor appeared earlier in the sequence.
156
+
157
+ ``G`` is a NetworkX graph. ``colors`` is ignored.
158
+
159
+ """
160
+ return strategy_connected_sequential(G, colors, "bfs")
161
+
162
+
163
+ @nx._dispatch
164
+ def strategy_connected_sequential_dfs(G, colors):
165
+ """Returns an iterable over nodes in ``G`` in the order given by a
166
+ depth-first traversal.
167
+
168
+ The generated sequence has the property that for each node except
169
+ the first, at least one neighbor appeared earlier in the sequence.
170
+
171
+ ``G`` is a NetworkX graph. ``colors`` is ignored.
172
+
173
+ """
174
+ return strategy_connected_sequential(G, colors, "dfs")
175
+
176
+
177
+ @nx._dispatch
178
+ def strategy_connected_sequential(G, colors, traversal="bfs"):
179
+ """Returns an iterable over nodes in ``G`` in the order given by a
180
+ breadth-first or depth-first traversal.
181
+
182
+ ``traversal`` must be one of the strings ``'dfs'`` or ``'bfs'``,
183
+ representing depth-first traversal or breadth-first traversal,
184
+ respectively.
185
+
186
+ The generated sequence has the property that for each node except
187
+ the first, at least one neighbor appeared earlier in the sequence.
188
+
189
+ ``G`` is a NetworkX graph. ``colors`` is ignored.
190
+
191
+ """
192
+ if traversal == "bfs":
193
+ traverse = nx.bfs_edges
194
+ elif traversal == "dfs":
195
+ traverse = nx.dfs_edges
196
+ else:
197
+ raise nx.NetworkXError(
198
+ "Please specify one of the strings 'bfs' or"
199
+ " 'dfs' for connected sequential ordering"
200
+ )
201
+ for component in nx.connected_components(G):
202
+ source = arbitrary_element(component)
203
+ # Yield the source node, then all the nodes in the specified
204
+ # traversal order.
205
+ yield source
206
+ for _, end in traverse(G.subgraph(component), source):
207
+ yield end
208
+
209
+
210
+ @nx._dispatch
211
+ def strategy_saturation_largest_first(G, colors):
212
+ """Iterates over all the nodes of ``G`` in "saturation order" (also
213
+ known as "DSATUR").
214
+
215
+ ``G`` is a NetworkX graph. ``colors`` is a dictionary mapping nodes of
216
+ ``G`` to colors, for those nodes that have already been colored.
217
+
218
+ """
219
+ distinct_colors = {v: set() for v in G}
220
+
221
+ # Add the node color assignments given in colors to the
222
+ # distinct colors set for each neighbor of that node
223
+ for node, color in colors.items():
224
+ for neighbor in G[node]:
225
+ distinct_colors[neighbor].add(color)
226
+
227
+ # Check that the color assignments in colors are valid
228
+ # i.e. no neighboring nodes have the same color
229
+ if len(colors) >= 2:
230
+ for node, color in colors.items():
231
+ if color in distinct_colors[node]:
232
+ raise nx.NetworkXError("Neighboring nodes must have different colors")
233
+
234
+ # If 0 nodes have been colored, simply choose the node of highest degree.
235
+ if not colors:
236
+ node = max(G, key=G.degree)
237
+ yield node
238
+ # Add the color 0 to the distinct colors set for each
239
+ # neighbor of that node.
240
+ for v in G[node]:
241
+ distinct_colors[v].add(0)
242
+
243
+ while len(G) != len(colors):
244
+ # Update the distinct color sets for the neighbors.
245
+ for node, color in colors.items():
246
+ for neighbor in G[node]:
247
+ distinct_colors[neighbor].add(color)
248
+
249
+ # Compute the maximum saturation and the set of nodes that
250
+ # achieve that saturation.
251
+ saturation = {v: len(c) for v, c in distinct_colors.items() if v not in colors}
252
+ # Yield the node with the highest saturation, and break ties by
253
+ # degree.
254
+ node = max(saturation, key=lambda v: (saturation[v], G.degree(v)))
255
+ yield node
256
+
257
+
258
+ #: Dictionary mapping name of a strategy as a string to the strategy function.
259
+ STRATEGIES = {
260
+ "largest_first": strategy_largest_first,
261
+ "random_sequential": strategy_random_sequential,
262
+ "smallest_last": strategy_smallest_last,
263
+ "independent_set": strategy_independent_set,
264
+ "connected_sequential_bfs": strategy_connected_sequential_bfs,
265
+ "connected_sequential_dfs": strategy_connected_sequential_dfs,
266
+ "connected_sequential": strategy_connected_sequential,
267
+ "saturation_largest_first": strategy_saturation_largest_first,
268
+ "DSATUR": strategy_saturation_largest_first,
269
+ }
270
+
271
+
272
+ @nx._dispatch
273
+ def greedy_color(G, strategy="largest_first", interchange=False):
274
+ """Color a graph using various strategies of greedy graph coloring.
275
+
276
+ Attempts to color a graph using as few colors as possible, where no
277
+ neighbours of a node can have same color as the node itself. The
278
+ given strategy determines the order in which nodes are colored.
279
+
280
+ The strategies are described in [1]_, and smallest-last is based on
281
+ [2]_.
282
+
283
+ Parameters
284
+ ----------
285
+ G : NetworkX graph
286
+
287
+ strategy : string or function(G, colors)
288
+ A function (or a string representing a function) that provides
289
+ the coloring strategy, by returning nodes in the ordering they
290
+ should be colored. ``G`` is the graph, and ``colors`` is a
291
+ dictionary of the currently assigned colors, keyed by nodes. The
292
+ function must return an iterable over all the nodes in ``G``.
293
+
294
+ If the strategy function is an iterator generator (that is, a
295
+ function with ``yield`` statements), keep in mind that the
296
+ ``colors`` dictionary will be updated after each ``yield``, since
297
+ this function chooses colors greedily.
298
+
299
+ If ``strategy`` is a string, it must be one of the following,
300
+ each of which represents one of the built-in strategy functions.
301
+
302
+ * ``'largest_first'``
303
+ * ``'random_sequential'``
304
+ * ``'smallest_last'``
305
+ * ``'independent_set'``
306
+ * ``'connected_sequential_bfs'``
307
+ * ``'connected_sequential_dfs'``
308
+ * ``'connected_sequential'`` (alias for the previous strategy)
309
+ * ``'saturation_largest_first'``
310
+ * ``'DSATUR'`` (alias for the previous strategy)
311
+
312
+ interchange: bool
313
+ Will use the color interchange algorithm described by [3]_ if set
314
+ to ``True``.
315
+
316
+ Note that ``saturation_largest_first`` and ``independent_set``
317
+ do not work with interchange. Furthermore, if you use
318
+ interchange with your own strategy function, you cannot rely
319
+ on the values in the ``colors`` argument.
320
+
321
+ Returns
322
+ -------
323
+ A dictionary with keys representing nodes and values representing
324
+ corresponding coloring.
325
+
326
+ Examples
327
+ --------
328
+ >>> G = nx.cycle_graph(4)
329
+ >>> d = nx.coloring.greedy_color(G, strategy="largest_first")
330
+ >>> d in [{0: 0, 1: 1, 2: 0, 3: 1}, {0: 1, 1: 0, 2: 1, 3: 0}]
331
+ True
332
+
333
+ Raises
334
+ ------
335
+ NetworkXPointlessConcept
336
+ If ``strategy`` is ``saturation_largest_first`` or
337
+ ``independent_set`` and ``interchange`` is ``True``.
338
+
339
+ References
340
+ ----------
341
+ .. [1] Adrian Kosowski, and Krzysztof Manuszewski,
342
+ Classical Coloring of Graphs, Graph Colorings, 2-19, 2004.
343
+ ISBN 0-8218-3458-4.
344
+ .. [2] David W. Matula, and Leland L. Beck, "Smallest-last
345
+ ordering and clustering and graph coloring algorithms." *J. ACM* 30,
346
+ 3 (July 1983), 417–427. <https://doi.org/10.1145/2402.322385>
347
+ .. [3] Maciej M. Sysło, Narsingh Deo, Janusz S. Kowalik,
348
+ Discrete Optimization Algorithms with Pascal Programs, 415-424, 1983.
349
+ ISBN 0-486-45353-7.
350
+
351
+ """
352
+ if len(G) == 0:
353
+ return {}
354
+ # Determine the strategy provided by the caller.
355
+ strategy = STRATEGIES.get(strategy, strategy)
356
+ if not callable(strategy):
357
+ raise nx.NetworkXError(
358
+ "strategy must be callable or a valid string. " f"{strategy} not valid."
359
+ )
360
+ # Perform some validation on the arguments before executing any
361
+ # strategy functions.
362
+ if interchange:
363
+ if strategy is strategy_independent_set:
364
+ msg = "interchange cannot be used with independent_set"
365
+ raise nx.NetworkXPointlessConcept(msg)
366
+ if strategy is strategy_saturation_largest_first:
367
+ msg = "interchange cannot be used with" " saturation_largest_first"
368
+ raise nx.NetworkXPointlessConcept(msg)
369
+ colors = {}
370
+ nodes = strategy(G, colors)
371
+ if interchange:
372
+ return _greedy_coloring_with_interchange(G, nodes)
373
+ for u in nodes:
374
+ # Set to keep track of colors of neighbours
375
+ neighbour_colors = {colors[v] for v in G[u] if v in colors}
376
+ # Find the first unused color.
377
+ for color in itertools.count():
378
+ if color not in neighbour_colors:
379
+ break
380
+ # Assign the new color to the current node.
381
+ colors[u] = color
382
+ return colors
383
+
384
+
385
+ # Tools for coloring with interchanges
386
+ class _Node:
387
+ __slots__ = ["node_id", "color", "adj_list", "adj_color"]
388
+
389
+ def __init__(self, node_id, n):
390
+ self.node_id = node_id
391
+ self.color = -1
392
+ self.adj_list = None
393
+ self.adj_color = [None for _ in range(n)]
394
+
395
+ def __repr__(self):
396
+ return (
397
+ f"Node_id: {self.node_id}, Color: {self.color}, "
398
+ f"Adj_list: ({self.adj_list}), adj_color: ({self.adj_color})"
399
+ )
400
+
401
+ def assign_color(self, adj_entry, color):
402
+ adj_entry.col_prev = None
403
+ adj_entry.col_next = self.adj_color[color]
404
+ self.adj_color[color] = adj_entry
405
+ if adj_entry.col_next is not None:
406
+ adj_entry.col_next.col_prev = adj_entry
407
+
408
+ def clear_color(self, adj_entry, color):
409
+ if adj_entry.col_prev is None:
410
+ self.adj_color[color] = adj_entry.col_next
411
+ else:
412
+ adj_entry.col_prev.col_next = adj_entry.col_next
413
+ if adj_entry.col_next is not None:
414
+ adj_entry.col_next.col_prev = adj_entry.col_prev
415
+
416
+ def iter_neighbors(self):
417
+ adj_node = self.adj_list
418
+ while adj_node is not None:
419
+ yield adj_node
420
+ adj_node = adj_node.next
421
+
422
+ def iter_neighbors_color(self, color):
423
+ adj_color_node = self.adj_color[color]
424
+ while adj_color_node is not None:
425
+ yield adj_color_node.node_id
426
+ adj_color_node = adj_color_node.col_next
427
+
428
+
429
+ class _AdjEntry:
430
+ __slots__ = ["node_id", "next", "mate", "col_next", "col_prev"]
431
+
432
+ def __init__(self, node_id):
433
+ self.node_id = node_id
434
+ self.next = None
435
+ self.mate = None
436
+ self.col_next = None
437
+ self.col_prev = None
438
+
439
+ def __repr__(self):
440
+ col_next = None if self.col_next is None else self.col_next.node_id
441
+ col_prev = None if self.col_prev is None else self.col_prev.node_id
442
+ return (
443
+ f"Node_id: {self.node_id}, Next: ({self.next}), "
444
+ f"Mate: ({self.mate.node_id}), "
445
+ f"col_next: ({col_next}), col_prev: ({col_prev})"
446
+ )
447
+
448
+
449
+ def _greedy_coloring_with_interchange(G, nodes):
450
+ """Return a coloring for `original_graph` using interchange approach
451
+
452
+ This procedure is an adaption of the algorithm described by [1]_,
453
+ and is an implementation of coloring with interchange. Please be
454
+ advised, that the datastructures used are rather complex because
455
+ they are optimized to minimize the time spent identifying
456
+ subcomponents of the graph, which are possible candidates for color
457
+ interchange.
458
+
459
+ Parameters
460
+ ----------
461
+ G : NetworkX graph
462
+ The graph to be colored
463
+
464
+ nodes : list
465
+ nodes ordered using the strategy of choice
466
+
467
+ Returns
468
+ -------
469
+ dict :
470
+ A dictionary keyed by node to a color value
471
+
472
+ References
473
+ ----------
474
+ .. [1] Maciej M. Syslo, Narsingh Deo, Janusz S. Kowalik,
475
+ Discrete Optimization Algorithms with Pascal Programs, 415-424, 1983.
476
+ ISBN 0-486-45353-7.
477
+ """
478
+ n = len(G)
479
+
480
+ graph = {node: _Node(node, n) for node in G}
481
+
482
+ for node1, node2 in G.edges():
483
+ adj_entry1 = _AdjEntry(node2)
484
+ adj_entry2 = _AdjEntry(node1)
485
+ adj_entry1.mate = adj_entry2
486
+ adj_entry2.mate = adj_entry1
487
+ node1_head = graph[node1].adj_list
488
+ adj_entry1.next = node1_head
489
+ graph[node1].adj_list = adj_entry1
490
+ node2_head = graph[node2].adj_list
491
+ adj_entry2.next = node2_head
492
+ graph[node2].adj_list = adj_entry2
493
+
494
+ k = 0
495
+ for node in nodes:
496
+ # Find the smallest possible, unused color
497
+ neighbors = graph[node].iter_neighbors()
498
+ col_used = {graph[adj_node.node_id].color for adj_node in neighbors}
499
+ col_used.discard(-1)
500
+ k1 = next(itertools.dropwhile(lambda x: x in col_used, itertools.count()))
501
+
502
+ # k1 is now the lowest available color
503
+ if k1 > k:
504
+ connected = True
505
+ visited = set()
506
+ col1 = -1
507
+ col2 = -1
508
+ while connected and col1 < k:
509
+ col1 += 1
510
+ neighbor_cols = graph[node].iter_neighbors_color(col1)
511
+ col1_adj = list(neighbor_cols)
512
+
513
+ col2 = col1
514
+ while connected and col2 < k:
515
+ col2 += 1
516
+ visited = set(col1_adj)
517
+ frontier = list(col1_adj)
518
+ i = 0
519
+ while i < len(frontier):
520
+ search_node = frontier[i]
521
+ i += 1
522
+ col_opp = col2 if graph[search_node].color == col1 else col1
523
+ neighbor_cols = graph[search_node].iter_neighbors_color(col_opp)
524
+
525
+ for neighbor in neighbor_cols:
526
+ if neighbor not in visited:
527
+ visited.add(neighbor)
528
+ frontier.append(neighbor)
529
+
530
+ # Search if node is not adj to any col2 vertex
531
+ connected = (
532
+ len(
533
+ visited.intersection(graph[node].iter_neighbors_color(col2))
534
+ )
535
+ > 0
536
+ )
537
+
538
+ # If connected is false then we can swap !!!
539
+ if not connected:
540
+ # Update all the nodes in the component
541
+ for search_node in visited:
542
+ graph[search_node].color = (
543
+ col2 if graph[search_node].color == col1 else col1
544
+ )
545
+ col2_adj = graph[search_node].adj_color[col2]
546
+ graph[search_node].adj_color[col2] = graph[search_node].adj_color[
547
+ col1
548
+ ]
549
+ graph[search_node].adj_color[col1] = col2_adj
550
+
551
+ # Update all the neighboring nodes
552
+ for search_node in visited:
553
+ col = graph[search_node].color
554
+ col_opp = col1 if col == col2 else col2
555
+ for adj_node in graph[search_node].iter_neighbors():
556
+ if graph[adj_node.node_id].color != col_opp:
557
+ # Direct reference to entry
558
+ adj_mate = adj_node.mate
559
+ graph[adj_node.node_id].clear_color(adj_mate, col_opp)
560
+ graph[adj_node.node_id].assign_color(adj_mate, col)
561
+ k1 = col1
562
+
563
+ # We can color this node color k1
564
+ graph[node].color = k1
565
+ k = max(k1, k)
566
+
567
+ # Update the neighbors of this node
568
+ for adj_node in graph[node].iter_neighbors():
569
+ adj_mate = adj_node.mate
570
+ graph[adj_node.node_id].assign_color(adj_mate, k1)
571
+
572
+ return {node.node_id: node.color for node in graph.values()}
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (589 Bytes). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/__pycache__/kcutsets.cpython-311.pyc ADDED
Binary file (10.6 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/__init__.py ADDED
File without changes
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (239 Bytes). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/__pycache__/test_connectivity.cpython-311.pyc ADDED
Binary file (29.7 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/__pycache__/test_cuts.cpython-311.pyc ADDED
Binary file (18.2 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/__pycache__/test_kcutsets.cpython-311.pyc ADDED
Binary file (15.3 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/__pycache__/test_stoer_wagner.cpython-311.pyc ADDED
Binary file (7.11 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/test_connectivity.py ADDED
@@ -0,0 +1,421 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import itertools
2
+
3
+ import pytest
4
+
5
+ import networkx as nx
6
+ from networkx.algorithms import flow
7
+ from networkx.algorithms.connectivity import (
8
+ local_edge_connectivity,
9
+ local_node_connectivity,
10
+ )
11
+
12
+ flow_funcs = [
13
+ flow.boykov_kolmogorov,
14
+ flow.dinitz,
15
+ flow.edmonds_karp,
16
+ flow.preflow_push,
17
+ flow.shortest_augmenting_path,
18
+ ]
19
+
20
+
21
+ # helper functions for tests
22
+
23
+
24
+ def _generate_no_biconnected(max_attempts=50):
25
+ attempts = 0
26
+ while True:
27
+ G = nx.fast_gnp_random_graph(100, 0.0575, seed=42)
28
+ if nx.is_connected(G) and not nx.is_biconnected(G):
29
+ attempts = 0
30
+ yield G
31
+ else:
32
+ if attempts >= max_attempts:
33
+ msg = f"Tried {max_attempts} times: no suitable Graph."
34
+ raise Exception(msg)
35
+ else:
36
+ attempts += 1
37
+
38
+
39
+ def test_average_connectivity():
40
+ # figure 1 from:
41
+ # Beineke, L., O. Oellermann, and R. Pippert (2002). The average
42
+ # connectivity of a graph. Discrete mathematics 252(1-3), 31-45
43
+ # http://www.sciencedirect.com/science/article/pii/S0012365X01001807
44
+ G1 = nx.path_graph(3)
45
+ G1.add_edges_from([(1, 3), (1, 4)])
46
+ G2 = nx.path_graph(3)
47
+ G2.add_edges_from([(1, 3), (1, 4), (0, 3), (0, 4), (3, 4)])
48
+ G3 = nx.Graph()
49
+ for flow_func in flow_funcs:
50
+ kwargs = {"flow_func": flow_func}
51
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
52
+ assert nx.average_node_connectivity(G1, **kwargs) == 1, errmsg
53
+ assert nx.average_node_connectivity(G2, **kwargs) == 2.2, errmsg
54
+ assert nx.average_node_connectivity(G3, **kwargs) == 0, errmsg
55
+
56
+
57
+ def test_average_connectivity_directed():
58
+ G = nx.DiGraph([(1, 3), (1, 4), (1, 5)])
59
+ for flow_func in flow_funcs:
60
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
61
+ assert nx.average_node_connectivity(G) == 0.25, errmsg
62
+
63
+
64
+ def test_articulation_points():
65
+ Ggen = _generate_no_biconnected()
66
+ for flow_func in flow_funcs:
67
+ for i in range(3):
68
+ G = next(Ggen)
69
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
70
+ assert nx.node_connectivity(G, flow_func=flow_func) == 1, errmsg
71
+
72
+
73
+ def test_brandes_erlebach():
74
+ # Figure 1 chapter 7: Connectivity
75
+ # http://www.informatik.uni-augsburg.de/thi/personen/kammer/Graph_Connectivity.pdf
76
+ G = nx.Graph()
77
+ G.add_edges_from(
78
+ [
79
+ (1, 2),
80
+ (1, 3),
81
+ (1, 4),
82
+ (1, 5),
83
+ (2, 3),
84
+ (2, 6),
85
+ (3, 4),
86
+ (3, 6),
87
+ (4, 6),
88
+ (4, 7),
89
+ (5, 7),
90
+ (6, 8),
91
+ (6, 9),
92
+ (7, 8),
93
+ (7, 10),
94
+ (8, 11),
95
+ (9, 10),
96
+ (9, 11),
97
+ (10, 11),
98
+ ]
99
+ )
100
+ for flow_func in flow_funcs:
101
+ kwargs = {"flow_func": flow_func}
102
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
103
+ assert 3 == local_edge_connectivity(G, 1, 11, **kwargs), errmsg
104
+ assert 3 == nx.edge_connectivity(G, 1, 11, **kwargs), errmsg
105
+ assert 2 == local_node_connectivity(G, 1, 11, **kwargs), errmsg
106
+ assert 2 == nx.node_connectivity(G, 1, 11, **kwargs), errmsg
107
+ assert 2 == nx.edge_connectivity(G, **kwargs), errmsg
108
+ assert 2 == nx.node_connectivity(G, **kwargs), errmsg
109
+ if flow_func is flow.preflow_push:
110
+ assert 3 == nx.edge_connectivity(G, 1, 11, cutoff=2, **kwargs), errmsg
111
+ else:
112
+ assert 2 == nx.edge_connectivity(G, 1, 11, cutoff=2, **kwargs), errmsg
113
+
114
+
115
+ def test_white_harary_1():
116
+ # Figure 1b white and harary (2001)
117
+ # https://doi.org/10.1111/0081-1750.00098
118
+ # A graph with high adhesion (edge connectivity) and low cohesion
119
+ # (vertex connectivity)
120
+ G = nx.disjoint_union(nx.complete_graph(4), nx.complete_graph(4))
121
+ G.remove_node(7)
122
+ for i in range(4, 7):
123
+ G.add_edge(0, i)
124
+ G = nx.disjoint_union(G, nx.complete_graph(4))
125
+ G.remove_node(G.order() - 1)
126
+ for i in range(7, 10):
127
+ G.add_edge(0, i)
128
+ for flow_func in flow_funcs:
129
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
130
+ assert 1 == nx.node_connectivity(G, flow_func=flow_func), errmsg
131
+ assert 3 == nx.edge_connectivity(G, flow_func=flow_func), errmsg
132
+
133
+
134
+ def test_white_harary_2():
135
+ # Figure 8 white and harary (2001)
136
+ # https://doi.org/10.1111/0081-1750.00098
137
+ G = nx.disjoint_union(nx.complete_graph(4), nx.complete_graph(4))
138
+ G.add_edge(0, 4)
139
+ # kappa <= lambda <= delta
140
+ assert 3 == min(nx.core_number(G).values())
141
+ for flow_func in flow_funcs:
142
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
143
+ assert 1 == nx.node_connectivity(G, flow_func=flow_func), errmsg
144
+ assert 1 == nx.edge_connectivity(G, flow_func=flow_func), errmsg
145
+
146
+
147
+ def test_complete_graphs():
148
+ for n in range(5, 20, 5):
149
+ for flow_func in flow_funcs:
150
+ G = nx.complete_graph(n)
151
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
152
+ assert n - 1 == nx.node_connectivity(G, flow_func=flow_func), errmsg
153
+ assert n - 1 == nx.node_connectivity(
154
+ G.to_directed(), flow_func=flow_func
155
+ ), errmsg
156
+ assert n - 1 == nx.edge_connectivity(G, flow_func=flow_func), errmsg
157
+ assert n - 1 == nx.edge_connectivity(
158
+ G.to_directed(), flow_func=flow_func
159
+ ), errmsg
160
+
161
+
162
+ def test_empty_graphs():
163
+ for k in range(5, 25, 5):
164
+ G = nx.empty_graph(k)
165
+ for flow_func in flow_funcs:
166
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
167
+ assert 0 == nx.node_connectivity(G, flow_func=flow_func), errmsg
168
+ assert 0 == nx.edge_connectivity(G, flow_func=flow_func), errmsg
169
+
170
+
171
+ def test_petersen():
172
+ G = nx.petersen_graph()
173
+ for flow_func in flow_funcs:
174
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
175
+ assert 3 == nx.node_connectivity(G, flow_func=flow_func), errmsg
176
+ assert 3 == nx.edge_connectivity(G, flow_func=flow_func), errmsg
177
+
178
+
179
+ def test_tutte():
180
+ G = nx.tutte_graph()
181
+ for flow_func in flow_funcs:
182
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
183
+ assert 3 == nx.node_connectivity(G, flow_func=flow_func), errmsg
184
+ assert 3 == nx.edge_connectivity(G, flow_func=flow_func), errmsg
185
+
186
+
187
+ def test_dodecahedral():
188
+ G = nx.dodecahedral_graph()
189
+ for flow_func in flow_funcs:
190
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
191
+ assert 3 == nx.node_connectivity(G, flow_func=flow_func), errmsg
192
+ assert 3 == nx.edge_connectivity(G, flow_func=flow_func), errmsg
193
+
194
+
195
+ def test_octahedral():
196
+ G = nx.octahedral_graph()
197
+ for flow_func in flow_funcs:
198
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
199
+ assert 4 == nx.node_connectivity(G, flow_func=flow_func), errmsg
200
+ assert 4 == nx.edge_connectivity(G, flow_func=flow_func), errmsg
201
+
202
+
203
+ def test_icosahedral():
204
+ G = nx.icosahedral_graph()
205
+ for flow_func in flow_funcs:
206
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
207
+ assert 5 == nx.node_connectivity(G, flow_func=flow_func), errmsg
208
+ assert 5 == nx.edge_connectivity(G, flow_func=flow_func), errmsg
209
+
210
+
211
+ def test_missing_source():
212
+ G = nx.path_graph(4)
213
+ for flow_func in flow_funcs:
214
+ pytest.raises(
215
+ nx.NetworkXError, nx.node_connectivity, G, 10, 1, flow_func=flow_func
216
+ )
217
+
218
+
219
+ def test_missing_target():
220
+ G = nx.path_graph(4)
221
+ for flow_func in flow_funcs:
222
+ pytest.raises(
223
+ nx.NetworkXError, nx.node_connectivity, G, 1, 10, flow_func=flow_func
224
+ )
225
+
226
+
227
+ def test_edge_missing_source():
228
+ G = nx.path_graph(4)
229
+ for flow_func in flow_funcs:
230
+ pytest.raises(
231
+ nx.NetworkXError, nx.edge_connectivity, G, 10, 1, flow_func=flow_func
232
+ )
233
+
234
+
235
+ def test_edge_missing_target():
236
+ G = nx.path_graph(4)
237
+ for flow_func in flow_funcs:
238
+ pytest.raises(
239
+ nx.NetworkXError, nx.edge_connectivity, G, 1, 10, flow_func=flow_func
240
+ )
241
+
242
+
243
+ def test_not_weakly_connected():
244
+ G = nx.DiGraph()
245
+ nx.add_path(G, [1, 2, 3])
246
+ nx.add_path(G, [4, 5])
247
+ for flow_func in flow_funcs:
248
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
249
+ assert nx.node_connectivity(G) == 0, errmsg
250
+ assert nx.edge_connectivity(G) == 0, errmsg
251
+
252
+
253
+ def test_not_connected():
254
+ G = nx.Graph()
255
+ nx.add_path(G, [1, 2, 3])
256
+ nx.add_path(G, [4, 5])
257
+ for flow_func in flow_funcs:
258
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
259
+ assert nx.node_connectivity(G) == 0, errmsg
260
+ assert nx.edge_connectivity(G) == 0, errmsg
261
+
262
+
263
+ def test_directed_edge_connectivity():
264
+ G = nx.cycle_graph(10, create_using=nx.DiGraph()) # only one direction
265
+ D = nx.cycle_graph(10).to_directed() # 2 reciprocal edges
266
+ for flow_func in flow_funcs:
267
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
268
+ assert 1 == nx.edge_connectivity(G, flow_func=flow_func), errmsg
269
+ assert 1 == local_edge_connectivity(G, 1, 4, flow_func=flow_func), errmsg
270
+ assert 1 == nx.edge_connectivity(G, 1, 4, flow_func=flow_func), errmsg
271
+ assert 2 == nx.edge_connectivity(D, flow_func=flow_func), errmsg
272
+ assert 2 == local_edge_connectivity(D, 1, 4, flow_func=flow_func), errmsg
273
+ assert 2 == nx.edge_connectivity(D, 1, 4, flow_func=flow_func), errmsg
274
+
275
+
276
+ def test_cutoff():
277
+ G = nx.complete_graph(5)
278
+ for local_func in [local_edge_connectivity, local_node_connectivity]:
279
+ for flow_func in flow_funcs:
280
+ if flow_func is flow.preflow_push:
281
+ # cutoff is not supported by preflow_push
282
+ continue
283
+ for cutoff in [3, 2, 1]:
284
+ result = local_func(G, 0, 4, flow_func=flow_func, cutoff=cutoff)
285
+ assert cutoff == result, f"cutoff error in {flow_func.__name__}"
286
+
287
+
288
+ def test_invalid_auxiliary():
289
+ G = nx.complete_graph(5)
290
+ pytest.raises(nx.NetworkXError, local_node_connectivity, G, 0, 3, auxiliary=G)
291
+
292
+
293
+ def test_interface_only_source():
294
+ G = nx.complete_graph(5)
295
+ for interface_func in [nx.node_connectivity, nx.edge_connectivity]:
296
+ pytest.raises(nx.NetworkXError, interface_func, G, s=0)
297
+
298
+
299
+ def test_interface_only_target():
300
+ G = nx.complete_graph(5)
301
+ for interface_func in [nx.node_connectivity, nx.edge_connectivity]:
302
+ pytest.raises(nx.NetworkXError, interface_func, G, t=3)
303
+
304
+
305
+ def test_edge_connectivity_flow_vs_stoer_wagner():
306
+ graph_funcs = [nx.icosahedral_graph, nx.octahedral_graph, nx.dodecahedral_graph]
307
+ for graph_func in graph_funcs:
308
+ G = graph_func()
309
+ assert nx.stoer_wagner(G)[0] == nx.edge_connectivity(G)
310
+
311
+
312
+ class TestAllPairsNodeConnectivity:
313
+ @classmethod
314
+ def setup_class(cls):
315
+ cls.path = nx.path_graph(7)
316
+ cls.directed_path = nx.path_graph(7, create_using=nx.DiGraph())
317
+ cls.cycle = nx.cycle_graph(7)
318
+ cls.directed_cycle = nx.cycle_graph(7, create_using=nx.DiGraph())
319
+ cls.gnp = nx.gnp_random_graph(30, 0.1, seed=42)
320
+ cls.directed_gnp = nx.gnp_random_graph(30, 0.1, directed=True, seed=42)
321
+ cls.K20 = nx.complete_graph(20)
322
+ cls.K10 = nx.complete_graph(10)
323
+ cls.K5 = nx.complete_graph(5)
324
+ cls.G_list = [
325
+ cls.path,
326
+ cls.directed_path,
327
+ cls.cycle,
328
+ cls.directed_cycle,
329
+ cls.gnp,
330
+ cls.directed_gnp,
331
+ cls.K10,
332
+ cls.K5,
333
+ cls.K20,
334
+ ]
335
+
336
+ def test_cycles(self):
337
+ K_undir = nx.all_pairs_node_connectivity(self.cycle)
338
+ for source in K_undir:
339
+ for target, k in K_undir[source].items():
340
+ assert k == 2
341
+ K_dir = nx.all_pairs_node_connectivity(self.directed_cycle)
342
+ for source in K_dir:
343
+ for target, k in K_dir[source].items():
344
+ assert k == 1
345
+
346
+ def test_complete(self):
347
+ for G in [self.K10, self.K5, self.K20]:
348
+ K = nx.all_pairs_node_connectivity(G)
349
+ for source in K:
350
+ for target, k in K[source].items():
351
+ assert k == len(G) - 1
352
+
353
+ def test_paths(self):
354
+ K_undir = nx.all_pairs_node_connectivity(self.path)
355
+ for source in K_undir:
356
+ for target, k in K_undir[source].items():
357
+ assert k == 1
358
+ K_dir = nx.all_pairs_node_connectivity(self.directed_path)
359
+ for source in K_dir:
360
+ for target, k in K_dir[source].items():
361
+ if source < target:
362
+ assert k == 1
363
+ else:
364
+ assert k == 0
365
+
366
+ def test_all_pairs_connectivity_nbunch(self):
367
+ G = nx.complete_graph(5)
368
+ nbunch = [0, 2, 3]
369
+ C = nx.all_pairs_node_connectivity(G, nbunch=nbunch)
370
+ assert len(C) == len(nbunch)
371
+
372
+ def test_all_pairs_connectivity_icosahedral(self):
373
+ G = nx.icosahedral_graph()
374
+ C = nx.all_pairs_node_connectivity(G)
375
+ assert all(5 == C[u][v] for u, v in itertools.combinations(G, 2))
376
+
377
+ def test_all_pairs_connectivity(self):
378
+ G = nx.Graph()
379
+ nodes = [0, 1, 2, 3]
380
+ nx.add_path(G, nodes)
381
+ A = {n: {} for n in G}
382
+ for u, v in itertools.combinations(nodes, 2):
383
+ A[u][v] = A[v][u] = nx.node_connectivity(G, u, v)
384
+ C = nx.all_pairs_node_connectivity(G)
385
+ assert sorted((k, sorted(v)) for k, v in A.items()) == sorted(
386
+ (k, sorted(v)) for k, v in C.items()
387
+ )
388
+
389
+ def test_all_pairs_connectivity_directed(self):
390
+ G = nx.DiGraph()
391
+ nodes = [0, 1, 2, 3]
392
+ nx.add_path(G, nodes)
393
+ A = {n: {} for n in G}
394
+ for u, v in itertools.permutations(nodes, 2):
395
+ A[u][v] = nx.node_connectivity(G, u, v)
396
+ C = nx.all_pairs_node_connectivity(G)
397
+ assert sorted((k, sorted(v)) for k, v in A.items()) == sorted(
398
+ (k, sorted(v)) for k, v in C.items()
399
+ )
400
+
401
+ def test_all_pairs_connectivity_nbunch_combinations(self):
402
+ G = nx.complete_graph(5)
403
+ nbunch = [0, 2, 3]
404
+ A = {n: {} for n in nbunch}
405
+ for u, v in itertools.combinations(nbunch, 2):
406
+ A[u][v] = A[v][u] = nx.node_connectivity(G, u, v)
407
+ C = nx.all_pairs_node_connectivity(G, nbunch=nbunch)
408
+ assert sorted((k, sorted(v)) for k, v in A.items()) == sorted(
409
+ (k, sorted(v)) for k, v in C.items()
410
+ )
411
+
412
+ def test_all_pairs_connectivity_nbunch_iter(self):
413
+ G = nx.complete_graph(5)
414
+ nbunch = [0, 2, 3]
415
+ A = {n: {} for n in nbunch}
416
+ for u, v in itertools.combinations(nbunch, 2):
417
+ A[u][v] = A[v][u] = nx.node_connectivity(G, u, v)
418
+ C = nx.all_pairs_node_connectivity(G, nbunch=iter(nbunch))
419
+ assert sorted((k, sorted(v)) for k, v in A.items()) == sorted(
420
+ (k, sorted(v)) for k, v in C.items()
421
+ )
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/test_cuts.py ADDED
@@ -0,0 +1,309 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+
3
+ import networkx as nx
4
+ from networkx.algorithms import flow
5
+ from networkx.algorithms.connectivity import minimum_st_edge_cut, minimum_st_node_cut
6
+ from networkx.utils import arbitrary_element
7
+
8
+ flow_funcs = [
9
+ flow.boykov_kolmogorov,
10
+ flow.dinitz,
11
+ flow.edmonds_karp,
12
+ flow.preflow_push,
13
+ flow.shortest_augmenting_path,
14
+ ]
15
+
16
+ # Tests for node and edge cutsets
17
+
18
+
19
+ def _generate_no_biconnected(max_attempts=50):
20
+ attempts = 0
21
+ while True:
22
+ G = nx.fast_gnp_random_graph(100, 0.0575, seed=42)
23
+ if nx.is_connected(G) and not nx.is_biconnected(G):
24
+ attempts = 0
25
+ yield G
26
+ else:
27
+ if attempts >= max_attempts:
28
+ msg = f"Tried {attempts} times: no suitable Graph."
29
+ raise Exception(msg)
30
+ else:
31
+ attempts += 1
32
+
33
+
34
+ def test_articulation_points():
35
+ Ggen = _generate_no_biconnected()
36
+ for flow_func in flow_funcs:
37
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
38
+ for i in range(1): # change 1 to 3 or more for more realizations.
39
+ G = next(Ggen)
40
+ cut = nx.minimum_node_cut(G, flow_func=flow_func)
41
+ assert len(cut) == 1, errmsg
42
+ assert cut.pop() in set(nx.articulation_points(G)), errmsg
43
+
44
+
45
+ def test_brandes_erlebach_book():
46
+ # Figure 1 chapter 7: Connectivity
47
+ # http://www.informatik.uni-augsburg.de/thi/personen/kammer/Graph_Connectivity.pdf
48
+ G = nx.Graph()
49
+ G.add_edges_from(
50
+ [
51
+ (1, 2),
52
+ (1, 3),
53
+ (1, 4),
54
+ (1, 5),
55
+ (2, 3),
56
+ (2, 6),
57
+ (3, 4),
58
+ (3, 6),
59
+ (4, 6),
60
+ (4, 7),
61
+ (5, 7),
62
+ (6, 8),
63
+ (6, 9),
64
+ (7, 8),
65
+ (7, 10),
66
+ (8, 11),
67
+ (9, 10),
68
+ (9, 11),
69
+ (10, 11),
70
+ ]
71
+ )
72
+ for flow_func in flow_funcs:
73
+ kwargs = {"flow_func": flow_func}
74
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
75
+ # edge cutsets
76
+ assert 3 == len(nx.minimum_edge_cut(G, 1, 11, **kwargs)), errmsg
77
+ edge_cut = nx.minimum_edge_cut(G, **kwargs)
78
+ # Node 5 has only two edges
79
+ assert 2 == len(edge_cut), errmsg
80
+ H = G.copy()
81
+ H.remove_edges_from(edge_cut)
82
+ assert not nx.is_connected(H), errmsg
83
+ # node cuts
84
+ assert {6, 7} == minimum_st_node_cut(G, 1, 11, **kwargs), errmsg
85
+ assert {6, 7} == nx.minimum_node_cut(G, 1, 11, **kwargs), errmsg
86
+ node_cut = nx.minimum_node_cut(G, **kwargs)
87
+ assert 2 == len(node_cut), errmsg
88
+ H = G.copy()
89
+ H.remove_nodes_from(node_cut)
90
+ assert not nx.is_connected(H), errmsg
91
+
92
+
93
+ def test_white_harary_paper():
94
+ # Figure 1b white and harary (2001)
95
+ # https://doi.org/10.1111/0081-1750.00098
96
+ # A graph with high adhesion (edge connectivity) and low cohesion
97
+ # (node connectivity)
98
+ G = nx.disjoint_union(nx.complete_graph(4), nx.complete_graph(4))
99
+ G.remove_node(7)
100
+ for i in range(4, 7):
101
+ G.add_edge(0, i)
102
+ G = nx.disjoint_union(G, nx.complete_graph(4))
103
+ G.remove_node(G.order() - 1)
104
+ for i in range(7, 10):
105
+ G.add_edge(0, i)
106
+ for flow_func in flow_funcs:
107
+ kwargs = {"flow_func": flow_func}
108
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
109
+ # edge cuts
110
+ edge_cut = nx.minimum_edge_cut(G, **kwargs)
111
+ assert 3 == len(edge_cut), errmsg
112
+ H = G.copy()
113
+ H.remove_edges_from(edge_cut)
114
+ assert not nx.is_connected(H), errmsg
115
+ # node cuts
116
+ node_cut = nx.minimum_node_cut(G, **kwargs)
117
+ assert {0} == node_cut, errmsg
118
+ H = G.copy()
119
+ H.remove_nodes_from(node_cut)
120
+ assert not nx.is_connected(H), errmsg
121
+
122
+
123
+ def test_petersen_cutset():
124
+ G = nx.petersen_graph()
125
+ for flow_func in flow_funcs:
126
+ kwargs = {"flow_func": flow_func}
127
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
128
+ # edge cuts
129
+ edge_cut = nx.minimum_edge_cut(G, **kwargs)
130
+ assert 3 == len(edge_cut), errmsg
131
+ H = G.copy()
132
+ H.remove_edges_from(edge_cut)
133
+ assert not nx.is_connected(H), errmsg
134
+ # node cuts
135
+ node_cut = nx.minimum_node_cut(G, **kwargs)
136
+ assert 3 == len(node_cut), errmsg
137
+ H = G.copy()
138
+ H.remove_nodes_from(node_cut)
139
+ assert not nx.is_connected(H), errmsg
140
+
141
+
142
+ def test_octahedral_cutset():
143
+ G = nx.octahedral_graph()
144
+ for flow_func in flow_funcs:
145
+ kwargs = {"flow_func": flow_func}
146
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
147
+ # edge cuts
148
+ edge_cut = nx.minimum_edge_cut(G, **kwargs)
149
+ assert 4 == len(edge_cut), errmsg
150
+ H = G.copy()
151
+ H.remove_edges_from(edge_cut)
152
+ assert not nx.is_connected(H), errmsg
153
+ # node cuts
154
+ node_cut = nx.minimum_node_cut(G, **kwargs)
155
+ assert 4 == len(node_cut), errmsg
156
+ H = G.copy()
157
+ H.remove_nodes_from(node_cut)
158
+ assert not nx.is_connected(H), errmsg
159
+
160
+
161
+ def test_icosahedral_cutset():
162
+ G = nx.icosahedral_graph()
163
+ for flow_func in flow_funcs:
164
+ kwargs = {"flow_func": flow_func}
165
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
166
+ # edge cuts
167
+ edge_cut = nx.minimum_edge_cut(G, **kwargs)
168
+ assert 5 == len(edge_cut), errmsg
169
+ H = G.copy()
170
+ H.remove_edges_from(edge_cut)
171
+ assert not nx.is_connected(H), errmsg
172
+ # node cuts
173
+ node_cut = nx.minimum_node_cut(G, **kwargs)
174
+ assert 5 == len(node_cut), errmsg
175
+ H = G.copy()
176
+ H.remove_nodes_from(node_cut)
177
+ assert not nx.is_connected(H), errmsg
178
+
179
+
180
+ def test_node_cutset_exception():
181
+ G = nx.Graph()
182
+ G.add_edges_from([(1, 2), (3, 4)])
183
+ for flow_func in flow_funcs:
184
+ pytest.raises(nx.NetworkXError, nx.minimum_node_cut, G, flow_func=flow_func)
185
+
186
+
187
+ def test_node_cutset_random_graphs():
188
+ for flow_func in flow_funcs:
189
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
190
+ for i in range(3):
191
+ G = nx.fast_gnp_random_graph(50, 0.25, seed=42)
192
+ if not nx.is_connected(G):
193
+ ccs = iter(nx.connected_components(G))
194
+ start = arbitrary_element(next(ccs))
195
+ G.add_edges_from((start, arbitrary_element(c)) for c in ccs)
196
+ cutset = nx.minimum_node_cut(G, flow_func=flow_func)
197
+ assert nx.node_connectivity(G) == len(cutset), errmsg
198
+ G.remove_nodes_from(cutset)
199
+ assert not nx.is_connected(G), errmsg
200
+
201
+
202
+ def test_edge_cutset_random_graphs():
203
+ for flow_func in flow_funcs:
204
+ errmsg = f"Assertion failed in function: {flow_func.__name__}"
205
+ for i in range(3):
206
+ G = nx.fast_gnp_random_graph(50, 0.25, seed=42)
207
+ if not nx.is_connected(G):
208
+ ccs = iter(nx.connected_components(G))
209
+ start = arbitrary_element(next(ccs))
210
+ G.add_edges_from((start, arbitrary_element(c)) for c in ccs)
211
+ cutset = nx.minimum_edge_cut(G, flow_func=flow_func)
212
+ assert nx.edge_connectivity(G) == len(cutset), errmsg
213
+ G.remove_edges_from(cutset)
214
+ assert not nx.is_connected(G), errmsg
215
+
216
+
217
+ def test_empty_graphs():
218
+ G = nx.Graph()
219
+ D = nx.DiGraph()
220
+ for interface_func in [nx.minimum_node_cut, nx.minimum_edge_cut]:
221
+ for flow_func in flow_funcs:
222
+ pytest.raises(
223
+ nx.NetworkXPointlessConcept, interface_func, G, flow_func=flow_func
224
+ )
225
+ pytest.raises(
226
+ nx.NetworkXPointlessConcept, interface_func, D, flow_func=flow_func
227
+ )
228
+
229
+
230
+ def test_unbounded():
231
+ G = nx.complete_graph(5)
232
+ for flow_func in flow_funcs:
233
+ assert 4 == len(minimum_st_edge_cut(G, 1, 4, flow_func=flow_func))
234
+
235
+
236
+ def test_missing_source():
237
+ G = nx.path_graph(4)
238
+ for interface_func in [nx.minimum_edge_cut, nx.minimum_node_cut]:
239
+ for flow_func in flow_funcs:
240
+ pytest.raises(
241
+ nx.NetworkXError, interface_func, G, 10, 1, flow_func=flow_func
242
+ )
243
+
244
+
245
+ def test_missing_target():
246
+ G = nx.path_graph(4)
247
+ for interface_func in [nx.minimum_edge_cut, nx.minimum_node_cut]:
248
+ for flow_func in flow_funcs:
249
+ pytest.raises(
250
+ nx.NetworkXError, interface_func, G, 1, 10, flow_func=flow_func
251
+ )
252
+
253
+
254
+ def test_not_weakly_connected():
255
+ G = nx.DiGraph()
256
+ nx.add_path(G, [1, 2, 3])
257
+ nx.add_path(G, [4, 5])
258
+ for interface_func in [nx.minimum_edge_cut, nx.minimum_node_cut]:
259
+ for flow_func in flow_funcs:
260
+ pytest.raises(nx.NetworkXError, interface_func, G, flow_func=flow_func)
261
+
262
+
263
+ def test_not_connected():
264
+ G = nx.Graph()
265
+ nx.add_path(G, [1, 2, 3])
266
+ nx.add_path(G, [4, 5])
267
+ for interface_func in [nx.minimum_edge_cut, nx.minimum_node_cut]:
268
+ for flow_func in flow_funcs:
269
+ pytest.raises(nx.NetworkXError, interface_func, G, flow_func=flow_func)
270
+
271
+
272
+ def tests_min_cut_complete():
273
+ G = nx.complete_graph(5)
274
+ for interface_func in [nx.minimum_edge_cut, nx.minimum_node_cut]:
275
+ for flow_func in flow_funcs:
276
+ assert 4 == len(interface_func(G, flow_func=flow_func))
277
+
278
+
279
+ def tests_min_cut_complete_directed():
280
+ G = nx.complete_graph(5)
281
+ G = G.to_directed()
282
+ for interface_func in [nx.minimum_edge_cut, nx.minimum_node_cut]:
283
+ for flow_func in flow_funcs:
284
+ assert 4 == len(interface_func(G, flow_func=flow_func))
285
+
286
+
287
+ def tests_minimum_st_node_cut():
288
+ G = nx.Graph()
289
+ G.add_nodes_from([0, 1, 2, 3, 7, 8, 11, 12])
290
+ G.add_edges_from([(7, 11), (1, 11), (1, 12), (12, 8), (0, 1)])
291
+ nodelist = minimum_st_node_cut(G, 7, 11)
292
+ assert nodelist == {}
293
+
294
+
295
+ def test_invalid_auxiliary():
296
+ G = nx.complete_graph(5)
297
+ pytest.raises(nx.NetworkXError, minimum_st_node_cut, G, 0, 3, auxiliary=G)
298
+
299
+
300
+ def test_interface_only_source():
301
+ G = nx.complete_graph(5)
302
+ for interface_func in [nx.minimum_node_cut, nx.minimum_edge_cut]:
303
+ pytest.raises(nx.NetworkXError, interface_func, G, s=0)
304
+
305
+
306
+ def test_interface_only_target():
307
+ G = nx.complete_graph(5)
308
+ for interface_func in [nx.minimum_node_cut, nx.minimum_edge_cut]:
309
+ pytest.raises(nx.NetworkXError, interface_func, G, t=3)
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/test_edge_augmentation.py ADDED
@@ -0,0 +1,502 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import itertools as it
2
+ import random
3
+
4
+ import pytest
5
+
6
+ import networkx as nx
7
+ from networkx.algorithms.connectivity import k_edge_augmentation
8
+ from networkx.algorithms.connectivity.edge_augmentation import (
9
+ _unpack_available_edges,
10
+ collapse,
11
+ complement_edges,
12
+ is_k_edge_connected,
13
+ is_locally_k_edge_connected,
14
+ )
15
+ from networkx.utils import pairwise
16
+
17
+ # This should be set to the largest k for which an efficient algorithm is
18
+ # explicitly defined.
19
+ MAX_EFFICIENT_K = 2
20
+
21
+
22
+ def tarjan_bridge_graph():
23
+ # graph from tarjan paper
24
+ # RE Tarjan - "A note on finding the bridges of a graph"
25
+ # Information Processing Letters, 1974 - Elsevier
26
+ # doi:10.1016/0020-0190(74)90003-9.
27
+ # define 2-connected components and bridges
28
+ ccs = [
29
+ (1, 2, 4, 3, 1, 4),
30
+ (5, 6, 7, 5),
31
+ (8, 9, 10, 8),
32
+ (17, 18, 16, 15, 17),
33
+ (11, 12, 14, 13, 11, 14),
34
+ ]
35
+ bridges = [(4, 8), (3, 5), (3, 17)]
36
+ G = nx.Graph(it.chain(*(pairwise(path) for path in ccs + bridges)))
37
+ return G
38
+
39
+
40
+ def test_weight_key():
41
+ G = nx.Graph()
42
+ G.add_nodes_from([1, 2, 3, 4, 5, 6, 7, 8, 9])
43
+ G.add_edges_from([(3, 8), (1, 2), (2, 3)])
44
+ impossible = {(3, 6), (3, 9)}
45
+ rng = random.Random(0)
46
+ avail_uv = list(set(complement_edges(G)) - impossible)
47
+ avail = [(u, v, {"cost": rng.random()}) for u, v in avail_uv]
48
+
49
+ _augment_and_check(G, k=1)
50
+ _augment_and_check(G, k=1, avail=avail_uv)
51
+ _augment_and_check(G, k=1, avail=avail, weight="cost")
52
+
53
+ _check_augmentations(G, avail, weight="cost")
54
+
55
+
56
+ def test_is_locally_k_edge_connected_exceptions():
57
+ pytest.raises(nx.NetworkXNotImplemented, is_k_edge_connected, nx.DiGraph(), k=0)
58
+ pytest.raises(nx.NetworkXNotImplemented, is_k_edge_connected, nx.MultiGraph(), k=0)
59
+ pytest.raises(ValueError, is_k_edge_connected, nx.Graph(), k=0)
60
+
61
+
62
+ def test_is_k_edge_connected():
63
+ G = nx.barbell_graph(10, 0)
64
+ assert is_k_edge_connected(G, k=1)
65
+ assert not is_k_edge_connected(G, k=2)
66
+
67
+ G = nx.Graph()
68
+ G.add_nodes_from([5, 15])
69
+ assert not is_k_edge_connected(G, k=1)
70
+ assert not is_k_edge_connected(G, k=2)
71
+
72
+ G = nx.complete_graph(5)
73
+ assert is_k_edge_connected(G, k=1)
74
+ assert is_k_edge_connected(G, k=2)
75
+ assert is_k_edge_connected(G, k=3)
76
+ assert is_k_edge_connected(G, k=4)
77
+
78
+ G = nx.compose(nx.complete_graph([0, 1, 2]), nx.complete_graph([3, 4, 5]))
79
+ assert not is_k_edge_connected(G, k=1)
80
+ assert not is_k_edge_connected(G, k=2)
81
+ assert not is_k_edge_connected(G, k=3)
82
+
83
+
84
+ def test_is_k_edge_connected_exceptions():
85
+ pytest.raises(
86
+ nx.NetworkXNotImplemented, is_locally_k_edge_connected, nx.DiGraph(), 1, 2, k=0
87
+ )
88
+ pytest.raises(
89
+ nx.NetworkXNotImplemented,
90
+ is_locally_k_edge_connected,
91
+ nx.MultiGraph(),
92
+ 1,
93
+ 2,
94
+ k=0,
95
+ )
96
+ pytest.raises(ValueError, is_locally_k_edge_connected, nx.Graph(), 1, 2, k=0)
97
+
98
+
99
+ def test_is_locally_k_edge_connected():
100
+ G = nx.barbell_graph(10, 0)
101
+ assert is_locally_k_edge_connected(G, 5, 15, k=1)
102
+ assert not is_locally_k_edge_connected(G, 5, 15, k=2)
103
+
104
+ G = nx.Graph()
105
+ G.add_nodes_from([5, 15])
106
+ assert not is_locally_k_edge_connected(G, 5, 15, k=2)
107
+
108
+
109
+ def test_null_graph():
110
+ G = nx.Graph()
111
+ _check_augmentations(G, max_k=MAX_EFFICIENT_K + 2)
112
+
113
+
114
+ def test_cliques():
115
+ for n in range(1, 10):
116
+ G = nx.complete_graph(n)
117
+ _check_augmentations(G, max_k=MAX_EFFICIENT_K + 2)
118
+
119
+
120
+ def test_clique_and_node():
121
+ for n in range(1, 10):
122
+ G = nx.complete_graph(n)
123
+ G.add_node(n + 1)
124
+ _check_augmentations(G, max_k=MAX_EFFICIENT_K + 2)
125
+
126
+
127
+ def test_point_graph():
128
+ G = nx.Graph()
129
+ G.add_node(1)
130
+ _check_augmentations(G, max_k=MAX_EFFICIENT_K + 2)
131
+
132
+
133
+ def test_edgeless_graph():
134
+ G = nx.Graph()
135
+ G.add_nodes_from([1, 2, 3, 4])
136
+ _check_augmentations(G)
137
+
138
+
139
+ def test_invalid_k():
140
+ G = nx.Graph()
141
+ pytest.raises(ValueError, list, k_edge_augmentation(G, k=-1))
142
+ pytest.raises(ValueError, list, k_edge_augmentation(G, k=0))
143
+
144
+
145
+ def test_unfeasible():
146
+ G = tarjan_bridge_graph()
147
+ pytest.raises(nx.NetworkXUnfeasible, list, k_edge_augmentation(G, k=1, avail=[]))
148
+
149
+ pytest.raises(nx.NetworkXUnfeasible, list, k_edge_augmentation(G, k=2, avail=[]))
150
+
151
+ pytest.raises(
152
+ nx.NetworkXUnfeasible, list, k_edge_augmentation(G, k=2, avail=[(7, 9)])
153
+ )
154
+
155
+ # partial solutions should not error if real solutions are infeasible
156
+ aug_edges = list(k_edge_augmentation(G, k=2, avail=[(7, 9)], partial=True))
157
+ assert aug_edges == [(7, 9)]
158
+
159
+ _check_augmentations(G, avail=[], max_k=MAX_EFFICIENT_K + 2)
160
+
161
+ _check_augmentations(G, avail=[(7, 9)], max_k=MAX_EFFICIENT_K + 2)
162
+
163
+
164
+ def test_tarjan():
165
+ G = tarjan_bridge_graph()
166
+
167
+ aug_edges = set(_augment_and_check(G, k=2)[0])
168
+ print(f"aug_edges = {aug_edges!r}")
169
+ # can't assert edge exactly equality due to non-determinant edge order
170
+ # but we do know the size of the solution must be 3
171
+ assert len(aug_edges) == 3
172
+
173
+ avail = [
174
+ (9, 7),
175
+ (8, 5),
176
+ (2, 10),
177
+ (6, 13),
178
+ (11, 18),
179
+ (1, 17),
180
+ (2, 3),
181
+ (16, 17),
182
+ (18, 14),
183
+ (15, 14),
184
+ ]
185
+ aug_edges = set(_augment_and_check(G, avail=avail, k=2)[0])
186
+
187
+ # Can't assert exact length since approximation depends on the order of a
188
+ # dict traversal.
189
+ assert len(aug_edges) <= 3 * 2
190
+
191
+ _check_augmentations(G, avail)
192
+
193
+
194
+ def test_configuration():
195
+ # seeds = [2718183590, 2470619828, 1694705158, 3001036531, 2401251497]
196
+ seeds = [1001, 1002, 1003, 1004]
197
+ for seed in seeds:
198
+ deg_seq = nx.random_powerlaw_tree_sequence(20, seed=seed, tries=5000)
199
+ G = nx.Graph(nx.configuration_model(deg_seq, seed=seed))
200
+ G.remove_edges_from(nx.selfloop_edges(G))
201
+ _check_augmentations(G)
202
+
203
+
204
+ def test_shell():
205
+ # seeds = [2057382236, 3331169846, 1840105863, 476020778, 2247498425]
206
+ seeds = [18]
207
+ for seed in seeds:
208
+ constructor = [(12, 70, 0.8), (15, 40, 0.6)]
209
+ G = nx.random_shell_graph(constructor, seed=seed)
210
+ _check_augmentations(G)
211
+
212
+
213
+ def test_karate():
214
+ G = nx.karate_club_graph()
215
+ _check_augmentations(G)
216
+
217
+
218
+ def test_star():
219
+ G = nx.star_graph(3)
220
+ _check_augmentations(G)
221
+
222
+ G = nx.star_graph(5)
223
+ _check_augmentations(G)
224
+
225
+ G = nx.star_graph(10)
226
+ _check_augmentations(G)
227
+
228
+
229
+ def test_barbell():
230
+ G = nx.barbell_graph(5, 0)
231
+ _check_augmentations(G)
232
+
233
+ G = nx.barbell_graph(5, 2)
234
+ _check_augmentations(G)
235
+
236
+ G = nx.barbell_graph(5, 3)
237
+ _check_augmentations(G)
238
+
239
+ G = nx.barbell_graph(5, 4)
240
+ _check_augmentations(G)
241
+
242
+
243
+ def test_bridge():
244
+ G = nx.Graph([(2393, 2257), (2393, 2685), (2685, 2257), (1758, 2257)])
245
+ _check_augmentations(G)
246
+
247
+
248
+ def test_gnp_augmentation():
249
+ rng = random.Random(0)
250
+ G = nx.gnp_random_graph(30, 0.005, seed=0)
251
+ # Randomly make edges available
252
+ avail = {
253
+ (u, v): 1 + rng.random() for u, v in complement_edges(G) if rng.random() < 0.25
254
+ }
255
+ _check_augmentations(G, avail)
256
+
257
+
258
+ def _assert_solution_properties(G, aug_edges, avail_dict=None):
259
+ """Checks that aug_edges are consistently formatted"""
260
+ if avail_dict is not None:
261
+ assert all(
262
+ e in avail_dict for e in aug_edges
263
+ ), "when avail is specified aug-edges should be in avail"
264
+
265
+ unique_aug = set(map(tuple, map(sorted, aug_edges)))
266
+ unique_aug = list(map(tuple, map(sorted, aug_edges)))
267
+ assert len(aug_edges) == len(unique_aug), "edges should be unique"
268
+
269
+ assert not any(u == v for u, v in unique_aug), "should be no self-edges"
270
+
271
+ assert not any(
272
+ G.has_edge(u, v) for u, v in unique_aug
273
+ ), "aug edges and G.edges should be disjoint"
274
+
275
+
276
+ def _augment_and_check(
277
+ G, k, avail=None, weight=None, verbose=False, orig_k=None, max_aug_k=None
278
+ ):
279
+ """
280
+ Does one specific augmentation and checks for properties of the result
281
+ """
282
+ if orig_k is None:
283
+ try:
284
+ orig_k = nx.edge_connectivity(G)
285
+ except nx.NetworkXPointlessConcept:
286
+ orig_k = 0
287
+ info = {}
288
+ try:
289
+ if avail is not None:
290
+ # ensure avail is in dict form
291
+ avail_dict = dict(zip(*_unpack_available_edges(avail, weight=weight)))
292
+ else:
293
+ avail_dict = None
294
+ try:
295
+ # Find the augmentation if possible
296
+ generator = nx.k_edge_augmentation(G, k=k, weight=weight, avail=avail)
297
+ assert not isinstance(generator, list), "should always return an iter"
298
+ aug_edges = []
299
+ for edge in generator:
300
+ aug_edges.append(edge)
301
+ except nx.NetworkXUnfeasible:
302
+ infeasible = True
303
+ info["infeasible"] = True
304
+ assert len(aug_edges) == 0, "should not generate anything if unfeasible"
305
+
306
+ if avail is None:
307
+ n_nodes = G.number_of_nodes()
308
+ assert n_nodes <= k, (
309
+ "unconstrained cases are only unfeasible if |V| <= k. "
310
+ f"Got |V|={n_nodes} and k={k}"
311
+ )
312
+ else:
313
+ if max_aug_k is None:
314
+ G_aug_all = G.copy()
315
+ G_aug_all.add_edges_from(avail_dict.keys())
316
+ try:
317
+ max_aug_k = nx.edge_connectivity(G_aug_all)
318
+ except nx.NetworkXPointlessConcept:
319
+ max_aug_k = 0
320
+
321
+ assert max_aug_k < k, (
322
+ "avail should only be unfeasible if using all edges "
323
+ "does not achieve k-edge-connectivity"
324
+ )
325
+
326
+ # Test for a partial solution
327
+ partial_edges = list(
328
+ nx.k_edge_augmentation(G, k=k, weight=weight, partial=True, avail=avail)
329
+ )
330
+
331
+ info["n_partial_edges"] = len(partial_edges)
332
+
333
+ if avail_dict is None:
334
+ assert set(partial_edges) == set(
335
+ complement_edges(G)
336
+ ), "unweighted partial solutions should be the complement"
337
+ elif len(avail_dict) > 0:
338
+ H = G.copy()
339
+
340
+ # Find the partial / full augmented connectivity
341
+ H.add_edges_from(partial_edges)
342
+ partial_conn = nx.edge_connectivity(H)
343
+
344
+ H.add_edges_from(set(avail_dict.keys()))
345
+ full_conn = nx.edge_connectivity(H)
346
+
347
+ # Full connectivity should be no better than our partial
348
+ # solution.
349
+ assert (
350
+ partial_conn == full_conn
351
+ ), "adding more edges should not increase k-conn"
352
+
353
+ # Find the new edge-connectivity after adding the augmenting edges
354
+ aug_edges = partial_edges
355
+ else:
356
+ infeasible = False
357
+
358
+ # Find the weight of the augmentation
359
+ num_edges = len(aug_edges)
360
+ if avail is not None:
361
+ total_weight = sum(avail_dict[e] for e in aug_edges)
362
+ else:
363
+ total_weight = num_edges
364
+
365
+ info["total_weight"] = total_weight
366
+ info["num_edges"] = num_edges
367
+
368
+ # Find the new edge-connectivity after adding the augmenting edges
369
+ G_aug = G.copy()
370
+ G_aug.add_edges_from(aug_edges)
371
+ try:
372
+ aug_k = nx.edge_connectivity(G_aug)
373
+ except nx.NetworkXPointlessConcept:
374
+ aug_k = 0
375
+ info["aug_k"] = aug_k
376
+
377
+ # Do checks
378
+ if not infeasible and orig_k < k:
379
+ assert info["aug_k"] >= k, f"connectivity should increase to k={k} or more"
380
+
381
+ assert info["aug_k"] >= orig_k, "augmenting should never reduce connectivity"
382
+
383
+ _assert_solution_properties(G, aug_edges, avail_dict)
384
+
385
+ except Exception:
386
+ info["failed"] = True
387
+ print(f"edges = {list(G.edges())}")
388
+ print(f"nodes = {list(G.nodes())}")
389
+ print(f"aug_edges = {list(aug_edges)}")
390
+ print(f"info = {info}")
391
+ raise
392
+ else:
393
+ if verbose:
394
+ print(f"info = {info}")
395
+
396
+ if infeasible:
397
+ aug_edges = None
398
+ return aug_edges, info
399
+
400
+
401
+ def _check_augmentations(G, avail=None, max_k=None, weight=None, verbose=False):
402
+ """Helper to check weighted/unweighted cases with multiple values of k"""
403
+ # Using all available edges, find the maximum edge-connectivity
404
+ try:
405
+ orig_k = nx.edge_connectivity(G)
406
+ except nx.NetworkXPointlessConcept:
407
+ orig_k = 0
408
+
409
+ if avail is not None:
410
+ all_aug_edges = _unpack_available_edges(avail, weight=weight)[0]
411
+ G_aug_all = G.copy()
412
+ G_aug_all.add_edges_from(all_aug_edges)
413
+ try:
414
+ max_aug_k = nx.edge_connectivity(G_aug_all)
415
+ except nx.NetworkXPointlessConcept:
416
+ max_aug_k = 0
417
+ else:
418
+ max_aug_k = G.number_of_nodes() - 1
419
+
420
+ if max_k is None:
421
+ max_k = min(4, max_aug_k)
422
+
423
+ avail_uniform = {e: 1 for e in complement_edges(G)}
424
+
425
+ if verbose:
426
+ print("\n=== CHECK_AUGMENTATION ===")
427
+ print(f"G.number_of_nodes = {G.number_of_nodes()!r}")
428
+ print(f"G.number_of_edges = {G.number_of_edges()!r}")
429
+ print(f"max_k = {max_k!r}")
430
+ print(f"max_aug_k = {max_aug_k!r}")
431
+ print(f"orig_k = {orig_k!r}")
432
+
433
+ # check augmentation for multiple values of k
434
+ for k in range(1, max_k + 1):
435
+ if verbose:
436
+ print("---------------")
437
+ print(f"Checking k = {k}")
438
+
439
+ # Check the unweighted version
440
+ if verbose:
441
+ print("unweighted case")
442
+ aug_edges1, info1 = _augment_and_check(G, k=k, verbose=verbose, orig_k=orig_k)
443
+
444
+ # Check that the weighted version with all available edges and uniform
445
+ # weights gives a similar solution to the unweighted case.
446
+ if verbose:
447
+ print("weighted uniform case")
448
+ aug_edges2, info2 = _augment_and_check(
449
+ G,
450
+ k=k,
451
+ avail=avail_uniform,
452
+ verbose=verbose,
453
+ orig_k=orig_k,
454
+ max_aug_k=G.number_of_nodes() - 1,
455
+ )
456
+
457
+ # Check the weighted version
458
+ if avail is not None:
459
+ if verbose:
460
+ print("weighted case")
461
+ aug_edges3, info3 = _augment_and_check(
462
+ G,
463
+ k=k,
464
+ avail=avail,
465
+ weight=weight,
466
+ verbose=verbose,
467
+ max_aug_k=max_aug_k,
468
+ orig_k=orig_k,
469
+ )
470
+
471
+ if aug_edges1 is not None:
472
+ # Check approximation ratios
473
+ if k == 1:
474
+ # when k=1, both solutions should be optimal
475
+ assert info2["total_weight"] == info1["total_weight"]
476
+ if k == 2:
477
+ # when k=2, the weighted version is an approximation
478
+ if orig_k == 0:
479
+ # the approximation ratio is 3 if G is not connected
480
+ assert info2["total_weight"] <= info1["total_weight"] * 3
481
+ else:
482
+ # the approximation ratio is 2 if G is was connected
483
+ assert info2["total_weight"] <= info1["total_weight"] * 2
484
+ _check_unconstrained_bridge_property(G, info1)
485
+
486
+
487
+ def _check_unconstrained_bridge_property(G, info1):
488
+ # Check Theorem 5 from Eswaran and Tarjan. (1975) Augmentation problems
489
+ import math
490
+
491
+ bridge_ccs = list(nx.connectivity.bridge_components(G))
492
+ # condense G into an forest C
493
+ C = collapse(G, bridge_ccs)
494
+
495
+ p = len([n for n, d in C.degree() if d == 1]) # leafs
496
+ q = len([n for n, d in C.degree() if d == 0]) # isolated
497
+ if p + q > 1:
498
+ size_target = math.ceil(p / 2) + q
499
+ size_aug = info1["num_edges"]
500
+ assert (
501
+ size_aug == size_target
502
+ ), "augmentation size is different from what theory predicts"
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/test_edge_kcomponents.py ADDED
@@ -0,0 +1,488 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import itertools as it
2
+
3
+ import pytest
4
+
5
+ import networkx as nx
6
+ from networkx.algorithms.connectivity import EdgeComponentAuxGraph, bridge_components
7
+ from networkx.algorithms.connectivity.edge_kcomponents import general_k_edge_subgraphs
8
+ from networkx.utils import pairwise
9
+
10
+ # ----------------
11
+ # Helper functions
12
+ # ----------------
13
+
14
+
15
+ def fset(list_of_sets):
16
+ """allows == to be used for list of sets"""
17
+ return set(map(frozenset, list_of_sets))
18
+
19
+
20
+ def _assert_subgraph_edge_connectivity(G, ccs_subgraph, k):
21
+ """
22
+ tests properties of k-edge-connected subgraphs
23
+
24
+ the actual edge connectivity should be no less than k unless the cc is a
25
+ single node.
26
+ """
27
+ for cc in ccs_subgraph:
28
+ C = G.subgraph(cc)
29
+ if len(cc) > 1:
30
+ connectivity = nx.edge_connectivity(C)
31
+ assert connectivity >= k
32
+
33
+
34
+ def _memo_connectivity(G, u, v, memo):
35
+ edge = (u, v)
36
+ if edge in memo:
37
+ return memo[edge]
38
+ if not G.is_directed():
39
+ redge = (v, u)
40
+ if redge in memo:
41
+ return memo[redge]
42
+ memo[edge] = nx.edge_connectivity(G, *edge)
43
+ return memo[edge]
44
+
45
+
46
+ def _all_pairs_connectivity(G, cc, k, memo):
47
+ # Brute force check
48
+ for u, v in it.combinations(cc, 2):
49
+ # Use a memoization dict to save on computation
50
+ connectivity = _memo_connectivity(G, u, v, memo)
51
+ if G.is_directed():
52
+ connectivity = min(connectivity, _memo_connectivity(G, v, u, memo))
53
+ assert connectivity >= k
54
+
55
+
56
+ def _assert_local_cc_edge_connectivity(G, ccs_local, k, memo):
57
+ """
58
+ tests properties of k-edge-connected components
59
+
60
+ the local edge connectivity between each pair of nodes in the original
61
+ graph should be no less than k unless the cc is a single node.
62
+ """
63
+ for cc in ccs_local:
64
+ if len(cc) > 1:
65
+ # Strategy for testing a bit faster: If the subgraph has high edge
66
+ # connectivity then it must have local connectivity
67
+ C = G.subgraph(cc)
68
+ connectivity = nx.edge_connectivity(C)
69
+ if connectivity < k:
70
+ # Otherwise do the brute force (with memoization) check
71
+ _all_pairs_connectivity(G, cc, k, memo)
72
+
73
+
74
+ # Helper function
75
+ def _check_edge_connectivity(G):
76
+ """
77
+ Helper - generates all k-edge-components using the aux graph. Checks the
78
+ both local and subgraph edge connectivity of each cc. Also checks that
79
+ alternate methods of computing the k-edge-ccs generate the same result.
80
+ """
81
+ # Construct the auxiliary graph that can be used to make each k-cc or k-sub
82
+ aux_graph = EdgeComponentAuxGraph.construct(G)
83
+
84
+ # memoize the local connectivity in this graph
85
+ memo = {}
86
+
87
+ for k in it.count(1):
88
+ # Test "local" k-edge-components and k-edge-subgraphs
89
+ ccs_local = fset(aux_graph.k_edge_components(k))
90
+ ccs_subgraph = fset(aux_graph.k_edge_subgraphs(k))
91
+
92
+ # Check connectivity properties that should be guaranteed by the
93
+ # algorithms.
94
+ _assert_local_cc_edge_connectivity(G, ccs_local, k, memo)
95
+ _assert_subgraph_edge_connectivity(G, ccs_subgraph, k)
96
+
97
+ if k == 1 or k == 2 and not G.is_directed():
98
+ assert (
99
+ ccs_local == ccs_subgraph
100
+ ), "Subgraphs and components should be the same when k == 1 or (k == 2 and not G.directed())"
101
+
102
+ if G.is_directed():
103
+ # Test special case methods are the same as the aux graph
104
+ if k == 1:
105
+ alt_sccs = fset(nx.strongly_connected_components(G))
106
+ assert alt_sccs == ccs_local, "k=1 failed alt"
107
+ assert alt_sccs == ccs_subgraph, "k=1 failed alt"
108
+ else:
109
+ # Test special case methods are the same as the aux graph
110
+ if k == 1:
111
+ alt_ccs = fset(nx.connected_components(G))
112
+ assert alt_ccs == ccs_local, "k=1 failed alt"
113
+ assert alt_ccs == ccs_subgraph, "k=1 failed alt"
114
+ elif k == 2:
115
+ alt_bridge_ccs = fset(bridge_components(G))
116
+ assert alt_bridge_ccs == ccs_local, "k=2 failed alt"
117
+ assert alt_bridge_ccs == ccs_subgraph, "k=2 failed alt"
118
+ # if new methods for k == 3 or k == 4 are implemented add them here
119
+
120
+ # Check the general subgraph method works by itself
121
+ alt_subgraph_ccs = fset(
122
+ [set(C.nodes()) for C in general_k_edge_subgraphs(G, k=k)]
123
+ )
124
+ assert alt_subgraph_ccs == ccs_subgraph, "alt subgraph method failed"
125
+
126
+ # Stop once k is larger than all special case methods
127
+ # and we cannot break down ccs any further.
128
+ if k > 2 and all(len(cc) == 1 for cc in ccs_local):
129
+ break
130
+
131
+
132
+ # ----------------
133
+ # Misc tests
134
+ # ----------------
135
+
136
+
137
+ def test_zero_k_exception():
138
+ G = nx.Graph()
139
+ # functions that return generators error immediately
140
+ pytest.raises(ValueError, nx.k_edge_components, G, k=0)
141
+ pytest.raises(ValueError, nx.k_edge_subgraphs, G, k=0)
142
+
143
+ # actual generators only error when you get the first item
144
+ aux_graph = EdgeComponentAuxGraph.construct(G)
145
+ pytest.raises(ValueError, list, aux_graph.k_edge_components(k=0))
146
+ pytest.raises(ValueError, list, aux_graph.k_edge_subgraphs(k=0))
147
+
148
+ pytest.raises(ValueError, list, general_k_edge_subgraphs(G, k=0))
149
+
150
+
151
+ def test_empty_input():
152
+ G = nx.Graph()
153
+ assert [] == list(nx.k_edge_components(G, k=5))
154
+ assert [] == list(nx.k_edge_subgraphs(G, k=5))
155
+
156
+ G = nx.DiGraph()
157
+ assert [] == list(nx.k_edge_components(G, k=5))
158
+ assert [] == list(nx.k_edge_subgraphs(G, k=5))
159
+
160
+
161
+ def test_not_implemented():
162
+ G = nx.MultiGraph()
163
+ pytest.raises(nx.NetworkXNotImplemented, EdgeComponentAuxGraph.construct, G)
164
+ pytest.raises(nx.NetworkXNotImplemented, nx.k_edge_components, G, k=2)
165
+ pytest.raises(nx.NetworkXNotImplemented, nx.k_edge_subgraphs, G, k=2)
166
+ with pytest.raises(nx.NetworkXNotImplemented):
167
+ next(bridge_components(G))
168
+ with pytest.raises(nx.NetworkXNotImplemented):
169
+ next(bridge_components(nx.DiGraph()))
170
+
171
+
172
+ def test_general_k_edge_subgraph_quick_return():
173
+ # tests quick return optimization
174
+ G = nx.Graph()
175
+ G.add_node(0)
176
+ subgraphs = list(general_k_edge_subgraphs(G, k=1))
177
+ assert len(subgraphs) == 1
178
+ for subgraph in subgraphs:
179
+ assert subgraph.number_of_nodes() == 1
180
+
181
+ G.add_node(1)
182
+ subgraphs = list(general_k_edge_subgraphs(G, k=1))
183
+ assert len(subgraphs) == 2
184
+ for subgraph in subgraphs:
185
+ assert subgraph.number_of_nodes() == 1
186
+
187
+
188
+ # ----------------
189
+ # Undirected tests
190
+ # ----------------
191
+
192
+
193
+ def test_random_gnp():
194
+ # seeds = [1550709854, 1309423156, 4208992358, 2785630813, 1915069929]
195
+ seeds = [12, 13]
196
+
197
+ for seed in seeds:
198
+ G = nx.gnp_random_graph(20, 0.2, seed=seed)
199
+ _check_edge_connectivity(G)
200
+
201
+
202
+ def test_configuration():
203
+ # seeds = [2718183590, 2470619828, 1694705158, 3001036531, 2401251497]
204
+ seeds = [14, 15]
205
+ for seed in seeds:
206
+ deg_seq = nx.random_powerlaw_tree_sequence(20, seed=seed, tries=5000)
207
+ G = nx.Graph(nx.configuration_model(deg_seq, seed=seed))
208
+ G.remove_edges_from(nx.selfloop_edges(G))
209
+ _check_edge_connectivity(G)
210
+
211
+
212
+ def test_shell():
213
+ # seeds = [2057382236, 3331169846, 1840105863, 476020778, 2247498425]
214
+ seeds = [20]
215
+ for seed in seeds:
216
+ constructor = [(12, 70, 0.8), (15, 40, 0.6)]
217
+ G = nx.random_shell_graph(constructor, seed=seed)
218
+ _check_edge_connectivity(G)
219
+
220
+
221
+ def test_karate():
222
+ G = nx.karate_club_graph()
223
+ _check_edge_connectivity(G)
224
+
225
+
226
+ def test_tarjan_bridge():
227
+ # graph from tarjan paper
228
+ # RE Tarjan - "A note on finding the bridges of a graph"
229
+ # Information Processing Letters, 1974 - Elsevier
230
+ # doi:10.1016/0020-0190(74)90003-9.
231
+ # define 2-connected components and bridges
232
+ ccs = [
233
+ (1, 2, 4, 3, 1, 4),
234
+ (5, 6, 7, 5),
235
+ (8, 9, 10, 8),
236
+ (17, 18, 16, 15, 17),
237
+ (11, 12, 14, 13, 11, 14),
238
+ ]
239
+ bridges = [(4, 8), (3, 5), (3, 17)]
240
+ G = nx.Graph(it.chain(*(pairwise(path) for path in ccs + bridges)))
241
+ _check_edge_connectivity(G)
242
+
243
+
244
+ def test_bridge_cc():
245
+ # define 2-connected components and bridges
246
+ cc2 = [(1, 2, 4, 3, 1, 4), (8, 9, 10, 8), (11, 12, 13, 11)]
247
+ bridges = [(4, 8), (3, 5), (20, 21), (22, 23, 24)]
248
+ G = nx.Graph(it.chain(*(pairwise(path) for path in cc2 + bridges)))
249
+ bridge_ccs = fset(bridge_components(G))
250
+ target_ccs = fset(
251
+ [{1, 2, 3, 4}, {5}, {8, 9, 10}, {11, 12, 13}, {20}, {21}, {22}, {23}, {24}]
252
+ )
253
+ assert bridge_ccs == target_ccs
254
+ _check_edge_connectivity(G)
255
+
256
+
257
+ def test_undirected_aux_graph():
258
+ # Graph similar to the one in
259
+ # http://journals.plos.org/plosone/article?id=10.1371/journal.pone.0136264
260
+ a, b, c, d, e, f, g, h, i = "abcdefghi"
261
+ paths = [
262
+ (a, d, b, f, c),
263
+ (a, e, b),
264
+ (a, e, b, c, g, b, a),
265
+ (c, b),
266
+ (f, g, f),
267
+ (h, i),
268
+ ]
269
+ G = nx.Graph(it.chain(*[pairwise(path) for path in paths]))
270
+ aux_graph = EdgeComponentAuxGraph.construct(G)
271
+
272
+ components_1 = fset(aux_graph.k_edge_subgraphs(k=1))
273
+ target_1 = fset([{a, b, c, d, e, f, g}, {h, i}])
274
+ assert target_1 == components_1
275
+
276
+ # Check that the undirected case for k=1 agrees with CCs
277
+ alt_1 = fset(nx.k_edge_subgraphs(G, k=1))
278
+ assert alt_1 == components_1
279
+
280
+ components_2 = fset(aux_graph.k_edge_subgraphs(k=2))
281
+ target_2 = fset([{a, b, c, d, e, f, g}, {h}, {i}])
282
+ assert target_2 == components_2
283
+
284
+ # Check that the undirected case for k=2 agrees with bridge components
285
+ alt_2 = fset(nx.k_edge_subgraphs(G, k=2))
286
+ assert alt_2 == components_2
287
+
288
+ components_3 = fset(aux_graph.k_edge_subgraphs(k=3))
289
+ target_3 = fset([{a}, {b, c, f, g}, {d}, {e}, {h}, {i}])
290
+ assert target_3 == components_3
291
+
292
+ components_4 = fset(aux_graph.k_edge_subgraphs(k=4))
293
+ target_4 = fset([{a}, {b}, {c}, {d}, {e}, {f}, {g}, {h}, {i}])
294
+ assert target_4 == components_4
295
+
296
+ _check_edge_connectivity(G)
297
+
298
+
299
+ def test_local_subgraph_difference():
300
+ paths = [
301
+ (11, 12, 13, 14, 11, 13, 14, 12), # first 4-clique
302
+ (21, 22, 23, 24, 21, 23, 24, 22), # second 4-clique
303
+ # paths connecting each node of the 4 cliques
304
+ (11, 101, 21),
305
+ (12, 102, 22),
306
+ (13, 103, 23),
307
+ (14, 104, 24),
308
+ ]
309
+ G = nx.Graph(it.chain(*[pairwise(path) for path in paths]))
310
+ aux_graph = EdgeComponentAuxGraph.construct(G)
311
+
312
+ # Each clique is returned separately in k-edge-subgraphs
313
+ subgraph_ccs = fset(aux_graph.k_edge_subgraphs(3))
314
+ subgraph_target = fset(
315
+ [{101}, {102}, {103}, {104}, {21, 22, 23, 24}, {11, 12, 13, 14}]
316
+ )
317
+ assert subgraph_ccs == subgraph_target
318
+
319
+ # But in k-edge-ccs they are returned together
320
+ # because they are locally 3-edge-connected
321
+ local_ccs = fset(aux_graph.k_edge_components(3))
322
+ local_target = fset([{101}, {102}, {103}, {104}, {11, 12, 13, 14, 21, 22, 23, 24}])
323
+ assert local_ccs == local_target
324
+
325
+
326
+ def test_local_subgraph_difference_directed():
327
+ dipaths = [(1, 2, 3, 4, 1), (1, 3, 1)]
328
+ G = nx.DiGraph(it.chain(*[pairwise(path) for path in dipaths]))
329
+
330
+ assert fset(nx.k_edge_components(G, k=1)) == fset(nx.k_edge_subgraphs(G, k=1))
331
+
332
+ # Unlike undirected graphs, when k=2, for directed graphs there is a case
333
+ # where the k-edge-ccs are not the same as the k-edge-subgraphs.
334
+ # (in directed graphs ccs and subgraphs are the same when k=2)
335
+ assert fset(nx.k_edge_components(G, k=2)) != fset(nx.k_edge_subgraphs(G, k=2))
336
+
337
+ assert fset(nx.k_edge_components(G, k=3)) == fset(nx.k_edge_subgraphs(G, k=3))
338
+
339
+ _check_edge_connectivity(G)
340
+
341
+
342
+ def test_triangles():
343
+ paths = [
344
+ (11, 12, 13, 11), # first 3-clique
345
+ (21, 22, 23, 21), # second 3-clique
346
+ (11, 21), # connected by an edge
347
+ ]
348
+ G = nx.Graph(it.chain(*[pairwise(path) for path in paths]))
349
+
350
+ # subgraph and ccs are the same in all cases here
351
+ assert fset(nx.k_edge_components(G, k=1)) == fset(nx.k_edge_subgraphs(G, k=1))
352
+
353
+ assert fset(nx.k_edge_components(G, k=2)) == fset(nx.k_edge_subgraphs(G, k=2))
354
+
355
+ assert fset(nx.k_edge_components(G, k=3)) == fset(nx.k_edge_subgraphs(G, k=3))
356
+
357
+ _check_edge_connectivity(G)
358
+
359
+
360
+ def test_four_clique():
361
+ paths = [
362
+ (11, 12, 13, 14, 11, 13, 14, 12), # first 4-clique
363
+ (21, 22, 23, 24, 21, 23, 24, 22), # second 4-clique
364
+ # paths connecting the 4 cliques such that they are
365
+ # 3-connected in G, but not in the subgraph.
366
+ # Case where the nodes bridging them do not have degree less than 3.
367
+ (100, 13),
368
+ (12, 100, 22),
369
+ (13, 200, 23),
370
+ (14, 300, 24),
371
+ ]
372
+ G = nx.Graph(it.chain(*[pairwise(path) for path in paths]))
373
+
374
+ # The subgraphs and ccs are different for k=3
375
+ local_ccs = fset(nx.k_edge_components(G, k=3))
376
+ subgraphs = fset(nx.k_edge_subgraphs(G, k=3))
377
+ assert local_ccs != subgraphs
378
+
379
+ # The cliques ares in the same cc
380
+ clique1 = frozenset(paths[0])
381
+ clique2 = frozenset(paths[1])
382
+ assert clique1.union(clique2).union({100}) in local_ccs
383
+
384
+ # but different subgraphs
385
+ assert clique1 in subgraphs
386
+ assert clique2 in subgraphs
387
+
388
+ assert G.degree(100) == 3
389
+
390
+ _check_edge_connectivity(G)
391
+
392
+
393
+ def test_five_clique():
394
+ # Make a graph that can be disconnected less than 4 edges, but no node has
395
+ # degree less than 4.
396
+ G = nx.disjoint_union(nx.complete_graph(5), nx.complete_graph(5))
397
+ paths = [
398
+ # add aux-connections
399
+ (1, 100, 6),
400
+ (2, 100, 7),
401
+ (3, 200, 8),
402
+ (4, 200, 100),
403
+ ]
404
+ G.add_edges_from(it.chain(*[pairwise(path) for path in paths]))
405
+ assert min(dict(nx.degree(G)).values()) == 4
406
+
407
+ # For k=3 they are the same
408
+ assert fset(nx.k_edge_components(G, k=3)) == fset(nx.k_edge_subgraphs(G, k=3))
409
+
410
+ # For k=4 they are the different
411
+ # the aux nodes are in the same CC as clique 1 but no the same subgraph
412
+ assert fset(nx.k_edge_components(G, k=4)) != fset(nx.k_edge_subgraphs(G, k=4))
413
+
414
+ # For k=5 they are not the same
415
+ assert fset(nx.k_edge_components(G, k=5)) != fset(nx.k_edge_subgraphs(G, k=5))
416
+
417
+ # For k=6 they are the same
418
+ assert fset(nx.k_edge_components(G, k=6)) == fset(nx.k_edge_subgraphs(G, k=6))
419
+ _check_edge_connectivity(G)
420
+
421
+
422
+ # ----------------
423
+ # Undirected tests
424
+ # ----------------
425
+
426
+
427
+ def test_directed_aux_graph():
428
+ # Graph similar to the one in
429
+ # http://journals.plos.org/plosone/article?id=10.1371/journal.pone.0136264
430
+ a, b, c, d, e, f, g, h, i = "abcdefghi"
431
+ dipaths = [
432
+ (a, d, b, f, c),
433
+ (a, e, b),
434
+ (a, e, b, c, g, b, a),
435
+ (c, b),
436
+ (f, g, f),
437
+ (h, i),
438
+ ]
439
+ G = nx.DiGraph(it.chain(*[pairwise(path) for path in dipaths]))
440
+ aux_graph = EdgeComponentAuxGraph.construct(G)
441
+
442
+ components_1 = fset(aux_graph.k_edge_subgraphs(k=1))
443
+ target_1 = fset([{a, b, c, d, e, f, g}, {h}, {i}])
444
+ assert target_1 == components_1
445
+
446
+ # Check that the directed case for k=1 agrees with SCCs
447
+ alt_1 = fset(nx.strongly_connected_components(G))
448
+ assert alt_1 == components_1
449
+
450
+ components_2 = fset(aux_graph.k_edge_subgraphs(k=2))
451
+ target_2 = fset([{i}, {e}, {d}, {b, c, f, g}, {h}, {a}])
452
+ assert target_2 == components_2
453
+
454
+ components_3 = fset(aux_graph.k_edge_subgraphs(k=3))
455
+ target_3 = fset([{a}, {b}, {c}, {d}, {e}, {f}, {g}, {h}, {i}])
456
+ assert target_3 == components_3
457
+
458
+
459
+ def test_random_gnp_directed():
460
+ # seeds = [3894723670, 500186844, 267231174, 2181982262, 1116750056]
461
+ seeds = [21]
462
+ for seed in seeds:
463
+ G = nx.gnp_random_graph(20, 0.2, directed=True, seed=seed)
464
+ _check_edge_connectivity(G)
465
+
466
+
467
+ def test_configuration_directed():
468
+ # seeds = [671221681, 2403749451, 124433910, 672335939, 1193127215]
469
+ seeds = [67]
470
+ for seed in seeds:
471
+ deg_seq = nx.random_powerlaw_tree_sequence(20, seed=seed, tries=5000)
472
+ G = nx.DiGraph(nx.configuration_model(deg_seq, seed=seed))
473
+ G.remove_edges_from(nx.selfloop_edges(G))
474
+ _check_edge_connectivity(G)
475
+
476
+
477
+ def test_shell_directed():
478
+ # seeds = [3134027055, 4079264063, 1350769518, 1405643020, 530038094]
479
+ seeds = [31]
480
+ for seed in seeds:
481
+ constructor = [(12, 70, 0.8), (15, 40, 0.6)]
482
+ G = nx.random_shell_graph(constructor, seed=seed).to_directed()
483
+ _check_edge_connectivity(G)
484
+
485
+
486
+ def test_karate_directed():
487
+ G = nx.karate_club_graph().to_directed()
488
+ _check_edge_connectivity(G)
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/test_kcomponents.py ADDED
@@ -0,0 +1,296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Test for Moody and White k-components algorithm
2
+ import pytest
3
+
4
+ import networkx as nx
5
+ from networkx.algorithms.connectivity.kcomponents import (
6
+ _consolidate,
7
+ build_k_number_dict,
8
+ )
9
+
10
+ ##
11
+ # A nice synthetic graph
12
+ ##
13
+
14
+
15
+ def torrents_and_ferraro_graph():
16
+ # Graph from https://arxiv.org/pdf/1503.04476v1 p.26
17
+ G = nx.convert_node_labels_to_integers(
18
+ nx.grid_graph([5, 5]), label_attribute="labels"
19
+ )
20
+ rlabels = nx.get_node_attributes(G, "labels")
21
+ labels = {v: k for k, v in rlabels.items()}
22
+
23
+ for nodes in [(labels[(0, 4)], labels[(1, 4)]), (labels[(3, 4)], labels[(4, 4)])]:
24
+ new_node = G.order() + 1
25
+ # Petersen graph is triconnected
26
+ P = nx.petersen_graph()
27
+ G = nx.disjoint_union(G, P)
28
+ # Add two edges between the grid and P
29
+ G.add_edge(new_node + 1, nodes[0])
30
+ G.add_edge(new_node, nodes[1])
31
+ # K5 is 4-connected
32
+ K = nx.complete_graph(5)
33
+ G = nx.disjoint_union(G, K)
34
+ # Add three edges between P and K5
35
+ G.add_edge(new_node + 2, new_node + 11)
36
+ G.add_edge(new_node + 3, new_node + 12)
37
+ G.add_edge(new_node + 4, new_node + 13)
38
+ # Add another K5 sharing a node
39
+ G = nx.disjoint_union(G, K)
40
+ nbrs = G[new_node + 10]
41
+ G.remove_node(new_node + 10)
42
+ for nbr in nbrs:
43
+ G.add_edge(new_node + 17, nbr)
44
+ # This edge makes the graph biconnected; it's
45
+ # needed because K5s share only one node.
46
+ G.add_edge(new_node + 16, new_node + 8)
47
+
48
+ for nodes in [(labels[(0, 0)], labels[(1, 0)]), (labels[(3, 0)], labels[(4, 0)])]:
49
+ new_node = G.order() + 1
50
+ # Petersen graph is triconnected
51
+ P = nx.petersen_graph()
52
+ G = nx.disjoint_union(G, P)
53
+ # Add two edges between the grid and P
54
+ G.add_edge(new_node + 1, nodes[0])
55
+ G.add_edge(new_node, nodes[1])
56
+ # K5 is 4-connected
57
+ K = nx.complete_graph(5)
58
+ G = nx.disjoint_union(G, K)
59
+ # Add three edges between P and K5
60
+ G.add_edge(new_node + 2, new_node + 11)
61
+ G.add_edge(new_node + 3, new_node + 12)
62
+ G.add_edge(new_node + 4, new_node + 13)
63
+ # Add another K5 sharing two nodes
64
+ G = nx.disjoint_union(G, K)
65
+ nbrs = G[new_node + 10]
66
+ G.remove_node(new_node + 10)
67
+ for nbr in nbrs:
68
+ G.add_edge(new_node + 17, nbr)
69
+ nbrs2 = G[new_node + 9]
70
+ G.remove_node(new_node + 9)
71
+ for nbr in nbrs2:
72
+ G.add_edge(new_node + 18, nbr)
73
+ return G
74
+
75
+
76
+ def test_directed():
77
+ with pytest.raises(nx.NetworkXNotImplemented):
78
+ G = nx.gnp_random_graph(10, 0.2, directed=True, seed=42)
79
+ nx.k_components(G)
80
+
81
+
82
+ # Helper function
83
+ def _check_connectivity(G, k_components):
84
+ for k, components in k_components.items():
85
+ if k < 3:
86
+ continue
87
+ # check that k-components have node connectivity >= k.
88
+ for component in components:
89
+ C = G.subgraph(component)
90
+ K = nx.node_connectivity(C)
91
+ assert K >= k
92
+
93
+
94
+ @pytest.mark.slow
95
+ def test_torrents_and_ferraro_graph():
96
+ G = torrents_and_ferraro_graph()
97
+ result = nx.k_components(G)
98
+ _check_connectivity(G, result)
99
+
100
+ # In this example graph there are 8 3-components, 4 with 15 nodes
101
+ # and 4 with 5 nodes.
102
+ assert len(result[3]) == 8
103
+ assert len([c for c in result[3] if len(c) == 15]) == 4
104
+ assert len([c for c in result[3] if len(c) == 5]) == 4
105
+ # There are also 8 4-components all with 5 nodes.
106
+ assert len(result[4]) == 8
107
+ assert all(len(c) == 5 for c in result[4])
108
+
109
+
110
+ @pytest.mark.slow
111
+ def test_random_gnp():
112
+ G = nx.gnp_random_graph(50, 0.2, seed=42)
113
+ result = nx.k_components(G)
114
+ _check_connectivity(G, result)
115
+
116
+
117
+ @pytest.mark.slow
118
+ def test_shell():
119
+ constructor = [(20, 80, 0.8), (80, 180, 0.6)]
120
+ G = nx.random_shell_graph(constructor, seed=42)
121
+ result = nx.k_components(G)
122
+ _check_connectivity(G, result)
123
+
124
+
125
+ def test_configuration():
126
+ deg_seq = nx.random_powerlaw_tree_sequence(100, tries=5, seed=72)
127
+ G = nx.Graph(nx.configuration_model(deg_seq))
128
+ G.remove_edges_from(nx.selfloop_edges(G))
129
+ result = nx.k_components(G)
130
+ _check_connectivity(G, result)
131
+
132
+
133
+ def test_karate():
134
+ G = nx.karate_club_graph()
135
+ result = nx.k_components(G)
136
+ _check_connectivity(G, result)
137
+
138
+
139
+ def test_karate_component_number():
140
+ karate_k_num = {
141
+ 0: 4,
142
+ 1: 4,
143
+ 2: 4,
144
+ 3: 4,
145
+ 4: 3,
146
+ 5: 3,
147
+ 6: 3,
148
+ 7: 4,
149
+ 8: 4,
150
+ 9: 2,
151
+ 10: 3,
152
+ 11: 1,
153
+ 12: 2,
154
+ 13: 4,
155
+ 14: 2,
156
+ 15: 2,
157
+ 16: 2,
158
+ 17: 2,
159
+ 18: 2,
160
+ 19: 3,
161
+ 20: 2,
162
+ 21: 2,
163
+ 22: 2,
164
+ 23: 3,
165
+ 24: 3,
166
+ 25: 3,
167
+ 26: 2,
168
+ 27: 3,
169
+ 28: 3,
170
+ 29: 3,
171
+ 30: 4,
172
+ 31: 3,
173
+ 32: 4,
174
+ 33: 4,
175
+ }
176
+ G = nx.karate_club_graph()
177
+ k_components = nx.k_components(G)
178
+ k_num = build_k_number_dict(k_components)
179
+ assert karate_k_num == k_num
180
+
181
+
182
+ def test_davis_southern_women():
183
+ G = nx.davis_southern_women_graph()
184
+ result = nx.k_components(G)
185
+ _check_connectivity(G, result)
186
+
187
+
188
+ def test_davis_southern_women_detail_3_and_4():
189
+ solution = {
190
+ 3: [
191
+ {
192
+ "Nora Fayette",
193
+ "E10",
194
+ "Myra Liddel",
195
+ "E12",
196
+ "E14",
197
+ "Frances Anderson",
198
+ "Evelyn Jefferson",
199
+ "Ruth DeSand",
200
+ "Helen Lloyd",
201
+ "Eleanor Nye",
202
+ "E9",
203
+ "E8",
204
+ "E5",
205
+ "E4",
206
+ "E7",
207
+ "E6",
208
+ "E1",
209
+ "Verne Sanderson",
210
+ "E3",
211
+ "E2",
212
+ "Theresa Anderson",
213
+ "Pearl Oglethorpe",
214
+ "Katherina Rogers",
215
+ "Brenda Rogers",
216
+ "E13",
217
+ "Charlotte McDowd",
218
+ "Sylvia Avondale",
219
+ "Laura Mandeville",
220
+ }
221
+ ],
222
+ 4: [
223
+ {
224
+ "Nora Fayette",
225
+ "E10",
226
+ "Verne Sanderson",
227
+ "E12",
228
+ "Frances Anderson",
229
+ "Evelyn Jefferson",
230
+ "Ruth DeSand",
231
+ "Helen Lloyd",
232
+ "Eleanor Nye",
233
+ "E9",
234
+ "E8",
235
+ "E5",
236
+ "E4",
237
+ "E7",
238
+ "E6",
239
+ "Myra Liddel",
240
+ "E3",
241
+ "Theresa Anderson",
242
+ "Katherina Rogers",
243
+ "Brenda Rogers",
244
+ "Charlotte McDowd",
245
+ "Sylvia Avondale",
246
+ "Laura Mandeville",
247
+ }
248
+ ],
249
+ }
250
+ G = nx.davis_southern_women_graph()
251
+ result = nx.k_components(G)
252
+ for k, components in result.items():
253
+ if k < 3:
254
+ continue
255
+ assert len(components) == len(solution[k])
256
+ for component in components:
257
+ assert component in solution[k]
258
+
259
+
260
+ def test_set_consolidation_rosettacode():
261
+ # Tests from http://rosettacode.org/wiki/Set_consolidation
262
+ def list_of_sets_equal(result, solution):
263
+ assert {frozenset(s) for s in result} == {frozenset(s) for s in solution}
264
+
265
+ question = [{"A", "B"}, {"C", "D"}]
266
+ solution = [{"A", "B"}, {"C", "D"}]
267
+ list_of_sets_equal(_consolidate(question, 1), solution)
268
+ question = [{"A", "B"}, {"B", "C"}]
269
+ solution = [{"A", "B", "C"}]
270
+ list_of_sets_equal(_consolidate(question, 1), solution)
271
+ question = [{"A", "B"}, {"C", "D"}, {"D", "B"}]
272
+ solution = [{"A", "C", "B", "D"}]
273
+ list_of_sets_equal(_consolidate(question, 1), solution)
274
+ question = [{"H", "I", "K"}, {"A", "B"}, {"C", "D"}, {"D", "B"}, {"F", "G", "H"}]
275
+ solution = [{"A", "C", "B", "D"}, {"G", "F", "I", "H", "K"}]
276
+ list_of_sets_equal(_consolidate(question, 1), solution)
277
+ question = [
278
+ {"A", "H"},
279
+ {"H", "I", "K"},
280
+ {"A", "B"},
281
+ {"C", "D"},
282
+ {"D", "B"},
283
+ {"F", "G", "H"},
284
+ ]
285
+ solution = [{"A", "C", "B", "D", "G", "F", "I", "H", "K"}]
286
+ list_of_sets_equal(_consolidate(question, 1), solution)
287
+ question = [
288
+ {"H", "I", "K"},
289
+ {"A", "B"},
290
+ {"C", "D"},
291
+ {"D", "B"},
292
+ {"F", "G", "H"},
293
+ {"A", "H"},
294
+ ]
295
+ solution = [{"A", "C", "B", "D", "G", "F", "I", "H", "K"}]
296
+ list_of_sets_equal(_consolidate(question, 1), solution)
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/connectivity/tests/test_kcutsets.py ADDED
@@ -0,0 +1,266 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Jordi Torrents
2
+ # Test for k-cutsets
3
+ import itertools
4
+
5
+ import pytest
6
+
7
+ import networkx as nx
8
+ from networkx.algorithms import flow
9
+ from networkx.algorithms.connectivity.kcutsets import _is_separating_set
10
+
11
+ MAX_CUTSETS_TO_TEST = 4 # originally 100. cut to decrease testing time
12
+
13
+ flow_funcs = [
14
+ flow.boykov_kolmogorov,
15
+ flow.dinitz,
16
+ flow.edmonds_karp,
17
+ flow.preflow_push,
18
+ flow.shortest_augmenting_path,
19
+ ]
20
+
21
+
22
+ ##
23
+ # Some nice synthetic graphs
24
+ ##
25
+ def graph_example_1():
26
+ G = nx.convert_node_labels_to_integers(
27
+ nx.grid_graph([5, 5]), label_attribute="labels"
28
+ )
29
+ rlabels = nx.get_node_attributes(G, "labels")
30
+ labels = {v: k for k, v in rlabels.items()}
31
+
32
+ for nodes in [
33
+ (labels[(0, 0)], labels[(1, 0)]),
34
+ (labels[(0, 4)], labels[(1, 4)]),
35
+ (labels[(3, 0)], labels[(4, 0)]),
36
+ (labels[(3, 4)], labels[(4, 4)]),
37
+ ]:
38
+ new_node = G.order() + 1
39
+ # Petersen graph is triconnected
40
+ P = nx.petersen_graph()
41
+ G = nx.disjoint_union(G, P)
42
+ # Add two edges between the grid and P
43
+ G.add_edge(new_node + 1, nodes[0])
44
+ G.add_edge(new_node, nodes[1])
45
+ # K5 is 4-connected
46
+ K = nx.complete_graph(5)
47
+ G = nx.disjoint_union(G, K)
48
+ # Add three edges between P and K5
49
+ G.add_edge(new_node + 2, new_node + 11)
50
+ G.add_edge(new_node + 3, new_node + 12)
51
+ G.add_edge(new_node + 4, new_node + 13)
52
+ # Add another K5 sharing a node
53
+ G = nx.disjoint_union(G, K)
54
+ nbrs = G[new_node + 10]
55
+ G.remove_node(new_node + 10)
56
+ for nbr in nbrs:
57
+ G.add_edge(new_node + 17, nbr)
58
+ G.add_edge(new_node + 16, new_node + 5)
59
+ return G
60
+
61
+
62
+ def torrents_and_ferraro_graph():
63
+ G = nx.convert_node_labels_to_integers(
64
+ nx.grid_graph([5, 5]), label_attribute="labels"
65
+ )
66
+ rlabels = nx.get_node_attributes(G, "labels")
67
+ labels = {v: k for k, v in rlabels.items()}
68
+
69
+ for nodes in [(labels[(0, 4)], labels[(1, 4)]), (labels[(3, 4)], labels[(4, 4)])]:
70
+ new_node = G.order() + 1
71
+ # Petersen graph is triconnected
72
+ P = nx.petersen_graph()
73
+ G = nx.disjoint_union(G, P)
74
+ # Add two edges between the grid and P
75
+ G.add_edge(new_node + 1, nodes[0])
76
+ G.add_edge(new_node, nodes[1])
77
+ # K5 is 4-connected
78
+ K = nx.complete_graph(5)
79
+ G = nx.disjoint_union(G, K)
80
+ # Add three edges between P and K5
81
+ G.add_edge(new_node + 2, new_node + 11)
82
+ G.add_edge(new_node + 3, new_node + 12)
83
+ G.add_edge(new_node + 4, new_node + 13)
84
+ # Add another K5 sharing a node
85
+ G = nx.disjoint_union(G, K)
86
+ nbrs = G[new_node + 10]
87
+ G.remove_node(new_node + 10)
88
+ for nbr in nbrs:
89
+ G.add_edge(new_node + 17, nbr)
90
+ # Commenting this makes the graph not biconnected !!
91
+ # This stupid mistake make one reviewer very angry :P
92
+ G.add_edge(new_node + 16, new_node + 8)
93
+
94
+ for nodes in [(labels[(0, 0)], labels[(1, 0)]), (labels[(3, 0)], labels[(4, 0)])]:
95
+ new_node = G.order() + 1
96
+ # Petersen graph is triconnected
97
+ P = nx.petersen_graph()
98
+ G = nx.disjoint_union(G, P)
99
+ # Add two edges between the grid and P
100
+ G.add_edge(new_node + 1, nodes[0])
101
+ G.add_edge(new_node, nodes[1])
102
+ # K5 is 4-connected
103
+ K = nx.complete_graph(5)
104
+ G = nx.disjoint_union(G, K)
105
+ # Add three edges between P and K5
106
+ G.add_edge(new_node + 2, new_node + 11)
107
+ G.add_edge(new_node + 3, new_node + 12)
108
+ G.add_edge(new_node + 4, new_node + 13)
109
+ # Add another K5 sharing two nodes
110
+ G = nx.disjoint_union(G, K)
111
+ nbrs = G[new_node + 10]
112
+ G.remove_node(new_node + 10)
113
+ for nbr in nbrs:
114
+ G.add_edge(new_node + 17, nbr)
115
+ nbrs2 = G[new_node + 9]
116
+ G.remove_node(new_node + 9)
117
+ for nbr in nbrs2:
118
+ G.add_edge(new_node + 18, nbr)
119
+ return G
120
+
121
+
122
+ # Helper function
123
+ def _check_separating_sets(G):
124
+ for cc in nx.connected_components(G):
125
+ if len(cc) < 3:
126
+ continue
127
+ Gc = G.subgraph(cc)
128
+ node_conn = nx.node_connectivity(Gc)
129
+ all_cuts = nx.all_node_cuts(Gc)
130
+ # Only test a limited number of cut sets to reduce test time.
131
+ for cut in itertools.islice(all_cuts, MAX_CUTSETS_TO_TEST):
132
+ assert node_conn == len(cut)
133
+ assert not nx.is_connected(nx.restricted_view(G, cut, []))
134
+
135
+
136
+ @pytest.mark.slow
137
+ def test_torrents_and_ferraro_graph():
138
+ G = torrents_and_ferraro_graph()
139
+ _check_separating_sets(G)
140
+
141
+
142
+ def test_example_1():
143
+ G = graph_example_1()
144
+ _check_separating_sets(G)
145
+
146
+
147
+ def test_random_gnp():
148
+ G = nx.gnp_random_graph(100, 0.1, seed=42)
149
+ _check_separating_sets(G)
150
+
151
+
152
+ def test_shell():
153
+ constructor = [(20, 80, 0.8), (80, 180, 0.6)]
154
+ G = nx.random_shell_graph(constructor, seed=42)
155
+ _check_separating_sets(G)
156
+
157
+
158
+ def test_configuration():
159
+ deg_seq = nx.random_powerlaw_tree_sequence(100, tries=5, seed=72)
160
+ G = nx.Graph(nx.configuration_model(deg_seq))
161
+ G.remove_edges_from(nx.selfloop_edges(G))
162
+ _check_separating_sets(G)
163
+
164
+
165
+ def test_karate():
166
+ G = nx.karate_club_graph()
167
+ _check_separating_sets(G)
168
+
169
+
170
+ def _generate_no_biconnected(max_attempts=50):
171
+ attempts = 0
172
+ while True:
173
+ G = nx.fast_gnp_random_graph(100, 0.0575, seed=42)
174
+ if nx.is_connected(G) and not nx.is_biconnected(G):
175
+ attempts = 0
176
+ yield G
177
+ else:
178
+ if attempts >= max_attempts:
179
+ msg = f"Tried {attempts} times: no suitable Graph."
180
+ raise Exception(msg)
181
+ else:
182
+ attempts += 1
183
+
184
+
185
+ def test_articulation_points():
186
+ Ggen = _generate_no_biconnected()
187
+ for i in range(1): # change 1 to 3 or more for more realizations.
188
+ G = next(Ggen)
189
+ articulation_points = [{a} for a in nx.articulation_points(G)]
190
+ for cut in nx.all_node_cuts(G):
191
+ assert cut in articulation_points
192
+
193
+
194
+ def test_grid_2d_graph():
195
+ # All minimum node cuts of a 2d grid
196
+ # are the four pairs of nodes that are
197
+ # neighbors of the four corner nodes.
198
+ G = nx.grid_2d_graph(5, 5)
199
+ solution = [{(0, 1), (1, 0)}, {(3, 0), (4, 1)}, {(3, 4), (4, 3)}, {(0, 3), (1, 4)}]
200
+ for cut in nx.all_node_cuts(G):
201
+ assert cut in solution
202
+
203
+
204
+ def test_disconnected_graph():
205
+ G = nx.fast_gnp_random_graph(100, 0.01, seed=42)
206
+ cuts = nx.all_node_cuts(G)
207
+ pytest.raises(nx.NetworkXError, next, cuts)
208
+
209
+
210
+ @pytest.mark.slow
211
+ def test_alternative_flow_functions():
212
+ graphs = [nx.grid_2d_graph(4, 4), nx.cycle_graph(5)]
213
+ for G in graphs:
214
+ node_conn = nx.node_connectivity(G)
215
+ for flow_func in flow_funcs:
216
+ all_cuts = nx.all_node_cuts(G, flow_func=flow_func)
217
+ # Only test a limited number of cut sets to reduce test time.
218
+ for cut in itertools.islice(all_cuts, MAX_CUTSETS_TO_TEST):
219
+ assert node_conn == len(cut)
220
+ assert not nx.is_connected(nx.restricted_view(G, cut, []))
221
+
222
+
223
+ def test_is_separating_set_complete_graph():
224
+ G = nx.complete_graph(5)
225
+ assert _is_separating_set(G, {0, 1, 2, 3})
226
+
227
+
228
+ def test_is_separating_set():
229
+ for i in [5, 10, 15]:
230
+ G = nx.star_graph(i)
231
+ max_degree_node = max(G, key=G.degree)
232
+ assert _is_separating_set(G, {max_degree_node})
233
+
234
+
235
+ def test_non_repeated_cuts():
236
+ # The algorithm was repeating the cut {0, 1} for the giant biconnected
237
+ # component of the Karate club graph.
238
+ K = nx.karate_club_graph()
239
+ bcc = max(list(nx.biconnected_components(K)), key=len)
240
+ G = K.subgraph(bcc)
241
+ solution = [{32, 33}, {2, 33}, {0, 3}, {0, 1}, {29, 33}]
242
+ cuts = list(nx.all_node_cuts(G))
243
+ if len(solution) != len(cuts):
244
+ print(f"Solution: {solution}")
245
+ print(f"Result: {cuts}")
246
+ assert len(solution) == len(cuts)
247
+ for cut in cuts:
248
+ assert cut in solution
249
+
250
+
251
+ def test_cycle_graph():
252
+ G = nx.cycle_graph(5)
253
+ solution = [{0, 2}, {0, 3}, {1, 3}, {1, 4}, {2, 4}]
254
+ cuts = list(nx.all_node_cuts(G))
255
+ assert len(solution) == len(cuts)
256
+ for cut in cuts:
257
+ assert cut in solution
258
+
259
+
260
+ def test_complete_graph():
261
+ G = nx.complete_graph(5)
262
+ solution = [{0, 1, 2, 3}, {0, 1, 2, 4}, {0, 1, 3, 4}, {0, 2, 3, 4}, {1, 2, 3, 4}]
263
+ cuts = list(nx.all_node_cuts(G))
264
+ assert len(solution) == len(cuts)
265
+ for cut in cuts:
266
+ assert cut in solution
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/__init__.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ from networkx.algorithms.shortest_paths.generic import *
2
+ from networkx.algorithms.shortest_paths.unweighted import *
3
+ from networkx.algorithms.shortest_paths.weighted import *
4
+ from networkx.algorithms.shortest_paths.astar import *
5
+ from networkx.algorithms.shortest_paths.dense import *
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (558 Bytes). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/__pycache__/astar.cpython-311.pyc ADDED
Binary file (7.82 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/__pycache__/dense.cpython-311.pyc ADDED
Binary file (9.79 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/__pycache__/generic.cpython-311.pyc ADDED
Binary file (27.1 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/__pycache__/weighted.cpython-311.pyc ADDED
Binary file (90.3 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/astar.py ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Shortest paths and path lengths using the A* ("A star") algorithm.
2
+ """
3
+ from heapq import heappop, heappush
4
+ from itertools import count
5
+
6
+ import networkx as nx
7
+ from networkx.algorithms.shortest_paths.weighted import _weight_function
8
+
9
+ __all__ = ["astar_path", "astar_path_length"]
10
+
11
+
12
+ @nx._dispatch(edge_attrs="weight", preserve_node_attrs="heuristic")
13
+ def astar_path(G, source, target, heuristic=None, weight="weight"):
14
+ """Returns a list of nodes in a shortest path between source and target
15
+ using the A* ("A-star") algorithm.
16
+
17
+ There may be more than one shortest path. This returns only one.
18
+
19
+ Parameters
20
+ ----------
21
+ G : NetworkX graph
22
+
23
+ source : node
24
+ Starting node for path
25
+
26
+ target : node
27
+ Ending node for path
28
+
29
+ heuristic : function
30
+ A function to evaluate the estimate of the distance
31
+ from the a node to the target. The function takes
32
+ two nodes arguments and must return a number.
33
+ If the heuristic is inadmissible (if it might
34
+ overestimate the cost of reaching the goal from a node),
35
+ the result may not be a shortest path.
36
+ The algorithm does not support updating heuristic
37
+ values for the same node due to caching the first
38
+ heuristic calculation per node.
39
+
40
+ weight : string or function
41
+ If this is a string, then edge weights will be accessed via the
42
+ edge attribute with this key (that is, the weight of the edge
43
+ joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
44
+ such edge attribute exists, the weight of the edge is assumed to
45
+ be one.
46
+ If this is a function, the weight of an edge is the value
47
+ returned by the function. The function must accept exactly three
48
+ positional arguments: the two endpoints of an edge and the
49
+ dictionary of edge attributes for that edge. The function must
50
+ return a number or None to indicate a hidden edge.
51
+
52
+ Raises
53
+ ------
54
+ NetworkXNoPath
55
+ If no path exists between source and target.
56
+
57
+ Examples
58
+ --------
59
+ >>> G = nx.path_graph(5)
60
+ >>> print(nx.astar_path(G, 0, 4))
61
+ [0, 1, 2, 3, 4]
62
+ >>> G = nx.grid_graph(dim=[3, 3]) # nodes are two-tuples (x,y)
63
+ >>> nx.set_edge_attributes(G, {e: e[1][0] * 2 for e in G.edges()}, "cost")
64
+ >>> def dist(a, b):
65
+ ... (x1, y1) = a
66
+ ... (x2, y2) = b
67
+ ... return ((x1 - x2) ** 2 + (y1 - y2) ** 2) ** 0.5
68
+ >>> print(nx.astar_path(G, (0, 0), (2, 2), heuristic=dist, weight="cost"))
69
+ [(0, 0), (0, 1), (0, 2), (1, 2), (2, 2)]
70
+
71
+ Notes
72
+ -----
73
+ Edge weight attributes must be numerical.
74
+ Distances are calculated as sums of weighted edges traversed.
75
+
76
+ The weight function can be used to hide edges by returning None.
77
+ So ``weight = lambda u, v, d: 1 if d['color']=="red" else None``
78
+ will find the shortest red path.
79
+
80
+ See Also
81
+ --------
82
+ shortest_path, dijkstra_path
83
+
84
+ """
85
+ if source not in G or target not in G:
86
+ msg = f"Either source {source} or target {target} is not in G"
87
+ raise nx.NodeNotFound(msg)
88
+
89
+ if heuristic is None:
90
+ # The default heuristic is h=0 - same as Dijkstra's algorithm
91
+ def heuristic(u, v):
92
+ return 0
93
+
94
+ push = heappush
95
+ pop = heappop
96
+ weight = _weight_function(G, weight)
97
+
98
+ G_succ = G._adj # For speed-up (and works for both directed and undirected graphs)
99
+
100
+ # The queue stores priority, node, cost to reach, and parent.
101
+ # Uses Python heapq to keep in priority order.
102
+ # Add a counter to the queue to prevent the underlying heap from
103
+ # attempting to compare the nodes themselves. The hash breaks ties in the
104
+ # priority and is guaranteed unique for all nodes in the graph.
105
+ c = count()
106
+ queue = [(0, next(c), source, 0, None)]
107
+
108
+ # Maps enqueued nodes to distance of discovered paths and the
109
+ # computed heuristics to target. We avoid computing the heuristics
110
+ # more than once and inserting the node into the queue too many times.
111
+ enqueued = {}
112
+ # Maps explored nodes to parent closest to the source.
113
+ explored = {}
114
+
115
+ while queue:
116
+ # Pop the smallest item from queue.
117
+ _, __, curnode, dist, parent = pop(queue)
118
+
119
+ if curnode == target:
120
+ path = [curnode]
121
+ node = parent
122
+ while node is not None:
123
+ path.append(node)
124
+ node = explored[node]
125
+ path.reverse()
126
+ return path
127
+
128
+ if curnode in explored:
129
+ # Do not override the parent of starting node
130
+ if explored[curnode] is None:
131
+ continue
132
+
133
+ # Skip bad paths that were enqueued before finding a better one
134
+ qcost, h = enqueued[curnode]
135
+ if qcost < dist:
136
+ continue
137
+
138
+ explored[curnode] = parent
139
+
140
+ for neighbor, w in G_succ[curnode].items():
141
+ cost = weight(curnode, neighbor, w)
142
+ if cost is None:
143
+ continue
144
+ ncost = dist + cost
145
+ if neighbor in enqueued:
146
+ qcost, h = enqueued[neighbor]
147
+ # if qcost <= ncost, a less costly path from the
148
+ # neighbor to the source was already determined.
149
+ # Therefore, we won't attempt to push this neighbor
150
+ # to the queue
151
+ if qcost <= ncost:
152
+ continue
153
+ else:
154
+ h = heuristic(neighbor, target)
155
+ enqueued[neighbor] = ncost, h
156
+ push(queue, (ncost + h, next(c), neighbor, ncost, curnode))
157
+
158
+ raise nx.NetworkXNoPath(f"Node {target} not reachable from {source}")
159
+
160
+
161
+ @nx._dispatch(edge_attrs="weight", preserve_node_attrs="heuristic")
162
+ def astar_path_length(G, source, target, heuristic=None, weight="weight"):
163
+ """Returns the length of the shortest path between source and target using
164
+ the A* ("A-star") algorithm.
165
+
166
+ Parameters
167
+ ----------
168
+ G : NetworkX graph
169
+
170
+ source : node
171
+ Starting node for path
172
+
173
+ target : node
174
+ Ending node for path
175
+
176
+ heuristic : function
177
+ A function to evaluate the estimate of the distance
178
+ from the a node to the target. The function takes
179
+ two nodes arguments and must return a number.
180
+ If the heuristic is inadmissible (if it might
181
+ overestimate the cost of reaching the goal from a node),
182
+ the result may not be a shortest path.
183
+ The algorithm does not support updating heuristic
184
+ values for the same node due to caching the first
185
+ heuristic calculation per node.
186
+
187
+ weight : string or function
188
+ If this is a string, then edge weights will be accessed via the
189
+ edge attribute with this key (that is, the weight of the edge
190
+ joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
191
+ such edge attribute exists, the weight of the edge is assumed to
192
+ be one.
193
+ If this is a function, the weight of an edge is the value
194
+ returned by the function. The function must accept exactly three
195
+ positional arguments: the two endpoints of an edge and the
196
+ dictionary of edge attributes for that edge. The function must
197
+ return a number or None to indicate a hidden edge.
198
+ Raises
199
+ ------
200
+ NetworkXNoPath
201
+ If no path exists between source and target.
202
+
203
+ See Also
204
+ --------
205
+ astar_path
206
+
207
+ """
208
+ if source not in G or target not in G:
209
+ msg = f"Either source {source} or target {target} is not in G"
210
+ raise nx.NodeNotFound(msg)
211
+
212
+ weight = _weight_function(G, weight)
213
+ path = astar_path(G, source, target, heuristic, weight)
214
+ return sum(weight(u, v, G[u][v]) for u, v in zip(path[:-1], path[1:]))
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/dense.py ADDED
@@ -0,0 +1,256 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Floyd-Warshall algorithm for shortest paths.
2
+ """
3
+ import networkx as nx
4
+
5
+ __all__ = [
6
+ "floyd_warshall",
7
+ "floyd_warshall_predecessor_and_distance",
8
+ "reconstruct_path",
9
+ "floyd_warshall_numpy",
10
+ ]
11
+
12
+
13
+ @nx._dispatch(edge_attrs="weight")
14
+ def floyd_warshall_numpy(G, nodelist=None, weight="weight"):
15
+ """Find all-pairs shortest path lengths using Floyd's algorithm.
16
+
17
+ This algorithm for finding shortest paths takes advantage of
18
+ matrix representations of a graph and works well for dense
19
+ graphs where all-pairs shortest path lengths are desired.
20
+ The results are returned as a NumPy array, distance[i, j],
21
+ where i and j are the indexes of two nodes in nodelist.
22
+ The entry distance[i, j] is the distance along a shortest
23
+ path from i to j. If no path exists the distance is Inf.
24
+
25
+ Parameters
26
+ ----------
27
+ G : NetworkX graph
28
+
29
+ nodelist : list, optional (default=G.nodes)
30
+ The rows and columns are ordered by the nodes in nodelist.
31
+ If nodelist is None then the ordering is produced by G.nodes.
32
+ Nodelist should include all nodes in G.
33
+
34
+ weight: string, optional (default='weight')
35
+ Edge data key corresponding to the edge weight.
36
+
37
+ Returns
38
+ -------
39
+ distance : 2D numpy.ndarray
40
+ A numpy array of shortest path distances between nodes.
41
+ If there is no path between two nodes the value is Inf.
42
+
43
+ Examples
44
+ --------
45
+ >>> G = nx.DiGraph()
46
+ >>> G.add_weighted_edges_from([(0, 1, 5), (1, 2, 2), (2, 3, -3), (1, 3, 10), (3, 2, 8)])
47
+ >>> nx.floyd_warshall_numpy(G)
48
+ array([[ 0., 5., 7., 4.],
49
+ [inf, 0., 2., -1.],
50
+ [inf, inf, 0., -3.],
51
+ [inf, inf, 8., 0.]])
52
+
53
+ Notes
54
+ -----
55
+ Floyd's algorithm is appropriate for finding shortest paths in
56
+ dense graphs or graphs with negative weights when Dijkstra's
57
+ algorithm fails. This algorithm can still fail if there are negative
58
+ cycles. It has running time $O(n^3)$ with running space of $O(n^2)$.
59
+
60
+ Raises
61
+ ------
62
+ NetworkXError
63
+ If nodelist is not a list of the nodes in G.
64
+ """
65
+ import numpy as np
66
+
67
+ if nodelist is not None:
68
+ if not (len(nodelist) == len(G) == len(set(nodelist))):
69
+ raise nx.NetworkXError(
70
+ "nodelist must contain every node in G with no repeats."
71
+ "If you wanted a subgraph of G use G.subgraph(nodelist)"
72
+ )
73
+
74
+ # To handle cases when an edge has weight=0, we must make sure that
75
+ # nonedges are not given the value 0 as well.
76
+ A = nx.to_numpy_array(
77
+ G, nodelist, multigraph_weight=min, weight=weight, nonedge=np.inf
78
+ )
79
+ n, m = A.shape
80
+ np.fill_diagonal(A, 0) # diagonal elements should be zero
81
+ for i in range(n):
82
+ # The second term has the same shape as A due to broadcasting
83
+ A = np.minimum(A, A[i, :][np.newaxis, :] + A[:, i][:, np.newaxis])
84
+ return A
85
+
86
+
87
+ @nx._dispatch(edge_attrs="weight")
88
+ def floyd_warshall_predecessor_and_distance(G, weight="weight"):
89
+ """Find all-pairs shortest path lengths using Floyd's algorithm.
90
+
91
+ Parameters
92
+ ----------
93
+ G : NetworkX graph
94
+
95
+ weight: string, optional (default= 'weight')
96
+ Edge data key corresponding to the edge weight.
97
+
98
+ Returns
99
+ -------
100
+ predecessor,distance : dictionaries
101
+ Dictionaries, keyed by source and target, of predecessors and distances
102
+ in the shortest path.
103
+
104
+ Examples
105
+ --------
106
+ >>> G = nx.DiGraph()
107
+ >>> G.add_weighted_edges_from(
108
+ ... [
109
+ ... ("s", "u", 10),
110
+ ... ("s", "x", 5),
111
+ ... ("u", "v", 1),
112
+ ... ("u", "x", 2),
113
+ ... ("v", "y", 1),
114
+ ... ("x", "u", 3),
115
+ ... ("x", "v", 5),
116
+ ... ("x", "y", 2),
117
+ ... ("y", "s", 7),
118
+ ... ("y", "v", 6),
119
+ ... ]
120
+ ... )
121
+ >>> predecessors, _ = nx.floyd_warshall_predecessor_and_distance(G)
122
+ >>> print(nx.reconstruct_path("s", "v", predecessors))
123
+ ['s', 'x', 'u', 'v']
124
+
125
+ Notes
126
+ -----
127
+ Floyd's algorithm is appropriate for finding shortest paths
128
+ in dense graphs or graphs with negative weights when Dijkstra's algorithm
129
+ fails. This algorithm can still fail if there are negative cycles.
130
+ It has running time $O(n^3)$ with running space of $O(n^2)$.
131
+
132
+ See Also
133
+ --------
134
+ floyd_warshall
135
+ floyd_warshall_numpy
136
+ all_pairs_shortest_path
137
+ all_pairs_shortest_path_length
138
+ """
139
+ from collections import defaultdict
140
+
141
+ # dictionary-of-dictionaries representation for dist and pred
142
+ # use some defaultdict magick here
143
+ # for dist the default is the floating point inf value
144
+ dist = defaultdict(lambda: defaultdict(lambda: float("inf")))
145
+ for u in G:
146
+ dist[u][u] = 0
147
+ pred = defaultdict(dict)
148
+ # initialize path distance dictionary to be the adjacency matrix
149
+ # also set the distance to self to 0 (zero diagonal)
150
+ undirected = not G.is_directed()
151
+ for u, v, d in G.edges(data=True):
152
+ e_weight = d.get(weight, 1.0)
153
+ dist[u][v] = min(e_weight, dist[u][v])
154
+ pred[u][v] = u
155
+ if undirected:
156
+ dist[v][u] = min(e_weight, dist[v][u])
157
+ pred[v][u] = v
158
+ for w in G:
159
+ dist_w = dist[w] # save recomputation
160
+ for u in G:
161
+ dist_u = dist[u] # save recomputation
162
+ for v in G:
163
+ d = dist_u[w] + dist_w[v]
164
+ if dist_u[v] > d:
165
+ dist_u[v] = d
166
+ pred[u][v] = pred[w][v]
167
+ return dict(pred), dict(dist)
168
+
169
+
170
+ @nx._dispatch(graphs=None)
171
+ def reconstruct_path(source, target, predecessors):
172
+ """Reconstruct a path from source to target using the predecessors
173
+ dict as returned by floyd_warshall_predecessor_and_distance
174
+
175
+ Parameters
176
+ ----------
177
+ source : node
178
+ Starting node for path
179
+
180
+ target : node
181
+ Ending node for path
182
+
183
+ predecessors: dictionary
184
+ Dictionary, keyed by source and target, of predecessors in the
185
+ shortest path, as returned by floyd_warshall_predecessor_and_distance
186
+
187
+ Returns
188
+ -------
189
+ path : list
190
+ A list of nodes containing the shortest path from source to target
191
+
192
+ If source and target are the same, an empty list is returned
193
+
194
+ Notes
195
+ -----
196
+ This function is meant to give more applicability to the
197
+ floyd_warshall_predecessor_and_distance function
198
+
199
+ See Also
200
+ --------
201
+ floyd_warshall_predecessor_and_distance
202
+ """
203
+ if source == target:
204
+ return []
205
+ prev = predecessors[source]
206
+ curr = prev[target]
207
+ path = [target, curr]
208
+ while curr != source:
209
+ curr = prev[curr]
210
+ path.append(curr)
211
+ return list(reversed(path))
212
+
213
+
214
+ @nx._dispatch(edge_attrs="weight")
215
+ def floyd_warshall(G, weight="weight"):
216
+ """Find all-pairs shortest path lengths using Floyd's algorithm.
217
+
218
+ Parameters
219
+ ----------
220
+ G : NetworkX graph
221
+
222
+ weight: string, optional (default= 'weight')
223
+ Edge data key corresponding to the edge weight.
224
+
225
+
226
+ Returns
227
+ -------
228
+ distance : dict
229
+ A dictionary, keyed by source and target, of shortest paths distances
230
+ between nodes.
231
+
232
+ Examples
233
+ --------
234
+ >>> G = nx.DiGraph()
235
+ >>> G.add_weighted_edges_from([(0, 1, 5), (1, 2, 2), (2, 3, -3), (1, 3, 10), (3, 2, 8)])
236
+ >>> fw = nx.floyd_warshall(G, weight='weight')
237
+ >>> results = {a: dict(b) for a, b in fw.items()}
238
+ >>> print(results)
239
+ {0: {0: 0, 1: 5, 2: 7, 3: 4}, 1: {1: 0, 2: 2, 3: -1, 0: inf}, 2: {2: 0, 3: -3, 0: inf, 1: inf}, 3: {3: 0, 2: 8, 0: inf, 1: inf}}
240
+
241
+ Notes
242
+ -----
243
+ Floyd's algorithm is appropriate for finding shortest paths
244
+ in dense graphs or graphs with negative weights when Dijkstra's algorithm
245
+ fails. This algorithm can still fail if there are negative cycles.
246
+ It has running time $O(n^3)$ with running space of $O(n^2)$.
247
+
248
+ See Also
249
+ --------
250
+ floyd_warshall_predecessor_and_distance
251
+ floyd_warshall_numpy
252
+ all_pairs_shortest_path
253
+ all_pairs_shortest_path_length
254
+ """
255
+ # could make this its own function to reduce memory costs
256
+ return floyd_warshall_predecessor_and_distance(G, weight=weight)[1]
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/tests/__pycache__/test_dense.cpython-311.pyc ADDED
Binary file (8.71 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/tests/__pycache__/test_generic.cpython-311.pyc ADDED
Binary file (34.2 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/tests/__pycache__/test_unweighted.cpython-311.pyc ADDED
Binary file (13 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/tests/__pycache__/test_weighted.cpython-311.pyc ADDED
Binary file (61.2 kB). View file
 
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/tests/test_astar.py ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+
3
+ import networkx as nx
4
+ from networkx.utils import pairwise
5
+
6
+
7
+ class TestAStar:
8
+ @classmethod
9
+ def setup_class(cls):
10
+ edges = [
11
+ ("s", "u", 10),
12
+ ("s", "x", 5),
13
+ ("u", "v", 1),
14
+ ("u", "x", 2),
15
+ ("v", "y", 1),
16
+ ("x", "u", 3),
17
+ ("x", "v", 5),
18
+ ("x", "y", 2),
19
+ ("y", "s", 7),
20
+ ("y", "v", 6),
21
+ ]
22
+ cls.XG = nx.DiGraph()
23
+ cls.XG.add_weighted_edges_from(edges)
24
+
25
+ def test_multiple_optimal_paths(self):
26
+ """Tests that A* algorithm finds any of multiple optimal paths"""
27
+ heuristic_values = {"a": 1.35, "b": 1.18, "c": 0.67, "d": 0}
28
+
29
+ def h(u, v):
30
+ return heuristic_values[u]
31
+
32
+ graph = nx.Graph()
33
+ points = ["a", "b", "c", "d"]
34
+ edges = [("a", "b", 0.18), ("a", "c", 0.68), ("b", "c", 0.50), ("c", "d", 0.67)]
35
+
36
+ graph.add_nodes_from(points)
37
+ graph.add_weighted_edges_from(edges)
38
+
39
+ path1 = ["a", "c", "d"]
40
+ path2 = ["a", "b", "c", "d"]
41
+ assert nx.astar_path(graph, "a", "d", h) in (path1, path2)
42
+
43
+ def test_astar_directed(self):
44
+ assert nx.astar_path(self.XG, "s", "v") == ["s", "x", "u", "v"]
45
+ assert nx.astar_path_length(self.XG, "s", "v") == 9
46
+
47
+ def test_astar_directed_weight_function(self):
48
+ w1 = lambda u, v, d: d["weight"]
49
+ assert nx.astar_path(self.XG, "x", "u", weight=w1) == ["x", "u"]
50
+ assert nx.astar_path_length(self.XG, "x", "u", weight=w1) == 3
51
+ assert nx.astar_path(self.XG, "s", "v", weight=w1) == ["s", "x", "u", "v"]
52
+ assert nx.astar_path_length(self.XG, "s", "v", weight=w1) == 9
53
+
54
+ w2 = lambda u, v, d: None if (u, v) == ("x", "u") else d["weight"]
55
+ assert nx.astar_path(self.XG, "x", "u", weight=w2) == ["x", "y", "s", "u"]
56
+ assert nx.astar_path_length(self.XG, "x", "u", weight=w2) == 19
57
+ assert nx.astar_path(self.XG, "s", "v", weight=w2) == ["s", "x", "v"]
58
+ assert nx.astar_path_length(self.XG, "s", "v", weight=w2) == 10
59
+
60
+ w3 = lambda u, v, d: d["weight"] + 10
61
+ assert nx.astar_path(self.XG, "x", "u", weight=w3) == ["x", "u"]
62
+ assert nx.astar_path_length(self.XG, "x", "u", weight=w3) == 13
63
+ assert nx.astar_path(self.XG, "s", "v", weight=w3) == ["s", "x", "v"]
64
+ assert nx.astar_path_length(self.XG, "s", "v", weight=w3) == 30
65
+
66
+ def test_astar_multigraph(self):
67
+ G = nx.MultiDiGraph(self.XG)
68
+ G.add_weighted_edges_from((u, v, 1000) for (u, v) in list(G.edges()))
69
+ assert nx.astar_path(G, "s", "v") == ["s", "x", "u", "v"]
70
+ assert nx.astar_path_length(G, "s", "v") == 9
71
+
72
+ def test_astar_undirected(self):
73
+ GG = self.XG.to_undirected()
74
+ # make sure we get lower weight
75
+ # to_undirected might choose either edge with weight 2 or weight 3
76
+ GG["u"]["x"]["weight"] = 2
77
+ GG["y"]["v"]["weight"] = 2
78
+ assert nx.astar_path(GG, "s", "v") == ["s", "x", "u", "v"]
79
+ assert nx.astar_path_length(GG, "s", "v") == 8
80
+
81
+ def test_astar_directed2(self):
82
+ XG2 = nx.DiGraph()
83
+ edges = [
84
+ (1, 4, 1),
85
+ (4, 5, 1),
86
+ (5, 6, 1),
87
+ (6, 3, 1),
88
+ (1, 3, 50),
89
+ (1, 2, 100),
90
+ (2, 3, 100),
91
+ ]
92
+ XG2.add_weighted_edges_from(edges)
93
+ assert nx.astar_path(XG2, 1, 3) == [1, 4, 5, 6, 3]
94
+
95
+ def test_astar_undirected2(self):
96
+ XG3 = nx.Graph()
97
+ edges = [(0, 1, 2), (1, 2, 12), (2, 3, 1), (3, 4, 5), (4, 5, 1), (5, 0, 10)]
98
+ XG3.add_weighted_edges_from(edges)
99
+ assert nx.astar_path(XG3, 0, 3) == [0, 1, 2, 3]
100
+ assert nx.astar_path_length(XG3, 0, 3) == 15
101
+
102
+ def test_astar_undirected3(self):
103
+ XG4 = nx.Graph()
104
+ edges = [
105
+ (0, 1, 2),
106
+ (1, 2, 2),
107
+ (2, 3, 1),
108
+ (3, 4, 1),
109
+ (4, 5, 1),
110
+ (5, 6, 1),
111
+ (6, 7, 1),
112
+ (7, 0, 1),
113
+ ]
114
+ XG4.add_weighted_edges_from(edges)
115
+ assert nx.astar_path(XG4, 0, 2) == [0, 1, 2]
116
+ assert nx.astar_path_length(XG4, 0, 2) == 4
117
+
118
+ """ Tests that A* finds correct path when multiple paths exist
119
+ and the best one is not expanded first (GH issue #3464)
120
+ """
121
+
122
+ def test_astar_directed3(self):
123
+ heuristic_values = {"n5": 36, "n2": 4, "n1": 0, "n0": 0}
124
+
125
+ def h(u, v):
126
+ return heuristic_values[u]
127
+
128
+ edges = [("n5", "n1", 11), ("n5", "n2", 9), ("n2", "n1", 1), ("n1", "n0", 32)]
129
+ graph = nx.DiGraph()
130
+ graph.add_weighted_edges_from(edges)
131
+ answer = ["n5", "n2", "n1", "n0"]
132
+ assert nx.astar_path(graph, "n5", "n0", h) == answer
133
+
134
+ """ Tests that parent is not wrongly overridden when a node
135
+ is re-explored multiple times.
136
+ """
137
+
138
+ def test_astar_directed4(self):
139
+ edges = [
140
+ ("a", "b", 1),
141
+ ("a", "c", 1),
142
+ ("b", "d", 2),
143
+ ("c", "d", 1),
144
+ ("d", "e", 1),
145
+ ]
146
+ graph = nx.DiGraph()
147
+ graph.add_weighted_edges_from(edges)
148
+ assert nx.astar_path(graph, "a", "e") == ["a", "c", "d", "e"]
149
+
150
+ # >>> MXG4=NX.MultiGraph(XG4)
151
+ # >>> MXG4.add_edge(0,1,3)
152
+ # >>> NX.dijkstra_path(MXG4,0,2)
153
+ # [0, 1, 2]
154
+
155
+ def test_astar_w1(self):
156
+ G = nx.DiGraph()
157
+ G.add_edges_from(
158
+ [
159
+ ("s", "u"),
160
+ ("s", "x"),
161
+ ("u", "v"),
162
+ ("u", "x"),
163
+ ("v", "y"),
164
+ ("x", "u"),
165
+ ("x", "w"),
166
+ ("w", "v"),
167
+ ("x", "y"),
168
+ ("y", "s"),
169
+ ("y", "v"),
170
+ ]
171
+ )
172
+ assert nx.astar_path(G, "s", "v") == ["s", "u", "v"]
173
+ assert nx.astar_path_length(G, "s", "v") == 2
174
+
175
+ def test_astar_nopath(self):
176
+ with pytest.raises(nx.NodeNotFound):
177
+ nx.astar_path(self.XG, "s", "moon")
178
+
179
+ def test_cycle(self):
180
+ C = nx.cycle_graph(7)
181
+ assert nx.astar_path(C, 0, 3) == [0, 1, 2, 3]
182
+ assert nx.dijkstra_path(C, 0, 4) == [0, 6, 5, 4]
183
+
184
+ def test_unorderable_nodes(self):
185
+ """Tests that A* accommodates nodes that are not orderable.
186
+
187
+ For more information, see issue #554.
188
+
189
+ """
190
+ # Create the cycle graph on four nodes, with nodes represented
191
+ # as (unorderable) Python objects.
192
+ nodes = [object() for n in range(4)]
193
+ G = nx.Graph()
194
+ G.add_edges_from(pairwise(nodes, cyclic=True))
195
+ path = nx.astar_path(G, nodes[0], nodes[2])
196
+ assert len(path) == 3
197
+
198
+ def test_astar_NetworkXNoPath(self):
199
+ """Tests that exception is raised when there exists no
200
+ path between source and target"""
201
+ G = nx.gnp_random_graph(10, 0.2, seed=10)
202
+ with pytest.raises(nx.NetworkXNoPath):
203
+ nx.astar_path(G, 4, 9)
204
+
205
+ def test_astar_NodeNotFound(self):
206
+ """Tests that exception is raised when either
207
+ source or target is not in graph"""
208
+ G = nx.gnp_random_graph(10, 0.2, seed=10)
209
+ with pytest.raises(nx.NodeNotFound):
210
+ nx.astar_path_length(G, 11, 9)
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/tests/test_dense_numpy.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+
3
+ np = pytest.importorskip("numpy")
4
+
5
+
6
+ import networkx as nx
7
+
8
+
9
+ def test_cycle_numpy():
10
+ dist = nx.floyd_warshall_numpy(nx.cycle_graph(7))
11
+ assert dist[0, 3] == 3
12
+ assert dist[0, 4] == 3
13
+
14
+
15
+ def test_weighted_numpy_three_edges():
16
+ XG3 = nx.Graph()
17
+ XG3.add_weighted_edges_from(
18
+ [[0, 1, 2], [1, 2, 12], [2, 3, 1], [3, 4, 5], [4, 5, 1], [5, 0, 10]]
19
+ )
20
+ dist = nx.floyd_warshall_numpy(XG3)
21
+ assert dist[0, 3] == 15
22
+
23
+
24
+ def test_weighted_numpy_two_edges():
25
+ XG4 = nx.Graph()
26
+ XG4.add_weighted_edges_from(
27
+ [
28
+ [0, 1, 2],
29
+ [1, 2, 2],
30
+ [2, 3, 1],
31
+ [3, 4, 1],
32
+ [4, 5, 1],
33
+ [5, 6, 1],
34
+ [6, 7, 1],
35
+ [7, 0, 1],
36
+ ]
37
+ )
38
+ dist = nx.floyd_warshall_numpy(XG4)
39
+ assert dist[0, 2] == 4
40
+
41
+
42
+ def test_weight_parameter_numpy():
43
+ XG4 = nx.Graph()
44
+ XG4.add_edges_from(
45
+ [
46
+ (0, 1, {"heavy": 2}),
47
+ (1, 2, {"heavy": 2}),
48
+ (2, 3, {"heavy": 1}),
49
+ (3, 4, {"heavy": 1}),
50
+ (4, 5, {"heavy": 1}),
51
+ (5, 6, {"heavy": 1}),
52
+ (6, 7, {"heavy": 1}),
53
+ (7, 0, {"heavy": 1}),
54
+ ]
55
+ )
56
+ dist = nx.floyd_warshall_numpy(XG4, weight="heavy")
57
+ assert dist[0, 2] == 4
58
+
59
+
60
+ def test_directed_cycle_numpy():
61
+ G = nx.DiGraph()
62
+ nx.add_cycle(G, [0, 1, 2, 3])
63
+ pred, dist = nx.floyd_warshall_predecessor_and_distance(G)
64
+ D = nx.utils.dict_to_numpy_array(dist)
65
+ np.testing.assert_equal(nx.floyd_warshall_numpy(G), D)
66
+
67
+
68
+ def test_zero_weight():
69
+ G = nx.DiGraph()
70
+ edges = [(1, 2, -2), (2, 3, -4), (1, 5, 1), (5, 4, 0), (4, 3, -5), (2, 5, -7)]
71
+ G.add_weighted_edges_from(edges)
72
+ dist = nx.floyd_warshall_numpy(G)
73
+ assert int(np.min(dist)) == -14
74
+
75
+ G = nx.MultiDiGraph()
76
+ edges.append((2, 5, -7))
77
+ G.add_weighted_edges_from(edges)
78
+ dist = nx.floyd_warshall_numpy(G)
79
+ assert int(np.min(dist)) == -14
80
+
81
+
82
+ def test_nodelist():
83
+ G = nx.path_graph(7)
84
+ dist = nx.floyd_warshall_numpy(G, nodelist=[3, 5, 4, 6, 2, 1, 0])
85
+ assert dist[0, 3] == 3
86
+ assert dist[0, 1] == 2
87
+ assert dist[6, 2] == 4
88
+ pytest.raises(nx.NetworkXError, nx.floyd_warshall_numpy, G, [1, 3])
89
+ pytest.raises(nx.NetworkXError, nx.floyd_warshall_numpy, G, list(range(9)))
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/shortest_paths/tests/test_unweighted.py ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+
3
+ import networkx as nx
4
+
5
+
6
+ def validate_grid_path(r, c, s, t, p):
7
+ assert isinstance(p, list)
8
+ assert p[0] == s
9
+ assert p[-1] == t
10
+ s = ((s - 1) // c, (s - 1) % c)
11
+ t = ((t - 1) // c, (t - 1) % c)
12
+ assert len(p) == abs(t[0] - s[0]) + abs(t[1] - s[1]) + 1
13
+ p = [((u - 1) // c, (u - 1) % c) for u in p]
14
+ for u in p:
15
+ assert 0 <= u[0] < r
16
+ assert 0 <= u[1] < c
17
+ for u, v in zip(p[:-1], p[1:]):
18
+ assert (abs(v[0] - u[0]), abs(v[1] - u[1])) in [(0, 1), (1, 0)]
19
+
20
+
21
+ class TestUnweightedPath:
22
+ @classmethod
23
+ def setup_class(cls):
24
+ from networkx import convert_node_labels_to_integers as cnlti
25
+
26
+ cls.grid = cnlti(nx.grid_2d_graph(4, 4), first_label=1, ordering="sorted")
27
+ cls.cycle = nx.cycle_graph(7)
28
+ cls.directed_cycle = nx.cycle_graph(7, create_using=nx.DiGraph())
29
+
30
+ def test_bidirectional_shortest_path(self):
31
+ assert nx.bidirectional_shortest_path(self.cycle, 0, 3) == [0, 1, 2, 3]
32
+ assert nx.bidirectional_shortest_path(self.cycle, 0, 4) == [0, 6, 5, 4]
33
+ validate_grid_path(
34
+ 4, 4, 1, 12, nx.bidirectional_shortest_path(self.grid, 1, 12)
35
+ )
36
+ assert nx.bidirectional_shortest_path(self.directed_cycle, 0, 3) == [0, 1, 2, 3]
37
+ # test source = target
38
+ assert nx.bidirectional_shortest_path(self.cycle, 3, 3) == [3]
39
+
40
+ @pytest.mark.parametrize(
41
+ ("src", "tgt"),
42
+ (
43
+ (8, 3), # source not in graph
44
+ (3, 8), # target not in graph
45
+ (8, 10), # neither source nor target in graph
46
+ (8, 8), # src == tgt, neither in graph - tests order of input checks
47
+ ),
48
+ )
49
+ def test_bidirectional_shortest_path_src_tgt_not_in_graph(self, src, tgt):
50
+ with pytest.raises(
51
+ nx.NodeNotFound,
52
+ match=f"Either source {src} or target {tgt} is not in G",
53
+ ):
54
+ nx.bidirectional_shortest_path(self.cycle, src, tgt)
55
+
56
+ def test_shortest_path_length(self):
57
+ assert nx.shortest_path_length(self.cycle, 0, 3) == 3
58
+ assert nx.shortest_path_length(self.grid, 1, 12) == 5
59
+ assert nx.shortest_path_length(self.directed_cycle, 0, 4) == 4
60
+ # now with weights
61
+ assert nx.shortest_path_length(self.cycle, 0, 3, weight=True) == 3
62
+ assert nx.shortest_path_length(self.grid, 1, 12, weight=True) == 5
63
+ assert nx.shortest_path_length(self.directed_cycle, 0, 4, weight=True) == 4
64
+
65
+ def test_single_source_shortest_path(self):
66
+ p = nx.single_source_shortest_path(self.directed_cycle, 3)
67
+ assert p[0] == [3, 4, 5, 6, 0]
68
+ p = nx.single_source_shortest_path(self.cycle, 0)
69
+ assert p[3] == [0, 1, 2, 3]
70
+ p = nx.single_source_shortest_path(self.cycle, 0, cutoff=0)
71
+ assert p == {0: [0]}
72
+
73
+ def test_single_source_shortest_path_length(self):
74
+ pl = nx.single_source_shortest_path_length
75
+ lengths = {0: 0, 1: 1, 2: 2, 3: 3, 4: 3, 5: 2, 6: 1}
76
+ assert dict(pl(self.cycle, 0)) == lengths
77
+ lengths = {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6}
78
+ assert dict(pl(self.directed_cycle, 0)) == lengths
79
+
80
+ def test_single_target_shortest_path(self):
81
+ p = nx.single_target_shortest_path(self.directed_cycle, 0)
82
+ assert p[3] == [3, 4, 5, 6, 0]
83
+ p = nx.single_target_shortest_path(self.cycle, 0)
84
+ assert p[3] == [3, 2, 1, 0]
85
+ p = nx.single_target_shortest_path(self.cycle, 0, cutoff=0)
86
+ assert p == {0: [0]}
87
+ # test missing targets
88
+ target = 8
89
+ with pytest.raises(nx.NodeNotFound, match=f"Target {target} not in G"):
90
+ nx.single_target_shortest_path(self.cycle, target)
91
+
92
+ def test_single_target_shortest_path_length(self):
93
+ pl = nx.single_target_shortest_path_length
94
+ lengths = {0: 0, 1: 1, 2: 2, 3: 3, 4: 3, 5: 2, 6: 1}
95
+ assert dict(pl(self.cycle, 0)) == lengths
96
+ lengths = {0: 0, 1: 6, 2: 5, 3: 4, 4: 3, 5: 2, 6: 1}
97
+ assert dict(pl(self.directed_cycle, 0)) == lengths
98
+ # test missing targets
99
+ target = 8
100
+ with pytest.raises(nx.NodeNotFound, match=f"Target {target} is not in G"):
101
+ nx.single_target_shortest_path_length(self.cycle, target)
102
+
103
+ def test_all_pairs_shortest_path(self):
104
+ p = dict(nx.all_pairs_shortest_path(self.cycle))
105
+ assert p[0][3] == [0, 1, 2, 3]
106
+ p = dict(nx.all_pairs_shortest_path(self.grid))
107
+ validate_grid_path(4, 4, 1, 12, p[1][12])
108
+
109
+ def test_all_pairs_shortest_path_length(self):
110
+ l = dict(nx.all_pairs_shortest_path_length(self.cycle))
111
+ assert l[0] == {0: 0, 1: 1, 2: 2, 3: 3, 4: 3, 5: 2, 6: 1}
112
+ l = dict(nx.all_pairs_shortest_path_length(self.grid))
113
+ assert l[1][16] == 6
114
+
115
+ def test_predecessor_path(self):
116
+ G = nx.path_graph(4)
117
+ assert nx.predecessor(G, 0) == {0: [], 1: [0], 2: [1], 3: [2]}
118
+ assert nx.predecessor(G, 0, 3) == [2]
119
+
120
+ def test_predecessor_cycle(self):
121
+ G = nx.cycle_graph(4)
122
+ pred = nx.predecessor(G, 0)
123
+ assert pred[0] == []
124
+ assert pred[1] == [0]
125
+ assert pred[2] in [[1, 3], [3, 1]]
126
+ assert pred[3] == [0]
127
+
128
+ def test_predecessor_cutoff(self):
129
+ G = nx.path_graph(4)
130
+ p = nx.predecessor(G, 0, 3)
131
+ assert 4 not in p
132
+
133
+ def test_predecessor_target(self):
134
+ G = nx.path_graph(4)
135
+ p = nx.predecessor(G, 0, 3)
136
+ assert p == [2]
137
+ p = nx.predecessor(G, 0, 3, cutoff=2)
138
+ assert p == []
139
+ p, s = nx.predecessor(G, 0, 3, return_seen=True)
140
+ assert p == [2]
141
+ assert s == 3
142
+ p, s = nx.predecessor(G, 0, 3, cutoff=2, return_seen=True)
143
+ assert p == []
144
+ assert s == -1
145
+
146
+ def test_predecessor_missing_source(self):
147
+ source = 8
148
+ with pytest.raises(nx.NodeNotFound, match=f"Source {source} not in G"):
149
+ nx.predecessor(self.cycle, source)