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.
- tsp_fast_solver-0.1.0/MANIFEST.in +7 -0
- tsp_fast_solver-0.1.0/PKG-INFO +202 -0
- tsp_fast_solver-0.1.0/README.md +188 -0
- tsp_fast_solver-0.1.0/cpp/tsp.cpp +40 -0
- tsp_fast_solver-0.1.0/cpp/tsp.h +18 -0
- tsp_fast_solver-0.1.0/cython_wrapper/tsp_wrapper.cpp +9210 -0
- tsp_fast_solver-0.1.0/cython_wrapper/tsp_wrapper.pxd +6 -0
- tsp_fast_solver-0.1.0/cython_wrapper/tsp_wrapper.pyx +39 -0
- tsp_fast_solver-0.1.0/pyproject.toml +23 -0
- tsp_fast_solver-0.1.0/python_solver/__init__.py +3 -0
- tsp_fast_solver-0.1.0/python_solver/tsp_pure.py +42 -0
- tsp_fast_solver-0.1.0/setup.cfg +4 -0
- tsp_fast_solver-0.1.0/setup.py +60 -0
- tsp_fast_solver-0.1.0/tests/test_tsp.py +56 -0
- tsp_fast_solver-0.1.0/tsp_fast_solver/__init__.py +17 -0
- tsp_fast_solver-0.1.0/tsp_fast_solver/tsp_pure.py +42 -0
- tsp_fast_solver-0.1.0/tsp_fast_solver.egg-info/PKG-INFO +202 -0
- tsp_fast_solver-0.1.0/tsp_fast_solver.egg-info/SOURCES.txt +18 -0
- tsp_fast_solver-0.1.0/tsp_fast_solver.egg-info/dependency_links.txt +1 -0
- tsp_fast_solver-0.1.0/tsp_fast_solver.egg-info/top_level.txt +2 -0
|
@@ -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
|
+
[](https://opensource.org/licenses/MIT)
|
|
18
|
+
[](https://www.python.org/downloads/)
|
|
19
|
+
[](https://en.cppreference.com/w/cpp/17)
|
|
20
|
+
[](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
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
[](https://www.python.org/downloads/)
|
|
5
|
+
[](https://en.cppreference.com/w/cpp/17)
|
|
6
|
+
[](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
|