Skip to content

Commit a9703e1

Browse files
committed
Add Traveling Salesman Problem implementation
1 parent 459613e commit a9703e1

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed
+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
from typing import List, Tuple
2+
3+
4+
def tsp_dp(distances: List[List[float]]) -> Tuple[float, List[int]]:
5+
"""
6+
Solves Traveling Salesman Problem using dynamic programming.
7+
8+
>>> distances = [[0, 10, 15, 20], [10, 0, 35, 25], [15, 35, 0, 30], [20, 25, 30, 0]]
9+
>>> cost, path = tsp_dp(distances)
10+
>>> float(cost)
11+
80.0
12+
>>> path[0]
13+
0
14+
15+
>>> distances = [[0, 5], [5, 0]]
16+
>>> cost, path = tsp_dp(distances)
17+
>>> float(cost)
18+
10.0
19+
>>> path
20+
[0, 1]
21+
"""
22+
if not distances:
23+
raise ValueError("Empty distance matrix")
24+
25+
n = len(distances)
26+
all_points = (1 << n) - 1
27+
dp = {}
28+
parent = {}
29+
30+
def solve(mask: int, pos: int) -> float:
31+
if mask == all_points:
32+
return distances[pos][0]
33+
34+
state = (mask, pos)
35+
if state in dp:
36+
return dp[state]
37+
38+
minimum = float('inf')
39+
min_next = -1
40+
41+
for next_city in range(n):
42+
if mask & (1 << next_city) == 0:
43+
new_mask = mask | (1 << next_city)
44+
new_dist = distances[pos][next_city] + solve(new_mask, next_city)
45+
46+
if new_dist < minimum:
47+
minimum = new_dist
48+
min_next = next_city
49+
50+
dp[state] = minimum
51+
parent[state] = min_next
52+
return minimum
53+
54+
optimal_cost = solve(1, 0)
55+
56+
path = [0]
57+
mask = 1
58+
pos = 0
59+
60+
for _ in range(n - 1):
61+
next_pos = parent[(mask, pos)]
62+
path.append(next_pos)
63+
mask |= (1 << next_pos)
64+
pos = next_pos
65+
66+
return optimal_cost, path
67+
68+
69+
if __name__ == "__main__":
70+
import doctest
71+
72+
doctest.testmod()

0 commit comments

Comments
 (0)