tsp-fast-solver 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,7 @@
1
+ include cpp/*.h
2
+ include cpp/*.cpp
3
+ include cython_wrapper/*.pyx
4
+ include cython_wrapper/*.pxd
5
+ include cython_wrapper/*.cpp
6
+ include README.md
7
+ include pyproject.toml
@@ -0,0 +1,202 @@
1
+ Metadata-Version: 2.4
2
+ Name: tsp-fast-solver
3
+ Version: 0.1.0
4
+ Summary: A blazing fast C++ TSP solver wrapped in Cython
5
+ Author-email: Vansh Shah <vansh.shah@example.com>
6
+ License-Expression: MIT
7
+ Keywords: tsp,cython,graph,c++,optimization
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: C++
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
12
+ Requires-Python: >=3.8
13
+ Description-Content-Type: text/markdown
14
+
15
+ # tsp-fast-solver: High-Performance C++ TSP Solver Wrapped in Cython
16
+
17
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
18
+ [![Python: 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
19
+ [![C++17](https://img.shields.io/badge/C++-17-00599C.svg?logo=c%2B%2B)](https://en.cppreference.com/w/cpp/17)
20
+ [![Cython](https://img.shields.io/badge/Cython-3.0+-gold.svg)](https://cython.org/)
21
+
22
+ An ultra-optimized brute-force solver for the **Traveling Salesperson Problem (TSP)** implemented in native **C++**, wrapped and exposed to Python via **Cython**, with a side-by-side **Pure Python** reference implementation.
23
+
24
+ ---
25
+
26
+ ## 📌 The Challenge
27
+
28
+ Graphs are fundamental data structures used to model transportation networks, routing topologies, and relational systems. The **Traveling Salesperson Problem (TSP)** is an NP-Hard problem:
29
+ > *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?*
30
+
31
+ Because the number of candidate tours scales factorially:
32
+ $$\text{Possible Closed Tours} = (N - 1)!$$
33
+
34
+ A brute-force search quickly overwhelms dynamic interpreted languages like Python due to bytecode evaluation overhead, dynamic typing, and boxing/unboxing objects. In production engineering, the performance-critical core is implemented in compiled C++ and bridged seamlessly to Python via Cython.
35
+
36
+ ### Real-World Applications
37
+ - **Logistics & Fleet Dispatch**: Minimizing delivery fleet mileage to save millions in fuel and vehicle wear.
38
+ - **Hardware Circuit Manufacturing**: Robotic arm path optimization when drilling thousands of micro-holes on printed circuit boards (PCBs).
39
+ - **Computational Genomics**: DNA fragment assembly and sequencing.
40
+
41
+ ---
42
+
43
+ ## 🏗️ Project Architecture
44
+
45
+ The codebase cleanly decouples native C++ algorithms, Cython interfacing definitions, pure Python baseline implementations, and packaging configuration:
46
+
47
+ ```
48
+ Graph/
49
+ ├── cpp/
50
+ │ ├── tsp.h # Native C++ solver declaration
51
+ │ └── tsp.cpp # Native C++ brute-force implementation using std::next_permutation
52
+ ├── cython_wrapper/
53
+ │ ├── tsp_wrapper.pxd # Cython external C++ signature declarations
54
+ │ └── tsp_wrapper.pyx # Cython bridge converting Python 2D lists to std::vector<int>
55
+ ├── python_solver/
56
+ │ ├── __init__.py # Python solver module entry point
57
+ │ └── tsp_pure.py # Pure Python baseline using itertools.permutations
58
+ ├── tsp_fast_solver/ # Pip-installable Python package
59
+ │ ├── __init__.py # Unified API exposing tsp_python & tsp_cython
60
+ │ └── tsp_pure.py # Packaged pure Python solver
61
+ ├── tests/
62
+ │ └── test_tsp.py # Pytest verification and edge-case unit tests
63
+ ├── benchmark.py # Automated performance benchmarking & verification suite
64
+ ├── tsp_wrapper.py # Top-level module shim for backward compatibility
65
+ ├── setup.py # Setuptools compilation and extension build script
66
+ ├── pyproject.toml # PEP 517 / PEP 621 build configuration
67
+ ├── .gitignore # Ignores build artifacts, object files, and compiled binaries
68
+ └── README.md # Documentation and benchmark results
69
+ ```
70
+
71
+ ---
72
+
73
+ ## ⚡ Algorithm Implementations
74
+
75
+ ### 1. Pure Python Solver (`tsp_python`)
76
+ - Location: `python_solver/tsp_pure.py`
77
+ - Algorithm: Fixes city `0` as the origin and generates all $(N - 1)!$ permutations of remaining cities $\{1, 2, \dots, N-1\}$ using Python's standard `itertools.permutations`.
78
+ - Accumulates distance for each cycle $0 \to p_1 \to p_2 \dots \to p_{N-1} \to 0$ and tracks the minimum cost.
79
+
80
+ ### 2. Native C++ Solver (`solve_tsp`)
81
+ - Location: `cpp/tsp.h`, `cpp/tsp.cpp`
82
+ - Algorithm: Populates a contiguous `std::vector<int>` with $\{1, 2, \dots, N-1\}$ and iteratively generates lexicographical permutations via `std::next_permutation`.
83
+ - Operates on a 1D flattened contiguous array for optimal cache locality ($O(1)$ memory overhead, zero dynamic heap allocations in inner loop).
84
+
85
+ ### 3. Cython Bridging Wrapper (`tsp_wrapper`)
86
+ - Location: `cython_wrapper/tsp_wrapper.pxd`, `cython_wrapper/tsp_wrapper.pyx`
87
+ - Converts incoming Python list-of-lists to a contiguous 1D `std::vector<int>` in $O(N^2)$ time once, releases/minimizes Python interpreter overhead, calls compiled C++ `solve_tsp`, and returns the optimal cost integer.
88
+
89
+ ---
90
+
91
+ ## 📊 Benchmark Results
92
+
93
+ Benchmarked on **Python 3.13.7 (64-bit)** with random symmetric distance matrices (edge weights $10 \le w \le 100$):
94
+
95
+ | Graph Size ($N$) | Routes $(N-1)!$ | Expected Python Time | Expected Cython Time | Recorded Python Time | Recorded Cython Time | Speedup Factor |
96
+ |:----------------:|:---------------:|:--------------------:|:--------------------:|:--------------------:|:--------------------:|:--------------:|
97
+ | **$N = 8$** | 5,040 | $< 0.1\,\text{s}$ | Instant | **$0.0016\,\text{s}$**| **$0.02\,\text{ms}$** | **$73.0\times$** |
98
+ | **$N = 10$** | 362,880 | $\sim 1 - 2\,\text{s}$| $< 0.05\,\text{s}$ | **$0.1429\,\text{s}$**| **$1.36\,\text{ms}$** | **$105.1\times$** |
99
+ | **$N = 11$** | 3,628,800 | $\sim 15 - 30\,\text{s}$| $\sim 0.5\,\text{s}$| **$1.5891\,\text{s}$**| **$14.20\,\text{ms}$**| **$111.9\times$** |
100
+
101
+ > **Key Takeaway**: At $N = 11$, Cython + C++ delivers a **$111.9\times$ speedup**, reducing computational runtime from seconds down to 14 milliseconds.
102
+
103
+ ### Why is C++ with Cython so much faster?
104
+ 1. **Zero Interpreter Overhead**: Python's iteration loops involve dynamic dispatch, reference counting, and bytecode instruction decoding on every step. C++ executes compiled machine code.
105
+ 2. **Cache Locality**: 1D contiguous vector access (`dist_matrix[i * n + j]`) fits within CPU L1/L2 caches, eliminating cache misses.
106
+ 3. **In-Place Permutation**: `std::next_permutation` modifies an integer array in place with minimal swaps and zero memory allocations, whereas Python creates tuple objects for permutations.
107
+ 4. **Compiler Optimization**: C++ compiler vectorization (`-O3`) optimizes inner loop calculations.
108
+
109
+ ---
110
+
111
+ ## 🚀 Quickstart & Usage
112
+
113
+ ### 1. Build In-Place Locally
114
+ ```bash
115
+ python setup.py build_ext --inplace
116
+ ```
117
+
118
+ ### 2. Run the Benchmark
119
+ ```bash
120
+ python benchmark.py
121
+ ```
122
+
123
+ ### 3. Run Unit Tests
124
+ ```bash
125
+ python -m pytest tests/
126
+ ```
127
+
128
+ ### 4. Example Python Code
129
+ ```python
130
+ from tsp_fast_solver import tsp_python, tsp_cython
131
+
132
+ # Define a 4-city distance matrix
133
+ dist_matrix = [
134
+ [0, 10, 15, 20],
135
+ [10, 0, 35, 25],
136
+ [15, 35, 0, 30],
137
+ [20, 25, 30, 0]
138
+ ]
139
+
140
+ # Calculate shortest tour cost
141
+ min_cost_py = tsp_python(dist_matrix)
142
+ min_cost_cy = tsp_cython(dist_matrix)
143
+
144
+ print(f"Optimal TSP Cost (Python): {min_cost_py}") # Output: 80
145
+ print(f"Optimal TSP Cost (Cython): {min_cost_cy}") # Output: 80
146
+ ```
147
+
148
+ ---
149
+
150
+ ## 📦 Packaging and PyPI Distribution
151
+
152
+ ### 1. Building Source Distribution (sdist)
153
+ As specified in PEP 517 / PEP 621, build the source distribution using `build`:
154
+ ```bash
155
+ # Upgrade build tool
156
+ python -m pip install --upgrade build
157
+
158
+ # Generate source distribution (.tar.gz)
159
+ python -m build --sdist
160
+ ```
161
+ This produces `dist/tsp_fast_solver-0.1.0.tar.gz` containing C++ sources, headers, and Cython code ready for any machine to compile during `pip install`.
162
+
163
+ ### 2. Uploading to PyPI via Twine
164
+ ```bash
165
+ # Install Twine
166
+ python -m pip install --upgrade twine
167
+
168
+ # Upload to PyPI (or TestPyPI)
169
+ python -m twine upload dist/*
170
+ ```
171
+ - **Username**: `__token__`
172
+ - **Password**: `<Your-PyPI-API-Token>`
173
+
174
+ *(For testing without modifying production PyPI, use TestPyPI: `python -m twine upload --repository testpypi dist/*`)*
175
+
176
+ ### 3. Verifying Installation
177
+ ```bash
178
+ # Install from PyPI
179
+ pip install tsp-fast-solver
180
+
181
+ # Test installation in Python
182
+ python -c "import tsp_fast_solver; print('Success!')"
183
+ ```
184
+
185
+ ---
186
+
187
+ ## 🌐 Version Control (Git)
188
+
189
+ Initialize and push to your GitHub repository:
190
+ ```bash
191
+ git init
192
+ git add .
193
+ git commit -m "Initial commit of TSP solvers"
194
+ git branch -M main
195
+ git remote add origin https://github.com/yourusername/tsp-solver.git
196
+ git push -u origin main
197
+ ```
198
+
199
+ ---
200
+
201
+ ## 📄 License
202
+ This project is licensed under the MIT License.
@@ -0,0 +1,188 @@
1
+ # tsp-fast-solver: High-Performance C++ TSP Solver Wrapped in Cython
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ [![Python: 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
5
+ [![C++17](https://img.shields.io/badge/C++-17-00599C.svg?logo=c%2B%2B)](https://en.cppreference.com/w/cpp/17)
6
+ [![Cython](https://img.shields.io/badge/Cython-3.0+-gold.svg)](https://cython.org/)
7
+
8
+ An ultra-optimized brute-force solver for the **Traveling Salesperson Problem (TSP)** implemented in native **C++**, wrapped and exposed to Python via **Cython**, with a side-by-side **Pure Python** reference implementation.
9
+
10
+ ---
11
+
12
+ ## 📌 The Challenge
13
+
14
+ Graphs are fundamental data structures used to model transportation networks, routing topologies, and relational systems. The **Traveling Salesperson Problem (TSP)** is an NP-Hard problem:
15
+ > *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?*
16
+
17
+ Because the number of candidate tours scales factorially:
18
+ $$\text{Possible Closed Tours} = (N - 1)!$$
19
+
20
+ A brute-force search quickly overwhelms dynamic interpreted languages like Python due to bytecode evaluation overhead, dynamic typing, and boxing/unboxing objects. In production engineering, the performance-critical core is implemented in compiled C++ and bridged seamlessly to Python via Cython.
21
+
22
+ ### Real-World Applications
23
+ - **Logistics & Fleet Dispatch**: Minimizing delivery fleet mileage to save millions in fuel and vehicle wear.
24
+ - **Hardware Circuit Manufacturing**: Robotic arm path optimization when drilling thousands of micro-holes on printed circuit boards (PCBs).
25
+ - **Computational Genomics**: DNA fragment assembly and sequencing.
26
+
27
+ ---
28
+
29
+ ## 🏗️ Project Architecture
30
+
31
+ The codebase cleanly decouples native C++ algorithms, Cython interfacing definitions, pure Python baseline implementations, and packaging configuration:
32
+
33
+ ```
34
+ Graph/
35
+ ├── cpp/
36
+ │ ├── tsp.h # Native C++ solver declaration
37
+ │ └── tsp.cpp # Native C++ brute-force implementation using std::next_permutation
38
+ ├── cython_wrapper/
39
+ │ ├── tsp_wrapper.pxd # Cython external C++ signature declarations
40
+ │ └── tsp_wrapper.pyx # Cython bridge converting Python 2D lists to std::vector<int>
41
+ ├── python_solver/
42
+ │ ├── __init__.py # Python solver module entry point
43
+ │ └── tsp_pure.py # Pure Python baseline using itertools.permutations
44
+ ├── tsp_fast_solver/ # Pip-installable Python package
45
+ │ ├── __init__.py # Unified API exposing tsp_python & tsp_cython
46
+ │ └── tsp_pure.py # Packaged pure Python solver
47
+ ├── tests/
48
+ │ └── test_tsp.py # Pytest verification and edge-case unit tests
49
+ ├── benchmark.py # Automated performance benchmarking & verification suite
50
+ ├── tsp_wrapper.py # Top-level module shim for backward compatibility
51
+ ├── setup.py # Setuptools compilation and extension build script
52
+ ├── pyproject.toml # PEP 517 / PEP 621 build configuration
53
+ ├── .gitignore # Ignores build artifacts, object files, and compiled binaries
54
+ └── README.md # Documentation and benchmark results
55
+ ```
56
+
57
+ ---
58
+
59
+ ## ⚡ Algorithm Implementations
60
+
61
+ ### 1. Pure Python Solver (`tsp_python`)
62
+ - Location: `python_solver/tsp_pure.py`
63
+ - Algorithm: Fixes city `0` as the origin and generates all $(N - 1)!$ permutations of remaining cities $\{1, 2, \dots, N-1\}$ using Python's standard `itertools.permutations`.
64
+ - Accumulates distance for each cycle $0 \to p_1 \to p_2 \dots \to p_{N-1} \to 0$ and tracks the minimum cost.
65
+
66
+ ### 2. Native C++ Solver (`solve_tsp`)
67
+ - Location: `cpp/tsp.h`, `cpp/tsp.cpp`
68
+ - Algorithm: Populates a contiguous `std::vector<int>` with $\{1, 2, \dots, N-1\}$ and iteratively generates lexicographical permutations via `std::next_permutation`.
69
+ - Operates on a 1D flattened contiguous array for optimal cache locality ($O(1)$ memory overhead, zero dynamic heap allocations in inner loop).
70
+
71
+ ### 3. Cython Bridging Wrapper (`tsp_wrapper`)
72
+ - Location: `cython_wrapper/tsp_wrapper.pxd`, `cython_wrapper/tsp_wrapper.pyx`
73
+ - Converts incoming Python list-of-lists to a contiguous 1D `std::vector<int>` in $O(N^2)$ time once, releases/minimizes Python interpreter overhead, calls compiled C++ `solve_tsp`, and returns the optimal cost integer.
74
+
75
+ ---
76
+
77
+ ## 📊 Benchmark Results
78
+
79
+ Benchmarked on **Python 3.13.7 (64-bit)** with random symmetric distance matrices (edge weights $10 \le w \le 100$):
80
+
81
+ | Graph Size ($N$) | Routes $(N-1)!$ | Expected Python Time | Expected Cython Time | Recorded Python Time | Recorded Cython Time | Speedup Factor |
82
+ |:----------------:|:---------------:|:--------------------:|:--------------------:|:--------------------:|:--------------------:|:--------------:|
83
+ | **$N = 8$** | 5,040 | $< 0.1\,\text{s}$ | Instant | **$0.0016\,\text{s}$**| **$0.02\,\text{ms}$** | **$73.0\times$** |
84
+ | **$N = 10$** | 362,880 | $\sim 1 - 2\,\text{s}$| $< 0.05\,\text{s}$ | **$0.1429\,\text{s}$**| **$1.36\,\text{ms}$** | **$105.1\times$** |
85
+ | **$N = 11$** | 3,628,800 | $\sim 15 - 30\,\text{s}$| $\sim 0.5\,\text{s}$| **$1.5891\,\text{s}$**| **$14.20\,\text{ms}$**| **$111.9\times$** |
86
+
87
+ > **Key Takeaway**: At $N = 11$, Cython + C++ delivers a **$111.9\times$ speedup**, reducing computational runtime from seconds down to 14 milliseconds.
88
+
89
+ ### Why is C++ with Cython so much faster?
90
+ 1. **Zero Interpreter Overhead**: Python's iteration loops involve dynamic dispatch, reference counting, and bytecode instruction decoding on every step. C++ executes compiled machine code.
91
+ 2. **Cache Locality**: 1D contiguous vector access (`dist_matrix[i * n + j]`) fits within CPU L1/L2 caches, eliminating cache misses.
92
+ 3. **In-Place Permutation**: `std::next_permutation` modifies an integer array in place with minimal swaps and zero memory allocations, whereas Python creates tuple objects for permutations.
93
+ 4. **Compiler Optimization**: C++ compiler vectorization (`-O3`) optimizes inner loop calculations.
94
+
95
+ ---
96
+
97
+ ## 🚀 Quickstart & Usage
98
+
99
+ ### 1. Build In-Place Locally
100
+ ```bash
101
+ python setup.py build_ext --inplace
102
+ ```
103
+
104
+ ### 2. Run the Benchmark
105
+ ```bash
106
+ python benchmark.py
107
+ ```
108
+
109
+ ### 3. Run Unit Tests
110
+ ```bash
111
+ python -m pytest tests/
112
+ ```
113
+
114
+ ### 4. Example Python Code
115
+ ```python
116
+ from tsp_fast_solver import tsp_python, tsp_cython
117
+
118
+ # Define a 4-city distance matrix
119
+ dist_matrix = [
120
+ [0, 10, 15, 20],
121
+ [10, 0, 35, 25],
122
+ [15, 35, 0, 30],
123
+ [20, 25, 30, 0]
124
+ ]
125
+
126
+ # Calculate shortest tour cost
127
+ min_cost_py = tsp_python(dist_matrix)
128
+ min_cost_cy = tsp_cython(dist_matrix)
129
+
130
+ print(f"Optimal TSP Cost (Python): {min_cost_py}") # Output: 80
131
+ print(f"Optimal TSP Cost (Cython): {min_cost_cy}") # Output: 80
132
+ ```
133
+
134
+ ---
135
+
136
+ ## 📦 Packaging and PyPI Distribution
137
+
138
+ ### 1. Building Source Distribution (sdist)
139
+ As specified in PEP 517 / PEP 621, build the source distribution using `build`:
140
+ ```bash
141
+ # Upgrade build tool
142
+ python -m pip install --upgrade build
143
+
144
+ # Generate source distribution (.tar.gz)
145
+ python -m build --sdist
146
+ ```
147
+ This produces `dist/tsp_fast_solver-0.1.0.tar.gz` containing C++ sources, headers, and Cython code ready for any machine to compile during `pip install`.
148
+
149
+ ### 2. Uploading to PyPI via Twine
150
+ ```bash
151
+ # Install Twine
152
+ python -m pip install --upgrade twine
153
+
154
+ # Upload to PyPI (or TestPyPI)
155
+ python -m twine upload dist/*
156
+ ```
157
+ - **Username**: `__token__`
158
+ - **Password**: `<Your-PyPI-API-Token>`
159
+
160
+ *(For testing without modifying production PyPI, use TestPyPI: `python -m twine upload --repository testpypi dist/*`)*
161
+
162
+ ### 3. Verifying Installation
163
+ ```bash
164
+ # Install from PyPI
165
+ pip install tsp-fast-solver
166
+
167
+ # Test installation in Python
168
+ python -c "import tsp_fast_solver; print('Success!')"
169
+ ```
170
+
171
+ ---
172
+
173
+ ## 🌐 Version Control (Git)
174
+
175
+ Initialize and push to your GitHub repository:
176
+ ```bash
177
+ git init
178
+ git add .
179
+ git commit -m "Initial commit of TSP solvers"
180
+ git branch -M main
181
+ git remote add origin https://github.com/yourusername/tsp-solver.git
182
+ git push -u origin main
183
+ ```
184
+
185
+ ---
186
+
187
+ ## 📄 License
188
+ This project is licensed under the MIT License.
@@ -0,0 +1,40 @@
1
+ #include "tsp.h"
2
+ #include <vector>
3
+ #include <algorithm>
4
+ #include <climits>
5
+ #include <numeric>
6
+
7
+ int solve_tsp(const std::vector<int>& dist_matrix, int n) {
8
+ if (n <= 1) {
9
+ return 0;
10
+ }
11
+ if (n == 2) {
12
+ return dist_matrix[0 * n + 1] + dist_matrix[1 * n + 0];
13
+ }
14
+
15
+ // Permute cities 1 through n-1, keeping city 0 fixed as origin
16
+ std::vector<int> cities(n - 1);
17
+ std::iota(cities.begin(), cities.end(), 1); // [1, 2, ..., n-1]
18
+
19
+ int min_cost = INT_MAX;
20
+
21
+ // Explore all (n - 1)! possible route permutations
22
+ do {
23
+ // Start from city 0 to the first visited city
24
+ int current_cost = dist_matrix[0 * n + cities[0]];
25
+
26
+ // Visit each subsequent city in the permutation
27
+ for (int i = 0; i < n - 2; ++i) {
28
+ current_cost += dist_matrix[cities[i] * n + cities[i + 1]];
29
+ }
30
+
31
+ // Return from the last city back to origin (city 0)
32
+ current_cost += dist_matrix[cities[n - 2] * n + 0];
33
+
34
+ if (current_cost < min_cost) {
35
+ min_cost = current_cost;
36
+ }
37
+ } while (std::next_permutation(cities.begin(), cities.end()));
38
+
39
+ return min_cost;
40
+ }
@@ -0,0 +1,18 @@
1
+ #ifndef TSP_H
2
+ #define TSP_H
3
+
4
+ #include <vector>
5
+
6
+ /**
7
+ * Solves the Traveling Salesperson Problem (TSP) using a brute-force approach.
8
+ * Fixes city 0 as the starting and ending city and explores all (n-1)! permutations
9
+ * using std::next_permutation.
10
+ *
11
+ * @param dist_matrix Flattened 1D vector representing the n x n distance matrix
12
+ * where dist_matrix[i * n + j] is the distance from city i to j.
13
+ * @param n Number of cities (nodes) in the graph.
14
+ * @return The minimum tour cost visiting every city once and returning to city 0.
15
+ */
16
+ int solve_tsp(const std::vector<int>& dist_matrix, int n);
17
+
18
+ #endif // TSP_H