I am trying to solve a travelling salesman problem with Pyomo framework. However, I am stuck, as the solver is informing me that I have formulated it as infeasible.
import numpy as np
import pyomo.environ as pyo
from pyomo.environ import *
from pyomo.opt import SolverFactory
journey_distances = np.array([[0, 28, 34, 45, 36],
[28, 0, 45, 52, 64],
[34, 45, 0, 11, 34],
[45, 52, 11, 0, 34],
[36, 64, 34, 34, 0]])
# create variables - integers
num_locations = M.shape[0]
model = pyo.ConcreteModel()
model.journeys = pyo.Var(range(num_locations), range(num_locations), domain=pyo.Binary, bounds = (0,None))
journeys = model.journeys
# add A to B constraints
model.AtoB = pyo.ConstraintList()
model.BtoA = pyo.ConstraintList()
AtoB = model.AtoB
BtoA = model.BtoA
AtoB_sum = [sum([ journeys[i,j] for j in range(num_locations) if i!=j]) for i in range(num_locations)]
BtoA_sum = [sum([ journeys[i,j] for i in range(num_locations) if j!=i]) for j in range(num_locations)]
for journey_sum in range(num_locations):
AtoB.add(AtoB_sum[journey_sum] == 1)
if journey_sum <num_locations -1:
BtoA.add(BtoA_sum[journey_sum] == 1)
# add auxilliary variables to ensure that each successive journey ends and starts on the same town. E.g. A to B, then B to C.
# u_j - u_i >= -(n+1) + num_locations*journeys_{ij} for i,j = 1...n, i!=j
model.successive_aux = pyo.Var(range(0,num_locations), domain = pyo.Integers, bounds = (0,num_locations-1))
model.successive_constr = pyo.ConstraintList()
successive_aux = model.successive_aux
successive_constr = model.successive_constr
successive_constr.add(successive_aux[0] == 1)
for i in range(num_locations):
for j in range(num_locations):
if i!=j:
successive_constr.add(successive_aux[j] - successive_aux[i] >= -(num_locations - 1) + num_locations*journeys[i,j])
obj_sum = sum([ sum([journey_distances [i,j]*journeys[i,j] for j in range(num_locations) if i!=j]) for i in range(num_locations)])
model.obj = pyo.Objective(expr = obj_sum, sense = minimize)
opt = SolverFactory('cplex')
opt.solve(model)
journey_res = np.array([model.journeys[journey].value for journey in journeys])
print(journey_res)
# results output is:
print(results)
Problem:
- Lower bound: -inf
Upper bound: inf
Number of objectives: 1
Number of constraints: 31
Number of variables: 26
Number of nonzeros: 98
Sense: unknown
Solver:
- Status: ok
User time: 0.02
Termination condition: infeasible
Termination message: MIP - Integer infeasible.
Error rc: 0
Time: 0.10198116302490234
# model.pprint()
7 Set Declarations
AtoB_index : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 5 : {1, 2, 3, 4, 5}
BtoA_index : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 4 : {1, 2, 3, 4}
journeys_index : Size=1, Index=None, Ordered=False
Key : Dimen : Domain : Size : Members
None : 2 : journeys_index_0*journeys_index_1 : 25 : {(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4)}
journeys_index_0 : Size=1, Index=None, Ordered=False
Key : Dimen : Domain : Size : Members
None : 1 : Any : 5 : {0, 1, 2, 3, 4}
journeys_index_1 : Size=1, Index=None, Ordered=False
Key : Dimen : Domain : Size : Members
None : 1 : Any : 5 : {0, 1, 2, 3, 4}
successive_aux_index : Size=1, Index=None, Ordered=False
Key : Dimen : Domain : Size : Members
None : 1 : Any : 5 : {0, 1, 2, 3, 4}
successive_constr_index : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 21 : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}
2 Var Declarations
journeys : Size=25, Index=journeys_index
Key : Lower : Value : Upper : Fixed : Stale : Domain
(0, 0) : 0 : None : 1 : False : True : Binary
(0, 1) : 0 : None : 1 : False : True : Binary
(0, 2) : 0 : None : 1 : False : True : Binary
(0, 3) : 0 : None : 1 : False : True : Binary
(0, 4) : 0 : None : 1 : False : True : Binary
(1, 0) : 0 : None : 1 : False : True : Binary
(1, 1) : 0 : None : 1 : False : True : Binary
(1, 2) : 0 : None : 1 : False : True : Binary
(1, 3) : 0 : None : 1 : False : True : Binary
(1, 4) : 0 : None : 1 : False : True : Binary
(2, 0) : 0 : None : 1 : False : True : Binary
(2, 1) : 0 : None : 1 : False : True : Binary
(2, 2) : 0 : None : 1 : False : True : Binary
(2, 3) : 0 : None : 1 : False : True : Binary
(2, 4) : 0 : None : 1 : False : True : Binary
(3, 0) : 0 : None : 1 : False : True : Binary
(3, 1) : 0 : None : 1 : False : True : Binary
(3, 2) : 0 : None : 1 : False : True : Binary
(3, 3) : 0 : None : 1 : False : True : Binary
(3, 4) : 0 : None : 1 : False : True : Binary
(4, 0) : 0 : None : 1 : False : True : Binary
(4, 1) : 0 : None : 1 : False : True : Binary
(4, 2) : 0 : None : 1 : False : True : Binary
(4, 3) : 0 : None : 1 : False : True : Binary
(4, 4) : 0 : None : 1 : False : True : Binary
successive_aux : Size=5, Index=successive_aux_index
Key : Lower : Value : Upper : Fixed : Stale : Domain
0 : 0 : None : 4 : False : True : Integers
1 : 0 : None : 4 : False : True : Integers
2 : 0 : None : 4 : False : True : Integers
3 : 0 : None : 4 : False : True : Integers
4 : 0 : None : 4 : False : True : Integers
1 Objective Declarations
obj : Size=1, Index=None, Active=True
Key : Active : Sense : Expression
None : True : minimize : 28*journeys[0,1] + 34*journeys[0,2] + 45*journeys[0,3] + 36*journeys[0,4] + 28*journeys[1,0] + 45*journeys[1,2] + 52*journeys[1,3] + 64*journeys[1,4] + 34*journeys[2,0] + 45*journeys[2,1] + 11*journeys[2,3] + 34*journeys[2,4] + 45*journeys[3,0] + 52*journeys[3,1] + 11*journeys[3,2] + 34*journeys[3,4] + 36*journeys[4,0] + 64*journeys[4,1] + 34*journeys[4,2] + 34*journeys[4,3]
3 Constraint Declarations
AtoB : Size=5, Index=AtoB_index, Active=True
Key : Lower : Body : Upper : Active
1 : 1.0 : journeys[0,1] + journeys[0,2] + journeys[0,3] + journeys[0,4] : 1.0 : True
2 : 1.0 : journeys[1,0] + journeys[1,2] + journeys[1,3] + journeys[1,4] : 1.0 : True
3 : 1.0 : journeys[2,0] + journeys[2,1] + journeys[2,3] + journeys[2,4] : 1.0 : True
4 : 1.0 : journeys[3,0] + journeys[3,1] + journeys[3,2] + journeys[3,4] : 1.0 : True
5 : 1.0 : journeys[4,0] + journeys[4,1] + journeys[4,2] + journeys[4,3] : 1.0 : True
BtoA : Size=4, Index=BtoA_index, Active=True
Key : Lower : Body : Upper : Active
1 : 1.0 : journeys[1,0] + journeys[2,0] + journeys[3,0] + journeys[4,0] : 1.0 : True
2 : 1.0 : journeys[0,1] + journeys[2,1] + journeys[3,1] + journeys[4,1] : 1.0 : True
3 : 1.0 : journeys[0,2] + journeys[1,2] + journeys[3,2] + journeys[4,2] : 1.0 : True
4 : 1.0 : journeys[0,3] + journeys[1,3] + journeys[2,3] + journeys[4,3] : 1.0 : True
successive_constr : Size=21, Index=successive_constr_index, Active=True
Key : Lower : Body : Upper : Active
1 : 1.0 : successive_aux[0] : 1.0 : True
2 : -Inf : -4 + 5*journeys[0,1] - (successive_aux[1] - successive_aux[0]) : 0.0 : True
3 : -Inf : -4 + 5*journeys[0,2] - (successive_aux[2] - successive_aux[0]) : 0.0 : True
4 : -Inf : -4 + 5*journeys[0,3] - (successive_aux[3] - successive_aux[0]) : 0.0 : True
5 : -Inf : -4 + 5*journeys[0,4] - (successive_aux[4] - successive_aux[0]) : 0.0 : True
6 : -Inf : -4 + 5*journeys[1,0] - (successive_aux[0] - successive_aux[1]) : 0.0 : True
7 : -Inf : -4 + 5*journeys[1,2] - (successive_aux[2] - successive_aux[1]) : 0.0 : True
8 : -Inf : -4 + 5*journeys[1,3] - (successive_aux[3] - successive_aux[1]) : 0.0 : True
9 : -Inf : -4 + 5*journeys[1,4] - (successive_aux[4] - successive_aux[1]) : 0.0 : True
10 : -Inf : -4 + 5*journeys[2,0] - (successive_aux[0] - successive_aux[2]) : 0.0 : True
11 : -Inf : -4 + 5*journeys[2,1] - (successive_aux[1] - successive_aux[2]) : 0.0 : True
12 : -Inf : -4 + 5*journeys[2,3] - (successive_aux[3] - successive_aux[2]) : 0.0 : True
13 : -Inf : -4 + 5*journeys[2,4] - (successive_aux[4] - successive_aux[2]) : 0.0 : True
14 : -Inf : -4 + 5*journeys[3,0] - (successive_aux[0] - successive_aux[3]) : 0.0 : True
15 : -Inf : -4 + 5*journeys[3,1] - (successive_aux[1] - successive_aux[3]) : 0.0 : True
16 : -Inf : -4 + 5*journeys[3,2] - (successive_aux[2] - successive_aux[3]) : 0.0 : True
17 : -Inf : -4 + 5*journeys[3,4] - (successive_aux[4] - successive_aux[3]) : 0.0 : True
18 : -Inf : -4 + 5*journeys[4,0] - (successive_aux[0] - successive_aux[4]) : 0.0 : True
19 : -Inf : -4 + 5*journeys[4,1] - (successive_aux[1] - successive_aux[4]) : 0.0 : True
20 : -Inf : -4 + 5*journeys[4,2] - (successive_aux[2] - successive_aux[4]) : 0.0 : True
21 : -Inf : -4 + 5*journeys[4,3] - (successive_aux[3] - successive_aux[4]) : 0.0 : True
13 Declarations: journeys_index_0 journeys_index_1 journeys_index journeys AtoB_index AtoB BtoA_index BtoA successive_aux_index successive_aux successive_constr_index successive_constr obj
If anyone can see what the problem is, and let me know, then that would be a great help.