Pyomo:从Python代码访问解决方案

7

我有一个线性整数规划需要解决。我安装了求解器glpk(感谢这个答案)和pyomo。我编写的代码如下:

from pyomo.environ import *
from pyomo.opt import SolverFactory

a = 370
b = 420
c = 2

model             = ConcreteModel()
model.x           = Var([1,2], domain=NonNegativeIntegers)
model.Objective   = Objective(expr = a * model.x[1] + b * model.x[2], sense=minimize)
model.Constraint1 = Constraint(expr = model.x[1] + model.x[2] == c)
# ... more constraints

opt = SolverFactory('glpk')

results = opt.solve(model)

这将生成名为results.yaml的文件解决方案。
我有许多问题想使用相同的模型但不同的abc值来解决。 我想分配不同的值给abc,解决模型,获得model.x [1]model.x [2]的解决方案,并列出abcmodel.x [1]model.x [2]。 我阅读了文档,但示例仅将解决方案写入文件,如results.yaml
有没有办法从代码中访问解决方案值?
谢谢,

有一段时间没有使用这个库了。你不能直接访问model.x.value吗?还有model.Objective.value。 - sascha
@sascha,谢谢。我尝试了for i in model.x: print(model.x[i].value),它有效。 - Ken
@sascha,如果您能告诉我为什么不应该使用这个库,那就太好了。您是指WinGLPK,对吗? - Ken
我并不推荐不使用它。我讨厌这个界面,但是pyomo非常强大。没有太多的替代品。cvxpy,如果你坚持凸规划(它通过内部推理构建可证明的凸规划,但代价较高;它也更加基于矩阵/数学运算;它支持很多好用的函数,如范数)。还有pulp。我认为这个只做混合整数规划。它更加基于数组,但比pyomo更容易上手。@ken_a - sascha
还有一个注意事项:如果您正在学术界工作,商业求解器有时是免费使用的:Gurobi(和Mosek;我认为没有整数规划支持)两者都带有良好的Python接口(仍在不断发展中)。这些与Pulp的方法大多相似。这些应该是最稳定和最有文档记录的。但是,在一次制定的方案中,只能接受一个求解器。@ken_a - sascha
显示剩余2条评论
3个回答

14

这是您的脚本的修改版,展示了两种打印变量值的不同方式:(1)通过直接引用每个变量和(2)通过迭代模型中的所有变量。

# Pyomo v4.4.1
# Python 2.7
from pyomo.environ import *
from pyomo.opt import SolverFactory

a = 370
b = 420
c = 4

model             = ConcreteModel()
model.x           = Var([1,2], domain=Binary)
model.y           = Var([1,2], domain=Binary)
model.Objective   = Objective(expr = a * model.x[1] + b * model.x[2] + (a-b)*model.y[1] + (a+b)*model.y[2], sense=maximize)
model.Constraint1 = Constraint(expr = model.x[1] + model.x[2] + model.y[1] + model.y[2] <= c)

opt = SolverFactory('glpk')

results = opt.solve(model)

#
# Print values for each variable explicitly
#
print("Print values for each variable explicitly")
for i in model.x:
  print str(model.x[i]), model.x[i].value
for i in model.y:
  print str(model.y[i]), model.y[i].value
print("")

#
# Print values for all variables
#
print("Print values for all variables")
for v in model.component_data_objects(Var):
  print str(v), v.value

这里是生成的输出结果:

Print values for each variable explicitly
x[1] 1.0
x[2] 1.0
y[1] 0.0
y[2] 1.0

Print values for all variables
x[1] 1.0
x[2] 1.0
y[1] 0.0
y[2] 1.0

12

我不确定这是否是你要找的,但这是我在其中一个脚本中打印一些变量的方法。

from pyomo.environ import *
from pyomo.opt import SolverFactory
from pyomo.core import Var

M = AbstractModel()
opt = SolverFactory('glpk')

# Vars, Params, Objective, Constraints....

instance = M.create_instance('input.dat') # reading in a datafile
results = opt.solve(instance, tee=True)
results.write()
instance.solutions.load_from(results)

for v in instance.component_objects(Var, active=True):
    print ("Variable",v)
    varobject = getattr(instance, str(v))
    for index in varobject:
        print ("   ",index, varobject[index].value)

谢谢。我在我的代码中放置了for循环和我的变量,它显示了我想要访问的值! - Ken
1
我非常确定这个循环遍历了所有定义的变量...不过我不知道。几年前在翻阅贫乏的Pyomo文档后,我找到了它 :) - OneCricketeer
是的,它可以。我已经尝试过了。 - EArwa

0
我在urbs项目中发现了pyomoio模块。它可以提取集合、参数、变量等,并将它们返回为pandas对象,非常方便在jupyter笔记本中进行可视化。
我构建了一个简单的模型。
model = ConcreteModel()
model.act = Set(initialize=list('IJK'))
model.goods = Set(initialize=list('ijk'))
u0 = {}
u0['i', 'J'] = 2.
u0['k', 'I'] = .3
model.U0 = Param(model.goods, model.act, initialize=u0, default=0)

然后我可以将其读入pandas DataFrame中,并适当设置所有标签。

import pyomoio as po
u_df = po.get_entity(model, 'U0').unstack()
print(u_df)

# act      I    J    K
# goods               
# i      0.0  2.0  0.0
# j      0.0  0.0  0.0
# k      0.3  0.0  0.0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接