python - Pyomo + Xpress 中的热启动
问题描述
我正在处理一个很大的优化问题。Pyomo 用作包装器,xpress 用作求解器。每次运行我都会保存变量的值,以便在再次解决问题之前将这些值加载到变量中。所以我想实现一个热启动。求解器调用如下所示:
opt = SolverFactory('xpress_direct')
results = opt.solve(model, warmstart=True, tee=True)
在 tee-log 中,我看到问题从一开始就解决了,我对初始值的假设没有考虑在内。我有两个问题:
- 如何解释 tee 日志(我在文档中没有找到详细信息);
- 如果我们保存了之前的模型及其变量值,如何进行热启动?
解决方案
这是一个小代码,说明了如何通过 Xpress 优化器使用热启动。请注意,我不是 Pyomo 方面的专家,因此可能有更好的方法来实现该create_model
功能,但对于使用热启动,您无论如何都应该关注其余代码。
import pyomo.environ as pyo
from pyomo.environ import value
from pyomo.opt import SolverFactory
def create_model():
"""Create a model that is non-trivial to solve.
The returned model has two variables: `x` and `s`. It also has an
objective function that is stored in `obj`.
"""
model = pyo.ConcreteModel()
model.X = pyo.RangeSet(50)
model.S = pyo.RangeSet(6)
model.x = pyo.Var(model.X, within=pyo.Binary)
x = model.x
model.s = pyo.Var(model.S, bounds = (0, None))
s = model.s
model.obj = pyo.Objective(expr=s[1] + s[2] + s[3] + s[4] + s[5] + s[6])
model.cons = pyo.ConstraintList()
model.cons.add(s[1] + 25*x[1] + 35*x[2] + 14*x[3] + 76*x[4] + 58*x[5] + 10*x[6] + 20*x[7]
+ 51*x[8] + 58*x[9] + x[10] + 35*x[11] + 40*x[12] + 65*x[13] + 59*x[14] + 24*x[15]
+ 44*x[16] + x[17] + 93*x[18] + 24*x[19] + 68*x[20] + 38*x[21] + 64*x[22] + 93*x[23]
+ 14*x[24] + 83*x[25] + 6*x[26] + 58*x[27] + 14*x[28] + 71*x[29] + 17*x[30]
+ 18*x[31] + 8*x[32] + 57*x[33] + 48*x[34] + 35*x[35] + 13*x[36] + 47*x[37]
+ 46*x[38] + 8*x[39] + 82*x[40] + 51*x[41] + 49*x[42] + 85*x[43] + 66*x[44]
+ 45*x[45] + 99*x[46] + 21*x[47] + 75*x[48] + 78*x[49] + 43*x[50] == 1116)
model.cons.add(s[2] + 97*x[1] + 64*x[2] + 24*x[3] + 63*x[4] + 58*x[5] + 45*x[6] + 20*x[7]
+ 71*x[8] + 32*x[9] + 7*x[10] + 28*x[11] + 77*x[12] + 95*x[13] + 96*x[14]
+ 70*x[15] + 22*x[16] + 93*x[17] + 32*x[18] + 17*x[19] + 56*x[20] + 74*x[21]
+ 62*x[22] + 94*x[23] + 9*x[24] + 92*x[25] + 90*x[26] + 40*x[27] + 45*x[28]
+ 84*x[29] + 62*x[30] + 62*x[31] + 34*x[32] + 21*x[33] + 2*x[34] + 75*x[35]
+ 42*x[36] + 75*x[37] + 29*x[38] + 4*x[39] + 64*x[40] + 80*x[41] + 17*x[42]
+ 55*x[43] + 73*x[44] + 23*x[45] + 13*x[46] + 91*x[47] + 70*x[48] + 73*x[49]
+ 28*x[50] == 1325)
model.cons.add(s[3] + 95*x[1] + 71*x[2] + 19*x[3] + 15*x[4] + 66*x[5] + 76*x[6] + 4*x[7]
+ 50*x[8] + 50*x[9] + 97*x[10] + 83*x[11] + 14*x[12] + 27*x[13] + 14*x[14]
+ 34*x[15] + 9*x[16] + 99*x[17] + 62*x[18] + 92*x[19] + 39*x[20] + 56*x[21]
+ 53*x[22] + 91*x[23] + 81*x[24] + 46*x[25] + 94*x[26] + 76*x[27] + 53*x[28]
+ 58*x[29] + 23*x[30] + 15*x[31] + 63*x[32] + 2*x[33] + 31*x[34] + 55*x[35]
+ 71*x[36] + 97*x[37] + 71*x[38] + 55*x[39] + 8*x[40] + 57*x[41] + 14*x[42]
+ 76*x[43] + x[44] + 46*x[45] + 87*x[46] + 22*x[47] + 97*x[48] + 99*x[49] + 92*x[50]
== 1353)
model.cons.add(s[4] + x[1] + 27*x[2] + 46*x[3] + 48*x[4] + 66*x[5] + 58*x[6] + 52*x[7] + 6*x[8]
+ 14*x[9] + 26*x[10] + 55*x[11] + 61*x[12] + 60*x[13] + 3*x[14] + 33*x[15]
+ 99*x[16] + 36*x[17] + 55*x[18] + 70*x[19] + 73*x[20] + 70*x[21] + 38*x[22]
+ 66*x[23] + 39*x[24] + 43*x[25] + 63*x[26] + 88*x[27] + 47*x[28] + 18*x[29]
+ 73*x[30] + 40*x[31] + 91*x[32] + 96*x[33] + 49*x[34] + 13*x[35] + 27*x[36]
+ 22*x[37] + 71*x[38] + 99*x[39] + 66*x[40] + 57*x[41] + x[42] + 54*x[43] + 35*x[44]
+ 52*x[45] + 66*x[46] + 26*x[47] + x[48] + 26*x[49] + 12*x[50] == 1169)
model.cons.add(s[5] + 3*x[1] + 94*x[2] + 51*x[3] + 4*x[4] + 25*x[5] + 46*x[6] + 30*x[7]
+ 2*x[8] + 89*x[9] + 65*x[10] + 28*x[11] + 46*x[12] + 36*x[13] + 53*x[14]
+ 30*x[15] + 73*x[16] + 37*x[17] + 60*x[18] + 21*x[19] + 41*x[20] + 2*x[21]
+ 21*x[22] + 93*x[23] + 82*x[24] + 16*x[25] + 97*x[26] + 75*x[27] + 50*x[28]
+ 13*x[29] + 43*x[30] + 45*x[31] + 64*x[32] + 78*x[33] + 78*x[34] + 6*x[35]
+ 35*x[36] + 72*x[37] + 31*x[38] + 28*x[39] + 56*x[40] + 60*x[41] + 23*x[42]
+ 70*x[43] + 46*x[44] + 88*x[45] + 20*x[46] + 69*x[47] + 13*x[48] + 40*x[49]
+ 73*x[50] == 1160)
model.cons.add(s[6] + 69*x[1] + 72*x[2] + 94*x[3] + 56*x[4] + 90*x[5] + 20*x[6] + 56*x[7]
+ 50*x[8] + 79*x[9] + 59*x[10] + 36*x[11] + 24*x[12] + 42*x[13] + 9*x[14]
+ 29*x[15] + 68*x[16] + 10*x[17] + x[18] + 44*x[19] + 74*x[20] + 61*x[21] + 37*x[22]
+ 71*x[23] + 63*x[24] + 44*x[25] + 77*x[26] + 57*x[27] + 46*x[28] + 51*x[29]
+ 43*x[30] + 4*x[31] + 85*x[32] + 59*x[33] + 7*x[34] + 25*x[35] + 46*x[36] + 25*x[37]
+ 70*x[38] + 78*x[39] + 88*x[40] + 20*x[41] + 40*x[42] + 40*x[43] + 16*x[44]
+ 3*x[45] + 3*x[46] + 5*x[47] + 77*x[48] + 88*x[49] + 16*x[50] == 1163)
return model
for load in [False, True]:
model = create_model()
opt = SolverFactory('xpress_direct')
opt.options['MAXNODE'] = 1
if not load:
# In the first iteration just solve and store the best solution
# found in x_start and s_start.
print('First iteration: Solve to get a feasible solution')
opt.solve(model, tee=True)
print('Saving solution with objective %f' % value(model.obj))
x_start, s_start = dict(), dict()
for i in model.x:
x_start[i] = model.x[i].value
for i in model.s:
s_start[i] = model.s[i].value
else:
# In the second iteration load the solution from x_start and
# s_start and then solve. The log should show lines like
# User solution (_) stored.
# ...
# Its Type BestSoln BestBound Sols Add Del Gap GInf Time
# User solution (_) accepted: Feasible after reoptimizing with fixed globals.
# U 62.000000 .000000 3 62 0 0
# That indicate that the user solution was used and accepted.
print('Second iteration: Solve with a warmstart')
for i in model.x:
model.x[i] = x_start[i]
for i in model.s:
model.s[i] = s_start[i]
opt.solve(model, warmstart=True, tee=True)
为了使用热启动,您将热启动值分配给每个变量并调用solve
. warmstart=True
通过显示的输出日志tee
将包含如下行:
User solution (_) stored.
...
User solution (_) accepted: Feasible after reoptimizing with fixed globals.
U 62.000000 .000000 3 62 0 0
第一行表示使用 Xpress 求解器注册了一个热启动解决方案。最后两行表明warmstart 解决方案已被处理和接受。热启动解决方案报告为日志中“U”启发式的解决方案。
请注意,热启动解决方案的处理可能会延迟到初始 LP 解决之后,因此可能需要一段时间才能在日志中报告它们。
推荐阅读
- c++ - Clang CMAKE 预编译头文件
- serenity-bdd - 在 Serenity 剧本报告中合并“子”可执行文件
- javascript - Javascript/Jquery 使文本完美地适合 div 给定尺寸和换行符(如果需要)
- android - 在下面的这种情况下,如何在 Android 中单击按钮时关闭活动并在后台退出应用程序?
- angular-material - Angular 材质切换按钮:如何设置自己的按钮样式?
- c# - 如果设置了 AutoDeleteOnIdle,服务总线是否会删除没有过滤器/规则的主题订阅?
- database - 如何使用 gorm 设置特定的数据库模式?
- delphi - 访问 Azure Key Vault
- css - 悬停在表格上时如何突出显示表格的行和列?
- javascript - keydown 函数分配给两个键,但在按下任意键时触发