I'm working on solving a TPS problem, testing it with different scenarios using Pulp. My Code so far:
from pulp import *
def k_tsp_mtz_encoding(n, k, cost_matrix):
# Check inputs are OK
assert 1 <= k < n
assert len(cost_matrix) == n, f'Cost matrix is not {n}x{n}'
assert all(len(cj) == n for cj in cost_matrix), f'Cost matrix is not {n}x{n}'
prob = LpProblem('kTSP', LpMinimize)
# Decision variables
x = LpVariable.dicts('x', [(i, j) for i in range(n) for j in range(n) if i != j], 0, 1, LpBinary)
u = LpVariable.dicts('u', [i for i in range(1, n)], 0, n-1, LpInteger)
# Objective function
prob += lpSum(cost_matrix[i][j] * x[(i, j)] for i in range(n) for j in range(n) if i != j)
# Constraints
for i in range(n):
prob += lpSum(x[(i, j)] for j in range(n) if i != j) == 1
prob += lpSum(x[(j, i)] for j in range(n) if i != j) == 1
for j in range(1, n):
prob += lpSum(x[(i, j)] for i in range(n) if i != j) == 1
prob += lpSum(x[(j, i)] for i in range(n) if i != j) == 1
# Subtour elimination constraints
for i in range(1, n):
for j in range(1, n): # Avoid accessing cost_matrix[i][i]
if i != j:
prob += u[i] - u[j] + n * x[(i, j)] <= n - 1
# Solve the problem
prob.solve()
# Extract tours
all_tours = []
for _ in range(k):
tour = [0]
j = 0
while True:
for i in range(n):
if value(x[(j, i)]) == 1:
tour.append(i)
j = i
break
if j == 0:
break
all_tours.append(tour)
return all_tours
I'm testing it with this lines of code but I keep getting errors. I'm doing this in Jupyter Notebooks
cost_matrix=[ [None,3,4,3,5],
[1, None, 2,4, 1],
[2, 1, None, 5, 4],
[1, 1, 5, None, 4],
[2, 1, 3, 5, None] ]
n=5
k=2
all_tours = k_tsp_mtz_encoding(n, k, cost_matrix)
print(f'Your code returned tours: {all_tours}')
assert len(all_tours) == k, f'k={k} must yield two tours -- your code returns {len(all_tours)} tours instead'
tour_cost = 0
for tour in all_tours:
assert tour[0] == 0, 'Each salesperson tour must start from vertex 0'
i = 0
for j in tour[1:]:
tour_cost += cost_matrix[i][j]
i = j
tour_cost += cost_matrix[i][0]
print(f'Tour cost obtained by your code: {tour_cost}')
assert abs(tour_cost - 12) <= 0.001, f'Expected tour cost is 12, your code returned {tour_cost}'
for i in range(1, n):
is_in_tour = [ 1 if i in tour else 0 for tour in all_tours]
assert sum(is_in_tour) == 1, f' vertex {i} is in {sum(is_in_tour)} tours -- this is incorrect'
print('Correct')
This is the most recent error, I was able to get the vertex visited output, but after I modified it I'm just getting this KeyError
KeyError Traceback (most recent call last)
<ipython-input-87-248518380ac2> in <module>
6 n=5
7 k=2
----> 8 all_tours = k_tsp_mtz_encoding(n, k, cost_matrix)
9 print(f'Your code returned tours: {all_tours}')
10 assert len(all_tours) == k, f'k={k} must yield two tours -- your code returns {len(all_tours)} tours instead'
<ipython-input-86-3fa3b44faee3> in k_tsp_mtz_encoding(n, k, cost_matrix)
54 while True:
55 for i in range(n):
---> 56 if value(x[(j, i)]) == 1:
57 tour.append(i)
58 j = i
KeyError: (0, 0)```
Break this up into multiple functions with typed parameters. This will reduce the risk of programming error. Also,
.dicts()is inappropriate for this application; use.matrix().The following does solve your key error but does not attempt to produce a meaningful linear problem. It successfully solves but then your assertion fails; I leave that to you to debug.