Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/TestTypes.py +77 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/__pycache__/TestCmdLine.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/__pycache__/TestFlowControl.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/__pycache__/TestGrammar.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/__pycache__/TestParseTreeTransforms.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/__pycache__/TestScanning.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/__pycache__/TestTypes.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/__pycache__/TestUtilityLoad.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/__pycache__/Utils.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Utility/ImportExport.c +939 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/simple_paths.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/walks.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/__init__.py +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/__pycache__/test_hybrid.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/__pycache__/test_link_prediction.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/__pycache__/test_polynomials.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/__pycache__/test_walks.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/__pycache__/test_wiener.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_asteroidal.py +23 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_bridges.py +144 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_clique.py +291 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_core.py +185 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_cycles.py +971 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_efficiency.py +58 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_lowest_common_ancestors.py +427 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_richclub.py +97 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_smetric.py +36 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_structuralholes.py +139 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_swap.py +156 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_time_dependent.py +431 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_voronoi.py +103 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_degree_seq.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_geometric.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_harary_graph.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_interval_graph.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_lattice.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_random_graphs.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_small.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_spectral_graph_forge.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_trees.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_triads.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/__pycache__/__init__.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/__pycache__/exceptions.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/cli/__init__.py +4 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-311.pyc +0 -0
- tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-311.pyc +0 -0
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/TestTypes.py
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import
|
| 2 |
+
|
| 3 |
+
import unittest
|
| 4 |
+
|
| 5 |
+
import Cython.Compiler.PyrexTypes as PT
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class TestMethodDispatcherTransform(unittest.TestCase):
|
| 9 |
+
|
| 10 |
+
def test_widest_numeric_type(self):
|
| 11 |
+
def assert_widest(type1, type2, widest):
|
| 12 |
+
self.assertEqual(widest, PT.widest_numeric_type(type1, type2))
|
| 13 |
+
|
| 14 |
+
assert_widest(PT.c_int_type, PT.c_long_type, PT.c_long_type)
|
| 15 |
+
assert_widest(PT.c_double_type, PT.c_long_type, PT.c_double_type)
|
| 16 |
+
assert_widest(PT.c_longdouble_type, PT.c_long_type, PT.c_longdouble_type)
|
| 17 |
+
|
| 18 |
+
cenum = PT.CEnumType("E", "cenum", typedef_flag=False)
|
| 19 |
+
assert_widest(PT.c_int_type, cenum, PT.c_int_type)
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
class TestTypeIdentifiers(unittest.TestCase):
|
| 23 |
+
|
| 24 |
+
TEST_DATA = [
|
| 25 |
+
("char*", "char__ptr"),
|
| 26 |
+
("char *", "char__ptr"),
|
| 27 |
+
("char **", "char__ptr__ptr"),
|
| 28 |
+
("_typedef", "_typedef"),
|
| 29 |
+
("__typedef", "__dundertypedef"),
|
| 30 |
+
("___typedef", "__dunder_typedef"),
|
| 31 |
+
("____typedef", "__dunder__dundertypedef"),
|
| 32 |
+
("_____typedef", "__dunder__dunder_typedef"),
|
| 33 |
+
("const __typedef", "__const___dundertypedef"),
|
| 34 |
+
("int[42]", "int__lArr42__rArr"),
|
| 35 |
+
("int[:]", "int__lArr__D__rArr"),
|
| 36 |
+
("int[:,:]", "int__lArr__D__comma___D__rArr"),
|
| 37 |
+
("int[:,:,:]", "int__lArr__D__comma___D__comma___D__rArr"),
|
| 38 |
+
("int[:,:,...]", "int__lArr__D__comma___D__comma___EL__rArr"),
|
| 39 |
+
("std::vector", "std__in_vector"),
|
| 40 |
+
("std::vector&&", "std__in_vector__fwref"),
|
| 41 |
+
("const std::vector", "__const_std__in_vector"),
|
| 42 |
+
("const std::vector&", "__const_std__in_vector__ref"),
|
| 43 |
+
("const_std", "const_std"),
|
| 44 |
+
]
|
| 45 |
+
|
| 46 |
+
def test_escape_special_type_characters(self):
|
| 47 |
+
test_func = PT._escape_special_type_characters # keep test usage visible for IDEs
|
| 48 |
+
function_name = "_escape_special_type_characters"
|
| 49 |
+
self._test_escape(function_name)
|
| 50 |
+
|
| 51 |
+
def test_type_identifier_for_declaration(self):
|
| 52 |
+
test_func = PT.type_identifier_from_declaration # keep test usage visible for IDEs
|
| 53 |
+
function_name = test_func.__name__
|
| 54 |
+
self._test_escape(function_name)
|
| 55 |
+
|
| 56 |
+
# differences due to whitespace removal
|
| 57 |
+
test_data = [
|
| 58 |
+
("const &std::vector", "const__refstd__in_vector"),
|
| 59 |
+
("const &std::vector<int>", "const__refstd__in_vector__lAngint__rAng"),
|
| 60 |
+
("const &&std::vector", "const__fwrefstd__in_vector"),
|
| 61 |
+
("const &&&std::vector", "const__fwref__refstd__in_vector"),
|
| 62 |
+
("const &&std::vector", "const__fwrefstd__in_vector"),
|
| 63 |
+
("void (*func)(int x, float y)",
|
| 64 |
+
"975d51__void__lParen__ptrfunc__rParen__lParenint__spac__etc"),
|
| 65 |
+
("float ** (*func)(int x, int[:] y)",
|
| 66 |
+
"31883a__float__ptr__ptr__lParen__ptrfunc__rParen__lPar__etc"),
|
| 67 |
+
]
|
| 68 |
+
self._test_escape(function_name, test_data)
|
| 69 |
+
|
| 70 |
+
def _test_escape(self, func_name, test_data=TEST_DATA):
|
| 71 |
+
escape = getattr(PT, func_name)
|
| 72 |
+
for declaration, expected in test_data:
|
| 73 |
+
escaped_value = escape(declaration)
|
| 74 |
+
self.assertEqual(escaped_value, expected, "%s('%s') == '%s' != '%s'" % (
|
| 75 |
+
func_name, declaration, escaped_value, expected))
|
| 76 |
+
# test that the length has been successfully capped
|
| 77 |
+
self.assertLessEqual(len(escaped_value), 64)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/__pycache__/TestCmdLine.cpython-311.pyc
ADDED
|
Binary file (34.9 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/__pycache__/TestFlowControl.cpython-311.pyc
ADDED
|
Binary file (4.43 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/__pycache__/TestGrammar.cpython-311.pyc
ADDED
|
Binary file (5.87 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/__pycache__/TestParseTreeTransforms.cpython-311.pyc
ADDED
|
Binary file (16.4 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/__pycache__/TestScanning.cpython-311.pyc
ADDED
|
Binary file (9.64 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/__pycache__/TestTypes.cpython-311.pyc
ADDED
|
Binary file (4.78 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/__pycache__/TestUtilityLoad.cpython-311.pyc
ADDED
|
Binary file (7.27 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Compiler/Tests/__pycache__/Utils.cpython-311.pyc
ADDED
|
Binary file (1.92 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/Cython/Utility/ImportExport.c
ADDED
|
@@ -0,0 +1,939 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/////////////// ImportDottedModule.proto ///////////////
|
| 2 |
+
|
| 3 |
+
static PyObject *__Pyx_ImportDottedModule(PyObject *name, PyObject *parts_tuple); /*proto*/
|
| 4 |
+
#if PY_MAJOR_VERSION >= 3
|
| 5 |
+
static PyObject *__Pyx_ImportDottedModule_WalkParts(PyObject *module, PyObject *name, PyObject *parts_tuple); /*proto*/
|
| 6 |
+
#endif
|
| 7 |
+
|
| 8 |
+
/////////////// ImportDottedModule ///////////////
|
| 9 |
+
//@requires: Import
|
| 10 |
+
|
| 11 |
+
#if PY_MAJOR_VERSION >= 3
|
| 12 |
+
static PyObject *__Pyx__ImportDottedModule_Error(PyObject *name, PyObject *parts_tuple, Py_ssize_t count) {
|
| 13 |
+
PyObject *partial_name = NULL, *slice = NULL, *sep = NULL;
|
| 14 |
+
if (unlikely(PyErr_Occurred())) {
|
| 15 |
+
PyErr_Clear();
|
| 16 |
+
}
|
| 17 |
+
if (likely(PyTuple_GET_SIZE(parts_tuple) == count)) {
|
| 18 |
+
partial_name = name;
|
| 19 |
+
} else {
|
| 20 |
+
slice = PySequence_GetSlice(parts_tuple, 0, count);
|
| 21 |
+
if (unlikely(!slice))
|
| 22 |
+
goto bad;
|
| 23 |
+
sep = PyUnicode_FromStringAndSize(".", 1);
|
| 24 |
+
if (unlikely(!sep))
|
| 25 |
+
goto bad;
|
| 26 |
+
partial_name = PyUnicode_Join(sep, slice);
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
PyErr_Format(
|
| 30 |
+
#if PY_MAJOR_VERSION < 3
|
| 31 |
+
PyExc_ImportError,
|
| 32 |
+
"No module named '%s'", PyString_AS_STRING(partial_name));
|
| 33 |
+
#else
|
| 34 |
+
#if PY_VERSION_HEX >= 0x030600B1
|
| 35 |
+
PyExc_ModuleNotFoundError,
|
| 36 |
+
#else
|
| 37 |
+
PyExc_ImportError,
|
| 38 |
+
#endif
|
| 39 |
+
"No module named '%U'", partial_name);
|
| 40 |
+
#endif
|
| 41 |
+
|
| 42 |
+
bad:
|
| 43 |
+
Py_XDECREF(sep);
|
| 44 |
+
Py_XDECREF(slice);
|
| 45 |
+
Py_XDECREF(partial_name);
|
| 46 |
+
return NULL;
|
| 47 |
+
}
|
| 48 |
+
#endif
|
| 49 |
+
|
| 50 |
+
#if PY_MAJOR_VERSION >= 3
|
| 51 |
+
static PyObject *__Pyx__ImportDottedModule_Lookup(PyObject *name) {
|
| 52 |
+
PyObject *imported_module;
|
| 53 |
+
#if PY_VERSION_HEX < 0x030700A1 || (CYTHON_COMPILING_IN_PYPY && PYPY_VERSION_NUM < 0x07030400)
|
| 54 |
+
PyObject *modules = PyImport_GetModuleDict();
|
| 55 |
+
if (unlikely(!modules))
|
| 56 |
+
return NULL;
|
| 57 |
+
imported_module = __Pyx_PyDict_GetItemStr(modules, name);
|
| 58 |
+
Py_XINCREF(imported_module);
|
| 59 |
+
#else
|
| 60 |
+
imported_module = PyImport_GetModule(name);
|
| 61 |
+
#endif
|
| 62 |
+
return imported_module;
|
| 63 |
+
}
|
| 64 |
+
#endif
|
| 65 |
+
|
| 66 |
+
#if PY_MAJOR_VERSION >= 3
|
| 67 |
+
static PyObject *__Pyx_ImportDottedModule_WalkParts(PyObject *module, PyObject *name, PyObject *parts_tuple) {
|
| 68 |
+
Py_ssize_t i, nparts;
|
| 69 |
+
nparts = PyTuple_GET_SIZE(parts_tuple);
|
| 70 |
+
for (i=1; i < nparts && module; i++) {
|
| 71 |
+
PyObject *part, *submodule;
|
| 72 |
+
#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
|
| 73 |
+
part = PyTuple_GET_ITEM(parts_tuple, i);
|
| 74 |
+
#else
|
| 75 |
+
part = PySequence_ITEM(parts_tuple, i);
|
| 76 |
+
#endif
|
| 77 |
+
submodule = __Pyx_PyObject_GetAttrStrNoError(module, part);
|
| 78 |
+
// We stop if the attribute isn't found, i.e. if submodule is NULL here.
|
| 79 |
+
#if !(CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS)
|
| 80 |
+
Py_DECREF(part);
|
| 81 |
+
#endif
|
| 82 |
+
Py_DECREF(module);
|
| 83 |
+
module = submodule;
|
| 84 |
+
}
|
| 85 |
+
if (unlikely(!module)) {
|
| 86 |
+
return __Pyx__ImportDottedModule_Error(name, parts_tuple, i);
|
| 87 |
+
}
|
| 88 |
+
return module;
|
| 89 |
+
}
|
| 90 |
+
#endif
|
| 91 |
+
|
| 92 |
+
static PyObject *__Pyx__ImportDottedModule(PyObject *name, PyObject *parts_tuple) {
|
| 93 |
+
#if PY_MAJOR_VERSION < 3
|
| 94 |
+
PyObject *module, *from_list, *star = PYIDENT("*");
|
| 95 |
+
CYTHON_UNUSED_VAR(parts_tuple);
|
| 96 |
+
from_list = PyList_New(1);
|
| 97 |
+
if (unlikely(!from_list))
|
| 98 |
+
return NULL;
|
| 99 |
+
Py_INCREF(star);
|
| 100 |
+
PyList_SET_ITEM(from_list, 0, star);
|
| 101 |
+
module = __Pyx_Import(name, from_list, 0);
|
| 102 |
+
Py_DECREF(from_list);
|
| 103 |
+
return module;
|
| 104 |
+
#else
|
| 105 |
+
PyObject *imported_module;
|
| 106 |
+
PyObject *module = __Pyx_Import(name, NULL, 0);
|
| 107 |
+
if (!parts_tuple || unlikely(!module))
|
| 108 |
+
return module;
|
| 109 |
+
|
| 110 |
+
// Look up module in sys.modules, which is safer than the attribute lookups below.
|
| 111 |
+
imported_module = __Pyx__ImportDottedModule_Lookup(name);
|
| 112 |
+
if (likely(imported_module)) {
|
| 113 |
+
Py_DECREF(module);
|
| 114 |
+
return imported_module;
|
| 115 |
+
}
|
| 116 |
+
PyErr_Clear();
|
| 117 |
+
return __Pyx_ImportDottedModule_WalkParts(module, name, parts_tuple);
|
| 118 |
+
#endif
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
static PyObject *__Pyx_ImportDottedModule(PyObject *name, PyObject *parts_tuple) {
|
| 122 |
+
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030400B1
|
| 123 |
+
PyObject *module = __Pyx__ImportDottedModule_Lookup(name);
|
| 124 |
+
if (likely(module)) {
|
| 125 |
+
// CPython guards against thread-concurrent initialisation in importlib.
|
| 126 |
+
// In this case, we let PyImport_ImportModuleLevelObject() handle the locking.
|
| 127 |
+
PyObject *spec = __Pyx_PyObject_GetAttrStrNoError(module, PYIDENT("__spec__"));
|
| 128 |
+
if (likely(spec)) {
|
| 129 |
+
PyObject *unsafe = __Pyx_PyObject_GetAttrStrNoError(spec, PYIDENT("_initializing"));
|
| 130 |
+
if (likely(!unsafe || !__Pyx_PyObject_IsTrue(unsafe))) {
|
| 131 |
+
Py_DECREF(spec);
|
| 132 |
+
spec = NULL;
|
| 133 |
+
}
|
| 134 |
+
Py_XDECREF(unsafe);
|
| 135 |
+
}
|
| 136 |
+
if (likely(!spec)) {
|
| 137 |
+
// Not in initialisation phase => use modules as is.
|
| 138 |
+
PyErr_Clear();
|
| 139 |
+
return module;
|
| 140 |
+
}
|
| 141 |
+
Py_DECREF(spec);
|
| 142 |
+
Py_DECREF(module);
|
| 143 |
+
} else if (PyErr_Occurred()) {
|
| 144 |
+
PyErr_Clear();
|
| 145 |
+
}
|
| 146 |
+
#endif
|
| 147 |
+
|
| 148 |
+
return __Pyx__ImportDottedModule(name, parts_tuple);
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
/////////////// ImportDottedModuleRelFirst.proto ///////////////
|
| 153 |
+
|
| 154 |
+
static PyObject *__Pyx_ImportDottedModuleRelFirst(PyObject *name, PyObject *parts_tuple); /*proto*/
|
| 155 |
+
|
| 156 |
+
/////////////// ImportDottedModuleRelFirst ///////////////
|
| 157 |
+
//@requires: ImportDottedModule
|
| 158 |
+
//@requires: Import
|
| 159 |
+
|
| 160 |
+
static PyObject *__Pyx_ImportDottedModuleRelFirst(PyObject *name, PyObject *parts_tuple) {
|
| 161 |
+
PyObject *module;
|
| 162 |
+
PyObject *from_list = NULL;
|
| 163 |
+
#if PY_MAJOR_VERSION < 3
|
| 164 |
+
PyObject *star = PYIDENT("*");
|
| 165 |
+
from_list = PyList_New(1);
|
| 166 |
+
if (unlikely(!from_list))
|
| 167 |
+
return NULL;
|
| 168 |
+
Py_INCREF(star);
|
| 169 |
+
PyList_SET_ITEM(from_list, 0, star);
|
| 170 |
+
#endif
|
| 171 |
+
module = __Pyx_Import(name, from_list, -1);
|
| 172 |
+
Py_XDECREF(from_list);
|
| 173 |
+
if (module) {
|
| 174 |
+
#if PY_MAJOR_VERSION >= 3
|
| 175 |
+
if (parts_tuple) {
|
| 176 |
+
module = __Pyx_ImportDottedModule_WalkParts(module, name, parts_tuple);
|
| 177 |
+
}
|
| 178 |
+
#endif
|
| 179 |
+
return module;
|
| 180 |
+
}
|
| 181 |
+
if (unlikely(!PyErr_ExceptionMatches(PyExc_ImportError)))
|
| 182 |
+
return NULL;
|
| 183 |
+
PyErr_Clear();
|
| 184 |
+
// try absolute import
|
| 185 |
+
return __Pyx_ImportDottedModule(name, parts_tuple);
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
|
| 189 |
+
/////////////// Import.proto ///////////////
|
| 190 |
+
|
| 191 |
+
static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); /*proto*/
|
| 192 |
+
|
| 193 |
+
/////////////// Import ///////////////
|
| 194 |
+
//@requires: ObjectHandling.c::PyObjectGetAttrStr
|
| 195 |
+
//@requires:StringTools.c::IncludeStringH
|
| 196 |
+
//@substitute: naming
|
| 197 |
+
|
| 198 |
+
static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) {
|
| 199 |
+
PyObject *module = 0;
|
| 200 |
+
PyObject *empty_dict = 0;
|
| 201 |
+
PyObject *empty_list = 0;
|
| 202 |
+
#if PY_MAJOR_VERSION < 3
|
| 203 |
+
PyObject *py_import;
|
| 204 |
+
py_import = __Pyx_PyObject_GetAttrStr($builtins_cname, PYIDENT("__import__"));
|
| 205 |
+
if (unlikely(!py_import))
|
| 206 |
+
goto bad;
|
| 207 |
+
if (!from_list) {
|
| 208 |
+
empty_list = PyList_New(0);
|
| 209 |
+
if (unlikely(!empty_list))
|
| 210 |
+
goto bad;
|
| 211 |
+
from_list = empty_list;
|
| 212 |
+
}
|
| 213 |
+
#endif
|
| 214 |
+
empty_dict = PyDict_New();
|
| 215 |
+
if (unlikely(!empty_dict))
|
| 216 |
+
goto bad;
|
| 217 |
+
{
|
| 218 |
+
#if PY_MAJOR_VERSION >= 3
|
| 219 |
+
if (level == -1) {
|
| 220 |
+
if (strchr(__Pyx_MODULE_NAME, '.') != NULL) {
|
| 221 |
+
/* try package relative import first */
|
| 222 |
+
module = PyImport_ImportModuleLevelObject(
|
| 223 |
+
name, $moddict_cname, empty_dict, from_list, 1);
|
| 224 |
+
if (unlikely(!module)) {
|
| 225 |
+
if (unlikely(!PyErr_ExceptionMatches(PyExc_ImportError)))
|
| 226 |
+
goto bad;
|
| 227 |
+
PyErr_Clear();
|
| 228 |
+
}
|
| 229 |
+
}
|
| 230 |
+
level = 0; /* try absolute import on failure */
|
| 231 |
+
}
|
| 232 |
+
#endif
|
| 233 |
+
if (!module) {
|
| 234 |
+
#if PY_MAJOR_VERSION < 3
|
| 235 |
+
PyObject *py_level = PyInt_FromLong(level);
|
| 236 |
+
if (unlikely(!py_level))
|
| 237 |
+
goto bad;
|
| 238 |
+
module = PyObject_CallFunctionObjArgs(py_import,
|
| 239 |
+
name, $moddict_cname, empty_dict, from_list, py_level, (PyObject *)NULL);
|
| 240 |
+
Py_DECREF(py_level);
|
| 241 |
+
#else
|
| 242 |
+
module = PyImport_ImportModuleLevelObject(
|
| 243 |
+
name, $moddict_cname, empty_dict, from_list, level);
|
| 244 |
+
#endif
|
| 245 |
+
}
|
| 246 |
+
}
|
| 247 |
+
bad:
|
| 248 |
+
Py_XDECREF(empty_dict);
|
| 249 |
+
Py_XDECREF(empty_list);
|
| 250 |
+
#if PY_MAJOR_VERSION < 3
|
| 251 |
+
Py_XDECREF(py_import);
|
| 252 |
+
#endif
|
| 253 |
+
return module;
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
|
| 257 |
+
/////////////// ImportFrom.proto ///////////////
|
| 258 |
+
|
| 259 |
+
static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name); /*proto*/
|
| 260 |
+
|
| 261 |
+
/////////////// ImportFrom ///////////////
|
| 262 |
+
//@requires: ObjectHandling.c::PyObjectGetAttrStr
|
| 263 |
+
|
| 264 |
+
static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name) {
|
| 265 |
+
PyObject* value = __Pyx_PyObject_GetAttrStr(module, name);
|
| 266 |
+
if (unlikely(!value) && PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
| 267 |
+
// 'name' may refer to a (sub-)module which has not finished initialization
|
| 268 |
+
// yet, and may not be assigned as an attribute to its parent, so try
|
| 269 |
+
// finding it by full name.
|
| 270 |
+
const char* module_name_str = 0;
|
| 271 |
+
PyObject* module_name = 0;
|
| 272 |
+
PyObject* module_dot = 0;
|
| 273 |
+
PyObject* full_name = 0;
|
| 274 |
+
PyErr_Clear();
|
| 275 |
+
module_name_str = PyModule_GetName(module);
|
| 276 |
+
if (unlikely(!module_name_str)) { goto modbad; }
|
| 277 |
+
module_name = PyUnicode_FromString(module_name_str);
|
| 278 |
+
if (unlikely(!module_name)) { goto modbad; }
|
| 279 |
+
module_dot = PyUnicode_Concat(module_name, PYUNICODE("."));
|
| 280 |
+
if (unlikely(!module_dot)) { goto modbad; }
|
| 281 |
+
full_name = PyUnicode_Concat(module_dot, name);
|
| 282 |
+
if (unlikely(!full_name)) { goto modbad; }
|
| 283 |
+
#if PY_VERSION_HEX < 0x030700A1 || (CYTHON_COMPILING_IN_PYPY && PYPY_VERSION_NUM < 0x07030400)
|
| 284 |
+
{
|
| 285 |
+
PyObject *modules = PyImport_GetModuleDict();
|
| 286 |
+
if (unlikely(!modules))
|
| 287 |
+
goto modbad;
|
| 288 |
+
value = PyObject_GetItem(modules, full_name);
|
| 289 |
+
}
|
| 290 |
+
#else
|
| 291 |
+
value = PyImport_GetModule(full_name);
|
| 292 |
+
#endif
|
| 293 |
+
|
| 294 |
+
modbad:
|
| 295 |
+
Py_XDECREF(full_name);
|
| 296 |
+
Py_XDECREF(module_dot);
|
| 297 |
+
Py_XDECREF(module_name);
|
| 298 |
+
}
|
| 299 |
+
if (unlikely(!value)) {
|
| 300 |
+
PyErr_Format(PyExc_ImportError,
|
| 301 |
+
#if PY_MAJOR_VERSION < 3
|
| 302 |
+
"cannot import name %.230s", PyString_AS_STRING(name));
|
| 303 |
+
#else
|
| 304 |
+
"cannot import name %S", name);
|
| 305 |
+
#endif
|
| 306 |
+
}
|
| 307 |
+
return value;
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
+
|
| 311 |
+
/////////////// ImportStar ///////////////
|
| 312 |
+
//@substitute: naming
|
| 313 |
+
|
| 314 |
+
/* import_all_from is an unexposed function from ceval.c */
|
| 315 |
+
|
| 316 |
+
static int
|
| 317 |
+
__Pyx_import_all_from(PyObject *locals, PyObject *v)
|
| 318 |
+
{
|
| 319 |
+
PyObject *all = PyObject_GetAttrString(v, "__all__");
|
| 320 |
+
PyObject *dict, *name, *value;
|
| 321 |
+
int skip_leading_underscores = 0;
|
| 322 |
+
int pos, err;
|
| 323 |
+
|
| 324 |
+
if (all == NULL) {
|
| 325 |
+
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
|
| 326 |
+
return -1; /* Unexpected error */
|
| 327 |
+
PyErr_Clear();
|
| 328 |
+
dict = PyObject_GetAttrString(v, "__dict__");
|
| 329 |
+
if (dict == NULL) {
|
| 330 |
+
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
|
| 331 |
+
return -1;
|
| 332 |
+
PyErr_SetString(PyExc_ImportError,
|
| 333 |
+
"from-import-* object has no __dict__ and no __all__");
|
| 334 |
+
return -1;
|
| 335 |
+
}
|
| 336 |
+
#if PY_MAJOR_VERSION < 3
|
| 337 |
+
all = PyObject_CallMethod(dict, (char *)"keys", NULL);
|
| 338 |
+
#else
|
| 339 |
+
all = PyMapping_Keys(dict);
|
| 340 |
+
#endif
|
| 341 |
+
Py_DECREF(dict);
|
| 342 |
+
if (all == NULL)
|
| 343 |
+
return -1;
|
| 344 |
+
skip_leading_underscores = 1;
|
| 345 |
+
}
|
| 346 |
+
|
| 347 |
+
for (pos = 0, err = 0; ; pos++) {
|
| 348 |
+
name = PySequence_GetItem(all, pos);
|
| 349 |
+
if (name == NULL) {
|
| 350 |
+
if (!PyErr_ExceptionMatches(PyExc_IndexError))
|
| 351 |
+
err = -1;
|
| 352 |
+
else
|
| 353 |
+
PyErr_Clear();
|
| 354 |
+
break;
|
| 355 |
+
}
|
| 356 |
+
if (skip_leading_underscores &&
|
| 357 |
+
#if PY_MAJOR_VERSION < 3
|
| 358 |
+
likely(PyString_Check(name)) &&
|
| 359 |
+
PyString_AS_STRING(name)[0] == '_')
|
| 360 |
+
#else
|
| 361 |
+
likely(PyUnicode_Check(name)) &&
|
| 362 |
+
likely(__Pyx_PyUnicode_GET_LENGTH(name)) &&
|
| 363 |
+
__Pyx_PyUnicode_READ_CHAR(name, 0) == '_')
|
| 364 |
+
#endif
|
| 365 |
+
{
|
| 366 |
+
Py_DECREF(name);
|
| 367 |
+
continue;
|
| 368 |
+
}
|
| 369 |
+
value = PyObject_GetAttr(v, name);
|
| 370 |
+
if (value == NULL)
|
| 371 |
+
err = -1;
|
| 372 |
+
else if (PyDict_CheckExact(locals))
|
| 373 |
+
err = PyDict_SetItem(locals, name, value);
|
| 374 |
+
else
|
| 375 |
+
err = PyObject_SetItem(locals, name, value);
|
| 376 |
+
Py_DECREF(name);
|
| 377 |
+
Py_XDECREF(value);
|
| 378 |
+
if (err != 0)
|
| 379 |
+
break;
|
| 380 |
+
}
|
| 381 |
+
Py_DECREF(all);
|
| 382 |
+
return err;
|
| 383 |
+
}
|
| 384 |
+
|
| 385 |
+
|
| 386 |
+
static int ${import_star}(PyObject* m) {
|
| 387 |
+
|
| 388 |
+
int i;
|
| 389 |
+
int ret = -1;
|
| 390 |
+
char* s;
|
| 391 |
+
PyObject *locals = 0;
|
| 392 |
+
PyObject *list = 0;
|
| 393 |
+
#if PY_MAJOR_VERSION >= 3
|
| 394 |
+
PyObject *utf8_name = 0;
|
| 395 |
+
#endif
|
| 396 |
+
PyObject *name;
|
| 397 |
+
PyObject *item;
|
| 398 |
+
|
| 399 |
+
locals = PyDict_New(); if (!locals) goto bad;
|
| 400 |
+
if (__Pyx_import_all_from(locals, m) < 0) goto bad;
|
| 401 |
+
list = PyDict_Items(locals); if (!list) goto bad;
|
| 402 |
+
|
| 403 |
+
for(i=0; i<PyList_GET_SIZE(list); i++) {
|
| 404 |
+
name = PyTuple_GET_ITEM(PyList_GET_ITEM(list, i), 0);
|
| 405 |
+
item = PyTuple_GET_ITEM(PyList_GET_ITEM(list, i), 1);
|
| 406 |
+
#if PY_MAJOR_VERSION >= 3
|
| 407 |
+
utf8_name = PyUnicode_AsUTF8String(name);
|
| 408 |
+
if (!utf8_name) goto bad;
|
| 409 |
+
s = PyBytes_AS_STRING(utf8_name);
|
| 410 |
+
if (${import_star_set}(item, name, s) < 0) goto bad;
|
| 411 |
+
Py_DECREF(utf8_name); utf8_name = 0;
|
| 412 |
+
#else
|
| 413 |
+
s = PyString_AsString(name);
|
| 414 |
+
if (!s) goto bad;
|
| 415 |
+
if (${import_star_set}(item, name, s) < 0) goto bad;
|
| 416 |
+
#endif
|
| 417 |
+
}
|
| 418 |
+
ret = 0;
|
| 419 |
+
|
| 420 |
+
bad:
|
| 421 |
+
Py_XDECREF(locals);
|
| 422 |
+
Py_XDECREF(list);
|
| 423 |
+
#if PY_MAJOR_VERSION >= 3
|
| 424 |
+
Py_XDECREF(utf8_name);
|
| 425 |
+
#endif
|
| 426 |
+
return ret;
|
| 427 |
+
}
|
| 428 |
+
|
| 429 |
+
|
| 430 |
+
/////////////// SetPackagePathFromImportLib.proto ///////////////
|
| 431 |
+
|
| 432 |
+
// PY_VERSION_HEX >= 0x03030000
|
| 433 |
+
#if PY_MAJOR_VERSION >= 3 && !CYTHON_PEP489_MULTI_PHASE_INIT
|
| 434 |
+
static int __Pyx_SetPackagePathFromImportLib(PyObject *module_name);
|
| 435 |
+
#else
|
| 436 |
+
#define __Pyx_SetPackagePathFromImportLib(a) 0
|
| 437 |
+
#endif
|
| 438 |
+
|
| 439 |
+
/////////////// SetPackagePathFromImportLib ///////////////
|
| 440 |
+
//@substitute: naming
|
| 441 |
+
|
| 442 |
+
// PY_VERSION_HEX >= 0x03030000
|
| 443 |
+
#if PY_MAJOR_VERSION >= 3 && !CYTHON_PEP489_MULTI_PHASE_INIT
|
| 444 |
+
static int __Pyx_SetPackagePathFromImportLib(PyObject *module_name) {
|
| 445 |
+
PyObject *importlib, *osmod, *ossep, *parts, *package_path;
|
| 446 |
+
PyObject *file_path = NULL;
|
| 447 |
+
int result;
|
| 448 |
+
PyObject *spec;
|
| 449 |
+
// package_path = [importlib.util.find_spec(module_name).origin.rsplit(os.sep, 1)[0]]
|
| 450 |
+
importlib = PyImport_ImportModule("importlib.util");
|
| 451 |
+
if (unlikely(!importlib))
|
| 452 |
+
goto bad;
|
| 453 |
+
spec = PyObject_CallMethod(importlib, "find_spec", "(O)", module_name);
|
| 454 |
+
Py_DECREF(importlib);
|
| 455 |
+
if (unlikely(!spec))
|
| 456 |
+
goto bad;
|
| 457 |
+
file_path = PyObject_GetAttrString(spec, "origin");
|
| 458 |
+
Py_DECREF(spec);
|
| 459 |
+
if (unlikely(!file_path))
|
| 460 |
+
goto bad;
|
| 461 |
+
|
| 462 |
+
if (unlikely(PyObject_SetAttrString($module_cname, "__file__", file_path) < 0))
|
| 463 |
+
goto bad;
|
| 464 |
+
|
| 465 |
+
osmod = PyImport_ImportModule("os");
|
| 466 |
+
if (unlikely(!osmod))
|
| 467 |
+
goto bad;
|
| 468 |
+
ossep = PyObject_GetAttrString(osmod, "sep");
|
| 469 |
+
Py_DECREF(osmod);
|
| 470 |
+
if (unlikely(!ossep))
|
| 471 |
+
goto bad;
|
| 472 |
+
parts = PyObject_CallMethod(file_path, "rsplit", "(Oi)", ossep, 1);
|
| 473 |
+
Py_DECREF(file_path); file_path = NULL;
|
| 474 |
+
Py_DECREF(ossep);
|
| 475 |
+
if (unlikely(!parts))
|
| 476 |
+
goto bad;
|
| 477 |
+
package_path = Py_BuildValue("[O]", PyList_GET_ITEM(parts, 0));
|
| 478 |
+
Py_DECREF(parts);
|
| 479 |
+
if (unlikely(!package_path))
|
| 480 |
+
goto bad;
|
| 481 |
+
goto set_path;
|
| 482 |
+
|
| 483 |
+
bad:
|
| 484 |
+
PyErr_WriteUnraisable(module_name);
|
| 485 |
+
Py_XDECREF(file_path);
|
| 486 |
+
|
| 487 |
+
// set an empty path list on failure
|
| 488 |
+
PyErr_Clear();
|
| 489 |
+
package_path = PyList_New(0);
|
| 490 |
+
if (unlikely(!package_path))
|
| 491 |
+
return -1;
|
| 492 |
+
|
| 493 |
+
set_path:
|
| 494 |
+
result = PyObject_SetAttrString($module_cname, "__path__", package_path);
|
| 495 |
+
Py_DECREF(package_path);
|
| 496 |
+
return result;
|
| 497 |
+
}
|
| 498 |
+
#endif
|
| 499 |
+
|
| 500 |
+
|
| 501 |
+
/////////////// TypeImport.proto ///////////////
|
| 502 |
+
//@substitute: naming
|
| 503 |
+
|
| 504 |
+
#ifndef __PYX_HAVE_RT_ImportType_proto_$cyversion
|
| 505 |
+
#define __PYX_HAVE_RT_ImportType_proto_$cyversion
|
| 506 |
+
|
| 507 |
+
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
| 508 |
+
#include <stdalign.h>
|
| 509 |
+
#endif
|
| 510 |
+
|
| 511 |
+
#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || __cplusplus >= 201103L
|
| 512 |
+
#define __PYX_GET_STRUCT_ALIGNMENT_$cyversion(s) alignof(s)
|
| 513 |
+
#else
|
| 514 |
+
// best guess at what the alignment could be since we can't measure it
|
| 515 |
+
#define __PYX_GET_STRUCT_ALIGNMENT_$cyversion(s) sizeof(void*)
|
| 516 |
+
#endif
|
| 517 |
+
|
| 518 |
+
enum __Pyx_ImportType_CheckSize_$cyversion {
|
| 519 |
+
__Pyx_ImportType_CheckSize_Error_$cyversion = 0,
|
| 520 |
+
__Pyx_ImportType_CheckSize_Warn_$cyversion = 1,
|
| 521 |
+
__Pyx_ImportType_CheckSize_Ignore_$cyversion = 2
|
| 522 |
+
};
|
| 523 |
+
|
| 524 |
+
static PyTypeObject *__Pyx_ImportType_$cyversion(PyObject* module, const char *module_name, const char *class_name, size_t size, size_t alignment, enum __Pyx_ImportType_CheckSize_$cyversion check_size); /*proto*/
|
| 525 |
+
|
| 526 |
+
#endif
|
| 527 |
+
|
| 528 |
+
/////////////// TypeImport ///////////////
|
| 529 |
+
//@substitute: naming
|
| 530 |
+
|
| 531 |
+
#ifndef __PYX_HAVE_RT_ImportType_$cyversion
|
| 532 |
+
#define __PYX_HAVE_RT_ImportType_$cyversion
|
| 533 |
+
static PyTypeObject *__Pyx_ImportType_$cyversion(PyObject *module, const char *module_name, const char *class_name,
|
| 534 |
+
size_t size, size_t alignment, enum __Pyx_ImportType_CheckSize_$cyversion check_size)
|
| 535 |
+
{
|
| 536 |
+
PyObject *result = 0;
|
| 537 |
+
char warning[200];
|
| 538 |
+
Py_ssize_t basicsize;
|
| 539 |
+
Py_ssize_t itemsize;
|
| 540 |
+
#if CYTHON_COMPILING_IN_LIMITED_API
|
| 541 |
+
PyObject *py_basicsize;
|
| 542 |
+
PyObject *py_itemsize;
|
| 543 |
+
#endif
|
| 544 |
+
|
| 545 |
+
result = PyObject_GetAttrString(module, class_name);
|
| 546 |
+
if (!result)
|
| 547 |
+
goto bad;
|
| 548 |
+
if (!PyType_Check(result)) {
|
| 549 |
+
PyErr_Format(PyExc_TypeError,
|
| 550 |
+
"%.200s.%.200s is not a type object",
|
| 551 |
+
module_name, class_name);
|
| 552 |
+
goto bad;
|
| 553 |
+
}
|
| 554 |
+
#if !CYTHON_COMPILING_IN_LIMITED_API
|
| 555 |
+
basicsize = ((PyTypeObject *)result)->tp_basicsize;
|
| 556 |
+
itemsize = ((PyTypeObject *)result)->tp_itemsize;
|
| 557 |
+
#else
|
| 558 |
+
py_basicsize = PyObject_GetAttrString(result, "__basicsize__");
|
| 559 |
+
if (!py_basicsize)
|
| 560 |
+
goto bad;
|
| 561 |
+
basicsize = PyLong_AsSsize_t(py_basicsize);
|
| 562 |
+
Py_DECREF(py_basicsize);
|
| 563 |
+
py_basicsize = 0;
|
| 564 |
+
if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred())
|
| 565 |
+
goto bad;
|
| 566 |
+
py_itemsize = PyObject_GetAttrString(result, "__itemsize__");
|
| 567 |
+
if (!py_itemsize)
|
| 568 |
+
goto bad;
|
| 569 |
+
itemsize = PyLong_AsSsize_t(py_itemsize);
|
| 570 |
+
Py_DECREF(py_itemsize);
|
| 571 |
+
py_itemsize = 0;
|
| 572 |
+
if (itemsize == (Py_ssize_t)-1 && PyErr_Occurred())
|
| 573 |
+
goto bad;
|
| 574 |
+
#endif
|
| 575 |
+
if (itemsize) {
|
| 576 |
+
// If itemsize is smaller than the alignment the struct can end up with some extra
|
| 577 |
+
// padding at the end. In this case we need to work out the maximum size that
|
| 578 |
+
// the padding could be when calculating the range of valid struct sizes.
|
| 579 |
+
if (size % alignment) {
|
| 580 |
+
// if this is true we've probably calculated the alignment wrongly
|
| 581 |
+
// (most likely because alignof isn't available)
|
| 582 |
+
alignment = size % alignment;
|
| 583 |
+
}
|
| 584 |
+
if (itemsize < (Py_ssize_t)alignment)
|
| 585 |
+
itemsize = (Py_ssize_t)alignment;
|
| 586 |
+
}
|
| 587 |
+
if ((size_t)(basicsize + itemsize) < size) {
|
| 588 |
+
PyErr_Format(PyExc_ValueError,
|
| 589 |
+
"%.200s.%.200s size changed, may indicate binary incompatibility. "
|
| 590 |
+
"Expected %zd from C header, got %zd from PyObject",
|
| 591 |
+
module_name, class_name, size, basicsize+itemsize);
|
| 592 |
+
goto bad;
|
| 593 |
+
}
|
| 594 |
+
// varobjects almost have structs between basicsize and basicsize + itemsize
|
| 595 |
+
// but the struct isn't always one of the two limiting values
|
| 596 |
+
if (check_size == __Pyx_ImportType_CheckSize_Error_$cyversion &&
|
| 597 |
+
((size_t)basicsize > size || (size_t)(basicsize + itemsize) < size)) {
|
| 598 |
+
PyErr_Format(PyExc_ValueError,
|
| 599 |
+
"%.200s.%.200s size changed, may indicate binary incompatibility. "
|
| 600 |
+
"Expected %zd from C header, got %zd-%zd from PyObject",
|
| 601 |
+
module_name, class_name, size, basicsize, basicsize+itemsize);
|
| 602 |
+
goto bad;
|
| 603 |
+
}
|
| 604 |
+
else if (check_size == __Pyx_ImportType_CheckSize_Warn_$cyversion && (size_t)basicsize > size) {
|
| 605 |
+
PyOS_snprintf(warning, sizeof(warning),
|
| 606 |
+
"%s.%s size changed, may indicate binary incompatibility. "
|
| 607 |
+
"Expected %zd from C header, got %zd from PyObject",
|
| 608 |
+
module_name, class_name, size, basicsize);
|
| 609 |
+
if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad;
|
| 610 |
+
}
|
| 611 |
+
/* check_size == __Pyx_ImportType_CheckSize_Ignore does not warn nor error */
|
| 612 |
+
return (PyTypeObject *)result;
|
| 613 |
+
bad:
|
| 614 |
+
Py_XDECREF(result);
|
| 615 |
+
return NULL;
|
| 616 |
+
}
|
| 617 |
+
#endif
|
| 618 |
+
|
| 619 |
+
/////////////// FunctionImport.proto ///////////////
|
| 620 |
+
//@substitute: naming
|
| 621 |
+
|
| 622 |
+
static int __Pyx_ImportFunction_$cyversion(PyObject *module, const char *funcname, void (**f)(void), const char *sig); /*proto*/
|
| 623 |
+
|
| 624 |
+
/////////////// FunctionImport ///////////////
|
| 625 |
+
//@substitute: naming
|
| 626 |
+
|
| 627 |
+
#ifndef __PYX_HAVE_RT_ImportFunction_$cyversion
|
| 628 |
+
#define __PYX_HAVE_RT_ImportFunction_$cyversion
|
| 629 |
+
static int __Pyx_ImportFunction_$cyversion(PyObject *module, const char *funcname, void (**f)(void), const char *sig) {
|
| 630 |
+
PyObject *d = 0;
|
| 631 |
+
PyObject *cobj = 0;
|
| 632 |
+
union {
|
| 633 |
+
void (*fp)(void);
|
| 634 |
+
void *p;
|
| 635 |
+
} tmp;
|
| 636 |
+
|
| 637 |
+
d = PyObject_GetAttrString(module, (char *)"$api_name");
|
| 638 |
+
if (!d)
|
| 639 |
+
goto bad;
|
| 640 |
+
cobj = PyDict_GetItemString(d, funcname);
|
| 641 |
+
if (!cobj) {
|
| 642 |
+
PyErr_Format(PyExc_ImportError,
|
| 643 |
+
"%.200s does not export expected C function %.200s",
|
| 644 |
+
PyModule_GetName(module), funcname);
|
| 645 |
+
goto bad;
|
| 646 |
+
}
|
| 647 |
+
if (!PyCapsule_IsValid(cobj, sig)) {
|
| 648 |
+
PyErr_Format(PyExc_TypeError,
|
| 649 |
+
"C function %.200s.%.200s has wrong signature (expected %.500s, got %.500s)",
|
| 650 |
+
PyModule_GetName(module), funcname, sig, PyCapsule_GetName(cobj));
|
| 651 |
+
goto bad;
|
| 652 |
+
}
|
| 653 |
+
tmp.p = PyCapsule_GetPointer(cobj, sig);
|
| 654 |
+
*f = tmp.fp;
|
| 655 |
+
if (!(*f))
|
| 656 |
+
goto bad;
|
| 657 |
+
Py_DECREF(d);
|
| 658 |
+
return 0;
|
| 659 |
+
bad:
|
| 660 |
+
Py_XDECREF(d);
|
| 661 |
+
return -1;
|
| 662 |
+
}
|
| 663 |
+
#endif
|
| 664 |
+
|
| 665 |
+
/////////////// FunctionExport.proto ///////////////
|
| 666 |
+
|
| 667 |
+
static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *sig); /*proto*/
|
| 668 |
+
|
| 669 |
+
/////////////// FunctionExport ///////////////
|
| 670 |
+
//@substitute: naming
|
| 671 |
+
|
| 672 |
+
static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *sig) {
|
| 673 |
+
PyObject *d = 0;
|
| 674 |
+
PyObject *cobj = 0;
|
| 675 |
+
union {
|
| 676 |
+
void (*fp)(void);
|
| 677 |
+
void *p;
|
| 678 |
+
} tmp;
|
| 679 |
+
|
| 680 |
+
d = PyObject_GetAttrString($module_cname, (char *)"$api_name");
|
| 681 |
+
if (!d) {
|
| 682 |
+
PyErr_Clear();
|
| 683 |
+
d = PyDict_New();
|
| 684 |
+
if (!d)
|
| 685 |
+
goto bad;
|
| 686 |
+
Py_INCREF(d);
|
| 687 |
+
if (PyModule_AddObject($module_cname, (char *)"$api_name", d) < 0)
|
| 688 |
+
goto bad;
|
| 689 |
+
}
|
| 690 |
+
tmp.fp = f;
|
| 691 |
+
cobj = PyCapsule_New(tmp.p, sig, 0);
|
| 692 |
+
if (!cobj)
|
| 693 |
+
goto bad;
|
| 694 |
+
if (PyDict_SetItemString(d, name, cobj) < 0)
|
| 695 |
+
goto bad;
|
| 696 |
+
Py_DECREF(cobj);
|
| 697 |
+
Py_DECREF(d);
|
| 698 |
+
return 0;
|
| 699 |
+
bad:
|
| 700 |
+
Py_XDECREF(cobj);
|
| 701 |
+
Py_XDECREF(d);
|
| 702 |
+
return -1;
|
| 703 |
+
}
|
| 704 |
+
|
| 705 |
+
/////////////// VoidPtrImport.proto ///////////////
|
| 706 |
+
//@substitute: naming
|
| 707 |
+
|
| 708 |
+
static int __Pyx_ImportVoidPtr_$cyversion(PyObject *module, const char *name, void **p, const char *sig); /*proto*/
|
| 709 |
+
|
| 710 |
+
/////////////// VoidPtrImport ///////////////
|
| 711 |
+
//@substitute: naming
|
| 712 |
+
|
| 713 |
+
#ifndef __PYX_HAVE_RT_ImportVoidPtr_$cyversion
|
| 714 |
+
#define __PYX_HAVE_RT_ImportVoidPtr_$cyversion
|
| 715 |
+
static int __Pyx_ImportVoidPtr_$cyversion(PyObject *module, const char *name, void **p, const char *sig) {
|
| 716 |
+
PyObject *d = 0;
|
| 717 |
+
PyObject *cobj = 0;
|
| 718 |
+
|
| 719 |
+
d = PyObject_GetAttrString(module, (char *)"$api_name");
|
| 720 |
+
if (!d)
|
| 721 |
+
goto bad;
|
| 722 |
+
cobj = PyDict_GetItemString(d, name);
|
| 723 |
+
if (!cobj) {
|
| 724 |
+
PyErr_Format(PyExc_ImportError,
|
| 725 |
+
"%.200s does not export expected C variable %.200s",
|
| 726 |
+
PyModule_GetName(module), name);
|
| 727 |
+
goto bad;
|
| 728 |
+
}
|
| 729 |
+
if (!PyCapsule_IsValid(cobj, sig)) {
|
| 730 |
+
PyErr_Format(PyExc_TypeError,
|
| 731 |
+
"C variable %.200s.%.200s has wrong signature (expected %.500s, got %.500s)",
|
| 732 |
+
PyModule_GetName(module), name, sig, PyCapsule_GetName(cobj));
|
| 733 |
+
goto bad;
|
| 734 |
+
}
|
| 735 |
+
*p = PyCapsule_GetPointer(cobj, sig);
|
| 736 |
+
if (!(*p))
|
| 737 |
+
goto bad;
|
| 738 |
+
Py_DECREF(d);
|
| 739 |
+
return 0;
|
| 740 |
+
bad:
|
| 741 |
+
Py_XDECREF(d);
|
| 742 |
+
return -1;
|
| 743 |
+
}
|
| 744 |
+
#endif
|
| 745 |
+
|
| 746 |
+
/////////////// VoidPtrExport.proto ///////////////
|
| 747 |
+
|
| 748 |
+
static int __Pyx_ExportVoidPtr(PyObject *name, void *p, const char *sig); /*proto*/
|
| 749 |
+
|
| 750 |
+
/////////////// VoidPtrExport ///////////////
|
| 751 |
+
//@substitute: naming
|
| 752 |
+
//@requires: ObjectHandling.c::PyObjectSetAttrStr
|
| 753 |
+
|
| 754 |
+
static int __Pyx_ExportVoidPtr(PyObject *name, void *p, const char *sig) {
|
| 755 |
+
PyObject *d;
|
| 756 |
+
PyObject *cobj = 0;
|
| 757 |
+
|
| 758 |
+
d = PyDict_GetItem($moddict_cname, PYIDENT("$api_name"));
|
| 759 |
+
Py_XINCREF(d);
|
| 760 |
+
if (!d) {
|
| 761 |
+
d = PyDict_New();
|
| 762 |
+
if (!d)
|
| 763 |
+
goto bad;
|
| 764 |
+
if (__Pyx_PyObject_SetAttrStr($module_cname, PYIDENT("$api_name"), d) < 0)
|
| 765 |
+
goto bad;
|
| 766 |
+
}
|
| 767 |
+
cobj = PyCapsule_New(p, sig, 0);
|
| 768 |
+
if (!cobj)
|
| 769 |
+
goto bad;
|
| 770 |
+
if (PyDict_SetItem(d, name, cobj) < 0)
|
| 771 |
+
goto bad;
|
| 772 |
+
Py_DECREF(cobj);
|
| 773 |
+
Py_DECREF(d);
|
| 774 |
+
return 0;
|
| 775 |
+
bad:
|
| 776 |
+
Py_XDECREF(cobj);
|
| 777 |
+
Py_XDECREF(d);
|
| 778 |
+
return -1;
|
| 779 |
+
}
|
| 780 |
+
|
| 781 |
+
|
| 782 |
+
/////////////// SetVTable.proto ///////////////
|
| 783 |
+
|
| 784 |
+
static int __Pyx_SetVtable(PyTypeObject* typeptr , void* vtable); /*proto*/
|
| 785 |
+
|
| 786 |
+
/////////////// SetVTable ///////////////
|
| 787 |
+
|
| 788 |
+
static int __Pyx_SetVtable(PyTypeObject *type, void *vtable) {
|
| 789 |
+
PyObject *ob = PyCapsule_New(vtable, 0, 0);
|
| 790 |
+
if (unlikely(!ob))
|
| 791 |
+
goto bad;
|
| 792 |
+
#if CYTHON_COMPILING_IN_LIMITED_API
|
| 793 |
+
if (unlikely(PyObject_SetAttr((PyObject *) type, PYIDENT("__pyx_vtable__"), ob) < 0))
|
| 794 |
+
#else
|
| 795 |
+
if (unlikely(PyDict_SetItem(type->tp_dict, PYIDENT("__pyx_vtable__"), ob) < 0))
|
| 796 |
+
#endif
|
| 797 |
+
goto bad;
|
| 798 |
+
Py_DECREF(ob);
|
| 799 |
+
return 0;
|
| 800 |
+
bad:
|
| 801 |
+
Py_XDECREF(ob);
|
| 802 |
+
return -1;
|
| 803 |
+
}
|
| 804 |
+
|
| 805 |
+
|
| 806 |
+
/////////////// GetVTable.proto ///////////////
|
| 807 |
+
|
| 808 |
+
static void* __Pyx_GetVtable(PyTypeObject *type); /*proto*/
|
| 809 |
+
|
| 810 |
+
/////////////// GetVTable ///////////////
|
| 811 |
+
|
| 812 |
+
static void* __Pyx_GetVtable(PyTypeObject *type) {
|
| 813 |
+
void* ptr;
|
| 814 |
+
#if CYTHON_COMPILING_IN_LIMITED_API
|
| 815 |
+
PyObject *ob = PyObject_GetAttr((PyObject *)type, PYIDENT("__pyx_vtable__"));
|
| 816 |
+
#else
|
| 817 |
+
PyObject *ob = PyObject_GetItem(type->tp_dict, PYIDENT("__pyx_vtable__"));
|
| 818 |
+
#endif
|
| 819 |
+
if (!ob)
|
| 820 |
+
goto bad;
|
| 821 |
+
ptr = PyCapsule_GetPointer(ob, 0);
|
| 822 |
+
if (!ptr && !PyErr_Occurred())
|
| 823 |
+
PyErr_SetString(PyExc_RuntimeError, "invalid vtable found for imported type");
|
| 824 |
+
Py_DECREF(ob);
|
| 825 |
+
return ptr;
|
| 826 |
+
bad:
|
| 827 |
+
Py_XDECREF(ob);
|
| 828 |
+
return NULL;
|
| 829 |
+
}
|
| 830 |
+
|
| 831 |
+
|
| 832 |
+
/////////////// MergeVTables.proto ///////////////
|
| 833 |
+
//@requires: GetVTable
|
| 834 |
+
|
| 835 |
+
// TODO: find a way to make this work with the Limited API!
|
| 836 |
+
#if !CYTHON_COMPILING_IN_LIMITED_API
|
| 837 |
+
static int __Pyx_MergeVtables(PyTypeObject *type); /*proto*/
|
| 838 |
+
#endif
|
| 839 |
+
|
| 840 |
+
/////////////// MergeVTables ///////////////
|
| 841 |
+
|
| 842 |
+
#if !CYTHON_COMPILING_IN_LIMITED_API
|
| 843 |
+
static int __Pyx_MergeVtables(PyTypeObject *type) {
|
| 844 |
+
int i;
|
| 845 |
+
void** base_vtables;
|
| 846 |
+
__Pyx_TypeName tp_base_name;
|
| 847 |
+
__Pyx_TypeName base_name;
|
| 848 |
+
void* unknown = (void*)-1;
|
| 849 |
+
PyObject* bases = type->tp_bases;
|
| 850 |
+
int base_depth = 0;
|
| 851 |
+
{
|
| 852 |
+
PyTypeObject* base = type->tp_base;
|
| 853 |
+
while (base) {
|
| 854 |
+
base_depth += 1;
|
| 855 |
+
base = base->tp_base;
|
| 856 |
+
}
|
| 857 |
+
}
|
| 858 |
+
base_vtables = (void**) malloc(sizeof(void*) * (size_t)(base_depth + 1));
|
| 859 |
+
base_vtables[0] = unknown;
|
| 860 |
+
// Could do MRO resolution of individual methods in the future, assuming
|
| 861 |
+
// compatible vtables, but for now simply require a common vtable base.
|
| 862 |
+
// Note that if the vtables of various bases are extended separately,
|
| 863 |
+
// resolution isn't possible and we must reject it just as when the
|
| 864 |
+
// instance struct is so extended. (It would be good to also do this
|
| 865 |
+
// check when a multiple-base class is created in pure Python as well.)
|
| 866 |
+
for (i = 1; i < PyTuple_GET_SIZE(bases); i++) {
|
| 867 |
+
void* base_vtable = __Pyx_GetVtable(((PyTypeObject*)PyTuple_GET_ITEM(bases, i)));
|
| 868 |
+
if (base_vtable != NULL) {
|
| 869 |
+
int j;
|
| 870 |
+
PyTypeObject* base = type->tp_base;
|
| 871 |
+
for (j = 0; j < base_depth; j++) {
|
| 872 |
+
if (base_vtables[j] == unknown) {
|
| 873 |
+
base_vtables[j] = __Pyx_GetVtable(base);
|
| 874 |
+
base_vtables[j + 1] = unknown;
|
| 875 |
+
}
|
| 876 |
+
if (base_vtables[j] == base_vtable) {
|
| 877 |
+
break;
|
| 878 |
+
} else if (base_vtables[j] == NULL) {
|
| 879 |
+
// No more potential matching bases (with vtables).
|
| 880 |
+
goto bad;
|
| 881 |
+
}
|
| 882 |
+
base = base->tp_base;
|
| 883 |
+
}
|
| 884 |
+
}
|
| 885 |
+
}
|
| 886 |
+
PyErr_Clear();
|
| 887 |
+
free(base_vtables);
|
| 888 |
+
return 0;
|
| 889 |
+
bad:
|
| 890 |
+
tp_base_name = __Pyx_PyType_GetName(type->tp_base);
|
| 891 |
+
base_name = __Pyx_PyType_GetName((PyTypeObject*)PyTuple_GET_ITEM(bases, i));
|
| 892 |
+
PyErr_Format(PyExc_TypeError,
|
| 893 |
+
"multiple bases have vtable conflict: '" __Pyx_FMT_TYPENAME "' and '" __Pyx_FMT_TYPENAME "'", tp_base_name, base_name);
|
| 894 |
+
__Pyx_DECREF_TypeName(tp_base_name);
|
| 895 |
+
__Pyx_DECREF_TypeName(base_name);
|
| 896 |
+
free(base_vtables);
|
| 897 |
+
return -1;
|
| 898 |
+
}
|
| 899 |
+
#endif
|
| 900 |
+
|
| 901 |
+
|
| 902 |
+
/////////////// ImportNumPyArray.proto ///////////////
|
| 903 |
+
|
| 904 |
+
static PyObject *__pyx_numpy_ndarray = NULL;
|
| 905 |
+
|
| 906 |
+
static PyObject* __Pyx_ImportNumPyArrayTypeIfAvailable(void); /*proto*/
|
| 907 |
+
|
| 908 |
+
/////////////// ImportNumPyArray.cleanup ///////////////
|
| 909 |
+
Py_CLEAR(__pyx_numpy_ndarray);
|
| 910 |
+
|
| 911 |
+
/////////////// ImportNumPyArray ///////////////
|
| 912 |
+
//@requires: ImportExport.c::Import
|
| 913 |
+
|
| 914 |
+
static PyObject* __Pyx__ImportNumPyArray(void) {
|
| 915 |
+
PyObject *numpy_module, *ndarray_object = NULL;
|
| 916 |
+
numpy_module = __Pyx_Import(PYIDENT("numpy"), NULL, 0);
|
| 917 |
+
if (likely(numpy_module)) {
|
| 918 |
+
ndarray_object = PyObject_GetAttrString(numpy_module, "ndarray");
|
| 919 |
+
Py_DECREF(numpy_module);
|
| 920 |
+
}
|
| 921 |
+
if (unlikely(!ndarray_object)) {
|
| 922 |
+
// ImportError, AttributeError, ...
|
| 923 |
+
PyErr_Clear();
|
| 924 |
+
}
|
| 925 |
+
if (unlikely(!ndarray_object || !PyObject_TypeCheck(ndarray_object, &PyType_Type))) {
|
| 926 |
+
Py_XDECREF(ndarray_object);
|
| 927 |
+
Py_INCREF(Py_None);
|
| 928 |
+
ndarray_object = Py_None;
|
| 929 |
+
}
|
| 930 |
+
return ndarray_object;
|
| 931 |
+
}
|
| 932 |
+
|
| 933 |
+
static CYTHON_INLINE PyObject* __Pyx_ImportNumPyArrayTypeIfAvailable(void) {
|
| 934 |
+
if (unlikely(!__pyx_numpy_ndarray)) {
|
| 935 |
+
__pyx_numpy_ndarray = __Pyx__ImportNumPyArray();
|
| 936 |
+
}
|
| 937 |
+
Py_INCREF(__pyx_numpy_ndarray);
|
| 938 |
+
return __pyx_numpy_ndarray;
|
| 939 |
+
}
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/simple_paths.cpython-311.pyc
ADDED
|
Binary file (37.3 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/__pycache__/walks.cpython-311.pyc
ADDED
|
Binary file (3.4 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/__init__.py
ADDED
|
File without changes
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/__pycache__/test_hybrid.cpython-311.pyc
ADDED
|
Binary file (1.52 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/__pycache__/test_link_prediction.cpython-311.pyc
ADDED
|
Binary file (40 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/__pycache__/test_polynomials.cpython-311.pyc
ADDED
|
Binary file (3.87 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/__pycache__/test_walks.cpython-311.pyc
ADDED
|
Binary file (3.13 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/__pycache__/test_wiener.cpython-311.pyc
ADDED
|
Binary file (2.97 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_asteroidal.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import networkx as nx
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def test_is_at_free():
|
| 5 |
+
is_at_free = nx.asteroidal.is_at_free
|
| 6 |
+
|
| 7 |
+
cycle = nx.cycle_graph(6)
|
| 8 |
+
assert not is_at_free(cycle)
|
| 9 |
+
|
| 10 |
+
path = nx.path_graph(6)
|
| 11 |
+
assert is_at_free(path)
|
| 12 |
+
|
| 13 |
+
small_graph = nx.complete_graph(2)
|
| 14 |
+
assert is_at_free(small_graph)
|
| 15 |
+
|
| 16 |
+
petersen = nx.petersen_graph()
|
| 17 |
+
assert not is_at_free(petersen)
|
| 18 |
+
|
| 19 |
+
clique = nx.complete_graph(6)
|
| 20 |
+
assert is_at_free(clique)
|
| 21 |
+
|
| 22 |
+
line_clique = nx.line_graph(clique)
|
| 23 |
+
assert not is_at_free(line_clique)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_bridges.py
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Unit tests for bridge-finding algorithms."""
|
| 2 |
+
|
| 3 |
+
import pytest
|
| 4 |
+
|
| 5 |
+
import networkx as nx
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class TestBridges:
|
| 9 |
+
"""Unit tests for the bridge-finding function."""
|
| 10 |
+
|
| 11 |
+
def test_single_bridge(self):
|
| 12 |
+
edges = [
|
| 13 |
+
# DFS tree edges.
|
| 14 |
+
(1, 2),
|
| 15 |
+
(2, 3),
|
| 16 |
+
(3, 4),
|
| 17 |
+
(3, 5),
|
| 18 |
+
(5, 6),
|
| 19 |
+
(6, 7),
|
| 20 |
+
(7, 8),
|
| 21 |
+
(5, 9),
|
| 22 |
+
(9, 10),
|
| 23 |
+
# Nontree edges.
|
| 24 |
+
(1, 3),
|
| 25 |
+
(1, 4),
|
| 26 |
+
(2, 5),
|
| 27 |
+
(5, 10),
|
| 28 |
+
(6, 8),
|
| 29 |
+
]
|
| 30 |
+
G = nx.Graph(edges)
|
| 31 |
+
source = 1
|
| 32 |
+
bridges = list(nx.bridges(G, source))
|
| 33 |
+
assert bridges == [(5, 6)]
|
| 34 |
+
|
| 35 |
+
def test_barbell_graph(self):
|
| 36 |
+
# The (3, 0) barbell graph has two triangles joined by a single edge.
|
| 37 |
+
G = nx.barbell_graph(3, 0)
|
| 38 |
+
source = 0
|
| 39 |
+
bridges = list(nx.bridges(G, source))
|
| 40 |
+
assert bridges == [(2, 3)]
|
| 41 |
+
|
| 42 |
+
def test_multiedge_bridge(self):
|
| 43 |
+
edges = [
|
| 44 |
+
(0, 1),
|
| 45 |
+
(0, 2),
|
| 46 |
+
(1, 2),
|
| 47 |
+
(1, 2),
|
| 48 |
+
(2, 3),
|
| 49 |
+
(3, 4),
|
| 50 |
+
(3, 4),
|
| 51 |
+
]
|
| 52 |
+
G = nx.MultiGraph(edges)
|
| 53 |
+
assert list(nx.bridges(G)) == [(2, 3)]
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
class TestHasBridges:
|
| 57 |
+
"""Unit tests for the has bridges function."""
|
| 58 |
+
|
| 59 |
+
def test_single_bridge(self):
|
| 60 |
+
edges = [
|
| 61 |
+
# DFS tree edges.
|
| 62 |
+
(1, 2),
|
| 63 |
+
(2, 3),
|
| 64 |
+
(3, 4),
|
| 65 |
+
(3, 5),
|
| 66 |
+
(5, 6), # The only bridge edge
|
| 67 |
+
(6, 7),
|
| 68 |
+
(7, 8),
|
| 69 |
+
(5, 9),
|
| 70 |
+
(9, 10),
|
| 71 |
+
# Nontree edges.
|
| 72 |
+
(1, 3),
|
| 73 |
+
(1, 4),
|
| 74 |
+
(2, 5),
|
| 75 |
+
(5, 10),
|
| 76 |
+
(6, 8),
|
| 77 |
+
]
|
| 78 |
+
G = nx.Graph(edges)
|
| 79 |
+
assert nx.has_bridges(G) # Default root
|
| 80 |
+
assert nx.has_bridges(G, root=1) # arbitrary root in G
|
| 81 |
+
|
| 82 |
+
def test_has_bridges_raises_root_not_in_G(self):
|
| 83 |
+
G = nx.Graph()
|
| 84 |
+
G.add_nodes_from([1, 2, 3])
|
| 85 |
+
with pytest.raises(nx.NodeNotFound):
|
| 86 |
+
nx.has_bridges(G, root=6)
|
| 87 |
+
|
| 88 |
+
def test_multiedge_bridge(self):
|
| 89 |
+
edges = [
|
| 90 |
+
(0, 1),
|
| 91 |
+
(0, 2),
|
| 92 |
+
(1, 2),
|
| 93 |
+
(1, 2),
|
| 94 |
+
(2, 3),
|
| 95 |
+
(3, 4),
|
| 96 |
+
(3, 4),
|
| 97 |
+
]
|
| 98 |
+
G = nx.MultiGraph(edges)
|
| 99 |
+
assert nx.has_bridges(G)
|
| 100 |
+
# Make every edge a multiedge
|
| 101 |
+
G.add_edges_from([(0, 1), (0, 2), (2, 3)])
|
| 102 |
+
assert not nx.has_bridges(G)
|
| 103 |
+
|
| 104 |
+
def test_bridges_multiple_components(self):
|
| 105 |
+
G = nx.Graph()
|
| 106 |
+
nx.add_path(G, [0, 1, 2]) # One connected component
|
| 107 |
+
nx.add_path(G, [4, 5, 6]) # Another connected component
|
| 108 |
+
assert list(nx.bridges(G, root=4)) == [(4, 5), (5, 6)]
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
class TestLocalBridges:
|
| 112 |
+
"""Unit tests for the local_bridge function."""
|
| 113 |
+
|
| 114 |
+
@classmethod
|
| 115 |
+
def setup_class(cls):
|
| 116 |
+
cls.BB = nx.barbell_graph(4, 0)
|
| 117 |
+
cls.square = nx.cycle_graph(4)
|
| 118 |
+
cls.tri = nx.cycle_graph(3)
|
| 119 |
+
|
| 120 |
+
def test_nospan(self):
|
| 121 |
+
expected = {(3, 4), (4, 3)}
|
| 122 |
+
assert next(nx.local_bridges(self.BB, with_span=False)) in expected
|
| 123 |
+
assert set(nx.local_bridges(self.square, with_span=False)) == self.square.edges
|
| 124 |
+
assert list(nx.local_bridges(self.tri, with_span=False)) == []
|
| 125 |
+
|
| 126 |
+
def test_no_weight(self):
|
| 127 |
+
inf = float("inf")
|
| 128 |
+
expected = {(3, 4, inf), (4, 3, inf)}
|
| 129 |
+
assert next(nx.local_bridges(self.BB)) in expected
|
| 130 |
+
expected = {(u, v, 3) for u, v, in self.square.edges}
|
| 131 |
+
assert set(nx.local_bridges(self.square)) == expected
|
| 132 |
+
assert list(nx.local_bridges(self.tri)) == []
|
| 133 |
+
|
| 134 |
+
def test_weight(self):
|
| 135 |
+
inf = float("inf")
|
| 136 |
+
G = self.square.copy()
|
| 137 |
+
|
| 138 |
+
G.edges[1, 2]["weight"] = 2
|
| 139 |
+
expected = {(u, v, 5 - wt) for u, v, wt in G.edges(data="weight", default=1)}
|
| 140 |
+
assert set(nx.local_bridges(G, weight="weight")) == expected
|
| 141 |
+
|
| 142 |
+
expected = {(u, v, 6) for u, v in G.edges}
|
| 143 |
+
lb = nx.local_bridges(G, weight=lambda u, v, d: 2)
|
| 144 |
+
assert set(lb) == expected
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_clique.py
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pytest
|
| 2 |
+
|
| 3 |
+
import networkx as nx
|
| 4 |
+
from networkx import convert_node_labels_to_integers as cnlti
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class TestCliques:
|
| 8 |
+
def setup_method(self):
|
| 9 |
+
z = [3, 4, 3, 4, 2, 4, 2, 1, 1, 1, 1]
|
| 10 |
+
self.G = cnlti(nx.generators.havel_hakimi_graph(z), first_label=1)
|
| 11 |
+
self.cl = list(nx.find_cliques(self.G))
|
| 12 |
+
H = nx.complete_graph(6)
|
| 13 |
+
H = nx.relabel_nodes(H, {i: i + 1 for i in range(6)})
|
| 14 |
+
H.remove_edges_from([(2, 6), (2, 5), (2, 4), (1, 3), (5, 3)])
|
| 15 |
+
self.H = H
|
| 16 |
+
|
| 17 |
+
def test_find_cliques1(self):
|
| 18 |
+
cl = list(nx.find_cliques(self.G))
|
| 19 |
+
rcl = nx.find_cliques_recursive(self.G)
|
| 20 |
+
expected = [[2, 6, 1, 3], [2, 6, 4], [5, 4, 7], [8, 9], [10, 11]]
|
| 21 |
+
assert sorted(map(sorted, cl)) == sorted(map(sorted, rcl))
|
| 22 |
+
assert sorted(map(sorted, cl)) == sorted(map(sorted, expected))
|
| 23 |
+
|
| 24 |
+
def test_selfloops(self):
|
| 25 |
+
self.G.add_edge(1, 1)
|
| 26 |
+
cl = list(nx.find_cliques(self.G))
|
| 27 |
+
rcl = list(nx.find_cliques_recursive(self.G))
|
| 28 |
+
assert set(map(frozenset, cl)) == set(map(frozenset, rcl))
|
| 29 |
+
answer = [{2, 6, 1, 3}, {2, 6, 4}, {5, 4, 7}, {8, 9}, {10, 11}]
|
| 30 |
+
assert len(answer) == len(cl)
|
| 31 |
+
assert all(set(c) in answer for c in cl)
|
| 32 |
+
|
| 33 |
+
def test_find_cliques2(self):
|
| 34 |
+
hcl = list(nx.find_cliques(self.H))
|
| 35 |
+
assert sorted(map(sorted, hcl)) == [[1, 2], [1, 4, 5, 6], [2, 3], [3, 4, 6]]
|
| 36 |
+
|
| 37 |
+
def test_find_cliques3(self):
|
| 38 |
+
# all cliques are [[2, 6, 1, 3], [2, 6, 4], [5, 4, 7], [8, 9], [10, 11]]
|
| 39 |
+
|
| 40 |
+
cl = list(nx.find_cliques(self.G, [2]))
|
| 41 |
+
rcl = nx.find_cliques_recursive(self.G, [2])
|
| 42 |
+
expected = [[2, 6, 1, 3], [2, 6, 4]]
|
| 43 |
+
assert sorted(map(sorted, rcl)) == sorted(map(sorted, expected))
|
| 44 |
+
assert sorted(map(sorted, cl)) == sorted(map(sorted, expected))
|
| 45 |
+
|
| 46 |
+
cl = list(nx.find_cliques(self.G, [2, 3]))
|
| 47 |
+
rcl = nx.find_cliques_recursive(self.G, [2, 3])
|
| 48 |
+
expected = [[2, 6, 1, 3]]
|
| 49 |
+
assert sorted(map(sorted, rcl)) == sorted(map(sorted, expected))
|
| 50 |
+
assert sorted(map(sorted, cl)) == sorted(map(sorted, expected))
|
| 51 |
+
|
| 52 |
+
cl = list(nx.find_cliques(self.G, [2, 6, 4]))
|
| 53 |
+
rcl = nx.find_cliques_recursive(self.G, [2, 6, 4])
|
| 54 |
+
expected = [[2, 6, 4]]
|
| 55 |
+
assert sorted(map(sorted, rcl)) == sorted(map(sorted, expected))
|
| 56 |
+
assert sorted(map(sorted, cl)) == sorted(map(sorted, expected))
|
| 57 |
+
|
| 58 |
+
cl = list(nx.find_cliques(self.G, [2, 6, 4]))
|
| 59 |
+
rcl = nx.find_cliques_recursive(self.G, [2, 6, 4])
|
| 60 |
+
expected = [[2, 6, 4]]
|
| 61 |
+
assert sorted(map(sorted, rcl)) == sorted(map(sorted, expected))
|
| 62 |
+
assert sorted(map(sorted, cl)) == sorted(map(sorted, expected))
|
| 63 |
+
|
| 64 |
+
with pytest.raises(ValueError):
|
| 65 |
+
list(nx.find_cliques(self.G, [2, 6, 4, 1]))
|
| 66 |
+
|
| 67 |
+
with pytest.raises(ValueError):
|
| 68 |
+
list(nx.find_cliques_recursive(self.G, [2, 6, 4, 1]))
|
| 69 |
+
|
| 70 |
+
def test_number_of_cliques(self):
|
| 71 |
+
G = self.G
|
| 72 |
+
assert nx.number_of_cliques(G, 1) == 1
|
| 73 |
+
assert list(nx.number_of_cliques(G, [1]).values()) == [1]
|
| 74 |
+
assert list(nx.number_of_cliques(G, [1, 2]).values()) == [1, 2]
|
| 75 |
+
assert nx.number_of_cliques(G, [1, 2]) == {1: 1, 2: 2}
|
| 76 |
+
assert nx.number_of_cliques(G, 2) == 2
|
| 77 |
+
assert nx.number_of_cliques(G) == {
|
| 78 |
+
1: 1,
|
| 79 |
+
2: 2,
|
| 80 |
+
3: 1,
|
| 81 |
+
4: 2,
|
| 82 |
+
5: 1,
|
| 83 |
+
6: 2,
|
| 84 |
+
7: 1,
|
| 85 |
+
8: 1,
|
| 86 |
+
9: 1,
|
| 87 |
+
10: 1,
|
| 88 |
+
11: 1,
|
| 89 |
+
}
|
| 90 |
+
assert nx.number_of_cliques(G, nodes=list(G)) == {
|
| 91 |
+
1: 1,
|
| 92 |
+
2: 2,
|
| 93 |
+
3: 1,
|
| 94 |
+
4: 2,
|
| 95 |
+
5: 1,
|
| 96 |
+
6: 2,
|
| 97 |
+
7: 1,
|
| 98 |
+
8: 1,
|
| 99 |
+
9: 1,
|
| 100 |
+
10: 1,
|
| 101 |
+
11: 1,
|
| 102 |
+
}
|
| 103 |
+
assert nx.number_of_cliques(G, nodes=[2, 3, 4]) == {2: 2, 3: 1, 4: 2}
|
| 104 |
+
assert nx.number_of_cliques(G, cliques=self.cl) == {
|
| 105 |
+
1: 1,
|
| 106 |
+
2: 2,
|
| 107 |
+
3: 1,
|
| 108 |
+
4: 2,
|
| 109 |
+
5: 1,
|
| 110 |
+
6: 2,
|
| 111 |
+
7: 1,
|
| 112 |
+
8: 1,
|
| 113 |
+
9: 1,
|
| 114 |
+
10: 1,
|
| 115 |
+
11: 1,
|
| 116 |
+
}
|
| 117 |
+
assert nx.number_of_cliques(G, list(G), cliques=self.cl) == {
|
| 118 |
+
1: 1,
|
| 119 |
+
2: 2,
|
| 120 |
+
3: 1,
|
| 121 |
+
4: 2,
|
| 122 |
+
5: 1,
|
| 123 |
+
6: 2,
|
| 124 |
+
7: 1,
|
| 125 |
+
8: 1,
|
| 126 |
+
9: 1,
|
| 127 |
+
10: 1,
|
| 128 |
+
11: 1,
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
def test_node_clique_number(self):
|
| 132 |
+
G = self.G
|
| 133 |
+
assert nx.node_clique_number(G, 1) == 4
|
| 134 |
+
assert list(nx.node_clique_number(G, [1]).values()) == [4]
|
| 135 |
+
assert list(nx.node_clique_number(G, [1, 2]).values()) == [4, 4]
|
| 136 |
+
assert nx.node_clique_number(G, [1, 2]) == {1: 4, 2: 4}
|
| 137 |
+
assert nx.node_clique_number(G, 1) == 4
|
| 138 |
+
assert nx.node_clique_number(G) == {
|
| 139 |
+
1: 4,
|
| 140 |
+
2: 4,
|
| 141 |
+
3: 4,
|
| 142 |
+
4: 3,
|
| 143 |
+
5: 3,
|
| 144 |
+
6: 4,
|
| 145 |
+
7: 3,
|
| 146 |
+
8: 2,
|
| 147 |
+
9: 2,
|
| 148 |
+
10: 2,
|
| 149 |
+
11: 2,
|
| 150 |
+
}
|
| 151 |
+
assert nx.node_clique_number(G, cliques=self.cl) == {
|
| 152 |
+
1: 4,
|
| 153 |
+
2: 4,
|
| 154 |
+
3: 4,
|
| 155 |
+
4: 3,
|
| 156 |
+
5: 3,
|
| 157 |
+
6: 4,
|
| 158 |
+
7: 3,
|
| 159 |
+
8: 2,
|
| 160 |
+
9: 2,
|
| 161 |
+
10: 2,
|
| 162 |
+
11: 2,
|
| 163 |
+
}
|
| 164 |
+
assert nx.node_clique_number(G, [1, 2], cliques=self.cl) == {1: 4, 2: 4}
|
| 165 |
+
assert nx.node_clique_number(G, 1, cliques=self.cl) == 4
|
| 166 |
+
|
| 167 |
+
def test_make_clique_bipartite(self):
|
| 168 |
+
G = self.G
|
| 169 |
+
B = nx.make_clique_bipartite(G)
|
| 170 |
+
assert sorted(B) == [-5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
| 171 |
+
# Project onto the nodes of the original graph.
|
| 172 |
+
H = nx.projected_graph(B, range(1, 12))
|
| 173 |
+
assert H.adj == G.adj
|
| 174 |
+
# Project onto the nodes representing the cliques.
|
| 175 |
+
H1 = nx.projected_graph(B, range(-5, 0))
|
| 176 |
+
# Relabel the negative numbers as positive ones.
|
| 177 |
+
H1 = nx.relabel_nodes(H1, {-v: v for v in range(1, 6)})
|
| 178 |
+
assert sorted(H1) == [1, 2, 3, 4, 5]
|
| 179 |
+
|
| 180 |
+
def test_make_max_clique_graph(self):
|
| 181 |
+
"""Tests that the maximal clique graph is the same as the bipartite
|
| 182 |
+
clique graph after being projected onto the nodes representing the
|
| 183 |
+
cliques.
|
| 184 |
+
|
| 185 |
+
"""
|
| 186 |
+
G = self.G
|
| 187 |
+
B = nx.make_clique_bipartite(G)
|
| 188 |
+
# Project onto the nodes representing the cliques.
|
| 189 |
+
H1 = nx.projected_graph(B, range(-5, 0))
|
| 190 |
+
# Relabel the negative numbers as nonnegative ones, starting at
|
| 191 |
+
# 0.
|
| 192 |
+
H1 = nx.relabel_nodes(H1, {-v: v - 1 for v in range(1, 6)})
|
| 193 |
+
H2 = nx.make_max_clique_graph(G)
|
| 194 |
+
assert H1.adj == H2.adj
|
| 195 |
+
|
| 196 |
+
def test_directed(self):
|
| 197 |
+
with pytest.raises(nx.NetworkXNotImplemented):
|
| 198 |
+
next(nx.find_cliques(nx.DiGraph()))
|
| 199 |
+
|
| 200 |
+
def test_find_cliques_trivial(self):
|
| 201 |
+
G = nx.Graph()
|
| 202 |
+
assert sorted(nx.find_cliques(G)) == []
|
| 203 |
+
assert sorted(nx.find_cliques_recursive(G)) == []
|
| 204 |
+
|
| 205 |
+
def test_make_max_clique_graph_create_using(self):
|
| 206 |
+
G = nx.Graph([(1, 2), (3, 1), (4, 1), (5, 6)])
|
| 207 |
+
E = nx.Graph([(0, 1), (0, 2), (1, 2)])
|
| 208 |
+
E.add_node(3)
|
| 209 |
+
assert nx.is_isomorphic(nx.make_max_clique_graph(G, create_using=nx.Graph), E)
|
| 210 |
+
|
| 211 |
+
|
| 212 |
+
class TestEnumerateAllCliques:
|
| 213 |
+
def test_paper_figure_4(self):
|
| 214 |
+
# Same graph as given in Fig. 4 of paper enumerate_all_cliques is
|
| 215 |
+
# based on.
|
| 216 |
+
# http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=1559964&isnumber=33129
|
| 217 |
+
G = nx.Graph()
|
| 218 |
+
edges_fig_4 = [
|
| 219 |
+
("a", "b"),
|
| 220 |
+
("a", "c"),
|
| 221 |
+
("a", "d"),
|
| 222 |
+
("a", "e"),
|
| 223 |
+
("b", "c"),
|
| 224 |
+
("b", "d"),
|
| 225 |
+
("b", "e"),
|
| 226 |
+
("c", "d"),
|
| 227 |
+
("c", "e"),
|
| 228 |
+
("d", "e"),
|
| 229 |
+
("f", "b"),
|
| 230 |
+
("f", "c"),
|
| 231 |
+
("f", "g"),
|
| 232 |
+
("g", "f"),
|
| 233 |
+
("g", "c"),
|
| 234 |
+
("g", "d"),
|
| 235 |
+
("g", "e"),
|
| 236 |
+
]
|
| 237 |
+
G.add_edges_from(edges_fig_4)
|
| 238 |
+
|
| 239 |
+
cliques = list(nx.enumerate_all_cliques(G))
|
| 240 |
+
clique_sizes = list(map(len, cliques))
|
| 241 |
+
assert sorted(clique_sizes) == clique_sizes
|
| 242 |
+
|
| 243 |
+
expected_cliques = [
|
| 244 |
+
["a"],
|
| 245 |
+
["b"],
|
| 246 |
+
["c"],
|
| 247 |
+
["d"],
|
| 248 |
+
["e"],
|
| 249 |
+
["f"],
|
| 250 |
+
["g"],
|
| 251 |
+
["a", "b"],
|
| 252 |
+
["a", "b", "d"],
|
| 253 |
+
["a", "b", "d", "e"],
|
| 254 |
+
["a", "b", "e"],
|
| 255 |
+
["a", "c"],
|
| 256 |
+
["a", "c", "d"],
|
| 257 |
+
["a", "c", "d", "e"],
|
| 258 |
+
["a", "c", "e"],
|
| 259 |
+
["a", "d"],
|
| 260 |
+
["a", "d", "e"],
|
| 261 |
+
["a", "e"],
|
| 262 |
+
["b", "c"],
|
| 263 |
+
["b", "c", "d"],
|
| 264 |
+
["b", "c", "d", "e"],
|
| 265 |
+
["b", "c", "e"],
|
| 266 |
+
["b", "c", "f"],
|
| 267 |
+
["b", "d"],
|
| 268 |
+
["b", "d", "e"],
|
| 269 |
+
["b", "e"],
|
| 270 |
+
["b", "f"],
|
| 271 |
+
["c", "d"],
|
| 272 |
+
["c", "d", "e"],
|
| 273 |
+
["c", "d", "e", "g"],
|
| 274 |
+
["c", "d", "g"],
|
| 275 |
+
["c", "e"],
|
| 276 |
+
["c", "e", "g"],
|
| 277 |
+
["c", "f"],
|
| 278 |
+
["c", "f", "g"],
|
| 279 |
+
["c", "g"],
|
| 280 |
+
["d", "e"],
|
| 281 |
+
["d", "e", "g"],
|
| 282 |
+
["d", "g"],
|
| 283 |
+
["e", "g"],
|
| 284 |
+
["f", "g"],
|
| 285 |
+
["a", "b", "c"],
|
| 286 |
+
["a", "b", "c", "d"],
|
| 287 |
+
["a", "b", "c", "d", "e"],
|
| 288 |
+
["a", "b", "c", "e"],
|
| 289 |
+
]
|
| 290 |
+
|
| 291 |
+
assert sorted(map(sorted, cliques)) == sorted(map(sorted, expected_cliques))
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_core.py
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pytest
|
| 2 |
+
|
| 3 |
+
import networkx as nx
|
| 4 |
+
from networkx.utils import nodes_equal
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class TestCore:
|
| 8 |
+
@classmethod
|
| 9 |
+
def setup_class(cls):
|
| 10 |
+
# G is the example graph in Figure 1 from Batagelj and
|
| 11 |
+
# Zaversnik's paper titled An O(m) Algorithm for Cores
|
| 12 |
+
# Decomposition of Networks, 2003,
|
| 13 |
+
# http://arXiv.org/abs/cs/0310049. With nodes labeled as
|
| 14 |
+
# shown, the 3-core is given by nodes 1-8, the 2-core by nodes
|
| 15 |
+
# 9-16, the 1-core by nodes 17-20 and node 21 is in the
|
| 16 |
+
# 0-core.
|
| 17 |
+
t1 = nx.convert_node_labels_to_integers(nx.tetrahedral_graph(), 1)
|
| 18 |
+
t2 = nx.convert_node_labels_to_integers(t1, 5)
|
| 19 |
+
G = nx.union(t1, t2)
|
| 20 |
+
G.add_edges_from(
|
| 21 |
+
[
|
| 22 |
+
(3, 7),
|
| 23 |
+
(2, 11),
|
| 24 |
+
(11, 5),
|
| 25 |
+
(11, 12),
|
| 26 |
+
(5, 12),
|
| 27 |
+
(12, 19),
|
| 28 |
+
(12, 18),
|
| 29 |
+
(3, 9),
|
| 30 |
+
(7, 9),
|
| 31 |
+
(7, 10),
|
| 32 |
+
(9, 10),
|
| 33 |
+
(9, 20),
|
| 34 |
+
(17, 13),
|
| 35 |
+
(13, 14),
|
| 36 |
+
(14, 15),
|
| 37 |
+
(15, 16),
|
| 38 |
+
(16, 13),
|
| 39 |
+
]
|
| 40 |
+
)
|
| 41 |
+
G.add_node(21)
|
| 42 |
+
cls.G = G
|
| 43 |
+
|
| 44 |
+
# Create the graph H resulting from the degree sequence
|
| 45 |
+
# [0, 1, 2, 2, 2, 2, 3] when using the Havel-Hakimi algorithm.
|
| 46 |
+
|
| 47 |
+
degseq = [0, 1, 2, 2, 2, 2, 3]
|
| 48 |
+
H = nx.havel_hakimi_graph(degseq)
|
| 49 |
+
mapping = {6: 0, 0: 1, 4: 3, 5: 6, 3: 4, 1: 2, 2: 5}
|
| 50 |
+
cls.H = nx.relabel_nodes(H, mapping)
|
| 51 |
+
|
| 52 |
+
def test_trivial(self):
|
| 53 |
+
"""Empty graph"""
|
| 54 |
+
G = nx.Graph()
|
| 55 |
+
assert nx.core_number(G) == {}
|
| 56 |
+
|
| 57 |
+
def test_core_number(self):
|
| 58 |
+
core = nx.core_number(self.G)
|
| 59 |
+
nodes_by_core = [sorted(n for n in core if core[n] == val) for val in range(4)]
|
| 60 |
+
assert nodes_equal(nodes_by_core[0], [21])
|
| 61 |
+
assert nodes_equal(nodes_by_core[1], [17, 18, 19, 20])
|
| 62 |
+
assert nodes_equal(nodes_by_core[2], [9, 10, 11, 12, 13, 14, 15, 16])
|
| 63 |
+
assert nodes_equal(nodes_by_core[3], [1, 2, 3, 4, 5, 6, 7, 8])
|
| 64 |
+
|
| 65 |
+
def test_core_number2(self):
|
| 66 |
+
core = nx.core_number(self.H)
|
| 67 |
+
nodes_by_core = [sorted(n for n in core if core[n] == val) for val in range(3)]
|
| 68 |
+
assert nodes_equal(nodes_by_core[0], [0])
|
| 69 |
+
assert nodes_equal(nodes_by_core[1], [1, 3])
|
| 70 |
+
assert nodes_equal(nodes_by_core[2], [2, 4, 5, 6])
|
| 71 |
+
|
| 72 |
+
def test_core_number_self_loop(self):
|
| 73 |
+
G = nx.cycle_graph(3)
|
| 74 |
+
G.add_edge(0, 0)
|
| 75 |
+
with pytest.raises(nx.NetworkXError, match="Input graph has self loops"):
|
| 76 |
+
nx.core_number(G)
|
| 77 |
+
|
| 78 |
+
def test_directed_core_number(self):
|
| 79 |
+
"""core number had a bug for directed graphs found in issue #1959"""
|
| 80 |
+
# small example where too timid edge removal can make cn[2] = 3
|
| 81 |
+
G = nx.DiGraph()
|
| 82 |
+
edges = [(1, 2), (2, 1), (2, 3), (2, 4), (3, 4), (4, 3)]
|
| 83 |
+
G.add_edges_from(edges)
|
| 84 |
+
assert nx.core_number(G) == {1: 2, 2: 2, 3: 2, 4: 2}
|
| 85 |
+
# small example where too aggressive edge removal can make cn[2] = 2
|
| 86 |
+
more_edges = [(1, 5), (3, 5), (4, 5), (3, 6), (4, 6), (5, 6)]
|
| 87 |
+
G.add_edges_from(more_edges)
|
| 88 |
+
assert nx.core_number(G) == {1: 3, 2: 3, 3: 3, 4: 3, 5: 3, 6: 3}
|
| 89 |
+
|
| 90 |
+
def test_main_core(self):
|
| 91 |
+
main_core_subgraph = nx.k_core(self.H)
|
| 92 |
+
assert sorted(main_core_subgraph.nodes()) == [2, 4, 5, 6]
|
| 93 |
+
|
| 94 |
+
def test_k_core(self):
|
| 95 |
+
# k=0
|
| 96 |
+
k_core_subgraph = nx.k_core(self.H, k=0)
|
| 97 |
+
assert sorted(k_core_subgraph.nodes()) == sorted(self.H.nodes())
|
| 98 |
+
# k=1
|
| 99 |
+
k_core_subgraph = nx.k_core(self.H, k=1)
|
| 100 |
+
assert sorted(k_core_subgraph.nodes()) == [1, 2, 3, 4, 5, 6]
|
| 101 |
+
# k = 2
|
| 102 |
+
k_core_subgraph = nx.k_core(self.H, k=2)
|
| 103 |
+
assert sorted(k_core_subgraph.nodes()) == [2, 4, 5, 6]
|
| 104 |
+
|
| 105 |
+
def test_main_crust(self):
|
| 106 |
+
main_crust_subgraph = nx.k_crust(self.H)
|
| 107 |
+
assert sorted(main_crust_subgraph.nodes()) == [0, 1, 3]
|
| 108 |
+
|
| 109 |
+
def test_k_crust(self):
|
| 110 |
+
# k = 0
|
| 111 |
+
k_crust_subgraph = nx.k_crust(self.H, k=2)
|
| 112 |
+
assert sorted(k_crust_subgraph.nodes()) == sorted(self.H.nodes())
|
| 113 |
+
# k=1
|
| 114 |
+
k_crust_subgraph = nx.k_crust(self.H, k=1)
|
| 115 |
+
assert sorted(k_crust_subgraph.nodes()) == [0, 1, 3]
|
| 116 |
+
# k=2
|
| 117 |
+
k_crust_subgraph = nx.k_crust(self.H, k=0)
|
| 118 |
+
assert sorted(k_crust_subgraph.nodes()) == [0]
|
| 119 |
+
|
| 120 |
+
def test_main_shell(self):
|
| 121 |
+
main_shell_subgraph = nx.k_shell(self.H)
|
| 122 |
+
assert sorted(main_shell_subgraph.nodes()) == [2, 4, 5, 6]
|
| 123 |
+
|
| 124 |
+
def test_k_shell(self):
|
| 125 |
+
# k=0
|
| 126 |
+
k_shell_subgraph = nx.k_shell(self.H, k=2)
|
| 127 |
+
assert sorted(k_shell_subgraph.nodes()) == [2, 4, 5, 6]
|
| 128 |
+
# k=1
|
| 129 |
+
k_shell_subgraph = nx.k_shell(self.H, k=1)
|
| 130 |
+
assert sorted(k_shell_subgraph.nodes()) == [1, 3]
|
| 131 |
+
# k=2
|
| 132 |
+
k_shell_subgraph = nx.k_shell(self.H, k=0)
|
| 133 |
+
assert sorted(k_shell_subgraph.nodes()) == [0]
|
| 134 |
+
|
| 135 |
+
def test_k_corona(self):
|
| 136 |
+
# k=0
|
| 137 |
+
k_corona_subgraph = nx.k_corona(self.H, k=2)
|
| 138 |
+
assert sorted(k_corona_subgraph.nodes()) == [2, 4, 5, 6]
|
| 139 |
+
# k=1
|
| 140 |
+
k_corona_subgraph = nx.k_corona(self.H, k=1)
|
| 141 |
+
assert sorted(k_corona_subgraph.nodes()) == [1]
|
| 142 |
+
# k=2
|
| 143 |
+
k_corona_subgraph = nx.k_corona(self.H, k=0)
|
| 144 |
+
assert sorted(k_corona_subgraph.nodes()) == [0]
|
| 145 |
+
|
| 146 |
+
def test_k_truss(self):
|
| 147 |
+
# k=-1
|
| 148 |
+
k_truss_subgraph = nx.k_truss(self.G, -1)
|
| 149 |
+
assert sorted(k_truss_subgraph.nodes()) == list(range(1, 21))
|
| 150 |
+
# k=0
|
| 151 |
+
k_truss_subgraph = nx.k_truss(self.G, 0)
|
| 152 |
+
assert sorted(k_truss_subgraph.nodes()) == list(range(1, 21))
|
| 153 |
+
# k=1
|
| 154 |
+
k_truss_subgraph = nx.k_truss(self.G, 1)
|
| 155 |
+
assert sorted(k_truss_subgraph.nodes()) == list(range(1, 21))
|
| 156 |
+
# k=2
|
| 157 |
+
k_truss_subgraph = nx.k_truss(self.G, 2)
|
| 158 |
+
assert sorted(k_truss_subgraph.nodes()) == list(range(1, 21))
|
| 159 |
+
# k=3
|
| 160 |
+
k_truss_subgraph = nx.k_truss(self.G, 3)
|
| 161 |
+
assert sorted(k_truss_subgraph.nodes()) == list(range(1, 13))
|
| 162 |
+
|
| 163 |
+
k_truss_subgraph = nx.k_truss(self.G, 4)
|
| 164 |
+
assert sorted(k_truss_subgraph.nodes()) == list(range(1, 9))
|
| 165 |
+
|
| 166 |
+
k_truss_subgraph = nx.k_truss(self.G, 5)
|
| 167 |
+
assert sorted(k_truss_subgraph.nodes()) == []
|
| 168 |
+
|
| 169 |
+
def test_onion_layers(self):
|
| 170 |
+
layers = nx.onion_layers(self.G)
|
| 171 |
+
nodes_by_layer = [
|
| 172 |
+
sorted(n for n in layers if layers[n] == val) for val in range(1, 7)
|
| 173 |
+
]
|
| 174 |
+
assert nodes_equal(nodes_by_layer[0], [21])
|
| 175 |
+
assert nodes_equal(nodes_by_layer[1], [17, 18, 19, 20])
|
| 176 |
+
assert nodes_equal(nodes_by_layer[2], [10, 12, 13, 14, 15, 16])
|
| 177 |
+
assert nodes_equal(nodes_by_layer[3], [9, 11])
|
| 178 |
+
assert nodes_equal(nodes_by_layer[4], [1, 2, 4, 5, 6, 8])
|
| 179 |
+
assert nodes_equal(nodes_by_layer[5], [3, 7])
|
| 180 |
+
|
| 181 |
+
def test_onion_self_loop(self):
|
| 182 |
+
G = nx.cycle_graph(3)
|
| 183 |
+
G.add_edge(0, 0)
|
| 184 |
+
with pytest.raises(nx.NetworkXError, match="Input graph contains self loops"):
|
| 185 |
+
nx.onion_layers(G)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_cycles.py
ADDED
|
@@ -0,0 +1,971 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from itertools import chain, islice, tee
|
| 2 |
+
from math import inf
|
| 3 |
+
from random import shuffle
|
| 4 |
+
|
| 5 |
+
import pytest
|
| 6 |
+
|
| 7 |
+
import networkx as nx
|
| 8 |
+
from networkx.algorithms.traversal.edgedfs import FORWARD, REVERSE
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def check_independent(basis):
|
| 12 |
+
if len(basis) == 0:
|
| 13 |
+
return
|
| 14 |
+
try:
|
| 15 |
+
import numpy as np
|
| 16 |
+
except ImportError:
|
| 17 |
+
return
|
| 18 |
+
|
| 19 |
+
H = nx.Graph()
|
| 20 |
+
for b in basis:
|
| 21 |
+
nx.add_cycle(H, b)
|
| 22 |
+
inc = nx.incidence_matrix(H, oriented=True)
|
| 23 |
+
rank = np.linalg.matrix_rank(inc.toarray(), tol=None, hermitian=False)
|
| 24 |
+
assert inc.shape[1] - rank == len(basis)
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
class TestCycles:
|
| 28 |
+
@classmethod
|
| 29 |
+
def setup_class(cls):
|
| 30 |
+
G = nx.Graph()
|
| 31 |
+
nx.add_cycle(G, [0, 1, 2, 3])
|
| 32 |
+
nx.add_cycle(G, [0, 3, 4, 5])
|
| 33 |
+
nx.add_cycle(G, [0, 1, 6, 7, 8])
|
| 34 |
+
G.add_edge(8, 9)
|
| 35 |
+
cls.G = G
|
| 36 |
+
|
| 37 |
+
def is_cyclic_permutation(self, a, b):
|
| 38 |
+
n = len(a)
|
| 39 |
+
if len(b) != n:
|
| 40 |
+
return False
|
| 41 |
+
l = a + a
|
| 42 |
+
return any(l[i : i + n] == b for i in range(n))
|
| 43 |
+
|
| 44 |
+
def test_cycle_basis(self):
|
| 45 |
+
G = self.G
|
| 46 |
+
cy = nx.cycle_basis(G, 0)
|
| 47 |
+
sort_cy = sorted(sorted(c) for c in cy)
|
| 48 |
+
assert sort_cy == [[0, 1, 2, 3], [0, 1, 6, 7, 8], [0, 3, 4, 5]]
|
| 49 |
+
cy = nx.cycle_basis(G, 1)
|
| 50 |
+
sort_cy = sorted(sorted(c) for c in cy)
|
| 51 |
+
assert sort_cy == [[0, 1, 2, 3], [0, 1, 6, 7, 8], [0, 3, 4, 5]]
|
| 52 |
+
cy = nx.cycle_basis(G, 9)
|
| 53 |
+
sort_cy = sorted(sorted(c) for c in cy)
|
| 54 |
+
assert sort_cy == [[0, 1, 2, 3], [0, 1, 6, 7, 8], [0, 3, 4, 5]]
|
| 55 |
+
# test disconnected graphs
|
| 56 |
+
nx.add_cycle(G, "ABC")
|
| 57 |
+
cy = nx.cycle_basis(G, 9)
|
| 58 |
+
sort_cy = sorted(sorted(c) for c in cy[:-1]) + [sorted(cy[-1])]
|
| 59 |
+
assert sort_cy == [[0, 1, 2, 3], [0, 1, 6, 7, 8], [0, 3, 4, 5], ["A", "B", "C"]]
|
| 60 |
+
|
| 61 |
+
def test_cycle_basis2(self):
|
| 62 |
+
with pytest.raises(nx.NetworkXNotImplemented):
|
| 63 |
+
G = nx.DiGraph()
|
| 64 |
+
cy = nx.cycle_basis(G, 0)
|
| 65 |
+
|
| 66 |
+
def test_cycle_basis3(self):
|
| 67 |
+
with pytest.raises(nx.NetworkXNotImplemented):
|
| 68 |
+
G = nx.MultiGraph()
|
| 69 |
+
cy = nx.cycle_basis(G, 0)
|
| 70 |
+
|
| 71 |
+
def test_cycle_basis_ordered(self):
|
| 72 |
+
# see gh-6654 replace sets with (ordered) dicts
|
| 73 |
+
G = nx.cycle_graph(5)
|
| 74 |
+
G.update(nx.cycle_graph(range(3, 8)))
|
| 75 |
+
cbG = nx.cycle_basis(G)
|
| 76 |
+
|
| 77 |
+
perm = {1: 0, 0: 1} # switch 0 and 1
|
| 78 |
+
H = nx.relabel_nodes(G, perm)
|
| 79 |
+
cbH = [[perm.get(n, n) for n in cyc] for cyc in nx.cycle_basis(H)]
|
| 80 |
+
assert cbG == cbH
|
| 81 |
+
|
| 82 |
+
def test_cycle_basis_self_loop(self):
|
| 83 |
+
"""Tests the function for graphs with self loops"""
|
| 84 |
+
G = nx.Graph()
|
| 85 |
+
nx.add_cycle(G, [0, 1, 2, 3])
|
| 86 |
+
nx.add_cycle(G, [0, 0, 6, 2])
|
| 87 |
+
cy = nx.cycle_basis(G)
|
| 88 |
+
sort_cy = sorted(sorted(c) for c in cy)
|
| 89 |
+
assert sort_cy == [[0], [0, 1, 2], [0, 2, 3], [0, 2, 6]]
|
| 90 |
+
|
| 91 |
+
def test_simple_cycles(self):
|
| 92 |
+
edges = [(0, 0), (0, 1), (0, 2), (1, 2), (2, 0), (2, 1), (2, 2)]
|
| 93 |
+
G = nx.DiGraph(edges)
|
| 94 |
+
cc = sorted(nx.simple_cycles(G))
|
| 95 |
+
ca = [[0], [0, 1, 2], [0, 2], [1, 2], [2]]
|
| 96 |
+
assert len(cc) == len(ca)
|
| 97 |
+
for c in cc:
|
| 98 |
+
assert any(self.is_cyclic_permutation(c, rc) for rc in ca)
|
| 99 |
+
|
| 100 |
+
def test_unsortable(self):
|
| 101 |
+
# this test ensures that graphs whose nodes without an intrinsic
|
| 102 |
+
# ordering do not cause issues
|
| 103 |
+
G = nx.DiGraph()
|
| 104 |
+
nx.add_cycle(G, ["a", 1])
|
| 105 |
+
c = list(nx.simple_cycles(G))
|
| 106 |
+
assert len(c) == 1
|
| 107 |
+
|
| 108 |
+
def test_simple_cycles_small(self):
|
| 109 |
+
G = nx.DiGraph()
|
| 110 |
+
nx.add_cycle(G, [1, 2, 3])
|
| 111 |
+
c = sorted(nx.simple_cycles(G))
|
| 112 |
+
assert len(c) == 1
|
| 113 |
+
assert self.is_cyclic_permutation(c[0], [1, 2, 3])
|
| 114 |
+
nx.add_cycle(G, [10, 20, 30])
|
| 115 |
+
cc = sorted(nx.simple_cycles(G))
|
| 116 |
+
assert len(cc) == 2
|
| 117 |
+
ca = [[1, 2, 3], [10, 20, 30]]
|
| 118 |
+
for c in cc:
|
| 119 |
+
assert any(self.is_cyclic_permutation(c, rc) for rc in ca)
|
| 120 |
+
|
| 121 |
+
def test_simple_cycles_empty(self):
|
| 122 |
+
G = nx.DiGraph()
|
| 123 |
+
assert list(nx.simple_cycles(G)) == []
|
| 124 |
+
|
| 125 |
+
def worst_case_graph(self, k):
|
| 126 |
+
# see figure 1 in Johnson's paper
|
| 127 |
+
# this graph has exactly 3k simple cycles
|
| 128 |
+
G = nx.DiGraph()
|
| 129 |
+
for n in range(2, k + 2):
|
| 130 |
+
G.add_edge(1, n)
|
| 131 |
+
G.add_edge(n, k + 2)
|
| 132 |
+
G.add_edge(2 * k + 1, 1)
|
| 133 |
+
for n in range(k + 2, 2 * k + 2):
|
| 134 |
+
G.add_edge(n, 2 * k + 2)
|
| 135 |
+
G.add_edge(n, n + 1)
|
| 136 |
+
G.add_edge(2 * k + 3, k + 2)
|
| 137 |
+
for n in range(2 * k + 3, 3 * k + 3):
|
| 138 |
+
G.add_edge(2 * k + 2, n)
|
| 139 |
+
G.add_edge(n, 3 * k + 3)
|
| 140 |
+
G.add_edge(3 * k + 3, 2 * k + 2)
|
| 141 |
+
return G
|
| 142 |
+
|
| 143 |
+
def test_worst_case_graph(self):
|
| 144 |
+
# see figure 1 in Johnson's paper
|
| 145 |
+
for k in range(3, 10):
|
| 146 |
+
G = self.worst_case_graph(k)
|
| 147 |
+
l = len(list(nx.simple_cycles(G)))
|
| 148 |
+
assert l == 3 * k
|
| 149 |
+
|
| 150 |
+
def test_recursive_simple_and_not(self):
|
| 151 |
+
for k in range(2, 10):
|
| 152 |
+
G = self.worst_case_graph(k)
|
| 153 |
+
cc = sorted(nx.simple_cycles(G))
|
| 154 |
+
rcc = sorted(nx.recursive_simple_cycles(G))
|
| 155 |
+
assert len(cc) == len(rcc)
|
| 156 |
+
for c in cc:
|
| 157 |
+
assert any(self.is_cyclic_permutation(c, r) for r in rcc)
|
| 158 |
+
for rc in rcc:
|
| 159 |
+
assert any(self.is_cyclic_permutation(rc, c) for c in cc)
|
| 160 |
+
|
| 161 |
+
def test_simple_graph_with_reported_bug(self):
|
| 162 |
+
G = nx.DiGraph()
|
| 163 |
+
edges = [
|
| 164 |
+
(0, 2),
|
| 165 |
+
(0, 3),
|
| 166 |
+
(1, 0),
|
| 167 |
+
(1, 3),
|
| 168 |
+
(2, 1),
|
| 169 |
+
(2, 4),
|
| 170 |
+
(3, 2),
|
| 171 |
+
(3, 4),
|
| 172 |
+
(4, 0),
|
| 173 |
+
(4, 1),
|
| 174 |
+
(4, 5),
|
| 175 |
+
(5, 0),
|
| 176 |
+
(5, 1),
|
| 177 |
+
(5, 2),
|
| 178 |
+
(5, 3),
|
| 179 |
+
]
|
| 180 |
+
G.add_edges_from(edges)
|
| 181 |
+
cc = sorted(nx.simple_cycles(G))
|
| 182 |
+
assert len(cc) == 26
|
| 183 |
+
rcc = sorted(nx.recursive_simple_cycles(G))
|
| 184 |
+
assert len(cc) == len(rcc)
|
| 185 |
+
for c in cc:
|
| 186 |
+
assert any(self.is_cyclic_permutation(c, rc) for rc in rcc)
|
| 187 |
+
for rc in rcc:
|
| 188 |
+
assert any(self.is_cyclic_permutation(rc, c) for c in cc)
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
def pairwise(iterable):
|
| 192 |
+
a, b = tee(iterable)
|
| 193 |
+
next(b, None)
|
| 194 |
+
return zip(a, b)
|
| 195 |
+
|
| 196 |
+
|
| 197 |
+
def cycle_edges(c):
|
| 198 |
+
return pairwise(chain(c, islice(c, 1)))
|
| 199 |
+
|
| 200 |
+
|
| 201 |
+
def directed_cycle_edgeset(c):
|
| 202 |
+
return frozenset(cycle_edges(c))
|
| 203 |
+
|
| 204 |
+
|
| 205 |
+
def undirected_cycle_edgeset(c):
|
| 206 |
+
if len(c) == 1:
|
| 207 |
+
return frozenset(cycle_edges(c))
|
| 208 |
+
return frozenset(map(frozenset, cycle_edges(c)))
|
| 209 |
+
|
| 210 |
+
|
| 211 |
+
def multigraph_cycle_edgeset(c):
|
| 212 |
+
if len(c) <= 2:
|
| 213 |
+
return frozenset(cycle_edges(c))
|
| 214 |
+
else:
|
| 215 |
+
return frozenset(map(frozenset, cycle_edges(c)))
|
| 216 |
+
|
| 217 |
+
|
| 218 |
+
class TestCycleEnumeration:
|
| 219 |
+
@staticmethod
|
| 220 |
+
def K(n):
|
| 221 |
+
return nx.complete_graph(n)
|
| 222 |
+
|
| 223 |
+
@staticmethod
|
| 224 |
+
def D(n):
|
| 225 |
+
return nx.complete_graph(n).to_directed()
|
| 226 |
+
|
| 227 |
+
@staticmethod
|
| 228 |
+
def edgeset_function(g):
|
| 229 |
+
if g.is_directed():
|
| 230 |
+
return directed_cycle_edgeset
|
| 231 |
+
elif g.is_multigraph():
|
| 232 |
+
return multigraph_cycle_edgeset
|
| 233 |
+
else:
|
| 234 |
+
return undirected_cycle_edgeset
|
| 235 |
+
|
| 236 |
+
def check_cycle(self, g, c, es, cache, source, original_c, length_bound, chordless):
|
| 237 |
+
if length_bound is not None and len(c) > length_bound:
|
| 238 |
+
raise RuntimeError(
|
| 239 |
+
f"computed cycle {original_c} exceeds length bound {length_bound}"
|
| 240 |
+
)
|
| 241 |
+
if source == "computed":
|
| 242 |
+
if es in cache:
|
| 243 |
+
raise RuntimeError(
|
| 244 |
+
f"computed cycle {original_c} has already been found!"
|
| 245 |
+
)
|
| 246 |
+
else:
|
| 247 |
+
cache[es] = tuple(original_c)
|
| 248 |
+
else:
|
| 249 |
+
if es in cache:
|
| 250 |
+
cache.pop(es)
|
| 251 |
+
else:
|
| 252 |
+
raise RuntimeError(f"expected cycle {original_c} was not computed")
|
| 253 |
+
|
| 254 |
+
if not all(g.has_edge(*e) for e in es):
|
| 255 |
+
raise RuntimeError(
|
| 256 |
+
f"{source} claimed cycle {original_c} is not a cycle of g"
|
| 257 |
+
)
|
| 258 |
+
if chordless and len(g.subgraph(c).edges) > len(c):
|
| 259 |
+
raise RuntimeError(f"{source} cycle {original_c} is not chordless")
|
| 260 |
+
|
| 261 |
+
def check_cycle_algorithm(
|
| 262 |
+
self,
|
| 263 |
+
g,
|
| 264 |
+
expected_cycles,
|
| 265 |
+
length_bound=None,
|
| 266 |
+
chordless=False,
|
| 267 |
+
algorithm=None,
|
| 268 |
+
):
|
| 269 |
+
if algorithm is None:
|
| 270 |
+
algorithm = nx.chordless_cycles if chordless else nx.simple_cycles
|
| 271 |
+
|
| 272 |
+
# note: we shuffle the labels of g to rule out accidentally-correct
|
| 273 |
+
# behavior which occurred during the development of chordless cycle
|
| 274 |
+
# enumeration algorithms
|
| 275 |
+
|
| 276 |
+
relabel = list(range(len(g)))
|
| 277 |
+
shuffle(relabel)
|
| 278 |
+
label = dict(zip(g, relabel))
|
| 279 |
+
unlabel = dict(zip(relabel, g))
|
| 280 |
+
h = nx.relabel_nodes(g, label, copy=True)
|
| 281 |
+
|
| 282 |
+
edgeset = self.edgeset_function(h)
|
| 283 |
+
|
| 284 |
+
params = {}
|
| 285 |
+
if length_bound is not None:
|
| 286 |
+
params["length_bound"] = length_bound
|
| 287 |
+
|
| 288 |
+
cycle_cache = {}
|
| 289 |
+
for c in algorithm(h, **params):
|
| 290 |
+
original_c = [unlabel[x] for x in c]
|
| 291 |
+
es = edgeset(c)
|
| 292 |
+
self.check_cycle(
|
| 293 |
+
h, c, es, cycle_cache, "computed", original_c, length_bound, chordless
|
| 294 |
+
)
|
| 295 |
+
|
| 296 |
+
if isinstance(expected_cycles, int):
|
| 297 |
+
if len(cycle_cache) != expected_cycles:
|
| 298 |
+
raise RuntimeError(
|
| 299 |
+
f"expected {expected_cycles} cycles, got {len(cycle_cache)}"
|
| 300 |
+
)
|
| 301 |
+
return
|
| 302 |
+
for original_c in expected_cycles:
|
| 303 |
+
c = [label[x] for x in original_c]
|
| 304 |
+
es = edgeset(c)
|
| 305 |
+
self.check_cycle(
|
| 306 |
+
h, c, es, cycle_cache, "expected", original_c, length_bound, chordless
|
| 307 |
+
)
|
| 308 |
+
|
| 309 |
+
if len(cycle_cache):
|
| 310 |
+
for c in cycle_cache.values():
|
| 311 |
+
raise RuntimeError(
|
| 312 |
+
f"computed cycle {c} is valid but not in the expected cycle set!"
|
| 313 |
+
)
|
| 314 |
+
|
| 315 |
+
def check_cycle_enumeration_integer_sequence(
|
| 316 |
+
self,
|
| 317 |
+
g_family,
|
| 318 |
+
cycle_counts,
|
| 319 |
+
length_bound=None,
|
| 320 |
+
chordless=False,
|
| 321 |
+
algorithm=None,
|
| 322 |
+
):
|
| 323 |
+
for g, num_cycles in zip(g_family, cycle_counts):
|
| 324 |
+
self.check_cycle_algorithm(
|
| 325 |
+
g,
|
| 326 |
+
num_cycles,
|
| 327 |
+
length_bound=length_bound,
|
| 328 |
+
chordless=chordless,
|
| 329 |
+
algorithm=algorithm,
|
| 330 |
+
)
|
| 331 |
+
|
| 332 |
+
def test_directed_chordless_cycle_digons(self):
|
| 333 |
+
g = nx.DiGraph()
|
| 334 |
+
nx.add_cycle(g, range(5))
|
| 335 |
+
nx.add_cycle(g, range(5)[::-1])
|
| 336 |
+
g.add_edge(0, 0)
|
| 337 |
+
expected_cycles = [(0,), (1, 2), (2, 3), (3, 4)]
|
| 338 |
+
self.check_cycle_algorithm(g, expected_cycles, chordless=True)
|
| 339 |
+
|
| 340 |
+
self.check_cycle_algorithm(g, expected_cycles, chordless=True, length_bound=2)
|
| 341 |
+
|
| 342 |
+
expected_cycles = [c for c in expected_cycles if len(c) < 2]
|
| 343 |
+
self.check_cycle_algorithm(g, expected_cycles, chordless=True, length_bound=1)
|
| 344 |
+
|
| 345 |
+
def test_directed_chordless_cycle_undirected(self):
|
| 346 |
+
g = nx.DiGraph([(1, 2), (2, 3), (3, 4), (4, 5), (5, 0), (5, 1), (0, 2)])
|
| 347 |
+
expected_cycles = [(0, 2, 3, 4, 5), (1, 2, 3, 4, 5)]
|
| 348 |
+
self.check_cycle_algorithm(g, expected_cycles, chordless=True)
|
| 349 |
+
|
| 350 |
+
g = nx.DiGraph()
|
| 351 |
+
nx.add_cycle(g, range(5))
|
| 352 |
+
nx.add_cycle(g, range(4, 9))
|
| 353 |
+
g.add_edge(7, 3)
|
| 354 |
+
expected_cycles = [(0, 1, 2, 3, 4), (3, 4, 5, 6, 7), (4, 5, 6, 7, 8)]
|
| 355 |
+
self.check_cycle_algorithm(g, expected_cycles, chordless=True)
|
| 356 |
+
|
| 357 |
+
g.add_edge(3, 7)
|
| 358 |
+
expected_cycles = [(0, 1, 2, 3, 4), (3, 7), (4, 5, 6, 7, 8)]
|
| 359 |
+
self.check_cycle_algorithm(g, expected_cycles, chordless=True)
|
| 360 |
+
|
| 361 |
+
expected_cycles = [(3, 7)]
|
| 362 |
+
self.check_cycle_algorithm(g, expected_cycles, chordless=True, length_bound=4)
|
| 363 |
+
|
| 364 |
+
g.remove_edge(7, 3)
|
| 365 |
+
expected_cycles = [(0, 1, 2, 3, 4), (4, 5, 6, 7, 8)]
|
| 366 |
+
self.check_cycle_algorithm(g, expected_cycles, chordless=True)
|
| 367 |
+
|
| 368 |
+
g = nx.DiGraph((i, j) for i in range(10) for j in range(i))
|
| 369 |
+
expected_cycles = []
|
| 370 |
+
self.check_cycle_algorithm(g, expected_cycles, chordless=True)
|
| 371 |
+
|
| 372 |
+
def test_chordless_cycles_directed(self):
|
| 373 |
+
G = nx.DiGraph()
|
| 374 |
+
nx.add_cycle(G, range(5))
|
| 375 |
+
nx.add_cycle(G, range(4, 12))
|
| 376 |
+
expected = [[*range(5)], [*range(4, 12)]]
|
| 377 |
+
self.check_cycle_algorithm(G, expected, chordless=True)
|
| 378 |
+
self.check_cycle_algorithm(
|
| 379 |
+
G, [c for c in expected if len(c) <= 5], length_bound=5, chordless=True
|
| 380 |
+
)
|
| 381 |
+
|
| 382 |
+
G.add_edge(7, 3)
|
| 383 |
+
expected.append([*range(3, 8)])
|
| 384 |
+
self.check_cycle_algorithm(G, expected, chordless=True)
|
| 385 |
+
self.check_cycle_algorithm(
|
| 386 |
+
G, [c for c in expected if len(c) <= 5], length_bound=5, chordless=True
|
| 387 |
+
)
|
| 388 |
+
|
| 389 |
+
G.add_edge(3, 7)
|
| 390 |
+
expected[-1] = [7, 3]
|
| 391 |
+
self.check_cycle_algorithm(G, expected, chordless=True)
|
| 392 |
+
self.check_cycle_algorithm(
|
| 393 |
+
G, [c for c in expected if len(c) <= 5], length_bound=5, chordless=True
|
| 394 |
+
)
|
| 395 |
+
|
| 396 |
+
expected.pop()
|
| 397 |
+
G.remove_edge(7, 3)
|
| 398 |
+
self.check_cycle_algorithm(G, expected, chordless=True)
|
| 399 |
+
self.check_cycle_algorithm(
|
| 400 |
+
G, [c for c in expected if len(c) <= 5], length_bound=5, chordless=True
|
| 401 |
+
)
|
| 402 |
+
|
| 403 |
+
def test_directed_chordless_cycle_diclique(self):
|
| 404 |
+
g_family = [self.D(n) for n in range(10)]
|
| 405 |
+
expected_cycles = [(n * n - n) // 2 for n in range(10)]
|
| 406 |
+
self.check_cycle_enumeration_integer_sequence(
|
| 407 |
+
g_family, expected_cycles, chordless=True
|
| 408 |
+
)
|
| 409 |
+
|
| 410 |
+
expected_cycles = [(n * n - n) // 2 for n in range(10)]
|
| 411 |
+
self.check_cycle_enumeration_integer_sequence(
|
| 412 |
+
g_family, expected_cycles, length_bound=2
|
| 413 |
+
)
|
| 414 |
+
|
| 415 |
+
def test_directed_chordless_loop_blockade(self):
|
| 416 |
+
g = nx.DiGraph((i, i) for i in range(10))
|
| 417 |
+
nx.add_cycle(g, range(10))
|
| 418 |
+
expected_cycles = [(i,) for i in range(10)]
|
| 419 |
+
self.check_cycle_algorithm(g, expected_cycles, chordless=True)
|
| 420 |
+
|
| 421 |
+
self.check_cycle_algorithm(g, expected_cycles, length_bound=1)
|
| 422 |
+
|
| 423 |
+
g = nx.MultiDiGraph(g)
|
| 424 |
+
g.add_edges_from((i, i) for i in range(0, 10, 2))
|
| 425 |
+
expected_cycles = [(i,) for i in range(1, 10, 2)]
|
| 426 |
+
self.check_cycle_algorithm(g, expected_cycles, chordless=True)
|
| 427 |
+
|
| 428 |
+
def test_simple_cycles_notable_clique_sequences(self):
|
| 429 |
+
# A000292: Number of labeled graphs on n+3 nodes that are triangles.
|
| 430 |
+
g_family = [self.K(n) for n in range(2, 12)]
|
| 431 |
+
expected = [0, 1, 4, 10, 20, 35, 56, 84, 120, 165, 220]
|
| 432 |
+
self.check_cycle_enumeration_integer_sequence(
|
| 433 |
+
g_family, expected, length_bound=3
|
| 434 |
+
)
|
| 435 |
+
|
| 436 |
+
def triangles(g, **kwargs):
|
| 437 |
+
yield from (c for c in nx.simple_cycles(g, **kwargs) if len(c) == 3)
|
| 438 |
+
|
| 439 |
+
# directed complete graphs have twice as many triangles thanks to reversal
|
| 440 |
+
g_family = [self.D(n) for n in range(2, 12)]
|
| 441 |
+
expected = [2 * e for e in expected]
|
| 442 |
+
self.check_cycle_enumeration_integer_sequence(
|
| 443 |
+
g_family, expected, length_bound=3, algorithm=triangles
|
| 444 |
+
)
|
| 445 |
+
|
| 446 |
+
def four_cycles(g, **kwargs):
|
| 447 |
+
yield from (c for c in nx.simple_cycles(g, **kwargs) if len(c) == 4)
|
| 448 |
+
|
| 449 |
+
# A050534: the number of 4-cycles in the complete graph K_{n+1}
|
| 450 |
+
expected = [0, 0, 0, 3, 15, 45, 105, 210, 378, 630, 990]
|
| 451 |
+
g_family = [self.K(n) for n in range(1, 12)]
|
| 452 |
+
self.check_cycle_enumeration_integer_sequence(
|
| 453 |
+
g_family, expected, length_bound=4, algorithm=four_cycles
|
| 454 |
+
)
|
| 455 |
+
|
| 456 |
+
# directed complete graphs have twice as many 4-cycles thanks to reversal
|
| 457 |
+
expected = [2 * e for e in expected]
|
| 458 |
+
g_family = [self.D(n) for n in range(1, 15)]
|
| 459 |
+
self.check_cycle_enumeration_integer_sequence(
|
| 460 |
+
g_family, expected, length_bound=4, algorithm=four_cycles
|
| 461 |
+
)
|
| 462 |
+
|
| 463 |
+
# A006231: the number of elementary circuits in a complete directed graph with n nodes
|
| 464 |
+
expected = [0, 1, 5, 20, 84, 409, 2365]
|
| 465 |
+
g_family = [self.D(n) for n in range(1, 8)]
|
| 466 |
+
self.check_cycle_enumeration_integer_sequence(g_family, expected)
|
| 467 |
+
|
| 468 |
+
# A002807: Number of cycles in the complete graph on n nodes K_{n}.
|
| 469 |
+
expected = [0, 0, 0, 1, 7, 37, 197, 1172]
|
| 470 |
+
g_family = [self.K(n) for n in range(8)]
|
| 471 |
+
self.check_cycle_enumeration_integer_sequence(g_family, expected)
|
| 472 |
+
|
| 473 |
+
def test_directed_chordless_cycle_parallel_multiedges(self):
|
| 474 |
+
g = nx.MultiGraph()
|
| 475 |
+
|
| 476 |
+
nx.add_cycle(g, range(5))
|
| 477 |
+
expected = [[*range(5)]]
|
| 478 |
+
self.check_cycle_algorithm(g, expected, chordless=True)
|
| 479 |
+
|
| 480 |
+
nx.add_cycle(g, range(5))
|
| 481 |
+
expected = [*cycle_edges(range(5))]
|
| 482 |
+
self.check_cycle_algorithm(g, expected, chordless=True)
|
| 483 |
+
|
| 484 |
+
nx.add_cycle(g, range(5))
|
| 485 |
+
expected = []
|
| 486 |
+
self.check_cycle_algorithm(g, expected, chordless=True)
|
| 487 |
+
|
| 488 |
+
g = nx.MultiDiGraph()
|
| 489 |
+
|
| 490 |
+
nx.add_cycle(g, range(5))
|
| 491 |
+
expected = [[*range(5)]]
|
| 492 |
+
self.check_cycle_algorithm(g, expected, chordless=True)
|
| 493 |
+
|
| 494 |
+
nx.add_cycle(g, range(5))
|
| 495 |
+
self.check_cycle_algorithm(g, [], chordless=True)
|
| 496 |
+
|
| 497 |
+
nx.add_cycle(g, range(5))
|
| 498 |
+
self.check_cycle_algorithm(g, [], chordless=True)
|
| 499 |
+
|
| 500 |
+
g = nx.MultiDiGraph()
|
| 501 |
+
|
| 502 |
+
nx.add_cycle(g, range(5))
|
| 503 |
+
nx.add_cycle(g, range(5)[::-1])
|
| 504 |
+
expected = [*cycle_edges(range(5))]
|
| 505 |
+
self.check_cycle_algorithm(g, expected, chordless=True)
|
| 506 |
+
|
| 507 |
+
nx.add_cycle(g, range(5))
|
| 508 |
+
self.check_cycle_algorithm(g, [], chordless=True)
|
| 509 |
+
|
| 510 |
+
def test_chordless_cycles_graph(self):
|
| 511 |
+
G = nx.Graph()
|
| 512 |
+
nx.add_cycle(G, range(5))
|
| 513 |
+
nx.add_cycle(G, range(4, 12))
|
| 514 |
+
expected = [[*range(5)], [*range(4, 12)]]
|
| 515 |
+
self.check_cycle_algorithm(G, expected, chordless=True)
|
| 516 |
+
self.check_cycle_algorithm(
|
| 517 |
+
G, [c for c in expected if len(c) <= 5], length_bound=5, chordless=True
|
| 518 |
+
)
|
| 519 |
+
|
| 520 |
+
G.add_edge(7, 3)
|
| 521 |
+
expected.append([*range(3, 8)])
|
| 522 |
+
expected.append([4, 3, 7, 8, 9, 10, 11])
|
| 523 |
+
self.check_cycle_algorithm(G, expected, chordless=True)
|
| 524 |
+
self.check_cycle_algorithm(
|
| 525 |
+
G, [c for c in expected if len(c) <= 5], length_bound=5, chordless=True
|
| 526 |
+
)
|
| 527 |
+
|
| 528 |
+
def test_chordless_cycles_giant_hamiltonian(self):
|
| 529 |
+
# ... o - e - o - e - o ... # o = odd, e = even
|
| 530 |
+
# ... ---/ \-----/ \--- ... # <-- "long" edges
|
| 531 |
+
#
|
| 532 |
+
# each long edge belongs to exactly one triangle, and one giant cycle
|
| 533 |
+
# of length n/2. The remaining edges each belong to a triangle
|
| 534 |
+
|
| 535 |
+
n = 1000
|
| 536 |
+
assert n % 2 == 0
|
| 537 |
+
G = nx.Graph()
|
| 538 |
+
for v in range(n):
|
| 539 |
+
if not v % 2:
|
| 540 |
+
G.add_edge(v, (v + 2) % n)
|
| 541 |
+
G.add_edge(v, (v + 1) % n)
|
| 542 |
+
|
| 543 |
+
expected = [[*range(0, n, 2)]] + [
|
| 544 |
+
[x % n for x in range(i, i + 3)] for i in range(0, n, 2)
|
| 545 |
+
]
|
| 546 |
+
self.check_cycle_algorithm(G, expected, chordless=True)
|
| 547 |
+
self.check_cycle_algorithm(
|
| 548 |
+
G, [c for c in expected if len(c) <= 3], length_bound=3, chordless=True
|
| 549 |
+
)
|
| 550 |
+
|
| 551 |
+
# ... o -> e -> o -> e -> o ... # o = odd, e = even
|
| 552 |
+
# ... <---/ \---<---/ \---< ... # <-- "long" edges
|
| 553 |
+
#
|
| 554 |
+
# this time, we orient the short and long edges in opposition
|
| 555 |
+
# the cycle structure of this graph is the same, but we need to reverse
|
| 556 |
+
# the long one in our representation. Also, we need to drop the size
|
| 557 |
+
# because our partitioning algorithm uses strongly connected components
|
| 558 |
+
# instead of separating graphs by their strong articulation points
|
| 559 |
+
|
| 560 |
+
n = 100
|
| 561 |
+
assert n % 2 == 0
|
| 562 |
+
G = nx.DiGraph()
|
| 563 |
+
for v in range(n):
|
| 564 |
+
G.add_edge(v, (v + 1) % n)
|
| 565 |
+
if not v % 2:
|
| 566 |
+
G.add_edge((v + 2) % n, v)
|
| 567 |
+
|
| 568 |
+
expected = [[*range(n - 2, -2, -2)]] + [
|
| 569 |
+
[x % n for x in range(i, i + 3)] for i in range(0, n, 2)
|
| 570 |
+
]
|
| 571 |
+
self.check_cycle_algorithm(G, expected, chordless=True)
|
| 572 |
+
self.check_cycle_algorithm(
|
| 573 |
+
G, [c for c in expected if len(c) <= 3], length_bound=3, chordless=True
|
| 574 |
+
)
|
| 575 |
+
|
| 576 |
+
def test_simple_cycles_acyclic_tournament(self):
|
| 577 |
+
n = 10
|
| 578 |
+
G = nx.DiGraph((x, y) for x in range(n) for y in range(x))
|
| 579 |
+
self.check_cycle_algorithm(G, [])
|
| 580 |
+
self.check_cycle_algorithm(G, [], chordless=True)
|
| 581 |
+
|
| 582 |
+
for k in range(n + 1):
|
| 583 |
+
self.check_cycle_algorithm(G, [], length_bound=k)
|
| 584 |
+
self.check_cycle_algorithm(G, [], length_bound=k, chordless=True)
|
| 585 |
+
|
| 586 |
+
def test_simple_cycles_graph(self):
|
| 587 |
+
testG = nx.cycle_graph(8)
|
| 588 |
+
cyc1 = tuple(range(8))
|
| 589 |
+
self.check_cycle_algorithm(testG, [cyc1])
|
| 590 |
+
|
| 591 |
+
testG.add_edge(4, -1)
|
| 592 |
+
nx.add_path(testG, [3, -2, -3, -4])
|
| 593 |
+
self.check_cycle_algorithm(testG, [cyc1])
|
| 594 |
+
|
| 595 |
+
testG.update(nx.cycle_graph(range(8, 16)))
|
| 596 |
+
cyc2 = tuple(range(8, 16))
|
| 597 |
+
self.check_cycle_algorithm(testG, [cyc1, cyc2])
|
| 598 |
+
|
| 599 |
+
testG.update(nx.cycle_graph(range(4, 12)))
|
| 600 |
+
cyc3 = tuple(range(4, 12))
|
| 601 |
+
expected = {
|
| 602 |
+
(0, 1, 2, 3, 4, 5, 6, 7), # cyc1
|
| 603 |
+
(8, 9, 10, 11, 12, 13, 14, 15), # cyc2
|
| 604 |
+
(4, 5, 6, 7, 8, 9, 10, 11), # cyc3
|
| 605 |
+
(4, 5, 6, 7, 8, 15, 14, 13, 12, 11), # cyc2 + cyc3
|
| 606 |
+
(0, 1, 2, 3, 4, 11, 10, 9, 8, 7), # cyc1 + cyc3
|
| 607 |
+
(0, 1, 2, 3, 4, 11, 12, 13, 14, 15, 8, 7), # cyc1 + cyc2 + cyc3
|
| 608 |
+
}
|
| 609 |
+
self.check_cycle_algorithm(testG, expected)
|
| 610 |
+
assert len(expected) == (2**3 - 1) - 1 # 1 disjoint comb: cyc1 + cyc2
|
| 611 |
+
|
| 612 |
+
# Basis size = 5 (2 loops overlapping gives 5 small loops
|
| 613 |
+
# E
|
| 614 |
+
# / \ Note: A-F = 10-15
|
| 615 |
+
# 1-2-3-4-5
|
| 616 |
+
# / | | \ cyc1=012DAB -- left
|
| 617 |
+
# 0 D F 6 cyc2=234E -- top
|
| 618 |
+
# \ | | / cyc3=45678F -- right
|
| 619 |
+
# B-A-9-8-7 cyc4=89AC -- bottom
|
| 620 |
+
# \ / cyc5=234F89AD -- middle
|
| 621 |
+
# C
|
| 622 |
+
#
|
| 623 |
+
# combinations of 5 basis elements: 2^5 - 1 (one includes no cycles)
|
| 624 |
+
#
|
| 625 |
+
# disjoint combs: (11 total) not simple cycles
|
| 626 |
+
# Any pair not including cyc5 => choose(4, 2) = 6
|
| 627 |
+
# Any triple not including cyc5 => choose(4, 3) = 4
|
| 628 |
+
# Any quad not including cyc5 => choose(4, 4) = 1
|
| 629 |
+
#
|
| 630 |
+
# we expect 31 - 11 = 20 simple cycles
|
| 631 |
+
#
|
| 632 |
+
testG = nx.cycle_graph(12)
|
| 633 |
+
testG.update(nx.cycle_graph([12, 10, 13, 2, 14, 4, 15, 8]).edges)
|
| 634 |
+
expected = (2**5 - 1) - 11 # 11 disjoint combinations
|
| 635 |
+
self.check_cycle_algorithm(testG, expected)
|
| 636 |
+
|
| 637 |
+
def test_simple_cycles_bounded(self):
|
| 638 |
+
# iteratively construct a cluster of nested cycles running in the same direction
|
| 639 |
+
# there should be one cycle of every length
|
| 640 |
+
d = nx.DiGraph()
|
| 641 |
+
expected = []
|
| 642 |
+
for n in range(10):
|
| 643 |
+
nx.add_cycle(d, range(n))
|
| 644 |
+
expected.append(n)
|
| 645 |
+
for k, e in enumerate(expected):
|
| 646 |
+
self.check_cycle_algorithm(d, e, length_bound=k)
|
| 647 |
+
|
| 648 |
+
# iteratively construct a path of undirected cycles, connected at articulation
|
| 649 |
+
# points. there should be one cycle of every length except 2: no digons
|
| 650 |
+
g = nx.Graph()
|
| 651 |
+
top = 0
|
| 652 |
+
expected = []
|
| 653 |
+
for n in range(10):
|
| 654 |
+
expected.append(n if n < 2 else n - 1)
|
| 655 |
+
if n == 2:
|
| 656 |
+
# no digons in undirected graphs
|
| 657 |
+
continue
|
| 658 |
+
nx.add_cycle(g, range(top, top + n))
|
| 659 |
+
top += n
|
| 660 |
+
for k, e in enumerate(expected):
|
| 661 |
+
self.check_cycle_algorithm(g, e, length_bound=k)
|
| 662 |
+
|
| 663 |
+
def test_simple_cycles_bound_corner_cases(self):
|
| 664 |
+
G = nx.cycle_graph(4)
|
| 665 |
+
DG = nx.cycle_graph(4, create_using=nx.DiGraph)
|
| 666 |
+
assert list(nx.simple_cycles(G, length_bound=0)) == []
|
| 667 |
+
assert list(nx.simple_cycles(DG, length_bound=0)) == []
|
| 668 |
+
assert list(nx.chordless_cycles(G, length_bound=0)) == []
|
| 669 |
+
assert list(nx.chordless_cycles(DG, length_bound=0)) == []
|
| 670 |
+
|
| 671 |
+
def test_simple_cycles_bound_error(self):
|
| 672 |
+
with pytest.raises(ValueError):
|
| 673 |
+
G = nx.DiGraph()
|
| 674 |
+
for c in nx.simple_cycles(G, -1):
|
| 675 |
+
assert False
|
| 676 |
+
|
| 677 |
+
with pytest.raises(ValueError):
|
| 678 |
+
G = nx.Graph()
|
| 679 |
+
for c in nx.simple_cycles(G, -1):
|
| 680 |
+
assert False
|
| 681 |
+
|
| 682 |
+
with pytest.raises(ValueError):
|
| 683 |
+
G = nx.Graph()
|
| 684 |
+
for c in nx.chordless_cycles(G, -1):
|
| 685 |
+
assert False
|
| 686 |
+
|
| 687 |
+
with pytest.raises(ValueError):
|
| 688 |
+
G = nx.DiGraph()
|
| 689 |
+
for c in nx.chordless_cycles(G, -1):
|
| 690 |
+
assert False
|
| 691 |
+
|
| 692 |
+
def test_chordless_cycles_clique(self):
|
| 693 |
+
g_family = [self.K(n) for n in range(2, 15)]
|
| 694 |
+
expected = [0, 1, 4, 10, 20, 35, 56, 84, 120, 165, 220, 286, 364]
|
| 695 |
+
self.check_cycle_enumeration_integer_sequence(
|
| 696 |
+
g_family, expected, chordless=True
|
| 697 |
+
)
|
| 698 |
+
|
| 699 |
+
# directed cliques have as many digons as undirected graphs have edges
|
| 700 |
+
expected = [(n * n - n) // 2 for n in range(15)]
|
| 701 |
+
g_family = [self.D(n) for n in range(15)]
|
| 702 |
+
self.check_cycle_enumeration_integer_sequence(
|
| 703 |
+
g_family, expected, chordless=True
|
| 704 |
+
)
|
| 705 |
+
|
| 706 |
+
|
| 707 |
+
# These tests might fail with hash randomization since they depend on
|
| 708 |
+
# edge_dfs. For more information, see the comments in:
|
| 709 |
+
# networkx/algorithms/traversal/tests/test_edgedfs.py
|
| 710 |
+
|
| 711 |
+
|
| 712 |
+
class TestFindCycle:
|
| 713 |
+
@classmethod
|
| 714 |
+
def setup_class(cls):
|
| 715 |
+
cls.nodes = [0, 1, 2, 3]
|
| 716 |
+
cls.edges = [(-1, 0), (0, 1), (1, 0), (1, 0), (2, 1), (3, 1)]
|
| 717 |
+
|
| 718 |
+
def test_graph_nocycle(self):
|
| 719 |
+
G = nx.Graph(self.edges)
|
| 720 |
+
pytest.raises(nx.exception.NetworkXNoCycle, nx.find_cycle, G, self.nodes)
|
| 721 |
+
|
| 722 |
+
def test_graph_cycle(self):
|
| 723 |
+
G = nx.Graph(self.edges)
|
| 724 |
+
G.add_edge(2, 0)
|
| 725 |
+
x = list(nx.find_cycle(G, self.nodes))
|
| 726 |
+
x_ = [(0, 1), (1, 2), (2, 0)]
|
| 727 |
+
assert x == x_
|
| 728 |
+
|
| 729 |
+
def test_graph_orientation_none(self):
|
| 730 |
+
G = nx.Graph(self.edges)
|
| 731 |
+
G.add_edge(2, 0)
|
| 732 |
+
x = list(nx.find_cycle(G, self.nodes, orientation=None))
|
| 733 |
+
x_ = [(0, 1), (1, 2), (2, 0)]
|
| 734 |
+
assert x == x_
|
| 735 |
+
|
| 736 |
+
def test_graph_orientation_original(self):
|
| 737 |
+
G = nx.Graph(self.edges)
|
| 738 |
+
G.add_edge(2, 0)
|
| 739 |
+
x = list(nx.find_cycle(G, self.nodes, orientation="original"))
|
| 740 |
+
x_ = [(0, 1, FORWARD), (1, 2, FORWARD), (2, 0, FORWARD)]
|
| 741 |
+
assert x == x_
|
| 742 |
+
|
| 743 |
+
def test_digraph(self):
|
| 744 |
+
G = nx.DiGraph(self.edges)
|
| 745 |
+
x = list(nx.find_cycle(G, self.nodes))
|
| 746 |
+
x_ = [(0, 1), (1, 0)]
|
| 747 |
+
assert x == x_
|
| 748 |
+
|
| 749 |
+
def test_digraph_orientation_none(self):
|
| 750 |
+
G = nx.DiGraph(self.edges)
|
| 751 |
+
x = list(nx.find_cycle(G, self.nodes, orientation=None))
|
| 752 |
+
x_ = [(0, 1), (1, 0)]
|
| 753 |
+
assert x == x_
|
| 754 |
+
|
| 755 |
+
def test_digraph_orientation_original(self):
|
| 756 |
+
G = nx.DiGraph(self.edges)
|
| 757 |
+
x = list(nx.find_cycle(G, self.nodes, orientation="original"))
|
| 758 |
+
x_ = [(0, 1, FORWARD), (1, 0, FORWARD)]
|
| 759 |
+
assert x == x_
|
| 760 |
+
|
| 761 |
+
def test_multigraph(self):
|
| 762 |
+
G = nx.MultiGraph(self.edges)
|
| 763 |
+
x = list(nx.find_cycle(G, self.nodes))
|
| 764 |
+
x_ = [(0, 1, 0), (1, 0, 1)] # or (1, 0, 2)
|
| 765 |
+
# Hash randomization...could be any edge.
|
| 766 |
+
assert x[0] == x_[0]
|
| 767 |
+
assert x[1][:2] == x_[1][:2]
|
| 768 |
+
|
| 769 |
+
def test_multidigraph(self):
|
| 770 |
+
G = nx.MultiDiGraph(self.edges)
|
| 771 |
+
x = list(nx.find_cycle(G, self.nodes))
|
| 772 |
+
x_ = [(0, 1, 0), (1, 0, 0)] # (1, 0, 1)
|
| 773 |
+
assert x[0] == x_[0]
|
| 774 |
+
assert x[1][:2] == x_[1][:2]
|
| 775 |
+
|
| 776 |
+
def test_digraph_ignore(self):
|
| 777 |
+
G = nx.DiGraph(self.edges)
|
| 778 |
+
x = list(nx.find_cycle(G, self.nodes, orientation="ignore"))
|
| 779 |
+
x_ = [(0, 1, FORWARD), (1, 0, FORWARD)]
|
| 780 |
+
assert x == x_
|
| 781 |
+
|
| 782 |
+
def test_digraph_reverse(self):
|
| 783 |
+
G = nx.DiGraph(self.edges)
|
| 784 |
+
x = list(nx.find_cycle(G, self.nodes, orientation="reverse"))
|
| 785 |
+
x_ = [(1, 0, REVERSE), (0, 1, REVERSE)]
|
| 786 |
+
assert x == x_
|
| 787 |
+
|
| 788 |
+
def test_multidigraph_ignore(self):
|
| 789 |
+
G = nx.MultiDiGraph(self.edges)
|
| 790 |
+
x = list(nx.find_cycle(G, self.nodes, orientation="ignore"))
|
| 791 |
+
x_ = [(0, 1, 0, FORWARD), (1, 0, 0, FORWARD)] # or (1, 0, 1, 1)
|
| 792 |
+
assert x[0] == x_[0]
|
| 793 |
+
assert x[1][:2] == x_[1][:2]
|
| 794 |
+
assert x[1][3] == x_[1][3]
|
| 795 |
+
|
| 796 |
+
def test_multidigraph_ignore2(self):
|
| 797 |
+
# Loop traversed an edge while ignoring its orientation.
|
| 798 |
+
G = nx.MultiDiGraph([(0, 1), (1, 2), (1, 2)])
|
| 799 |
+
x = list(nx.find_cycle(G, [0, 1, 2], orientation="ignore"))
|
| 800 |
+
x_ = [(1, 2, 0, FORWARD), (1, 2, 1, REVERSE)]
|
| 801 |
+
assert x == x_
|
| 802 |
+
|
| 803 |
+
def test_multidigraph_original(self):
|
| 804 |
+
# Node 2 doesn't need to be searched again from visited from 4.
|
| 805 |
+
# The goal here is to cover the case when 2 to be researched from 4,
|
| 806 |
+
# when 4 is visited from the first time (so we must make sure that 4
|
| 807 |
+
# is not visited from 2, and hence, we respect the edge orientation).
|
| 808 |
+
G = nx.MultiDiGraph([(0, 1), (1, 2), (2, 3), (4, 2)])
|
| 809 |
+
pytest.raises(
|
| 810 |
+
nx.exception.NetworkXNoCycle,
|
| 811 |
+
nx.find_cycle,
|
| 812 |
+
G,
|
| 813 |
+
[0, 1, 2, 3, 4],
|
| 814 |
+
orientation="original",
|
| 815 |
+
)
|
| 816 |
+
|
| 817 |
+
def test_dag(self):
|
| 818 |
+
G = nx.DiGraph([(0, 1), (0, 2), (1, 2)])
|
| 819 |
+
pytest.raises(
|
| 820 |
+
nx.exception.NetworkXNoCycle, nx.find_cycle, G, orientation="original"
|
| 821 |
+
)
|
| 822 |
+
x = list(nx.find_cycle(G, orientation="ignore"))
|
| 823 |
+
assert x == [(0, 1, FORWARD), (1, 2, FORWARD), (0, 2, REVERSE)]
|
| 824 |
+
|
| 825 |
+
def test_prev_explored(self):
|
| 826 |
+
# https://github.com/networkx/networkx/issues/2323
|
| 827 |
+
|
| 828 |
+
G = nx.DiGraph()
|
| 829 |
+
G.add_edges_from([(1, 0), (2, 0), (1, 2), (2, 1)])
|
| 830 |
+
pytest.raises(nx.NetworkXNoCycle, nx.find_cycle, G, source=0)
|
| 831 |
+
x = list(nx.find_cycle(G, 1))
|
| 832 |
+
x_ = [(1, 2), (2, 1)]
|
| 833 |
+
assert x == x_
|
| 834 |
+
|
| 835 |
+
x = list(nx.find_cycle(G, 2))
|
| 836 |
+
x_ = [(2, 1), (1, 2)]
|
| 837 |
+
assert x == x_
|
| 838 |
+
|
| 839 |
+
x = list(nx.find_cycle(G))
|
| 840 |
+
x_ = [(1, 2), (2, 1)]
|
| 841 |
+
assert x == x_
|
| 842 |
+
|
| 843 |
+
def test_no_cycle(self):
|
| 844 |
+
# https://github.com/networkx/networkx/issues/2439
|
| 845 |
+
|
| 846 |
+
G = nx.DiGraph()
|
| 847 |
+
G.add_edges_from([(1, 2), (2, 0), (3, 1), (3, 2)])
|
| 848 |
+
pytest.raises(nx.NetworkXNoCycle, nx.find_cycle, G, source=0)
|
| 849 |
+
pytest.raises(nx.NetworkXNoCycle, nx.find_cycle, G)
|
| 850 |
+
|
| 851 |
+
|
| 852 |
+
def assert_basis_equal(a, b):
|
| 853 |
+
assert sorted(a) == sorted(b)
|
| 854 |
+
|
| 855 |
+
|
| 856 |
+
class TestMinimumCycleBasis:
|
| 857 |
+
@classmethod
|
| 858 |
+
def setup_class(cls):
|
| 859 |
+
T = nx.Graph()
|
| 860 |
+
nx.add_cycle(T, [1, 2, 3, 4], weight=1)
|
| 861 |
+
T.add_edge(2, 4, weight=5)
|
| 862 |
+
cls.diamond_graph = T
|
| 863 |
+
|
| 864 |
+
def test_unweighted_diamond(self):
|
| 865 |
+
mcb = nx.minimum_cycle_basis(self.diamond_graph)
|
| 866 |
+
assert_basis_equal(mcb, [[2, 4, 1], [3, 4, 2]])
|
| 867 |
+
|
| 868 |
+
def test_weighted_diamond(self):
|
| 869 |
+
mcb = nx.minimum_cycle_basis(self.diamond_graph, weight="weight")
|
| 870 |
+
assert_basis_equal(mcb, [[2, 4, 1], [4, 3, 2, 1]])
|
| 871 |
+
|
| 872 |
+
def test_dimensionality(self):
|
| 873 |
+
# checks |MCB|=|E|-|V|+|NC|
|
| 874 |
+
ntrial = 10
|
| 875 |
+
for seed in range(1234, 1234 + ntrial):
|
| 876 |
+
rg = nx.erdos_renyi_graph(10, 0.3, seed=seed)
|
| 877 |
+
nnodes = rg.number_of_nodes()
|
| 878 |
+
nedges = rg.number_of_edges()
|
| 879 |
+
ncomp = nx.number_connected_components(rg)
|
| 880 |
+
|
| 881 |
+
mcb = nx.minimum_cycle_basis(rg)
|
| 882 |
+
assert len(mcb) == nedges - nnodes + ncomp
|
| 883 |
+
check_independent(mcb)
|
| 884 |
+
|
| 885 |
+
def test_complete_graph(self):
|
| 886 |
+
cg = nx.complete_graph(5)
|
| 887 |
+
mcb = nx.minimum_cycle_basis(cg)
|
| 888 |
+
assert all(len(cycle) == 3 for cycle in mcb)
|
| 889 |
+
check_independent(mcb)
|
| 890 |
+
|
| 891 |
+
def test_tree_graph(self):
|
| 892 |
+
tg = nx.balanced_tree(3, 3)
|
| 893 |
+
assert not nx.minimum_cycle_basis(tg)
|
| 894 |
+
|
| 895 |
+
def test_petersen_graph(self):
|
| 896 |
+
G = nx.petersen_graph()
|
| 897 |
+
mcb = list(nx.minimum_cycle_basis(G))
|
| 898 |
+
expected = [
|
| 899 |
+
[4, 9, 7, 5, 0],
|
| 900 |
+
[1, 2, 3, 4, 0],
|
| 901 |
+
[1, 6, 8, 5, 0],
|
| 902 |
+
[4, 3, 8, 5, 0],
|
| 903 |
+
[1, 6, 9, 4, 0],
|
| 904 |
+
[1, 2, 7, 5, 0],
|
| 905 |
+
]
|
| 906 |
+
assert len(mcb) == len(expected)
|
| 907 |
+
assert all(c in expected for c in mcb)
|
| 908 |
+
|
| 909 |
+
# check that order of the nodes is a path
|
| 910 |
+
for c in mcb:
|
| 911 |
+
assert all(G.has_edge(u, v) for u, v in nx.utils.pairwise(c, cyclic=True))
|
| 912 |
+
# check independence of the basis
|
| 913 |
+
check_independent(mcb)
|
| 914 |
+
|
| 915 |
+
def test_gh6787_variable_weighted_complete_graph(self):
|
| 916 |
+
N = 8
|
| 917 |
+
cg = nx.complete_graph(N)
|
| 918 |
+
cg.add_weighted_edges_from([(u, v, 9) for u, v in cg.edges])
|
| 919 |
+
cg.add_weighted_edges_from([(u, v, 1) for u, v in nx.cycle_graph(N).edges])
|
| 920 |
+
mcb = nx.minimum_cycle_basis(cg, weight="weight")
|
| 921 |
+
check_independent(mcb)
|
| 922 |
+
|
| 923 |
+
def test_gh6787_and_edge_attribute_names(self):
|
| 924 |
+
G = nx.cycle_graph(4)
|
| 925 |
+
G.add_weighted_edges_from([(0, 2, 10), (1, 3, 10)], weight="dist")
|
| 926 |
+
expected = [[1, 3, 0], [3, 2, 1, 0], [1, 2, 0]]
|
| 927 |
+
mcb = list(nx.minimum_cycle_basis(G, weight="dist"))
|
| 928 |
+
assert len(mcb) == len(expected)
|
| 929 |
+
assert all(c in expected for c in mcb)
|
| 930 |
+
|
| 931 |
+
# test not using a weight with weight attributes
|
| 932 |
+
expected = [[1, 3, 0], [1, 2, 0], [3, 2, 0]]
|
| 933 |
+
mcb = list(nx.minimum_cycle_basis(G))
|
| 934 |
+
assert len(mcb) == len(expected)
|
| 935 |
+
assert all(c in expected for c in mcb)
|
| 936 |
+
|
| 937 |
+
|
| 938 |
+
class TestGirth:
|
| 939 |
+
@pytest.mark.parametrize(
|
| 940 |
+
("G", "expected"),
|
| 941 |
+
(
|
| 942 |
+
(nx.chvatal_graph(), 4),
|
| 943 |
+
(nx.tutte_graph(), 4),
|
| 944 |
+
(nx.petersen_graph(), 5),
|
| 945 |
+
(nx.heawood_graph(), 6),
|
| 946 |
+
(nx.pappus_graph(), 6),
|
| 947 |
+
(nx.random_tree(10, seed=42), inf),
|
| 948 |
+
(nx.empty_graph(10), inf),
|
| 949 |
+
(nx.Graph(chain(cycle_edges(range(5)), cycle_edges(range(6, 10)))), 4),
|
| 950 |
+
(
|
| 951 |
+
nx.Graph(
|
| 952 |
+
[
|
| 953 |
+
(0, 6),
|
| 954 |
+
(0, 8),
|
| 955 |
+
(0, 9),
|
| 956 |
+
(1, 8),
|
| 957 |
+
(2, 8),
|
| 958 |
+
(2, 9),
|
| 959 |
+
(4, 9),
|
| 960 |
+
(5, 9),
|
| 961 |
+
(6, 8),
|
| 962 |
+
(6, 9),
|
| 963 |
+
(7, 8),
|
| 964 |
+
]
|
| 965 |
+
),
|
| 966 |
+
3,
|
| 967 |
+
),
|
| 968 |
+
),
|
| 969 |
+
)
|
| 970 |
+
def test_girth(self, G, expected):
|
| 971 |
+
assert nx.girth(G) == expected
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_efficiency.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Unit tests for the :mod:`networkx.algorithms.efficiency` module."""
|
| 2 |
+
|
| 3 |
+
import networkx as nx
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
class TestEfficiency:
|
| 7 |
+
def setup_method(self):
|
| 8 |
+
# G1 is a disconnected graph
|
| 9 |
+
self.G1 = nx.Graph()
|
| 10 |
+
self.G1.add_nodes_from([1, 2, 3])
|
| 11 |
+
# G2 is a cycle graph
|
| 12 |
+
self.G2 = nx.cycle_graph(4)
|
| 13 |
+
# G3 is the triangle graph with one additional edge
|
| 14 |
+
self.G3 = nx.lollipop_graph(3, 1)
|
| 15 |
+
|
| 16 |
+
def test_efficiency_disconnected_nodes(self):
|
| 17 |
+
"""
|
| 18 |
+
When nodes are disconnected, efficiency is 0
|
| 19 |
+
"""
|
| 20 |
+
assert nx.efficiency(self.G1, 1, 2) == 0
|
| 21 |
+
|
| 22 |
+
def test_local_efficiency_disconnected_graph(self):
|
| 23 |
+
"""
|
| 24 |
+
In a disconnected graph the efficiency is 0
|
| 25 |
+
"""
|
| 26 |
+
assert nx.local_efficiency(self.G1) == 0
|
| 27 |
+
|
| 28 |
+
def test_efficiency(self):
|
| 29 |
+
assert nx.efficiency(self.G2, 0, 1) == 1
|
| 30 |
+
assert nx.efficiency(self.G2, 0, 2) == 1 / 2
|
| 31 |
+
|
| 32 |
+
def test_global_efficiency(self):
|
| 33 |
+
assert nx.global_efficiency(self.G2) == 5 / 6
|
| 34 |
+
|
| 35 |
+
def test_global_efficiency_complete_graph(self):
|
| 36 |
+
"""
|
| 37 |
+
Tests that the average global efficiency of the complete graph is one.
|
| 38 |
+
"""
|
| 39 |
+
for n in range(2, 10):
|
| 40 |
+
G = nx.complete_graph(n)
|
| 41 |
+
assert nx.global_efficiency(G) == 1
|
| 42 |
+
|
| 43 |
+
def test_local_efficiency_complete_graph(self):
|
| 44 |
+
"""
|
| 45 |
+
Test that the local efficiency for a complete graph with at least 3
|
| 46 |
+
nodes should be one. For a graph with only 2 nodes, the induced
|
| 47 |
+
subgraph has no edges.
|
| 48 |
+
"""
|
| 49 |
+
for n in range(3, 10):
|
| 50 |
+
G = nx.complete_graph(n)
|
| 51 |
+
assert nx.local_efficiency(G) == 1
|
| 52 |
+
|
| 53 |
+
def test_using_ego_graph(self):
|
| 54 |
+
"""
|
| 55 |
+
Test that the ego graph is used when computing local efficiency.
|
| 56 |
+
For more information, see GitHub issue #2710.
|
| 57 |
+
"""
|
| 58 |
+
assert nx.local_efficiency(self.G3) == 7 / 12
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_lowest_common_ancestors.py
ADDED
|
@@ -0,0 +1,427 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from itertools import chain, combinations, product
|
| 2 |
+
|
| 3 |
+
import pytest
|
| 4 |
+
|
| 5 |
+
import networkx as nx
|
| 6 |
+
|
| 7 |
+
tree_all_pairs_lca = nx.tree_all_pairs_lowest_common_ancestor
|
| 8 |
+
all_pairs_lca = nx.all_pairs_lowest_common_ancestor
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def get_pair(dictionary, n1, n2):
|
| 12 |
+
if (n1, n2) in dictionary:
|
| 13 |
+
return dictionary[n1, n2]
|
| 14 |
+
else:
|
| 15 |
+
return dictionary[n2, n1]
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
class TestTreeLCA:
|
| 19 |
+
@classmethod
|
| 20 |
+
def setup_class(cls):
|
| 21 |
+
cls.DG = nx.DiGraph()
|
| 22 |
+
edges = [(0, 1), (0, 2), (1, 3), (1, 4), (2, 5), (2, 6)]
|
| 23 |
+
cls.DG.add_edges_from(edges)
|
| 24 |
+
cls.ans = dict(tree_all_pairs_lca(cls.DG, 0))
|
| 25 |
+
gold = {(n, n): n for n in cls.DG}
|
| 26 |
+
gold.update({(0, i): 0 for i in range(1, 7)})
|
| 27 |
+
gold.update(
|
| 28 |
+
{
|
| 29 |
+
(1, 2): 0,
|
| 30 |
+
(1, 3): 1,
|
| 31 |
+
(1, 4): 1,
|
| 32 |
+
(1, 5): 0,
|
| 33 |
+
(1, 6): 0,
|
| 34 |
+
(2, 3): 0,
|
| 35 |
+
(2, 4): 0,
|
| 36 |
+
(2, 5): 2,
|
| 37 |
+
(2, 6): 2,
|
| 38 |
+
(3, 4): 1,
|
| 39 |
+
(3, 5): 0,
|
| 40 |
+
(3, 6): 0,
|
| 41 |
+
(4, 5): 0,
|
| 42 |
+
(4, 6): 0,
|
| 43 |
+
(5, 6): 2,
|
| 44 |
+
}
|
| 45 |
+
)
|
| 46 |
+
|
| 47 |
+
cls.gold = gold
|
| 48 |
+
|
| 49 |
+
@staticmethod
|
| 50 |
+
def assert_has_same_pairs(d1, d2):
|
| 51 |
+
for a, b in ((min(pair), max(pair)) for pair in chain(d1, d2)):
|
| 52 |
+
assert get_pair(d1, a, b) == get_pair(d2, a, b)
|
| 53 |
+
|
| 54 |
+
def test_tree_all_pairs_lca_default_root(self):
|
| 55 |
+
assert dict(tree_all_pairs_lca(self.DG)) == self.ans
|
| 56 |
+
|
| 57 |
+
def test_tree_all_pairs_lca_return_subset(self):
|
| 58 |
+
test_pairs = [(0, 1), (0, 1), (1, 0)]
|
| 59 |
+
ans = dict(tree_all_pairs_lca(self.DG, 0, test_pairs))
|
| 60 |
+
assert (0, 1) in ans and (1, 0) in ans
|
| 61 |
+
assert len(ans) == 2
|
| 62 |
+
|
| 63 |
+
def test_tree_all_pairs_lca(self):
|
| 64 |
+
all_pairs = chain(combinations(self.DG, 2), ((node, node) for node in self.DG))
|
| 65 |
+
|
| 66 |
+
ans = dict(tree_all_pairs_lca(self.DG, 0, all_pairs))
|
| 67 |
+
self.assert_has_same_pairs(ans, self.ans)
|
| 68 |
+
|
| 69 |
+
def test_tree_all_pairs_gold_example(self):
|
| 70 |
+
ans = dict(tree_all_pairs_lca(self.DG))
|
| 71 |
+
self.assert_has_same_pairs(self.gold, ans)
|
| 72 |
+
|
| 73 |
+
def test_tree_all_pairs_lca_invalid_input(self):
|
| 74 |
+
empty_digraph = tree_all_pairs_lca(nx.DiGraph())
|
| 75 |
+
pytest.raises(nx.NetworkXPointlessConcept, list, empty_digraph)
|
| 76 |
+
|
| 77 |
+
bad_pairs_digraph = tree_all_pairs_lca(self.DG, pairs=[(-1, -2)])
|
| 78 |
+
pytest.raises(nx.NodeNotFound, list, bad_pairs_digraph)
|
| 79 |
+
|
| 80 |
+
def test_tree_all_pairs_lca_subtrees(self):
|
| 81 |
+
ans = dict(tree_all_pairs_lca(self.DG, 1))
|
| 82 |
+
gold = {
|
| 83 |
+
pair: lca
|
| 84 |
+
for (pair, lca) in self.gold.items()
|
| 85 |
+
if all(n in (1, 3, 4) for n in pair)
|
| 86 |
+
}
|
| 87 |
+
self.assert_has_same_pairs(gold, ans)
|
| 88 |
+
|
| 89 |
+
def test_tree_all_pairs_lca_disconnected_nodes(self):
|
| 90 |
+
G = nx.DiGraph()
|
| 91 |
+
G.add_node(1)
|
| 92 |
+
assert {(1, 1): 1} == dict(tree_all_pairs_lca(G))
|
| 93 |
+
|
| 94 |
+
G.add_node(0)
|
| 95 |
+
assert {(1, 1): 1} == dict(tree_all_pairs_lca(G, 1))
|
| 96 |
+
assert {(0, 0): 0} == dict(tree_all_pairs_lca(G, 0))
|
| 97 |
+
|
| 98 |
+
pytest.raises(nx.NetworkXError, list, tree_all_pairs_lca(G))
|
| 99 |
+
|
| 100 |
+
def test_tree_all_pairs_lca_error_if_input_not_tree(self):
|
| 101 |
+
# Cycle
|
| 102 |
+
G = nx.DiGraph([(1, 2), (2, 1)])
|
| 103 |
+
pytest.raises(nx.NetworkXError, list, tree_all_pairs_lca(G))
|
| 104 |
+
# DAG
|
| 105 |
+
G = nx.DiGraph([(0, 2), (1, 2)])
|
| 106 |
+
pytest.raises(nx.NetworkXError, list, tree_all_pairs_lca(G))
|
| 107 |
+
|
| 108 |
+
def test_tree_all_pairs_lca_generator(self):
|
| 109 |
+
pairs = iter([(0, 1), (0, 1), (1, 0)])
|
| 110 |
+
some_pairs = dict(tree_all_pairs_lca(self.DG, 0, pairs))
|
| 111 |
+
assert (0, 1) in some_pairs and (1, 0) in some_pairs
|
| 112 |
+
assert len(some_pairs) == 2
|
| 113 |
+
|
| 114 |
+
def test_tree_all_pairs_lca_nonexisting_pairs_exception(self):
|
| 115 |
+
lca = tree_all_pairs_lca(self.DG, 0, [(-1, -1)])
|
| 116 |
+
pytest.raises(nx.NodeNotFound, list, lca)
|
| 117 |
+
# check if node is None
|
| 118 |
+
lca = tree_all_pairs_lca(self.DG, None, [(-1, -1)])
|
| 119 |
+
pytest.raises(nx.NodeNotFound, list, lca)
|
| 120 |
+
|
| 121 |
+
def test_tree_all_pairs_lca_routine_bails_on_DAGs(self):
|
| 122 |
+
G = nx.DiGraph([(3, 4), (5, 4)])
|
| 123 |
+
pytest.raises(nx.NetworkXError, list, tree_all_pairs_lca(G))
|
| 124 |
+
|
| 125 |
+
def test_tree_all_pairs_lca_not_implemented(self):
|
| 126 |
+
NNI = nx.NetworkXNotImplemented
|
| 127 |
+
G = nx.Graph([(0, 1)])
|
| 128 |
+
with pytest.raises(NNI):
|
| 129 |
+
next(tree_all_pairs_lca(G))
|
| 130 |
+
with pytest.raises(NNI):
|
| 131 |
+
next(all_pairs_lca(G))
|
| 132 |
+
pytest.raises(NNI, nx.lowest_common_ancestor, G, 0, 1)
|
| 133 |
+
G = nx.MultiGraph([(0, 1)])
|
| 134 |
+
with pytest.raises(NNI):
|
| 135 |
+
next(tree_all_pairs_lca(G))
|
| 136 |
+
with pytest.raises(NNI):
|
| 137 |
+
next(all_pairs_lca(G))
|
| 138 |
+
pytest.raises(NNI, nx.lowest_common_ancestor, G, 0, 1)
|
| 139 |
+
|
| 140 |
+
def test_tree_all_pairs_lca_trees_without_LCAs(self):
|
| 141 |
+
G = nx.DiGraph()
|
| 142 |
+
G.add_node(3)
|
| 143 |
+
ans = list(tree_all_pairs_lca(G))
|
| 144 |
+
assert ans == [((3, 3), 3)]
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
class TestMultiTreeLCA(TestTreeLCA):
|
| 148 |
+
@classmethod
|
| 149 |
+
def setup_class(cls):
|
| 150 |
+
cls.DG = nx.MultiDiGraph()
|
| 151 |
+
edges = [(0, 1), (0, 2), (1, 3), (1, 4), (2, 5), (2, 6)]
|
| 152 |
+
cls.DG.add_edges_from(edges)
|
| 153 |
+
cls.ans = dict(tree_all_pairs_lca(cls.DG, 0))
|
| 154 |
+
# add multiedges
|
| 155 |
+
cls.DG.add_edges_from(edges)
|
| 156 |
+
|
| 157 |
+
gold = {(n, n): n for n in cls.DG}
|
| 158 |
+
gold.update({(0, i): 0 for i in range(1, 7)})
|
| 159 |
+
gold.update(
|
| 160 |
+
{
|
| 161 |
+
(1, 2): 0,
|
| 162 |
+
(1, 3): 1,
|
| 163 |
+
(1, 4): 1,
|
| 164 |
+
(1, 5): 0,
|
| 165 |
+
(1, 6): 0,
|
| 166 |
+
(2, 3): 0,
|
| 167 |
+
(2, 4): 0,
|
| 168 |
+
(2, 5): 2,
|
| 169 |
+
(2, 6): 2,
|
| 170 |
+
(3, 4): 1,
|
| 171 |
+
(3, 5): 0,
|
| 172 |
+
(3, 6): 0,
|
| 173 |
+
(4, 5): 0,
|
| 174 |
+
(4, 6): 0,
|
| 175 |
+
(5, 6): 2,
|
| 176 |
+
}
|
| 177 |
+
)
|
| 178 |
+
|
| 179 |
+
cls.gold = gold
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
class TestDAGLCA:
|
| 183 |
+
@classmethod
|
| 184 |
+
def setup_class(cls):
|
| 185 |
+
cls.DG = nx.DiGraph()
|
| 186 |
+
nx.add_path(cls.DG, (0, 1, 2, 3))
|
| 187 |
+
nx.add_path(cls.DG, (0, 4, 3))
|
| 188 |
+
nx.add_path(cls.DG, (0, 5, 6, 8, 3))
|
| 189 |
+
nx.add_path(cls.DG, (5, 7, 8))
|
| 190 |
+
cls.DG.add_edge(6, 2)
|
| 191 |
+
cls.DG.add_edge(7, 2)
|
| 192 |
+
|
| 193 |
+
cls.root_distance = nx.shortest_path_length(cls.DG, source=0)
|
| 194 |
+
|
| 195 |
+
cls.gold = {
|
| 196 |
+
(1, 1): 1,
|
| 197 |
+
(1, 2): 1,
|
| 198 |
+
(1, 3): 1,
|
| 199 |
+
(1, 4): 0,
|
| 200 |
+
(1, 5): 0,
|
| 201 |
+
(1, 6): 0,
|
| 202 |
+
(1, 7): 0,
|
| 203 |
+
(1, 8): 0,
|
| 204 |
+
(2, 2): 2,
|
| 205 |
+
(2, 3): 2,
|
| 206 |
+
(2, 4): 0,
|
| 207 |
+
(2, 5): 5,
|
| 208 |
+
(2, 6): 6,
|
| 209 |
+
(2, 7): 7,
|
| 210 |
+
(2, 8): 7,
|
| 211 |
+
(3, 3): 3,
|
| 212 |
+
(3, 4): 4,
|
| 213 |
+
(3, 5): 5,
|
| 214 |
+
(3, 6): 6,
|
| 215 |
+
(3, 7): 7,
|
| 216 |
+
(3, 8): 8,
|
| 217 |
+
(4, 4): 4,
|
| 218 |
+
(4, 5): 0,
|
| 219 |
+
(4, 6): 0,
|
| 220 |
+
(4, 7): 0,
|
| 221 |
+
(4, 8): 0,
|
| 222 |
+
(5, 5): 5,
|
| 223 |
+
(5, 6): 5,
|
| 224 |
+
(5, 7): 5,
|
| 225 |
+
(5, 8): 5,
|
| 226 |
+
(6, 6): 6,
|
| 227 |
+
(6, 7): 5,
|
| 228 |
+
(6, 8): 6,
|
| 229 |
+
(7, 7): 7,
|
| 230 |
+
(7, 8): 7,
|
| 231 |
+
(8, 8): 8,
|
| 232 |
+
}
|
| 233 |
+
cls.gold.update(((0, n), 0) for n in cls.DG)
|
| 234 |
+
|
| 235 |
+
def assert_lca_dicts_same(self, d1, d2, G=None):
|
| 236 |
+
"""Checks if d1 and d2 contain the same pairs and
|
| 237 |
+
have a node at the same distance from root for each.
|
| 238 |
+
If G is None use self.DG."""
|
| 239 |
+
if G is None:
|
| 240 |
+
G = self.DG
|
| 241 |
+
root_distance = self.root_distance
|
| 242 |
+
else:
|
| 243 |
+
roots = [n for n, deg in G.in_degree if deg == 0]
|
| 244 |
+
assert len(roots) == 1
|
| 245 |
+
root_distance = nx.shortest_path_length(G, source=roots[0])
|
| 246 |
+
|
| 247 |
+
for a, b in ((min(pair), max(pair)) for pair in chain(d1, d2)):
|
| 248 |
+
assert (
|
| 249 |
+
root_distance[get_pair(d1, a, b)] == root_distance[get_pair(d2, a, b)]
|
| 250 |
+
)
|
| 251 |
+
|
| 252 |
+
def test_all_pairs_lca_gold_example(self):
|
| 253 |
+
self.assert_lca_dicts_same(dict(all_pairs_lca(self.DG)), self.gold)
|
| 254 |
+
|
| 255 |
+
def test_all_pairs_lca_all_pairs_given(self):
|
| 256 |
+
all_pairs = list(product(self.DG.nodes(), self.DG.nodes()))
|
| 257 |
+
ans = all_pairs_lca(self.DG, pairs=all_pairs)
|
| 258 |
+
self.assert_lca_dicts_same(dict(ans), self.gold)
|
| 259 |
+
|
| 260 |
+
def test_all_pairs_lca_generator(self):
|
| 261 |
+
all_pairs = product(self.DG.nodes(), self.DG.nodes())
|
| 262 |
+
ans = all_pairs_lca(self.DG, pairs=all_pairs)
|
| 263 |
+
self.assert_lca_dicts_same(dict(ans), self.gold)
|
| 264 |
+
|
| 265 |
+
def test_all_pairs_lca_input_graph_with_two_roots(self):
|
| 266 |
+
G = self.DG.copy()
|
| 267 |
+
G.add_edge(9, 10)
|
| 268 |
+
G.add_edge(9, 4)
|
| 269 |
+
gold = self.gold.copy()
|
| 270 |
+
gold[9, 9] = 9
|
| 271 |
+
gold[9, 10] = 9
|
| 272 |
+
gold[9, 4] = 9
|
| 273 |
+
gold[9, 3] = 9
|
| 274 |
+
gold[10, 4] = 9
|
| 275 |
+
gold[10, 3] = 9
|
| 276 |
+
gold[10, 10] = 10
|
| 277 |
+
|
| 278 |
+
testing = dict(all_pairs_lca(G))
|
| 279 |
+
|
| 280 |
+
G.add_edge(-1, 9)
|
| 281 |
+
G.add_edge(-1, 0)
|
| 282 |
+
self.assert_lca_dicts_same(testing, gold, G)
|
| 283 |
+
|
| 284 |
+
def test_all_pairs_lca_nonexisting_pairs_exception(self):
|
| 285 |
+
pytest.raises(nx.NodeNotFound, all_pairs_lca, self.DG, [(-1, -1)])
|
| 286 |
+
|
| 287 |
+
def test_all_pairs_lca_pairs_without_lca(self):
|
| 288 |
+
G = self.DG.copy()
|
| 289 |
+
G.add_node(-1)
|
| 290 |
+
gen = all_pairs_lca(G, [(-1, -1), (-1, 0)])
|
| 291 |
+
assert dict(gen) == {(-1, -1): -1}
|
| 292 |
+
|
| 293 |
+
def test_all_pairs_lca_null_graph(self):
|
| 294 |
+
pytest.raises(nx.NetworkXPointlessConcept, all_pairs_lca, nx.DiGraph())
|
| 295 |
+
|
| 296 |
+
def test_all_pairs_lca_non_dags(self):
|
| 297 |
+
pytest.raises(nx.NetworkXError, all_pairs_lca, nx.DiGraph([(3, 4), (4, 3)]))
|
| 298 |
+
|
| 299 |
+
def test_all_pairs_lca_nonempty_graph_without_lca(self):
|
| 300 |
+
G = nx.DiGraph()
|
| 301 |
+
G.add_node(3)
|
| 302 |
+
ans = list(all_pairs_lca(G))
|
| 303 |
+
assert ans == [((3, 3), 3)]
|
| 304 |
+
|
| 305 |
+
def test_all_pairs_lca_bug_gh4942(self):
|
| 306 |
+
G = nx.DiGraph([(0, 2), (1, 2), (2, 3)])
|
| 307 |
+
ans = list(all_pairs_lca(G))
|
| 308 |
+
assert len(ans) == 9
|
| 309 |
+
|
| 310 |
+
def test_all_pairs_lca_default_kwarg(self):
|
| 311 |
+
G = nx.DiGraph([(0, 1), (2, 1)])
|
| 312 |
+
sentinel = object()
|
| 313 |
+
assert nx.lowest_common_ancestor(G, 0, 2, default=sentinel) is sentinel
|
| 314 |
+
|
| 315 |
+
def test_all_pairs_lca_identity(self):
|
| 316 |
+
G = nx.DiGraph()
|
| 317 |
+
G.add_node(3)
|
| 318 |
+
assert nx.lowest_common_ancestor(G, 3, 3) == 3
|
| 319 |
+
|
| 320 |
+
def test_all_pairs_lca_issue_4574(self):
|
| 321 |
+
G = nx.DiGraph()
|
| 322 |
+
G.add_nodes_from(range(17))
|
| 323 |
+
G.add_edges_from(
|
| 324 |
+
[
|
| 325 |
+
(2, 0),
|
| 326 |
+
(1, 2),
|
| 327 |
+
(3, 2),
|
| 328 |
+
(5, 2),
|
| 329 |
+
(8, 2),
|
| 330 |
+
(11, 2),
|
| 331 |
+
(4, 5),
|
| 332 |
+
(6, 5),
|
| 333 |
+
(7, 8),
|
| 334 |
+
(10, 8),
|
| 335 |
+
(13, 11),
|
| 336 |
+
(14, 11),
|
| 337 |
+
(15, 11),
|
| 338 |
+
(9, 10),
|
| 339 |
+
(12, 13),
|
| 340 |
+
(16, 15),
|
| 341 |
+
]
|
| 342 |
+
)
|
| 343 |
+
|
| 344 |
+
assert nx.lowest_common_ancestor(G, 7, 9) == None
|
| 345 |
+
|
| 346 |
+
def test_all_pairs_lca_one_pair_gh4942(self):
|
| 347 |
+
G = nx.DiGraph()
|
| 348 |
+
# Note: order edge addition is critical to the test
|
| 349 |
+
G.add_edge(0, 1)
|
| 350 |
+
G.add_edge(2, 0)
|
| 351 |
+
G.add_edge(2, 3)
|
| 352 |
+
G.add_edge(4, 0)
|
| 353 |
+
G.add_edge(5, 2)
|
| 354 |
+
|
| 355 |
+
assert nx.lowest_common_ancestor(G, 1, 3) == 2
|
| 356 |
+
|
| 357 |
+
|
| 358 |
+
class TestMultiDiGraph_DAGLCA(TestDAGLCA):
|
| 359 |
+
@classmethod
|
| 360 |
+
def setup_class(cls):
|
| 361 |
+
cls.DG = nx.MultiDiGraph()
|
| 362 |
+
nx.add_path(cls.DG, (0, 1, 2, 3))
|
| 363 |
+
# add multiedges
|
| 364 |
+
nx.add_path(cls.DG, (0, 1, 2, 3))
|
| 365 |
+
nx.add_path(cls.DG, (0, 4, 3))
|
| 366 |
+
nx.add_path(cls.DG, (0, 5, 6, 8, 3))
|
| 367 |
+
nx.add_path(cls.DG, (5, 7, 8))
|
| 368 |
+
cls.DG.add_edge(6, 2)
|
| 369 |
+
cls.DG.add_edge(7, 2)
|
| 370 |
+
|
| 371 |
+
cls.root_distance = nx.shortest_path_length(cls.DG, source=0)
|
| 372 |
+
|
| 373 |
+
cls.gold = {
|
| 374 |
+
(1, 1): 1,
|
| 375 |
+
(1, 2): 1,
|
| 376 |
+
(1, 3): 1,
|
| 377 |
+
(1, 4): 0,
|
| 378 |
+
(1, 5): 0,
|
| 379 |
+
(1, 6): 0,
|
| 380 |
+
(1, 7): 0,
|
| 381 |
+
(1, 8): 0,
|
| 382 |
+
(2, 2): 2,
|
| 383 |
+
(2, 3): 2,
|
| 384 |
+
(2, 4): 0,
|
| 385 |
+
(2, 5): 5,
|
| 386 |
+
(2, 6): 6,
|
| 387 |
+
(2, 7): 7,
|
| 388 |
+
(2, 8): 7,
|
| 389 |
+
(3, 3): 3,
|
| 390 |
+
(3, 4): 4,
|
| 391 |
+
(3, 5): 5,
|
| 392 |
+
(3, 6): 6,
|
| 393 |
+
(3, 7): 7,
|
| 394 |
+
(3, 8): 8,
|
| 395 |
+
(4, 4): 4,
|
| 396 |
+
(4, 5): 0,
|
| 397 |
+
(4, 6): 0,
|
| 398 |
+
(4, 7): 0,
|
| 399 |
+
(4, 8): 0,
|
| 400 |
+
(5, 5): 5,
|
| 401 |
+
(5, 6): 5,
|
| 402 |
+
(5, 7): 5,
|
| 403 |
+
(5, 8): 5,
|
| 404 |
+
(6, 6): 6,
|
| 405 |
+
(6, 7): 5,
|
| 406 |
+
(6, 8): 6,
|
| 407 |
+
(7, 7): 7,
|
| 408 |
+
(7, 8): 7,
|
| 409 |
+
(8, 8): 8,
|
| 410 |
+
}
|
| 411 |
+
cls.gold.update(((0, n), 0) for n in cls.DG)
|
| 412 |
+
|
| 413 |
+
|
| 414 |
+
def test_all_pairs_lca_self_ancestors():
|
| 415 |
+
"""Self-ancestors should always be the node itself, i.e. lca of (0, 0) is 0.
|
| 416 |
+
See gh-4458."""
|
| 417 |
+
# DAG for test - note order of node/edge addition is relevant
|
| 418 |
+
G = nx.DiGraph()
|
| 419 |
+
G.add_nodes_from(range(5))
|
| 420 |
+
G.add_edges_from([(1, 0), (2, 0), (3, 2), (4, 1), (4, 3)])
|
| 421 |
+
|
| 422 |
+
ap_lca = nx.all_pairs_lowest_common_ancestor
|
| 423 |
+
assert all(u == v == a for (u, v), a in ap_lca(G) if u == v)
|
| 424 |
+
MG = nx.MultiDiGraph(G)
|
| 425 |
+
assert all(u == v == a for (u, v), a in ap_lca(MG) if u == v)
|
| 426 |
+
MG.add_edges_from([(1, 0), (2, 0)])
|
| 427 |
+
assert all(u == v == a for (u, v), a in ap_lca(MG) if u == v)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_richclub.py
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pytest
|
| 2 |
+
|
| 3 |
+
import networkx as nx
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def test_richclub():
|
| 7 |
+
G = nx.Graph([(0, 1), (0, 2), (1, 2), (1, 3), (1, 4), (4, 5)])
|
| 8 |
+
rc = nx.richclub.rich_club_coefficient(G, normalized=False)
|
| 9 |
+
assert rc == {0: 12.0 / 30, 1: 8.0 / 12}
|
| 10 |
+
|
| 11 |
+
# test single value
|
| 12 |
+
rc0 = nx.richclub.rich_club_coefficient(G, normalized=False)[0]
|
| 13 |
+
assert rc0 == 12.0 / 30.0
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def test_richclub_seed():
|
| 17 |
+
G = nx.Graph([(0, 1), (0, 2), (1, 2), (1, 3), (1, 4), (4, 5)])
|
| 18 |
+
rcNorm = nx.richclub.rich_club_coefficient(G, Q=2, seed=1)
|
| 19 |
+
assert rcNorm == {0: 1.0, 1: 1.0}
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
def test_richclub_normalized():
|
| 23 |
+
G = nx.Graph([(0, 1), (0, 2), (1, 2), (1, 3), (1, 4), (4, 5)])
|
| 24 |
+
rcNorm = nx.richclub.rich_club_coefficient(G, Q=2)
|
| 25 |
+
assert rcNorm == {0: 1.0, 1: 1.0}
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def test_richclub2():
|
| 29 |
+
T = nx.balanced_tree(2, 10)
|
| 30 |
+
rc = nx.richclub.rich_club_coefficient(T, normalized=False)
|
| 31 |
+
assert rc == {
|
| 32 |
+
0: 4092 / (2047 * 2046.0),
|
| 33 |
+
1: (2044.0 / (1023 * 1022)),
|
| 34 |
+
2: (2040.0 / (1022 * 1021)),
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
def test_richclub3():
|
| 39 |
+
# tests edgecase
|
| 40 |
+
G = nx.karate_club_graph()
|
| 41 |
+
rc = nx.rich_club_coefficient(G, normalized=False)
|
| 42 |
+
assert rc == {
|
| 43 |
+
0: 156.0 / 1122,
|
| 44 |
+
1: 154.0 / 1056,
|
| 45 |
+
2: 110.0 / 462,
|
| 46 |
+
3: 78.0 / 240,
|
| 47 |
+
4: 44.0 / 90,
|
| 48 |
+
5: 22.0 / 42,
|
| 49 |
+
6: 10.0 / 20,
|
| 50 |
+
7: 10.0 / 20,
|
| 51 |
+
8: 10.0 / 20,
|
| 52 |
+
9: 6.0 / 12,
|
| 53 |
+
10: 2.0 / 6,
|
| 54 |
+
11: 2.0 / 6,
|
| 55 |
+
12: 0.0,
|
| 56 |
+
13: 0.0,
|
| 57 |
+
14: 0.0,
|
| 58 |
+
15: 0.0,
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def test_richclub4():
|
| 63 |
+
G = nx.Graph()
|
| 64 |
+
G.add_edges_from(
|
| 65 |
+
[(0, 1), (0, 2), (0, 3), (0, 4), (4, 5), (5, 9), (6, 9), (7, 9), (8, 9)]
|
| 66 |
+
)
|
| 67 |
+
rc = nx.rich_club_coefficient(G, normalized=False)
|
| 68 |
+
assert rc == {0: 18 / 90.0, 1: 6 / 12.0, 2: 0.0, 3: 0.0}
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
def test_richclub_exception():
|
| 72 |
+
with pytest.raises(nx.NetworkXNotImplemented):
|
| 73 |
+
G = nx.DiGraph()
|
| 74 |
+
nx.rich_club_coefficient(G)
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def test_rich_club_exception2():
|
| 78 |
+
with pytest.raises(nx.NetworkXNotImplemented):
|
| 79 |
+
G = nx.MultiGraph()
|
| 80 |
+
nx.rich_club_coefficient(G)
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def test_rich_club_selfloop():
|
| 84 |
+
G = nx.Graph() # or DiGraph, MultiGraph, MultiDiGraph, etc
|
| 85 |
+
G.add_edge(1, 1) # self loop
|
| 86 |
+
G.add_edge(1, 2)
|
| 87 |
+
with pytest.raises(
|
| 88 |
+
Exception,
|
| 89 |
+
match="rich_club_coefficient is not implemented for " "graphs with self loops.",
|
| 90 |
+
):
|
| 91 |
+
nx.rich_club_coefficient(G)
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
# def test_richclub2_normalized():
|
| 95 |
+
# T = nx.balanced_tree(2,10)
|
| 96 |
+
# rcNorm = nx.richclub.rich_club_coefficient(T,Q=2)
|
| 97 |
+
# assert_true(rcNorm[0] ==1.0 and rcNorm[1] < 0.9 and rcNorm[2] < 0.9)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_smetric.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import warnings
|
| 2 |
+
|
| 3 |
+
import pytest
|
| 4 |
+
|
| 5 |
+
import networkx as nx
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def test_smetric():
|
| 9 |
+
g = nx.Graph()
|
| 10 |
+
g.add_edge(1, 2)
|
| 11 |
+
g.add_edge(2, 3)
|
| 12 |
+
g.add_edge(2, 4)
|
| 13 |
+
g.add_edge(1, 4)
|
| 14 |
+
sm = nx.s_metric(g, normalized=False)
|
| 15 |
+
assert sm == 19.0
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
# NOTE: Tests below to be deleted when deprecation of `normalized` kwarg expires
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def test_normalized_deprecation_warning():
|
| 22 |
+
"""Test that a deprecation warning is raised when s_metric is called with
|
| 23 |
+
a `normalized` kwarg."""
|
| 24 |
+
G = nx.cycle_graph(7)
|
| 25 |
+
# No warning raised when called without kwargs (future behavior)
|
| 26 |
+
with warnings.catch_warnings():
|
| 27 |
+
warnings.simplefilter("error") # Fail the test if warning caught
|
| 28 |
+
assert nx.s_metric(G) == 28
|
| 29 |
+
|
| 30 |
+
# Deprecation warning
|
| 31 |
+
with pytest.deprecated_call():
|
| 32 |
+
nx.s_metric(G, normalized=True)
|
| 33 |
+
|
| 34 |
+
# Make sure you get standard Python behavior when unrecognized keyword provided
|
| 35 |
+
with pytest.raises(TypeError):
|
| 36 |
+
nx.s_metric(G, normalize=True)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_structuralholes.py
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Unit tests for the :mod:`networkx.algorithms.structuralholes` module."""
|
| 2 |
+
import math
|
| 3 |
+
|
| 4 |
+
import pytest
|
| 5 |
+
|
| 6 |
+
import networkx as nx
|
| 7 |
+
from networkx.classes.tests import dispatch_interface
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class TestStructuralHoles:
|
| 11 |
+
"""Unit tests for computing measures of structural holes.
|
| 12 |
+
|
| 13 |
+
The expected values for these functions were originally computed using the
|
| 14 |
+
proprietary software `UCINET`_ and the free software `IGraph`_ , and then
|
| 15 |
+
computed by hand to make sure that the results are correct.
|
| 16 |
+
|
| 17 |
+
.. _UCINET: https://sites.google.com/site/ucinetsoftware/home
|
| 18 |
+
.. _IGraph: http://igraph.org/
|
| 19 |
+
|
| 20 |
+
"""
|
| 21 |
+
|
| 22 |
+
def setup_method(self):
|
| 23 |
+
self.D = nx.DiGraph()
|
| 24 |
+
self.D.add_edges_from([(0, 1), (0, 2), (1, 0), (2, 1)])
|
| 25 |
+
self.D_weights = {(0, 1): 2, (0, 2): 2, (1, 0): 1, (2, 1): 1}
|
| 26 |
+
# Example from http://www.analytictech.com/connections/v20(1)/holes.htm
|
| 27 |
+
self.G = nx.Graph()
|
| 28 |
+
self.G.add_edges_from(
|
| 29 |
+
[
|
| 30 |
+
("A", "B"),
|
| 31 |
+
("A", "F"),
|
| 32 |
+
("A", "G"),
|
| 33 |
+
("A", "E"),
|
| 34 |
+
("E", "G"),
|
| 35 |
+
("F", "G"),
|
| 36 |
+
("B", "G"),
|
| 37 |
+
("B", "D"),
|
| 38 |
+
("D", "G"),
|
| 39 |
+
("G", "C"),
|
| 40 |
+
]
|
| 41 |
+
)
|
| 42 |
+
self.G_weights = {
|
| 43 |
+
("A", "B"): 2,
|
| 44 |
+
("A", "F"): 3,
|
| 45 |
+
("A", "G"): 5,
|
| 46 |
+
("A", "E"): 2,
|
| 47 |
+
("E", "G"): 8,
|
| 48 |
+
("F", "G"): 3,
|
| 49 |
+
("B", "G"): 4,
|
| 50 |
+
("B", "D"): 1,
|
| 51 |
+
("D", "G"): 3,
|
| 52 |
+
("G", "C"): 10,
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
# This additionally tests the @nx._dispatch mechanism, treating
|
| 56 |
+
# nx.mutual_weight as if it were a re-implementation from another package
|
| 57 |
+
@pytest.mark.parametrize("wrapper", [lambda x: x, dispatch_interface.convert])
|
| 58 |
+
def test_constraint_directed(self, wrapper):
|
| 59 |
+
constraint = nx.constraint(wrapper(self.D))
|
| 60 |
+
assert constraint[0] == pytest.approx(1.003, abs=1e-3)
|
| 61 |
+
assert constraint[1] == pytest.approx(1.003, abs=1e-3)
|
| 62 |
+
assert constraint[2] == pytest.approx(1.389, abs=1e-3)
|
| 63 |
+
|
| 64 |
+
def test_effective_size_directed(self):
|
| 65 |
+
effective_size = nx.effective_size(self.D)
|
| 66 |
+
assert effective_size[0] == pytest.approx(1.167, abs=1e-3)
|
| 67 |
+
assert effective_size[1] == pytest.approx(1.167, abs=1e-3)
|
| 68 |
+
assert effective_size[2] == pytest.approx(1, abs=1e-3)
|
| 69 |
+
|
| 70 |
+
def test_constraint_weighted_directed(self):
|
| 71 |
+
D = self.D.copy()
|
| 72 |
+
nx.set_edge_attributes(D, self.D_weights, "weight")
|
| 73 |
+
constraint = nx.constraint(D, weight="weight")
|
| 74 |
+
assert constraint[0] == pytest.approx(0.840, abs=1e-3)
|
| 75 |
+
assert constraint[1] == pytest.approx(1.143, abs=1e-3)
|
| 76 |
+
assert constraint[2] == pytest.approx(1.378, abs=1e-3)
|
| 77 |
+
|
| 78 |
+
def test_effective_size_weighted_directed(self):
|
| 79 |
+
D = self.D.copy()
|
| 80 |
+
nx.set_edge_attributes(D, self.D_weights, "weight")
|
| 81 |
+
effective_size = nx.effective_size(D, weight="weight")
|
| 82 |
+
assert effective_size[0] == pytest.approx(1.567, abs=1e-3)
|
| 83 |
+
assert effective_size[1] == pytest.approx(1.083, abs=1e-3)
|
| 84 |
+
assert effective_size[2] == pytest.approx(1, abs=1e-3)
|
| 85 |
+
|
| 86 |
+
def test_constraint_undirected(self):
|
| 87 |
+
constraint = nx.constraint(self.G)
|
| 88 |
+
assert constraint["G"] == pytest.approx(0.400, abs=1e-3)
|
| 89 |
+
assert constraint["A"] == pytest.approx(0.595, abs=1e-3)
|
| 90 |
+
assert constraint["C"] == pytest.approx(1, abs=1e-3)
|
| 91 |
+
|
| 92 |
+
def test_effective_size_undirected_borgatti(self):
|
| 93 |
+
effective_size = nx.effective_size(self.G)
|
| 94 |
+
assert effective_size["G"] == pytest.approx(4.67, abs=1e-2)
|
| 95 |
+
assert effective_size["A"] == pytest.approx(2.50, abs=1e-2)
|
| 96 |
+
assert effective_size["C"] == pytest.approx(1, abs=1e-2)
|
| 97 |
+
|
| 98 |
+
def test_effective_size_undirected(self):
|
| 99 |
+
G = self.G.copy()
|
| 100 |
+
nx.set_edge_attributes(G, 1, "weight")
|
| 101 |
+
effective_size = nx.effective_size(G, weight="weight")
|
| 102 |
+
assert effective_size["G"] == pytest.approx(4.67, abs=1e-2)
|
| 103 |
+
assert effective_size["A"] == pytest.approx(2.50, abs=1e-2)
|
| 104 |
+
assert effective_size["C"] == pytest.approx(1, abs=1e-2)
|
| 105 |
+
|
| 106 |
+
def test_constraint_weighted_undirected(self):
|
| 107 |
+
G = self.G.copy()
|
| 108 |
+
nx.set_edge_attributes(G, self.G_weights, "weight")
|
| 109 |
+
constraint = nx.constraint(G, weight="weight")
|
| 110 |
+
assert constraint["G"] == pytest.approx(0.299, abs=1e-3)
|
| 111 |
+
assert constraint["A"] == pytest.approx(0.795, abs=1e-3)
|
| 112 |
+
assert constraint["C"] == pytest.approx(1, abs=1e-3)
|
| 113 |
+
|
| 114 |
+
def test_effective_size_weighted_undirected(self):
|
| 115 |
+
G = self.G.copy()
|
| 116 |
+
nx.set_edge_attributes(G, self.G_weights, "weight")
|
| 117 |
+
effective_size = nx.effective_size(G, weight="weight")
|
| 118 |
+
assert effective_size["G"] == pytest.approx(5.47, abs=1e-2)
|
| 119 |
+
assert effective_size["A"] == pytest.approx(2.47, abs=1e-2)
|
| 120 |
+
assert effective_size["C"] == pytest.approx(1, abs=1e-2)
|
| 121 |
+
|
| 122 |
+
def test_constraint_isolated(self):
|
| 123 |
+
G = self.G.copy()
|
| 124 |
+
G.add_node(1)
|
| 125 |
+
constraint = nx.constraint(G)
|
| 126 |
+
assert math.isnan(constraint[1])
|
| 127 |
+
|
| 128 |
+
def test_effective_size_isolated(self):
|
| 129 |
+
G = self.G.copy()
|
| 130 |
+
G.add_node(1)
|
| 131 |
+
nx.set_edge_attributes(G, self.G_weights, "weight")
|
| 132 |
+
effective_size = nx.effective_size(G, weight="weight")
|
| 133 |
+
assert math.isnan(effective_size[1])
|
| 134 |
+
|
| 135 |
+
def test_effective_size_borgatti_isolated(self):
|
| 136 |
+
G = self.G.copy()
|
| 137 |
+
G.add_node(1)
|
| 138 |
+
effective_size = nx.effective_size(G)
|
| 139 |
+
assert math.isnan(effective_size[1])
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_swap.py
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pytest
|
| 2 |
+
|
| 3 |
+
import networkx as nx
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def test_directed_edge_swap():
|
| 7 |
+
graph = nx.path_graph(200, create_using=nx.DiGraph)
|
| 8 |
+
in_degrees = sorted((n, d) for n, d in graph.in_degree())
|
| 9 |
+
out_degrees = sorted((n, d) for n, d in graph.out_degree())
|
| 10 |
+
G = nx.directed_edge_swap(graph, nswap=40, max_tries=500, seed=1)
|
| 11 |
+
assert in_degrees == sorted((n, d) for n, d in G.in_degree())
|
| 12 |
+
assert out_degrees == sorted((n, d) for n, d in G.out_degree())
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
def test_edge_cases_directed_edge_swap():
|
| 16 |
+
# Tests cases when swaps are impossible, either too few edges exist, or self loops/cycles are unavoidable
|
| 17 |
+
# TODO: Rewrite function to explicitly check for impossible swaps and raise error
|
| 18 |
+
e = (
|
| 19 |
+
"Maximum number of swap attempts \\(11\\) exceeded "
|
| 20 |
+
"before desired swaps achieved \\(\\d\\)."
|
| 21 |
+
)
|
| 22 |
+
graph = nx.DiGraph([(0, 0), (0, 1), (1, 0), (2, 3), (3, 2)])
|
| 23 |
+
with pytest.raises(nx.NetworkXAlgorithmError, match=e):
|
| 24 |
+
nx.directed_edge_swap(graph, nswap=1, max_tries=10, seed=1)
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def test_double_edge_swap():
|
| 28 |
+
graph = nx.barabasi_albert_graph(200, 1)
|
| 29 |
+
degrees = sorted(d for n, d in graph.degree())
|
| 30 |
+
G = nx.double_edge_swap(graph, 40)
|
| 31 |
+
assert degrees == sorted(d for n, d in graph.degree())
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def test_double_edge_swap_seed():
|
| 35 |
+
graph = nx.barabasi_albert_graph(200, 1)
|
| 36 |
+
degrees = sorted(d for n, d in graph.degree())
|
| 37 |
+
G = nx.double_edge_swap(graph, 40, seed=1)
|
| 38 |
+
assert degrees == sorted(d for n, d in graph.degree())
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def test_connected_double_edge_swap():
|
| 42 |
+
graph = nx.barabasi_albert_graph(200, 1)
|
| 43 |
+
degrees = sorted(d for n, d in graph.degree())
|
| 44 |
+
G = nx.connected_double_edge_swap(graph, 40, seed=1)
|
| 45 |
+
assert nx.is_connected(graph)
|
| 46 |
+
assert degrees == sorted(d for n, d in graph.degree())
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def test_connected_double_edge_swap_low_window_threshold():
|
| 50 |
+
graph = nx.barabasi_albert_graph(200, 1)
|
| 51 |
+
degrees = sorted(d for n, d in graph.degree())
|
| 52 |
+
G = nx.connected_double_edge_swap(graph, 40, _window_threshold=0, seed=1)
|
| 53 |
+
assert nx.is_connected(graph)
|
| 54 |
+
assert degrees == sorted(d for n, d in graph.degree())
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def test_connected_double_edge_swap_star():
|
| 58 |
+
# Testing ui==xi in connected_double_edge_swap
|
| 59 |
+
graph = nx.star_graph(40)
|
| 60 |
+
degrees = sorted(d for n, d in graph.degree())
|
| 61 |
+
G = nx.connected_double_edge_swap(graph, 1, seed=4)
|
| 62 |
+
assert nx.is_connected(graph)
|
| 63 |
+
assert degrees == sorted(d for n, d in graph.degree())
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
def test_connected_double_edge_swap_star_low_window_threshold():
|
| 67 |
+
# Testing ui==xi in connected_double_edge_swap with low window threshold
|
| 68 |
+
graph = nx.star_graph(40)
|
| 69 |
+
degrees = sorted(d for n, d in graph.degree())
|
| 70 |
+
G = nx.connected_double_edge_swap(graph, 1, _window_threshold=0, seed=4)
|
| 71 |
+
assert nx.is_connected(graph)
|
| 72 |
+
assert degrees == sorted(d for n, d in graph.degree())
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def test_directed_edge_swap_small():
|
| 76 |
+
with pytest.raises(nx.NetworkXError):
|
| 77 |
+
G = nx.directed_edge_swap(nx.path_graph(3, create_using=nx.DiGraph))
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def test_directed_edge_swap_tries():
|
| 81 |
+
with pytest.raises(nx.NetworkXError):
|
| 82 |
+
G = nx.directed_edge_swap(
|
| 83 |
+
nx.path_graph(3, create_using=nx.DiGraph), nswap=1, max_tries=0
|
| 84 |
+
)
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
def test_directed_exception_undirected():
|
| 88 |
+
graph = nx.Graph([(0, 1), (2, 3)])
|
| 89 |
+
with pytest.raises(nx.NetworkXNotImplemented):
|
| 90 |
+
G = nx.directed_edge_swap(graph)
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def test_directed_edge_max_tries():
|
| 94 |
+
with pytest.raises(nx.NetworkXAlgorithmError):
|
| 95 |
+
G = nx.directed_edge_swap(
|
| 96 |
+
nx.complete_graph(4, nx.DiGraph()), nswap=1, max_tries=5
|
| 97 |
+
)
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
def test_double_edge_swap_small():
|
| 101 |
+
with pytest.raises(nx.NetworkXError):
|
| 102 |
+
G = nx.double_edge_swap(nx.path_graph(3))
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
def test_double_edge_swap_tries():
|
| 106 |
+
with pytest.raises(nx.NetworkXError):
|
| 107 |
+
G = nx.double_edge_swap(nx.path_graph(10), nswap=1, max_tries=0)
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
def test_double_edge_directed():
|
| 111 |
+
graph = nx.DiGraph([(0, 1), (2, 3)])
|
| 112 |
+
with pytest.raises(nx.NetworkXError, match="not defined for directed graphs."):
|
| 113 |
+
G = nx.double_edge_swap(graph)
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
def test_double_edge_max_tries():
|
| 117 |
+
with pytest.raises(nx.NetworkXAlgorithmError):
|
| 118 |
+
G = nx.double_edge_swap(nx.complete_graph(4), nswap=1, max_tries=5)
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
def test_connected_double_edge_swap_small():
|
| 122 |
+
with pytest.raises(nx.NetworkXError):
|
| 123 |
+
G = nx.connected_double_edge_swap(nx.path_graph(3))
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
def test_connected_double_edge_swap_not_connected():
|
| 127 |
+
with pytest.raises(nx.NetworkXError):
|
| 128 |
+
G = nx.path_graph(3)
|
| 129 |
+
nx.add_path(G, [10, 11, 12])
|
| 130 |
+
G = nx.connected_double_edge_swap(G)
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
def test_degree_seq_c4():
|
| 134 |
+
G = nx.cycle_graph(4)
|
| 135 |
+
degrees = sorted(d for n, d in G.degree())
|
| 136 |
+
G = nx.double_edge_swap(G, 1, 100)
|
| 137 |
+
assert degrees == sorted(d for n, d in G.degree())
|
| 138 |
+
|
| 139 |
+
|
| 140 |
+
def test_fewer_than_4_nodes():
|
| 141 |
+
G = nx.DiGraph()
|
| 142 |
+
G.add_nodes_from([0, 1, 2])
|
| 143 |
+
with pytest.raises(nx.NetworkXError, match=".*fewer than four nodes."):
|
| 144 |
+
nx.directed_edge_swap(G)
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
def test_less_than_3_edges():
|
| 148 |
+
G = nx.DiGraph([(0, 1), (1, 2)])
|
| 149 |
+
G.add_nodes_from([3, 4])
|
| 150 |
+
with pytest.raises(nx.NetworkXError, match=".*fewer than 3 edges"):
|
| 151 |
+
nx.directed_edge_swap(G)
|
| 152 |
+
|
| 153 |
+
G = nx.Graph()
|
| 154 |
+
G.add_nodes_from([0, 1, 2, 3])
|
| 155 |
+
with pytest.raises(nx.NetworkXError, match=".*fewer than 2 edges"):
|
| 156 |
+
nx.double_edge_swap(G)
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_time_dependent.py
ADDED
|
@@ -0,0 +1,431 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Unit testing for time dependent algorithms."""
|
| 2 |
+
|
| 3 |
+
from datetime import datetime, timedelta
|
| 4 |
+
|
| 5 |
+
import pytest
|
| 6 |
+
|
| 7 |
+
import networkx as nx
|
| 8 |
+
|
| 9 |
+
_delta = timedelta(days=5 * 365)
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class TestCdIndex:
|
| 13 |
+
"""Unit testing for the cd index function."""
|
| 14 |
+
|
| 15 |
+
def test_common_graph(self):
|
| 16 |
+
G = nx.DiGraph()
|
| 17 |
+
G.add_nodes_from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
| 18 |
+
G.add_edge(4, 2)
|
| 19 |
+
G.add_edge(4, 0)
|
| 20 |
+
G.add_edge(4, 1)
|
| 21 |
+
G.add_edge(4, 3)
|
| 22 |
+
G.add_edge(5, 2)
|
| 23 |
+
G.add_edge(6, 2)
|
| 24 |
+
G.add_edge(6, 4)
|
| 25 |
+
G.add_edge(7, 4)
|
| 26 |
+
G.add_edge(8, 4)
|
| 27 |
+
G.add_edge(9, 4)
|
| 28 |
+
G.add_edge(9, 1)
|
| 29 |
+
G.add_edge(9, 3)
|
| 30 |
+
G.add_edge(10, 4)
|
| 31 |
+
|
| 32 |
+
node_attrs = {
|
| 33 |
+
0: {"time": datetime(1992, 1, 1)},
|
| 34 |
+
1: {"time": datetime(1992, 1, 1)},
|
| 35 |
+
2: {"time": datetime(1993, 1, 1)},
|
| 36 |
+
3: {"time": datetime(1993, 1, 1)},
|
| 37 |
+
4: {"time": datetime(1995, 1, 1)},
|
| 38 |
+
5: {"time": datetime(1997, 1, 1)},
|
| 39 |
+
6: {"time": datetime(1998, 1, 1)},
|
| 40 |
+
7: {"time": datetime(1999, 1, 1)},
|
| 41 |
+
8: {"time": datetime(1999, 1, 1)},
|
| 42 |
+
9: {"time": datetime(1998, 1, 1)},
|
| 43 |
+
10: {"time": datetime(1997, 4, 1)},
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
nx.set_node_attributes(G, node_attrs)
|
| 47 |
+
|
| 48 |
+
assert nx.cd_index(G, 4, time_delta=_delta) == 0.17
|
| 49 |
+
|
| 50 |
+
def test_common_graph_with_given_attributes(self):
|
| 51 |
+
G = nx.DiGraph()
|
| 52 |
+
G.add_nodes_from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
| 53 |
+
G.add_edge(4, 2)
|
| 54 |
+
G.add_edge(4, 0)
|
| 55 |
+
G.add_edge(4, 1)
|
| 56 |
+
G.add_edge(4, 3)
|
| 57 |
+
G.add_edge(5, 2)
|
| 58 |
+
G.add_edge(6, 2)
|
| 59 |
+
G.add_edge(6, 4)
|
| 60 |
+
G.add_edge(7, 4)
|
| 61 |
+
G.add_edge(8, 4)
|
| 62 |
+
G.add_edge(9, 4)
|
| 63 |
+
G.add_edge(9, 1)
|
| 64 |
+
G.add_edge(9, 3)
|
| 65 |
+
G.add_edge(10, 4)
|
| 66 |
+
|
| 67 |
+
node_attrs = {
|
| 68 |
+
0: {"date": datetime(1992, 1, 1)},
|
| 69 |
+
1: {"date": datetime(1992, 1, 1)},
|
| 70 |
+
2: {"date": datetime(1993, 1, 1)},
|
| 71 |
+
3: {"date": datetime(1993, 1, 1)},
|
| 72 |
+
4: {"date": datetime(1995, 1, 1)},
|
| 73 |
+
5: {"date": datetime(1997, 1, 1)},
|
| 74 |
+
6: {"date": datetime(1998, 1, 1)},
|
| 75 |
+
7: {"date": datetime(1999, 1, 1)},
|
| 76 |
+
8: {"date": datetime(1999, 1, 1)},
|
| 77 |
+
9: {"date": datetime(1998, 1, 1)},
|
| 78 |
+
10: {"date": datetime(1997, 4, 1)},
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
nx.set_node_attributes(G, node_attrs)
|
| 82 |
+
|
| 83 |
+
assert nx.cd_index(G, 4, time_delta=_delta, time="date") == 0.17
|
| 84 |
+
|
| 85 |
+
def test_common_graph_with_int_attributes(self):
|
| 86 |
+
G = nx.DiGraph()
|
| 87 |
+
G.add_nodes_from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
| 88 |
+
G.add_edge(4, 2)
|
| 89 |
+
G.add_edge(4, 0)
|
| 90 |
+
G.add_edge(4, 1)
|
| 91 |
+
G.add_edge(4, 3)
|
| 92 |
+
G.add_edge(5, 2)
|
| 93 |
+
G.add_edge(6, 2)
|
| 94 |
+
G.add_edge(6, 4)
|
| 95 |
+
G.add_edge(7, 4)
|
| 96 |
+
G.add_edge(8, 4)
|
| 97 |
+
G.add_edge(9, 4)
|
| 98 |
+
G.add_edge(9, 1)
|
| 99 |
+
G.add_edge(9, 3)
|
| 100 |
+
G.add_edge(10, 4)
|
| 101 |
+
|
| 102 |
+
node_attrs = {
|
| 103 |
+
0: {"time": 20},
|
| 104 |
+
1: {"time": 20},
|
| 105 |
+
2: {"time": 30},
|
| 106 |
+
3: {"time": 30},
|
| 107 |
+
4: {"time": 50},
|
| 108 |
+
5: {"time": 70},
|
| 109 |
+
6: {"time": 80},
|
| 110 |
+
7: {"time": 90},
|
| 111 |
+
8: {"time": 90},
|
| 112 |
+
9: {"time": 80},
|
| 113 |
+
10: {"time": 74},
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
nx.set_node_attributes(G, node_attrs)
|
| 117 |
+
|
| 118 |
+
assert nx.cd_index(G, 4, time_delta=50) == 0.17
|
| 119 |
+
|
| 120 |
+
def test_common_graph_with_float_attributes(self):
|
| 121 |
+
G = nx.DiGraph()
|
| 122 |
+
G.add_nodes_from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
| 123 |
+
G.add_edge(4, 2)
|
| 124 |
+
G.add_edge(4, 0)
|
| 125 |
+
G.add_edge(4, 1)
|
| 126 |
+
G.add_edge(4, 3)
|
| 127 |
+
G.add_edge(5, 2)
|
| 128 |
+
G.add_edge(6, 2)
|
| 129 |
+
G.add_edge(6, 4)
|
| 130 |
+
G.add_edge(7, 4)
|
| 131 |
+
G.add_edge(8, 4)
|
| 132 |
+
G.add_edge(9, 4)
|
| 133 |
+
G.add_edge(9, 1)
|
| 134 |
+
G.add_edge(9, 3)
|
| 135 |
+
G.add_edge(10, 4)
|
| 136 |
+
|
| 137 |
+
node_attrs = {
|
| 138 |
+
0: {"time": 20.2},
|
| 139 |
+
1: {"time": 20.2},
|
| 140 |
+
2: {"time": 30.7},
|
| 141 |
+
3: {"time": 30.7},
|
| 142 |
+
4: {"time": 50.9},
|
| 143 |
+
5: {"time": 70.1},
|
| 144 |
+
6: {"time": 80.6},
|
| 145 |
+
7: {"time": 90.7},
|
| 146 |
+
8: {"time": 90.7},
|
| 147 |
+
9: {"time": 80.6},
|
| 148 |
+
10: {"time": 74.2},
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
nx.set_node_attributes(G, node_attrs)
|
| 152 |
+
|
| 153 |
+
assert nx.cd_index(G, 4, time_delta=50) == 0.17
|
| 154 |
+
|
| 155 |
+
def test_common_graph_with_weights(self):
|
| 156 |
+
G = nx.DiGraph()
|
| 157 |
+
G.add_nodes_from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
| 158 |
+
G.add_edge(4, 2)
|
| 159 |
+
G.add_edge(4, 0)
|
| 160 |
+
G.add_edge(4, 1)
|
| 161 |
+
G.add_edge(4, 3)
|
| 162 |
+
G.add_edge(5, 2)
|
| 163 |
+
G.add_edge(6, 2)
|
| 164 |
+
G.add_edge(6, 4)
|
| 165 |
+
G.add_edge(7, 4)
|
| 166 |
+
G.add_edge(8, 4)
|
| 167 |
+
G.add_edge(9, 4)
|
| 168 |
+
G.add_edge(9, 1)
|
| 169 |
+
G.add_edge(9, 3)
|
| 170 |
+
G.add_edge(10, 4)
|
| 171 |
+
|
| 172 |
+
node_attrs = {
|
| 173 |
+
0: {"time": datetime(1992, 1, 1)},
|
| 174 |
+
1: {"time": datetime(1992, 1, 1)},
|
| 175 |
+
2: {"time": datetime(1993, 1, 1)},
|
| 176 |
+
3: {"time": datetime(1993, 1, 1)},
|
| 177 |
+
4: {"time": datetime(1995, 1, 1)},
|
| 178 |
+
5: {"time": datetime(1997, 1, 1)},
|
| 179 |
+
6: {"time": datetime(1998, 1, 1), "weight": 5},
|
| 180 |
+
7: {"time": datetime(1999, 1, 1), "weight": 2},
|
| 181 |
+
8: {"time": datetime(1999, 1, 1), "weight": 6},
|
| 182 |
+
9: {"time": datetime(1998, 1, 1), "weight": 3},
|
| 183 |
+
10: {"time": datetime(1997, 4, 1), "weight": 10},
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
nx.set_node_attributes(G, node_attrs)
|
| 187 |
+
assert nx.cd_index(G, 4, time_delta=_delta, weight="weight") == 0.04
|
| 188 |
+
|
| 189 |
+
def test_node_with_no_predecessors(self):
|
| 190 |
+
G = nx.DiGraph()
|
| 191 |
+
G.add_nodes_from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
| 192 |
+
G.add_edge(4, 2)
|
| 193 |
+
G.add_edge(4, 0)
|
| 194 |
+
G.add_edge(4, 3)
|
| 195 |
+
G.add_edge(5, 2)
|
| 196 |
+
G.add_edge(6, 2)
|
| 197 |
+
G.add_edge(6, 4)
|
| 198 |
+
G.add_edge(7, 4)
|
| 199 |
+
G.add_edge(8, 4)
|
| 200 |
+
G.add_edge(9, 4)
|
| 201 |
+
G.add_edge(9, 1)
|
| 202 |
+
G.add_edge(9, 3)
|
| 203 |
+
G.add_edge(10, 4)
|
| 204 |
+
|
| 205 |
+
node_attrs = {
|
| 206 |
+
0: {"time": datetime(1992, 1, 1)},
|
| 207 |
+
1: {"time": datetime(1992, 1, 1)},
|
| 208 |
+
2: {"time": datetime(1993, 1, 1)},
|
| 209 |
+
3: {"time": datetime(1993, 1, 1)},
|
| 210 |
+
4: {"time": datetime(1995, 1, 1)},
|
| 211 |
+
5: {"time": datetime(2005, 1, 1)},
|
| 212 |
+
6: {"time": datetime(2010, 1, 1)},
|
| 213 |
+
7: {"time": datetime(2001, 1, 1)},
|
| 214 |
+
8: {"time": datetime(2020, 1, 1)},
|
| 215 |
+
9: {"time": datetime(2017, 1, 1)},
|
| 216 |
+
10: {"time": datetime(2004, 4, 1)},
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
nx.set_node_attributes(G, node_attrs)
|
| 220 |
+
assert nx.cd_index(G, 4, time_delta=_delta) == 0.0
|
| 221 |
+
|
| 222 |
+
def test_node_with_no_successors(self):
|
| 223 |
+
G = nx.DiGraph()
|
| 224 |
+
G.add_nodes_from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
| 225 |
+
G.add_edge(8, 2)
|
| 226 |
+
G.add_edge(6, 0)
|
| 227 |
+
G.add_edge(6, 3)
|
| 228 |
+
G.add_edge(5, 2)
|
| 229 |
+
G.add_edge(6, 2)
|
| 230 |
+
G.add_edge(6, 4)
|
| 231 |
+
G.add_edge(7, 4)
|
| 232 |
+
G.add_edge(8, 4)
|
| 233 |
+
G.add_edge(9, 4)
|
| 234 |
+
G.add_edge(9, 1)
|
| 235 |
+
G.add_edge(9, 3)
|
| 236 |
+
G.add_edge(10, 4)
|
| 237 |
+
|
| 238 |
+
node_attrs = {
|
| 239 |
+
0: {"time": datetime(1992, 1, 1)},
|
| 240 |
+
1: {"time": datetime(1992, 1, 1)},
|
| 241 |
+
2: {"time": datetime(1993, 1, 1)},
|
| 242 |
+
3: {"time": datetime(1993, 1, 1)},
|
| 243 |
+
4: {"time": datetime(1995, 1, 1)},
|
| 244 |
+
5: {"time": datetime(1997, 1, 1)},
|
| 245 |
+
6: {"time": datetime(1998, 1, 1)},
|
| 246 |
+
7: {"time": datetime(1999, 1, 1)},
|
| 247 |
+
8: {"time": datetime(1999, 1, 1)},
|
| 248 |
+
9: {"time": datetime(1998, 1, 1)},
|
| 249 |
+
10: {"time": datetime(1997, 4, 1)},
|
| 250 |
+
}
|
| 251 |
+
|
| 252 |
+
nx.set_node_attributes(G, node_attrs)
|
| 253 |
+
assert nx.cd_index(G, 4, time_delta=_delta) == 1.0
|
| 254 |
+
|
| 255 |
+
def test_n_equals_zero(self):
|
| 256 |
+
G = nx.DiGraph()
|
| 257 |
+
G.add_nodes_from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
| 258 |
+
G.add_edge(4, 2)
|
| 259 |
+
G.add_edge(4, 0)
|
| 260 |
+
G.add_edge(4, 3)
|
| 261 |
+
G.add_edge(6, 4)
|
| 262 |
+
G.add_edge(7, 4)
|
| 263 |
+
G.add_edge(8, 4)
|
| 264 |
+
G.add_edge(9, 4)
|
| 265 |
+
G.add_edge(9, 1)
|
| 266 |
+
G.add_edge(10, 4)
|
| 267 |
+
|
| 268 |
+
node_attrs = {
|
| 269 |
+
0: {"time": datetime(1992, 1, 1)},
|
| 270 |
+
1: {"time": datetime(1992, 1, 1)},
|
| 271 |
+
2: {"time": datetime(1993, 1, 1)},
|
| 272 |
+
3: {"time": datetime(1993, 1, 1)},
|
| 273 |
+
4: {"time": datetime(1995, 1, 1)},
|
| 274 |
+
5: {"time": datetime(2005, 1, 1)},
|
| 275 |
+
6: {"time": datetime(2010, 1, 1)},
|
| 276 |
+
7: {"time": datetime(2001, 1, 1)},
|
| 277 |
+
8: {"time": datetime(2020, 1, 1)},
|
| 278 |
+
9: {"time": datetime(2017, 1, 1)},
|
| 279 |
+
10: {"time": datetime(2004, 4, 1)},
|
| 280 |
+
}
|
| 281 |
+
|
| 282 |
+
nx.set_node_attributes(G, node_attrs)
|
| 283 |
+
|
| 284 |
+
with pytest.raises(
|
| 285 |
+
nx.NetworkXError, match="The cd index cannot be defined."
|
| 286 |
+
) as ve:
|
| 287 |
+
nx.cd_index(G, 4, time_delta=_delta)
|
| 288 |
+
|
| 289 |
+
def test_time_timedelta_compatibility(self):
|
| 290 |
+
G = nx.DiGraph()
|
| 291 |
+
G.add_nodes_from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
| 292 |
+
G.add_edge(4, 2)
|
| 293 |
+
G.add_edge(4, 0)
|
| 294 |
+
G.add_edge(4, 3)
|
| 295 |
+
G.add_edge(6, 4)
|
| 296 |
+
G.add_edge(7, 4)
|
| 297 |
+
G.add_edge(8, 4)
|
| 298 |
+
G.add_edge(9, 4)
|
| 299 |
+
G.add_edge(9, 1)
|
| 300 |
+
G.add_edge(10, 4)
|
| 301 |
+
|
| 302 |
+
node_attrs = {
|
| 303 |
+
0: {"time": 20.2},
|
| 304 |
+
1: {"time": 20.2},
|
| 305 |
+
2: {"time": 30.7},
|
| 306 |
+
3: {"time": 30.7},
|
| 307 |
+
4: {"time": 50.9},
|
| 308 |
+
5: {"time": 70.1},
|
| 309 |
+
6: {"time": 80.6},
|
| 310 |
+
7: {"time": 90.7},
|
| 311 |
+
8: {"time": 90.7},
|
| 312 |
+
9: {"time": 80.6},
|
| 313 |
+
10: {"time": 74.2},
|
| 314 |
+
}
|
| 315 |
+
|
| 316 |
+
nx.set_node_attributes(G, node_attrs)
|
| 317 |
+
|
| 318 |
+
with pytest.raises(
|
| 319 |
+
nx.NetworkXError,
|
| 320 |
+
match="Addition and comparison are not supported between",
|
| 321 |
+
) as ve:
|
| 322 |
+
nx.cd_index(G, 4, time_delta=_delta)
|
| 323 |
+
|
| 324 |
+
def test_node_with_no_time(self):
|
| 325 |
+
G = nx.DiGraph()
|
| 326 |
+
G.add_nodes_from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
| 327 |
+
G.add_edge(8, 2)
|
| 328 |
+
G.add_edge(6, 0)
|
| 329 |
+
G.add_edge(6, 3)
|
| 330 |
+
G.add_edge(5, 2)
|
| 331 |
+
G.add_edge(6, 2)
|
| 332 |
+
G.add_edge(6, 4)
|
| 333 |
+
G.add_edge(7, 4)
|
| 334 |
+
G.add_edge(8, 4)
|
| 335 |
+
G.add_edge(9, 4)
|
| 336 |
+
G.add_edge(9, 1)
|
| 337 |
+
G.add_edge(9, 3)
|
| 338 |
+
G.add_edge(10, 4)
|
| 339 |
+
|
| 340 |
+
node_attrs = {
|
| 341 |
+
0: {"time": datetime(1992, 1, 1)},
|
| 342 |
+
1: {"time": datetime(1992, 1, 1)},
|
| 343 |
+
2: {"time": datetime(1993, 1, 1)},
|
| 344 |
+
3: {"time": datetime(1993, 1, 1)},
|
| 345 |
+
4: {"time": datetime(1995, 1, 1)},
|
| 346 |
+
6: {"time": datetime(1998, 1, 1)},
|
| 347 |
+
7: {"time": datetime(1999, 1, 1)},
|
| 348 |
+
8: {"time": datetime(1999, 1, 1)},
|
| 349 |
+
9: {"time": datetime(1998, 1, 1)},
|
| 350 |
+
10: {"time": datetime(1997, 4, 1)},
|
| 351 |
+
}
|
| 352 |
+
|
| 353 |
+
nx.set_node_attributes(G, node_attrs)
|
| 354 |
+
|
| 355 |
+
with pytest.raises(
|
| 356 |
+
nx.NetworkXError, match="Not all nodes have a 'time' attribute."
|
| 357 |
+
) as ve:
|
| 358 |
+
nx.cd_index(G, 4, time_delta=_delta)
|
| 359 |
+
|
| 360 |
+
def test_maximally_consolidating(self):
|
| 361 |
+
G = nx.DiGraph()
|
| 362 |
+
G.add_nodes_from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
|
| 363 |
+
G.add_edge(5, 1)
|
| 364 |
+
G.add_edge(5, 2)
|
| 365 |
+
G.add_edge(5, 3)
|
| 366 |
+
G.add_edge(5, 4)
|
| 367 |
+
G.add_edge(6, 1)
|
| 368 |
+
G.add_edge(6, 5)
|
| 369 |
+
G.add_edge(7, 1)
|
| 370 |
+
G.add_edge(7, 5)
|
| 371 |
+
G.add_edge(8, 2)
|
| 372 |
+
G.add_edge(8, 5)
|
| 373 |
+
G.add_edge(9, 5)
|
| 374 |
+
G.add_edge(9, 3)
|
| 375 |
+
G.add_edge(10, 5)
|
| 376 |
+
G.add_edge(10, 3)
|
| 377 |
+
G.add_edge(10, 4)
|
| 378 |
+
G.add_edge(11, 5)
|
| 379 |
+
G.add_edge(11, 4)
|
| 380 |
+
|
| 381 |
+
node_attrs = {
|
| 382 |
+
0: {"time": datetime(1992, 1, 1)},
|
| 383 |
+
1: {"time": datetime(1992, 1, 1)},
|
| 384 |
+
2: {"time": datetime(1993, 1, 1)},
|
| 385 |
+
3: {"time": datetime(1993, 1, 1)},
|
| 386 |
+
4: {"time": datetime(1995, 1, 1)},
|
| 387 |
+
5: {"time": datetime(1997, 1, 1)},
|
| 388 |
+
6: {"time": datetime(1998, 1, 1)},
|
| 389 |
+
7: {"time": datetime(1999, 1, 1)},
|
| 390 |
+
8: {"time": datetime(1999, 1, 1)},
|
| 391 |
+
9: {"time": datetime(1998, 1, 1)},
|
| 392 |
+
10: {"time": datetime(1997, 4, 1)},
|
| 393 |
+
11: {"time": datetime(1998, 5, 1)},
|
| 394 |
+
}
|
| 395 |
+
|
| 396 |
+
nx.set_node_attributes(G, node_attrs)
|
| 397 |
+
|
| 398 |
+
assert nx.cd_index(G, 5, time_delta=_delta) == -1
|
| 399 |
+
|
| 400 |
+
def test_maximally_destabilizing(self):
|
| 401 |
+
G = nx.DiGraph()
|
| 402 |
+
G.add_nodes_from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
|
| 403 |
+
G.add_edge(5, 1)
|
| 404 |
+
G.add_edge(5, 2)
|
| 405 |
+
G.add_edge(5, 3)
|
| 406 |
+
G.add_edge(5, 4)
|
| 407 |
+
G.add_edge(6, 5)
|
| 408 |
+
G.add_edge(7, 5)
|
| 409 |
+
G.add_edge(8, 5)
|
| 410 |
+
G.add_edge(9, 5)
|
| 411 |
+
G.add_edge(10, 5)
|
| 412 |
+
G.add_edge(11, 5)
|
| 413 |
+
|
| 414 |
+
node_attrs = {
|
| 415 |
+
0: {"time": datetime(1992, 1, 1)},
|
| 416 |
+
1: {"time": datetime(1992, 1, 1)},
|
| 417 |
+
2: {"time": datetime(1993, 1, 1)},
|
| 418 |
+
3: {"time": datetime(1993, 1, 1)},
|
| 419 |
+
4: {"time": datetime(1995, 1, 1)},
|
| 420 |
+
5: {"time": datetime(1997, 1, 1)},
|
| 421 |
+
6: {"time": datetime(1998, 1, 1)},
|
| 422 |
+
7: {"time": datetime(1999, 1, 1)},
|
| 423 |
+
8: {"time": datetime(1999, 1, 1)},
|
| 424 |
+
9: {"time": datetime(1998, 1, 1)},
|
| 425 |
+
10: {"time": datetime(1997, 4, 1)},
|
| 426 |
+
11: {"time": datetime(1998, 5, 1)},
|
| 427 |
+
}
|
| 428 |
+
|
| 429 |
+
nx.set_node_attributes(G, node_attrs)
|
| 430 |
+
|
| 431 |
+
assert nx.cd_index(G, 5, time_delta=_delta) == 1
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/algorithms/tests/test_voronoi.py
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import networkx as nx
|
| 2 |
+
from networkx.utils import pairwise
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class TestVoronoiCells:
|
| 6 |
+
"""Unit tests for the Voronoi cells function."""
|
| 7 |
+
|
| 8 |
+
def test_isolates(self):
|
| 9 |
+
"""Tests that a graph with isolated nodes has all isolates in
|
| 10 |
+
one block of the partition.
|
| 11 |
+
|
| 12 |
+
"""
|
| 13 |
+
G = nx.empty_graph(5)
|
| 14 |
+
cells = nx.voronoi_cells(G, {0, 2, 4})
|
| 15 |
+
expected = {0: {0}, 2: {2}, 4: {4}, "unreachable": {1, 3}}
|
| 16 |
+
assert expected == cells
|
| 17 |
+
|
| 18 |
+
def test_undirected_unweighted(self):
|
| 19 |
+
G = nx.cycle_graph(6)
|
| 20 |
+
cells = nx.voronoi_cells(G, {0, 3})
|
| 21 |
+
expected = {0: {0, 1, 5}, 3: {2, 3, 4}}
|
| 22 |
+
assert expected == cells
|
| 23 |
+
|
| 24 |
+
def test_directed_unweighted(self):
|
| 25 |
+
# This is the singly-linked directed cycle graph on six nodes.
|
| 26 |
+
G = nx.DiGraph(pairwise(range(6), cyclic=True))
|
| 27 |
+
cells = nx.voronoi_cells(G, {0, 3})
|
| 28 |
+
expected = {0: {0, 1, 2}, 3: {3, 4, 5}}
|
| 29 |
+
assert expected == cells
|
| 30 |
+
|
| 31 |
+
def test_directed_inward(self):
|
| 32 |
+
"""Tests that reversing the graph gives the "inward" Voronoi
|
| 33 |
+
partition.
|
| 34 |
+
|
| 35 |
+
"""
|
| 36 |
+
# This is the singly-linked reverse directed cycle graph on six nodes.
|
| 37 |
+
G = nx.DiGraph(pairwise(range(6), cyclic=True))
|
| 38 |
+
G = G.reverse(copy=False)
|
| 39 |
+
cells = nx.voronoi_cells(G, {0, 3})
|
| 40 |
+
expected = {0: {0, 4, 5}, 3: {1, 2, 3}}
|
| 41 |
+
assert expected == cells
|
| 42 |
+
|
| 43 |
+
def test_undirected_weighted(self):
|
| 44 |
+
edges = [(0, 1, 10), (1, 2, 1), (2, 3, 1)]
|
| 45 |
+
G = nx.Graph()
|
| 46 |
+
G.add_weighted_edges_from(edges)
|
| 47 |
+
cells = nx.voronoi_cells(G, {0, 3})
|
| 48 |
+
expected = {0: {0}, 3: {1, 2, 3}}
|
| 49 |
+
assert expected == cells
|
| 50 |
+
|
| 51 |
+
def test_directed_weighted(self):
|
| 52 |
+
edges = [(0, 1, 10), (1, 2, 1), (2, 3, 1), (3, 2, 1), (2, 1, 1)]
|
| 53 |
+
G = nx.DiGraph()
|
| 54 |
+
G.add_weighted_edges_from(edges)
|
| 55 |
+
cells = nx.voronoi_cells(G, {0, 3})
|
| 56 |
+
expected = {0: {0}, 3: {1, 2, 3}}
|
| 57 |
+
assert expected == cells
|
| 58 |
+
|
| 59 |
+
def test_multigraph_unweighted(self):
|
| 60 |
+
"""Tests that the Voronoi cells for a multigraph are the same as
|
| 61 |
+
for a simple graph.
|
| 62 |
+
|
| 63 |
+
"""
|
| 64 |
+
edges = [(0, 1), (1, 2), (2, 3)]
|
| 65 |
+
G = nx.MultiGraph(2 * edges)
|
| 66 |
+
H = nx.Graph(G)
|
| 67 |
+
G_cells = nx.voronoi_cells(G, {0, 3})
|
| 68 |
+
H_cells = nx.voronoi_cells(H, {0, 3})
|
| 69 |
+
assert G_cells == H_cells
|
| 70 |
+
|
| 71 |
+
def test_multidigraph_unweighted(self):
|
| 72 |
+
# This is the twice-singly-linked directed cycle graph on six nodes.
|
| 73 |
+
edges = list(pairwise(range(6), cyclic=True))
|
| 74 |
+
G = nx.MultiDiGraph(2 * edges)
|
| 75 |
+
H = nx.DiGraph(G)
|
| 76 |
+
G_cells = nx.voronoi_cells(G, {0, 3})
|
| 77 |
+
H_cells = nx.voronoi_cells(H, {0, 3})
|
| 78 |
+
assert G_cells == H_cells
|
| 79 |
+
|
| 80 |
+
def test_multigraph_weighted(self):
|
| 81 |
+
edges = [(0, 1, 10), (0, 1, 10), (1, 2, 1), (1, 2, 100), (2, 3, 1), (2, 3, 100)]
|
| 82 |
+
G = nx.MultiGraph()
|
| 83 |
+
G.add_weighted_edges_from(edges)
|
| 84 |
+
cells = nx.voronoi_cells(G, {0, 3})
|
| 85 |
+
expected = {0: {0}, 3: {1, 2, 3}}
|
| 86 |
+
assert expected == cells
|
| 87 |
+
|
| 88 |
+
def test_multidigraph_weighted(self):
|
| 89 |
+
edges = [
|
| 90 |
+
(0, 1, 10),
|
| 91 |
+
(0, 1, 10),
|
| 92 |
+
(1, 2, 1),
|
| 93 |
+
(2, 3, 1),
|
| 94 |
+
(3, 2, 10),
|
| 95 |
+
(3, 2, 1),
|
| 96 |
+
(2, 1, 10),
|
| 97 |
+
(2, 1, 1),
|
| 98 |
+
]
|
| 99 |
+
G = nx.MultiDiGraph()
|
| 100 |
+
G.add_weighted_edges_from(edges)
|
| 101 |
+
cells = nx.voronoi_cells(G, {0, 3})
|
| 102 |
+
expected = {0: {0}, 3: {1, 2, 3}}
|
| 103 |
+
assert expected == cells
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_degree_seq.cpython-311.pyc
ADDED
|
Binary file (15.9 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_geometric.cpython-311.pyc
ADDED
|
Binary file (25.3 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_harary_graph.cpython-311.pyc
ADDED
|
Binary file (6.28 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_interval_graph.cpython-311.pyc
ADDED
|
Binary file (7.47 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_lattice.cpython-311.pyc
ADDED
|
Binary file (19.9 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_random_graphs.cpython-311.pyc
ADDED
|
Binary file (23.3 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_small.cpython-311.pyc
ADDED
|
Binary file (19.5 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_spectral_graph_forge.cpython-311.pyc
ADDED
|
Binary file (2.16 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_trees.cpython-311.pyc
ADDED
|
Binary file (15 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/networkx/generators/tests/__pycache__/test_triads.cpython-311.pyc
ADDED
|
Binary file (1.38 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (907 Bytes). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/__pycache__/exceptions.cpython-311.pyc
ADDED
|
Binary file (41.6 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/cli/__init__.py
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Subpackage containing all of pip's command line interface related code
|
| 2 |
+
"""
|
| 3 |
+
|
| 4 |
+
# This file intentionally does not import submodules
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (311 Bytes). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-311.pyc
ADDED
|
Binary file (10.4 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-311.pyc
ADDED
|
Binary file (11.6 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-311.pyc
ADDED
|
Binary file (33.8 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-311.pyc
ADDED
|
Binary file (2.13 kB). View file
|
|
|
tuning-competition-baseline/.venv/lib/python3.11/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-311.pyc
ADDED
|
Binary file (8.86 kB). View file
|
|
|