【问题标题】:How to set MIP start (initial solution) with Gurobi solver from PuLP?如何使用 PuLP 的 Gurobi 求解器设置 MIP 启动(初始解决方案)?
【发布时间】:2017-03-01 20:17:10
【问题描述】:

我在 Python 中使用 PuLP 模块来制定混合整数程序。我正在尝试通过PuLP 接口设置MIP start(即程序启动的可行解决方案)。

MIP start的设置方法详见here

PuLP 包的开发者声称您可以通过PuLP 接口here 访问完整的 Gurobi 模型

下面贴的是两个完整的模型。我已经使这些尽可能小,同时防止 gurobi 求解器使用启发式方法找到最佳值。

我已尝试在两个模型中设置初始解决方案(最佳值),但在 PuLP 模型中它被忽略,但在 gurobipy 模型中它按预期工作。

如何通过 PuLP 界面为 Gurobi 求解设置初始求解?

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()[0].start = 1
prob.solverModel.getVars()[1].start = 1
prob.solverModel.getVars()[2].start = 0
prob.solverModel.getVars()[3].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)

返回:

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

其次,我可以使用gurobipy 模块实现相同的模型,但在这种情况下,实际使用的是 MIP 启动:

from gurobipy import *

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

objFcnCoeffs = [3, 5, 6, 9]
xVars = []
for i in range(4):
    xVars.append(m.addVar(vtype=GRB.INTEGER, obj=objFcnCoeffs[i], name="Open%d" % i))

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

# Constraints
m.addConstr(-2*xVars[0] + 6*xVars[1] -3*xVars[2] + 4*xVars[3] >= 2, "Con1")
m.addConstr(-5*xVars[0] + 3*xVars[1] + xVars[2] + 3*xVars[3] >= -2, "Con2")
m.addConstr(5*xVars[0] - xVars[1] + 4*xVars[2] - 2*xVars[3] >= 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])

返回:

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

Loaded MIP start with objective 8

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[0] = 1

 xVar[1] = 1

 xVar[2] = 0

 xVar[3] = 0

【问题讨论】:

  • 你能解释一下这里的“xVars[i].start”有什么用吗?我参考了文档,但对我来说似乎没有多大意义。
  • 它正在尝试为求解器设置一个初始解。但请参阅下面的答案,了解如何使其正常工作,并评论缺乏文档。

标签: python mathematical-optimization gurobi integer-programming pulp


【解决方案1】:

您正在像这样设置起始值

prob.solverModel.getVars()[0].start = 1

然后您正在使用此调用解决模型

prob.solve().

原来的prob不改,如果你调用

prob.solver.callSolver(prob)

Gurobi 将使用起始向量。

【讨论】:

  • 这很好用,谢谢。我认为我对pulp.pulp.LpProblemgurobipy.Model 类的理解有点有限。你有什么文档可以指点我吗?
  • 非常感谢您回答这个问题。 Pulp 和 Gurobi 之间的交互没有很好的文档记录,但是如果您查看solvers.py 中的代码,您会发现在构建模型后,gurobi 变量和模型附加到了纸浆变量和模型。如果您正在执行此级别的求解器特定建模,我建议您花 30 分钟左右的时间将您的纸浆模型转换为适当的 gurobi(语法非常相似)并从那里继续。斯图
【解决方案2】:

这个问题已经很晚了,但希望这会对新访客有所帮助。从 PuLP 2.3 版开始,通用的 warmStart 接口支持 GUROBI api。按照here 的说明,您应该能够热启动 gurobi 求解器,而无需修改纸浆内部部件或 gurobi 包。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-21
    • 1970-01-01
    • 1970-01-01
    • 2018-03-04
    • 2021-11-24
    • 1970-01-01
    • 1970-01-01
    • 2019-11-21
    相关资源
    最近更新 更多