Pyomo模型求解结果显示解数量为0,但实际存在可行解的原因排查
问题描述
我用以下代码创建并求解了一个简单的优化问题:
import pyomo.environ as pyo from pyomo.core.expr.numeric_expr import LinearExpression model = pyo.ConcreteModel() model.nVars = pyo.Param(initialize=4) model.N = pyo.RangeSet(model.nVars) model.x = pyo.Var(model.N, within=pyo.Binary) model.coefs = [1, 1, 3, 4] model.linexp = LinearExpression(constant=0, linear_coefs=model.coefs, linear_vars=[model.x[i] for i in model.N]) def caprule(m): return m.linexp <= 50 model.capme = pyo.Constraint(rule=caprule) model.obj = pyo.Objective(expr = model.linexp, sense = maximize) results = SolverFactory('glpk', executable='/usr/bin/glpsol').solve(model) results.write()
得到的输出如下:
# ========================================================== # = Solver Results = # ========================================================== # ---------------------------------------------------------- # Problem Information # ---------------------------------------------------------- Problem: - Name: unknown Lower bound: 50.0 Upper bound: 50.0 Number of objectives: 1 Number of constraints: 2 Number of variables: 5 Number of nonzeros: 5 Sense: maximize # ---------------------------------------------------------- # Solver Information # ---------------------------------------------------------- Solver: - Status: ok Termination condition: optimal Statistics: Branch and bound: Number of bounded subproblems: 0 Number of created subproblems: 0 Error rc: 0 Time: 0.09727835655212402 # ---------------------------------------------------------- # Solution Information # ---------------------------------------------------------- Solution: - number of solutions: 0 number of solutions displayed: 0
结果显示解数量为0,但实际上问题已经求解完成,执行以下代码:
print(list(model.x[i]() for i in model.N))
会输出正确的可行解:
[1.0, 1.0, 1.0, 1.0]
请问这种矛盾现象的原因是什么?
原因分析
- Pyomo默认解存储逻辑:默认情况下,
solve()方法会直接将求解结果写入model对象(这也是你能通过model.x[i]()获取到正确值的原因),但不会自动把解的详细信息填充到返回的results对象中。 - GLPK求解器的输出特性:对于这种极简单的问题(所有变量取1即可满足约束且达到目标上限),GLPK可能不会生成完整的解报告写入
results,导致results.write()显示解数量为0,但实际解已经被加载到模型变量里。 - 两种验证方式的数据源差异:
model.x[i]()读取的是模型变量的当前值(求解后已更新),而results.write()输出的是results对象存储的信息,两者数据源不同,因此出现看似矛盾的结果。
如果想让results对象包含解的信息,可以在调用solve()时添加load_solutions=False参数,之后手动调用results.load()将解加载到模型,此时results对象就会存储解的信息,results.write()就能正常显示解的数量和具体值。修改后的代码片段如下:
results = SolverFactory('glpk', executable='/usr/bin/glpsol').solve(model, load_solutions=False) results.load() results.write()
内容的提问来源于stack exchange,提问作者lara_toff
相关产品推荐
相关产品推荐

