问题
I am trying to use pyomo to solve TSP problem. I have successfully implemented using python and Gurobi but my Gurobi license expired so I want to now use pyomo and GLPK to implement the TSP problem. This is what I could come up with so far. It is not working the objective value is 0. Can you please help.
from pyomo.environ import *
from pyomo.opt import SolverFactory
import pyomo.environ
n=13
distanceMatrix=[[0,8,4,10,12,9,15,8,11,5,9,4,10],
[8,0,7,6,8,6,7,10,12,9,8,7,5],
[4,7,0,7,9,5,8,5,4,8,6 ,10,8],
[10,6 ,7,0,6,11,5 ,9,8,12,11,6,9],
[12,8 ,9,6, 0,7,9,6,9,8,4,11,10],
[9,6,5,11,7,0,10,4,3,10,6,5,7],
[15,7 ,8,5,9,10,0,10,9,8,5,9,10],
[8,10 ,5,9,6,4,10,0,11,5,9,6,7],
[11,12,4,8, 9,3,9,11,0, 9,11,11,6],
[5,9,8,12,8,10,8,5,9,0,6,7,5],
[9,8,6,11,4,6,5,9,11,6,0,10,7],
[4,7,10,6,11,5,9,6,11,7,10,0,9],
[10,5,8,9,10,7,10,7,6,5,7,9,0]]
startCity = 0
model = ConcreteModel()
model.N=Set()
model.M=Set()
model.c=Param(model.N,model.M, initialize=distanceMatrix)
model.x=Var(model.N,model.M, within=NonNegativeReals)
def obj_rule(model):
return sum(model.c[n,j]*model.x[n,j] for n in model.N for j in model.M)
model.obj = Objective(rule=obj_rule,sense=minimize)
def con_rule(model, n):
return sum(model.x[j,n] for j in model.M if j < n) + sum(model.x[n,j] for j in Model.M if j > i) == 2
model.con = Constraint(model.N, rule=con_rule,doc='constraint1')
opt = SolverFactory("glpk")
results = opt.solve(model)
results.write()
print('Printing Values')
回答1:
The following answer has been tested for Python 3.5.3 and Pyomo 5.1.1.
The sets
model.M
andmodel.N
have not been initialised.This has the effect of declaring empty sets. So if you run:
model.con.pprint()
you will find that no constraints have been declared. Similarly,
model.obj
is trivially equal to 0 andmodel.c
andmodel.x
are empty declarations.You can fix this with (I'm assuming that you want to index from 1 to n):
model.M = Set(initialize=range(1, n+1)) model.N = Set(initialize=range(1, n+1))
Since
model.M
andmodel.N
are ranges using aRangeSet
is probably more suitable, i.e. using the following instead of the above:model.M = RangeSet(n) model.N = RangeSet(n)
The above Pyomo
RangeSet
is equal to the set {1, 2, ..., n}.Furthermore, since
model.M
andmodel.N
are the same, declaring one of the sets is sufficient. So if we remove the declaration ofmodel.N
and replace any reference tomodel.N
withmodel.M
, we get the same behaviour.The initialisation of
model.c
has to be carried out per(i, j)
index.You can fix this with (using
lambda
function):model.c = Param(model.N, model.M, initialize=lambda model, i, j: distanceMatrix[i-1][j-1])
Python lists index from 0,
model.M
andmodel.N
start from 1 therefore we use the indexdistanceMatrix[i-1][j-1]
.The variables
model.x
are not binary.In a TSP, the variables that
model.x
represent are usually binary. Solving the problem after carrying out steps 1 and 2 allows themodel.x
variables to take values such as 2.You can change the domain of
model.x
to binary with:model.x = Var(model.N, model.M, within=Binary)
The constraint
model.con
does not allow a TSP tour.model.con
is equivalent to:If we take n = 1,
model.con
will cause the TSP solution to have two cities visited from starting city 1 (assuming that themodel.x
are binary), which is not allowed by the definition of TSP.
来源:https://stackoverflow.com/questions/43422144/traveling-salesman-using-pyomo