 Khalid Abdulla - 4 years ago 643
Python Question

# How to set MIP start (initial solution) with Gurobi solver from PuLP?

I'm using the

`PuLP`
module in Python to formulate a mixed integer program. I am trying to work out how to set a
`MIP start`
(i.e. a feasible solution for the program to start from) via the
`PuLP`
interface.

Details on how to set
`MIP start`
are given here

And the developer of the
`PuLP`
package claims that you can access the full Gurobi model via the
`PuLP`
interface here

Pasted below are two complete models. I have made these as small as possible whilst preventing the gurobi solver from finding the optimal value using a heuristic.

I have attempted to set an initial solution (to the optimal values) in both models, but in the
`PuLP`
model it is ignored, but in the
`gurobipy`
model it works as expected.

How do you set an initial solution for the Gurobi solve via the PuLP interface?

``````from pulp import *

prob = LpProblem("min example",LpMinimize)

x1=LpVariable("x1",0,None,LpInteger)
x2=LpVariable("x2",0,None,LpInteger)
x3=LpVariable("x3",0,None,LpInteger)
x4=LpVariable("x4",0,None,LpInteger)

# Objective function
prob += 3*x1 + 5*x2 + 6*x3 + 9*x4

# A constraint
prob += -2*x1 + 6*x2 -3*x3 + 4*x4 >= 2, "Con1"
prob += -5*x1 + 3*x2 + x3 + 3*x4 >= -2, "Con2"
prob += 5*x1 - x2 + 4*x3 - 2*x4 >= 3, "Con3"

# Choose solver, and set it to problem, and build the Gurobi model
solver = pulp.GUROBI()
prob.setSolver(solver)
prob.solver.buildSolverModel(prob)

# Attempt to set an initial feasible solution (in this case to an optimal solution)
prob.solverModel.getVars().start = 1
prob.solverModel.getVars().start = 1
prob.solverModel.getVars().start = 0
prob.solverModel.getVars().start = 0

# Solve model
prob.solve()

# Status of the solution is printed to the screen
print "Status:", LpStatus[prob.status]

# Each of the variables is printed with it's resolved optimum value
for v in prob.variables():
print v.name, "=", v.varValue

# Optimised objective function value is printed to the screen
print "OF = ", value(prob.objective)
``````

Which returns:

``````Optimize a model with 3 rows, 4 columns and 12 nonzeros
Coefficient statistics:
Matrix range    [1e+00, 6e+00]
Objective range [3e+00, 9e+00]
Bounds range    [0e+00, 0e+00]
RHS range       [2e+00, 3e+00]
Found heuristic solution: objective 12
Presolve removed 0 rows and 1 columns
Presolve time: 0.00s
Presolved: 3 rows, 3 columns, 9 nonzeros
Variable types: 0 continuous, 3 integer (0 binary)

Root relaxation: objective 7.400000e+00, 1 iterations, 0.00 seconds

Nodes    |    Current Node    |     Objective Bounds      |     Work
Expl Unexpl |  Obj  Depth IntInf | Incumbent    BestBd   Gap | It/Node Time

0     0    7.40000    0    1   12.00000    7.40000  38.3%     -    0s
H    0     0                       8.0000000    7.40000  7.50%     -    0s

Explored 0 nodes (1 simplex iterations) in 0.00 seconds
Thread count was 8 (of 8 available processors)

Optimal solution found (tolerance 1.00e-04)
Best objective 8.000000000000e+00, best bound 8.000000000000e+00, gap 0.0%
('Gurobi status=', 2)
Status: Optimal
x1 = 1.0
x2 = 1.0
x3 = -0.0
x4 = -0.0
OF =  8.0
``````

Secondly I can implement the same model using the
`gurobipy`
module, but in this case the MIP start is actually used:

``````from gurobipy import *

m = Model("min example")
m.modelSense = GRB.MINIMIZE

objFcnCoeffs = [3, 5, 6, 9]
xVars = []
for i in range(4):

# Update model to integrate new variables
m.update()

# Constraints
m.addConstr(-2*xVars + 6*xVars -3*xVars + 4*xVars >= 2, "Con1")
m.addConstr(-5*xVars + 3*xVars + xVars + 3*xVars >= -2, "Con2")
m.addConstr(5*xVars - xVars + 4*xVars - 2*xVars >= 3, "Con3")

# Attempt to set an initial feasible solution (in this case to an optimal solution)
startValues = [1, 1, 0, 0]
for i in range(4):
xVars[i].start = startValues[i]

# Solve model
m.optimize()

# Print solution
print('\nTOTAL COSTS: %g' % m.objVal)
for i in range(4):
print('\n xVar[%s] = %g' % i, xVars[i])
``````

Which returns:

``````Optimize a model with 3 rows, 4 columns and 12 nonzeros
Coefficient statistics:
Matrix range    [1e+00, 6e+00]
Objective range [3e+00, 9e+00]
Bounds range    [0e+00, 0e+00]
RHS range       [2e+00, 3e+00]
Found heuristic solution: objective 12
Presolve removed 0 rows and 1 columns
Presolve time: 0.00s
Presolved: 3 rows, 3 columns, 9 nonzeros

Variable types: 0 continuous, 3 integer (0 binary)

Root relaxation: infeasible, 0 iterations, 0.00 seconds

Explored 0 nodes (0 simplex iterations) in 0.00 seconds
Thread count was 8 (of 8 available processors)

Optimal solution found (tolerance 1.00e-04)
Best objective 8.000000000000e+00, best bound 8.000000000000e+00, gap 0.0%

TOTAL COSTS: 8

xVar = 1

xVar = 1

xVar = 0

xVar = 0
`````` Smars

You are setting the start values like this

``````prob.solverModel.getVars().start = 1
``````

and you are then solving the model with this call

``````prob.solve().
``````

The oritinal `prob` is not changed, if you call

``````prob.solver.callSolver(prob)
``````

Gurobi will use the start vector.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download