tsp-fast-solver-codingwizard34 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,179 @@
1
+ Metadata-Version: 2.4
2
+ Name: tsp-fast-solver-codingwizard34
3
+ Version: 0.1.0
4
+ Summary: A blazing fast C++ TSP solver wrapped in Cython
5
+ Author-email: CodingWizard34 <developer@example.com>
6
+ Keywords: tsp,graph-algorithms,cython,cplusplus,combinatorial-optimization
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: C++
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
11
+ Requires-Python: >=3.8
12
+ Description-Content-Type: text/markdown
13
+
14
+ # tsp-fast-solver-codingwizard34: Graph Algorithms in Production (TSP)
15
+
16
+ A high-performance implementation of the Traveling Salesperson Problem (TSP) brute-force solver comparing pure Python against native C++ wrapped with Cython.
17
+
18
+ ## Overview
19
+
20
+ The Traveling Salesperson Problem (TSP) is an NP-hard combinatorial graph problem: given a list of cities and the distances between each pair of cities, what is the shortest possible route that visits each city exactly once and returns to the origin city?
21
+
22
+ Because the number of Hamiltonian cycles scales factorially:
23
+ $$\text{Possible Routes} = (N - 1)!$$
24
+ a pure Python search quickly slows down due to interpreter overhead and dynamic type checking. By offloading the permutation traversal to native C++ using `std::next_permutation` and bridging it with a Cython C-extension, we achieve up to **~90x–100x speedup**.
25
+
26
+ ---
27
+
28
+ ## Architecture & Project Structure
29
+
30
+ ```
31
+ tsp-fast-solver/
32
+ ├── pyproject.toml # Build system metadata (PEP 517/518)
33
+ ├── setup.py # Setuptools & Cython C++ build configuration
34
+ ├── benchmark.py # Benchmarking script comparing both solvers
35
+ ├── README.md # Project documentation and benchmarks
36
+ ├── .gitignore # Excludes compiled binaries (.pyd, .so, build/)
37
+ ├── tests/
38
+ │ └── test_tsp.py # Comprehensive unit tests (correctness & edge cases)
39
+ └── tsp_fast_solver/
40
+ ├── __init__.py # Package exports (tsp_python, tsp_cython)
41
+ ├── python_solver.py # Pure Python solver using itertools.permutations
42
+ ├── tsp.h # C++ header declaring tsp_cpp
43
+ ├── tsp.cpp # C++ native solver using std::next_permutation
44
+ ├── c_tsp.pxd # Cython C++ header declaration
45
+ └── _tsp_cython.pyx # Cython wrapper bridging Python 2D lists to std::vector<int>
46
+ ```
47
+
48
+ ### Components
49
+
50
+ 1. **Pure Python Solver (`tsp_python`)**:
51
+ - Uses Python's `itertools.permutations` over nodes $\{1, \dots, N-1\}$.
52
+ - Evaluates $(N-1)!$ possible paths starting and ending at node 0.
53
+
54
+ 2. **Native C++ Solver (`tsp_cpp`)**:
55
+ - Implemented in `tsp.h` and `tsp.cpp`.
56
+ - Uses `std::next_permutation` on a flat `std::vector<int>` distance matrix representation with contiguous memory layout and pointer arithmetic.
57
+
58
+ 3. **Cython Wrapper (`tsp_cython`)**:
59
+ - Defined across `c_tsp.pxd` and `_tsp_cython.pyx`.
60
+ - Validates that the input is a square $N \times N$ matrix.
61
+ - Converts the Python list-of-lists into a 1D `std::vector<int>`, delegates to `tsp_cpp`, and returns the optimal cost.
62
+
63
+ ---
64
+
65
+ ## Benchmark Results
66
+
67
+ Benchmarked on **Python 3.14 (x86_64 Windows)** using `benchmark.py` with reproducible random symmetric distance matrices:
68
+
69
+ | Graph Size (Nodes) | Possible Routes $(N-1)!$ | Pure Python Time (s) | Cython + C++ Time (s) | Speedup Delta | Deliverable Expected Time |
70
+ |:------------------:|:------------------------:|:--------------------:|:---------------------:|:-------------:|:-------------------------:|
71
+ | **$N = 8$** | 5,040 | 0.0026 s | 0.00004 s | **65.2x** | Python < 0.1s / Instant |
72
+ | **$N = 10$** | 362,880 | 0.2208 s | 0.0022 s | **98.5x** | Python ~1–2s / < 0.05s |
73
+ | **$N = 11$** | 3,628,800 | 3.2364 s | 0.0359 s | **90.2x** | Python ~15–30s / ~ 0.5s |
74
+
75
+ *Note: The native C++ implementation solves 3.6+ million permutations in just ~36 milliseconds.*
76
+
77
+ ---
78
+
79
+ ## Quick Start & Usage
80
+
81
+ ### 1. Installation
82
+
83
+ #### From Source (Local Development)
84
+ ```bash
85
+ # Clone the repository
86
+ git clone https://github.com/CodingWizard34/tsp-solver.git
87
+ cd tsp-solver
88
+
89
+ # Build extension in-place
90
+ python setup.py build_ext --inplace
91
+ ```
92
+
93
+ #### Via pip
94
+ ```bash
95
+ pip install .
96
+ # Or once published:
97
+ pip install tsp-fast-solver-codingwizard34
98
+ ```
99
+
100
+ ### 2. Python API
101
+
102
+ ```python
103
+ from tsp_fast_solver import tsp_python, tsp_cython
104
+
105
+ # Define an N x N distance matrix (symmetric or asymmetric)
106
+ distance_matrix = [
107
+ [0, 10, 15, 20],
108
+ [10, 0, 35, 25],
109
+ [15, 35, 0, 30],
110
+ [20, 25, 30, 0]
111
+ ]
112
+
113
+ # Run pure Python solver
114
+ py_cost = tsp_python(distance_matrix)
115
+ print("Pure Python optimal cost:", py_cost) # Output: 80
116
+
117
+ # Run compiled Cython / C++ solver
118
+ cy_cost = tsp_cython(distance_matrix)
119
+ print("Cython / C++ optimal cost:", cy_cost) # Output: 80
120
+ ```
121
+
122
+ ### 3. Running Tests
123
+
124
+ ```bash
125
+ python -m unittest discover -s tests -v
126
+ ```
127
+
128
+ ### 4. Running Benchmarks
129
+
130
+ ```bash
131
+ python benchmark.py
132
+ ```
133
+
134
+ ---
135
+
136
+ ## Packaging and Publishing to PyPI
137
+
138
+ ### 1. Build Source Distribution (sdist) and Wheel
139
+
140
+ ```bash
141
+ # Install the build tool
142
+ python -m pip install --upgrade build
143
+
144
+ # Generate distributions
145
+ python -m build --sdist
146
+ ```
147
+
148
+ The generated `.tar.gz` archive in `dist/` contains all C++ sources, headers, and Cython `.pyx`/`.pxd` files ready for cross-platform compilation upon `pip install`.
149
+
150
+ ### 2. Upload to PyPI with Twine
151
+
152
+ ```bash
153
+ # Install Twine
154
+ python -m pip install --upgrade twine
155
+
156
+ # Upload to TestPyPI (recommended first):
157
+ python -m twine upload --repository testpypi dist/*
158
+
159
+ # Upload to production PyPI:
160
+ python -m twine upload dist/*
161
+ ```
162
+
163
+ When prompted:
164
+ - **Username**: `__token__`
165
+ - **Password**: `<your-pypi-api-token>`
166
+
167
+ ### 3. Verifying Installation
168
+
169
+ In a clean virtual environment:
170
+ ```bash
171
+ pip install tsp-fast-solver-codingwizard34
172
+ python -c "import tsp_fast_solver; print('Success! tsp-fast-solver loaded version:', tsp_fast_solver.__version__)"
173
+ ```
174
+
175
+ ---
176
+
177
+ ## License
178
+
179
+ MIT License.
@@ -0,0 +1,166 @@
1
+ # tsp-fast-solver-codingwizard34: Graph Algorithms in Production (TSP)
2
+
3
+ A high-performance implementation of the Traveling Salesperson Problem (TSP) brute-force solver comparing pure Python against native C++ wrapped with Cython.
4
+
5
+ ## Overview
6
+
7
+ The Traveling Salesperson Problem (TSP) is an NP-hard combinatorial graph problem: given a list of cities and the distances between each pair of cities, what is the shortest possible route that visits each city exactly once and returns to the origin city?
8
+
9
+ Because the number of Hamiltonian cycles scales factorially:
10
+ $$\text{Possible Routes} = (N - 1)!$$
11
+ a pure Python search quickly slows down due to interpreter overhead and dynamic type checking. By offloading the permutation traversal to native C++ using `std::next_permutation` and bridging it with a Cython C-extension, we achieve up to **~90x–100x speedup**.
12
+
13
+ ---
14
+
15
+ ## Architecture & Project Structure
16
+
17
+ ```
18
+ tsp-fast-solver/
19
+ ├── pyproject.toml # Build system metadata (PEP 517/518)
20
+ ├── setup.py # Setuptools & Cython C++ build configuration
21
+ ├── benchmark.py # Benchmarking script comparing both solvers
22
+ ├── README.md # Project documentation and benchmarks
23
+ ├── .gitignore # Excludes compiled binaries (.pyd, .so, build/)
24
+ ├── tests/
25
+ │ └── test_tsp.py # Comprehensive unit tests (correctness & edge cases)
26
+ └── tsp_fast_solver/
27
+ ├── __init__.py # Package exports (tsp_python, tsp_cython)
28
+ ├── python_solver.py # Pure Python solver using itertools.permutations
29
+ ├── tsp.h # C++ header declaring tsp_cpp
30
+ ├── tsp.cpp # C++ native solver using std::next_permutation
31
+ ├── c_tsp.pxd # Cython C++ header declaration
32
+ └── _tsp_cython.pyx # Cython wrapper bridging Python 2D lists to std::vector<int>
33
+ ```
34
+
35
+ ### Components
36
+
37
+ 1. **Pure Python Solver (`tsp_python`)**:
38
+ - Uses Python's `itertools.permutations` over nodes $\{1, \dots, N-1\}$.
39
+ - Evaluates $(N-1)!$ possible paths starting and ending at node 0.
40
+
41
+ 2. **Native C++ Solver (`tsp_cpp`)**:
42
+ - Implemented in `tsp.h` and `tsp.cpp`.
43
+ - Uses `std::next_permutation` on a flat `std::vector<int>` distance matrix representation with contiguous memory layout and pointer arithmetic.
44
+
45
+ 3. **Cython Wrapper (`tsp_cython`)**:
46
+ - Defined across `c_tsp.pxd` and `_tsp_cython.pyx`.
47
+ - Validates that the input is a square $N \times N$ matrix.
48
+ - Converts the Python list-of-lists into a 1D `std::vector<int>`, delegates to `tsp_cpp`, and returns the optimal cost.
49
+
50
+ ---
51
+
52
+ ## Benchmark Results
53
+
54
+ Benchmarked on **Python 3.14 (x86_64 Windows)** using `benchmark.py` with reproducible random symmetric distance matrices:
55
+
56
+ | Graph Size (Nodes) | Possible Routes $(N-1)!$ | Pure Python Time (s) | Cython + C++ Time (s) | Speedup Delta | Deliverable Expected Time |
57
+ |:------------------:|:------------------------:|:--------------------:|:---------------------:|:-------------:|:-------------------------:|
58
+ | **$N = 8$** | 5,040 | 0.0026 s | 0.00004 s | **65.2x** | Python < 0.1s / Instant |
59
+ | **$N = 10$** | 362,880 | 0.2208 s | 0.0022 s | **98.5x** | Python ~1–2s / < 0.05s |
60
+ | **$N = 11$** | 3,628,800 | 3.2364 s | 0.0359 s | **90.2x** | Python ~15–30s / ~ 0.5s |
61
+
62
+ *Note: The native C++ implementation solves 3.6+ million permutations in just ~36 milliseconds.*
63
+
64
+ ---
65
+
66
+ ## Quick Start & Usage
67
+
68
+ ### 1. Installation
69
+
70
+ #### From Source (Local Development)
71
+ ```bash
72
+ # Clone the repository
73
+ git clone https://github.com/CodingWizard34/tsp-solver.git
74
+ cd tsp-solver
75
+
76
+ # Build extension in-place
77
+ python setup.py build_ext --inplace
78
+ ```
79
+
80
+ #### Via pip
81
+ ```bash
82
+ pip install .
83
+ # Or once published:
84
+ pip install tsp-fast-solver-codingwizard34
85
+ ```
86
+
87
+ ### 2. Python API
88
+
89
+ ```python
90
+ from tsp_fast_solver import tsp_python, tsp_cython
91
+
92
+ # Define an N x N distance matrix (symmetric or asymmetric)
93
+ distance_matrix = [
94
+ [0, 10, 15, 20],
95
+ [10, 0, 35, 25],
96
+ [15, 35, 0, 30],
97
+ [20, 25, 30, 0]
98
+ ]
99
+
100
+ # Run pure Python solver
101
+ py_cost = tsp_python(distance_matrix)
102
+ print("Pure Python optimal cost:", py_cost) # Output: 80
103
+
104
+ # Run compiled Cython / C++ solver
105
+ cy_cost = tsp_cython(distance_matrix)
106
+ print("Cython / C++ optimal cost:", cy_cost) # Output: 80
107
+ ```
108
+
109
+ ### 3. Running Tests
110
+
111
+ ```bash
112
+ python -m unittest discover -s tests -v
113
+ ```
114
+
115
+ ### 4. Running Benchmarks
116
+
117
+ ```bash
118
+ python benchmark.py
119
+ ```
120
+
121
+ ---
122
+
123
+ ## Packaging and Publishing to PyPI
124
+
125
+ ### 1. Build Source Distribution (sdist) and Wheel
126
+
127
+ ```bash
128
+ # Install the build tool
129
+ python -m pip install --upgrade build
130
+
131
+ # Generate distributions
132
+ python -m build --sdist
133
+ ```
134
+
135
+ The generated `.tar.gz` archive in `dist/` contains all C++ sources, headers, and Cython `.pyx`/`.pxd` files ready for cross-platform compilation upon `pip install`.
136
+
137
+ ### 2. Upload to PyPI with Twine
138
+
139
+ ```bash
140
+ # Install Twine
141
+ python -m pip install --upgrade twine
142
+
143
+ # Upload to TestPyPI (recommended first):
144
+ python -m twine upload --repository testpypi dist/*
145
+
146
+ # Upload to production PyPI:
147
+ python -m twine upload dist/*
148
+ ```
149
+
150
+ When prompted:
151
+ - **Username**: `__token__`
152
+ - **Password**: `<your-pypi-api-token>`
153
+
154
+ ### 3. Verifying Installation
155
+
156
+ In a clean virtual environment:
157
+ ```bash
158
+ pip install tsp-fast-solver-codingwizard34
159
+ python -c "import tsp_fast_solver; print('Success! tsp-fast-solver loaded version:', tsp_fast_solver.__version__)"
160
+ ```
161
+
162
+ ---
163
+
164
+ ## License
165
+
166
+ MIT License.
@@ -0,0 +1,20 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "cython"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "tsp-fast-solver-codingwizard34"
7
+ version = "0.1.0"
8
+ authors = [
9
+ { name = "CodingWizard34", email = "developer@example.com" }
10
+ ]
11
+ description = "A blazing fast C++ TSP solver wrapped in Cython"
12
+ readme = "README.md"
13
+ requires-python = ">=3.8"
14
+ keywords = ["tsp", "graph-algorithms", "cython", "cplusplus", "combinatorial-optimization"]
15
+ classifiers = [
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: C++",
18
+ "Operating System :: OS Independent",
19
+ "Topic :: Scientific/Engineering :: Mathematics",
20
+ ]
@@ -0,0 +1,10 @@
1
+ [build]
2
+ compiler = mingw32
3
+
4
+ [build_ext]
5
+ compiler = mingw32
6
+
7
+ [egg_info]
8
+ tag_build =
9
+ tag_date = 0
10
+
@@ -0,0 +1,50 @@
1
+ import os
2
+ import sys
3
+ from setuptools import setup, find_packages, Extension
4
+
5
+ try:
6
+ from Cython.Build import cythonize
7
+ USE_CYTHON = True
8
+ except ImportError:
9
+ USE_CYTHON = False
10
+
11
+ source_ext = ".pyx" if USE_CYTHON else ".cpp"
12
+
13
+ extra_compile_args = []
14
+ extra_link_args = []
15
+
16
+ if sys.platform != "win32":
17
+ extra_compile_args.extend(["-O3", "-std=c++11"])
18
+
19
+ pkg_dir = os.path.abspath("tsp_fast_solver")
20
+
21
+ extensions = [
22
+ Extension(
23
+ name="tsp_fast_solver._tsp_cython",
24
+ sources=[
25
+ os.path.join("tsp_fast_solver", f"_tsp_cython{source_ext}"),
26
+ os.path.join("tsp_fast_solver", "tsp.cpp"),
27
+ ],
28
+ include_dirs=[pkg_dir],
29
+ language="c++",
30
+ extra_compile_args=extra_compile_args,
31
+ extra_link_args=extra_link_args,
32
+ ),
33
+ ]
34
+
35
+ if USE_CYTHON:
36
+ ext_modules = cythonize(
37
+ extensions,
38
+ include_path=[pkg_dir, "."],
39
+ compiler_directives={"language_level": "3"},
40
+ )
41
+ else:
42
+ ext_modules = extensions
43
+
44
+ setup(
45
+ packages=find_packages(),
46
+ ext_modules=ext_modules,
47
+ package_data={
48
+ "tsp_fast_solver": ["*.h", "*.pxd", "*.pyx", "*.cpp"],
49
+ },
50
+ )
@@ -0,0 +1,83 @@
1
+ import unittest
2
+ import random
3
+ from tsp_fast_solver.python_solver import tsp_python
4
+
5
+ try:
6
+ from tsp_fast_solver._tsp_cython import tsp_cython
7
+ CYTHON_AVAILABLE = True
8
+ except ImportError:
9
+ CYTHON_AVAILABLE = False
10
+
11
+
12
+ def generate_random_matrix(n, seed=None):
13
+ if seed is not None:
14
+ random.seed(seed)
15
+ matrix = [[0] * n for _ in range(n)]
16
+ for i in range(n):
17
+ for j in range(i + 1, n):
18
+ d = random.randint(5, 100)
19
+ matrix[i][j] = d
20
+ matrix[j][i] = d
21
+ return matrix
22
+
23
+
24
+ class TestTSPSolvers(unittest.TestCase):
25
+
26
+ def test_trivial_cases(self):
27
+ self.assertEqual(tsp_python([]), 0)
28
+ self.assertEqual(tsp_python([[0]]), 0)
29
+
30
+ if CYTHON_AVAILABLE:
31
+ self.assertEqual(tsp_cython([]), 0)
32
+ self.assertEqual(tsp_cython([[0]]), 0)
33
+
34
+ def test_two_cities(self):
35
+ mat = [
36
+ [0, 15],
37
+ [15, 0]
38
+ ]
39
+ self.assertEqual(tsp_python(mat), 30)
40
+ if CYTHON_AVAILABLE:
41
+ self.assertEqual(tsp_cython(mat), 30)
42
+
43
+ def test_three_cities(self):
44
+ mat = [
45
+ [0, 10, 20],
46
+ [10, 0, 15],
47
+ [20, 15, 0]
48
+ ]
49
+ # Only one distinct cycle (both directions have same length): 0 -> 1 -> 2 -> 0 => 10 + 15 + 20 = 45
50
+ self.assertEqual(tsp_python(mat), 45)
51
+ if CYTHON_AVAILABLE:
52
+ self.assertEqual(tsp_cython(mat), 45)
53
+
54
+ def test_four_cities_known(self):
55
+ mat = [
56
+ [0, 10, 15, 20],
57
+ [10, 0, 35, 25],
58
+ [15, 35, 0, 30],
59
+ [20, 25, 30, 0]
60
+ ]
61
+ # Best route: 0 -> 1 -> 3 -> 2 -> 0 => 10 + 25 + 30 + 15 = 80
62
+ self.assertEqual(tsp_python(mat), 80)
63
+ if CYTHON_AVAILABLE:
64
+ self.assertEqual(tsp_cython(mat), 80)
65
+
66
+ def test_python_and_cython_equivalence(self):
67
+ if not CYTHON_AVAILABLE:
68
+ self.skipTest("Cython extension not built yet")
69
+
70
+ for size in [4, 5, 6, 7]:
71
+ mat = generate_random_matrix(size, seed=100 + size)
72
+ py_cost = tsp_python(mat)
73
+ cy_cost = tsp_cython(mat)
74
+ self.assertEqual(py_cost, cy_cost, f"Mismatch on size {size}: Python={py_cost}, Cython={cy_cost}")
75
+
76
+ def test_invalid_dimension(self):
77
+ if CYTHON_AVAILABLE:
78
+ with self.assertRaises(ValueError):
79
+ tsp_cython([[0, 10], [10]])
80
+
81
+
82
+ if __name__ == "__main__":
83
+ unittest.main()
@@ -0,0 +1,15 @@
1
+ """
2
+ tsp-fast-solver: High-performance Traveling Salesperson Problem (TSP) solver
3
+ comparing pure Python against Cython-wrapped C++ std::next_permutation.
4
+ """
5
+
6
+ from .python_solver import tsp_python
7
+
8
+ try:
9
+ from ._tsp_cython import tsp_cython
10
+ except ImportError:
11
+ # Fallback for environments where the compiled C-extension has not been built yet
12
+ tsp_cython = None
13
+
14
+ __version__ = "0.1.0"
15
+ __all__ = ["tsp_python", "tsp_cython"]