0

I'm solving the traveling salesman problem using PuLP optimizer on python. The code takes the time matrix as an ndarray and uses it to calculate the optimal route. My first version is running perfectly but i am facing some issue when i add a variable which calculates the time at which the vehicle reaches each point.

Version 1

import numpy as np 
from pulp import *

time_matrix = np.array([[0,5,4,6,7,10], 
                      [5,0,3,2,6,15], 
                      [4,3,0,4,5,6],
                      [6,2,4,0,7,8],
                      [7,6,5,7,0,11],
                      [10,15,6,8,11,0]])

row,col = time_matrix.shape

problem = LpProblem('TravellingSalesmanProblem', LpMinimize)

# Decision variable X for truck route
decisionVariableX = LpVariable.dicts('decisionVariable_X', ((i, j) for i in range(row) for j in range(row)), lowBound=0, upBound=1, cat='Integer')

# subtours elimination
decisionVariableU = LpVariable.dicts('decisionVariable_U', (i for i in range(row)), lowBound=1, cat='Integer')

# Objective Function
problem += lpSum(time_matrix[i][j] * decisionVariableX[i, j] for i in range(row) for j in range(row))

# Constraint
for i in range(row):
  problem += (decisionVariableX[i,i] == 0) # elimination of (1 to 1) route
  problem += lpSum(decisionVariableX[i,j] for j in range(row))==1 # truck reaches all points once
  problem += lpSum(decisionVariableX[j,i] for j in range(row)) ==1 #truck dispatches from all points once
  for j in range(row):
    if i != j and (i != 0 and j != 0):
        problem += decisionVariableU[i]  <=  decisionVariableU[j] + row * (1 - decisionVariableX[i, j])-1 # sub-tour elimination for truck

status = problem.solve() 
print(f"status: {problem.status}, {LpStatus[problem.status]}")
print(f"objective: {problem.objective.value()}")
for var in problem.variables():
    if (problem.status == 1):
        if (var.value() !=0):
            print(f"{var.name}: {var.value()}")

In version 2 I add another variable decisionVariableT which stores the value of time at which the truck reaches each node. But adding this constraint makes the problem infeasible. Can someone help me in identifying whats wrong with the code?

TIA

Version 2 addition

# Decision variable T for truck arrival time
decisionVariableT = LpVariable.dicts('decisionVariable_T', (i for i in range(row)), lowBound=0, cat='Integer')

M=1000

# Calculating truck arrival time at each node
for i in range(row):
    for j in range(row):
        if (decisionVariableX[i,j]==1):
            problem += decisionVariableT[j] == decisionVariableT[i] + time_matrix[i][j]

The result of Version 1:

status: 1, Optimal
objective: 33.0
decisionVariable_U_1: 5.0
decisionVariable_U_2: 2.0
decisionVariable_U_3: 4.0
decisionVariable_U_4: 1.0
decisionVariable_U_5: 3.0
decisionVariable_X_(0,_4): 1.0
decisionVariable_X_(1,_0): 1.0
decisionVariable_X_(2,_5): 1.0
decisionVariable_X_(3,_1): 1.0
decisionVariable_X_(4,_2): 1.0
decisionVariable_X_(5,_3): 1.0

The result of Version 2:

status: -1, Infeasible
objective: 0.0
s.p
  • 1
  • 1

1 Answers1

0

Consider if your timing matrix had these values:

t[2,3] = 2
t[3,2] = 4

Because you are enumerating over all of the combos in your matrix, you are then making the (infeasible) statement that

t[2] >= t[3] + 4 + C
t[3] >= t[2] + 2 + C

Where C is a constant and the result of your big-M constraint in the case that neither (or both) are used.

Rearranged that is:

t[2] >= t[3] + 4
t[2] <= t[3] - 2

Edit... ideas on fix

As for a fix... You could either...

make a variable and keep a running sum over the rows only not the columns. In pseudocode:

problem += cumulative_time[0] >= sum(x[0,c] * t[0,c] for c in cols)
for r in rows[1:]:
    prob += cumulative_time[r] >= cumulative_time[r-1] + <above, with 'r' instead of '0'>

Or

realize that it isn't necessary to treat cumulative time as a variable, because you can deduce it from your solution and just do the same construct over the result values when you are looping over them to print....

AirSquid
  • 10,214
  • 2
  • 7
  • 31
  • Thanks @AirSquid. I tried modifying the code as below but it does not seem to work: `for i in range(row):` `for j in range(row):` `if (decisionVariableX[i,j]==1):` `problem += decisionVariableT[j] >= decisionVariableT[i] + time_matrix[i][j]` – s.p Aug 21 '22 at 18:19
  • see edits for suggestion on how to fix... – AirSquid Aug 21 '22 at 18:36