在使用pyomo
建模优化问题时,我注意到在使用list
of Var
或Param
时有一种奇怪的行为:我总是得到以下错误ValueError: Evaluating the numeric value of parameter 'SimpleParam' before the Param has been constructed (there is currently no value to return).
以下代码(最小化4*x+1,使x >= 0)完全按照预期运行:
import pyomo.environ as pyo
from pyomo.opt import SolverFactory
def _obj(model):
return model.c*model.x + 1
model = pyo.ConcreteModel()
model.x = pyo.Var(domain=pyo.NonNegativeReals)
model.c = pyo.Param(initialize=lambda model: 4, domain=pyo.NonNegativeReals)
model.obj = pyo.Objective(rule=_obj, sense=pyo.minimize)
opt = SolverFactory('glpk')
opt.solve(model)
但是,当我在model.x
和model.c
中设置list
时,程序在创建目标函数时崩溃:
import pyomo.environ as pyo
from pyomo.opt import SolverFactory
def _obj(model):
return model.c[0]*model.x[0] + 1
model = pyo.ConcreteModel()
model.x = [pyo.Var(domain=pyo.NonNegativeReals)]
model.c = [pyo.Param(initialize=lambda model: 4, domain=pyo.NonNegativeReals)]
model.obj = pyo.Objective(rule=_obj, sense=pyo.minimize)
opt = SolverFactory('glpk')
opt.solve(model)
是什么导致了这个错误?这是因为我不明白的原因而想要的行为,还是一个错误?无论如何,如何在问题中使用Param
s和Var
s的列表?我知道,理论上我可以将所有参数和变量都压缩到一个IndexedVar
或IndexedParam
中,并自己处理新的索引,但这会很繁琐,因为我的x
和c
的第3和第4索引的范围取决于第1和第2索引,因此,如果我可以使用list
s,代码中就会清楚得多。
更确切地说:我有一个类似于这样的代码(尽管我仍然对了解上面的MWE不工作的原因感兴趣):
# I, J are lists of indices and N is a list of integer values
model.Vs = [pyo.RangeSet(N[i]) for i in range(len(N))]
model.xs = [[pyo.Var(model.Vs[i], model.Vs[j]) for j in J] for i in I]
model.cs = [[pyo.Param(model.Vs[i], model.Vs[j]) for j in J] for i in I]
def _obj(model):
sum(model.xs[i][j][k,ell] * model.xs[i][j][k,ell] \\
for i in I for j in J \\
for k in model.Vs[i] for ell in model.Vs[j])
model.obj = Objective(rule=_obj, sense=pyo.minimize)
model.constraints = [
[pyo.Constraint(model.Vs[i], model.Vs[j], rule=...) for j in J]
for i in I
]
opt = SolverFactory('glpk')
opt.solve(model)
发布于 2020-09-18 22:57:09
你的最小例子
import pyomo.environ as pyo
from pyomo.opt import SolverFactory
def _obj(model):
return model.c[0]*model.x[0] + 1
model = pyo.ConcreteModel()
model.x = [pyo.Var(domain=pyo.NonNegativeReals)]
model.c = [pyo.Param(initialize=lambda model: 4, domain=pyo.NonNegativeReals)]
model.obj = pyo.Objective(rule=_obj, sense=pyo.minimize)
opt = SolverFactory('glpk')
opt.solve(model)
生成以下错误:
ValueError: Evaluating the numeric value of parameter 'SimpleParam' before
the Param has been constructed (there is currently no value to return).
原因是没有将生成的Var
和Param
直接附加到模型。当将Pyomo建模组件附加到Block
(ConcreteModel
对象是构造的块的实例)时,会发生很多事情:
组件被分配了一个名称(与块属性名称匹配),组件被插入到层次结构中(基本上,设置了指针,以便方法可以在模型hierarchy)
)。
通过将组件放置在列表中,您实际上是在对Pyomo“隐藏”它的存在。第一个错误与最后一个项目有关( Param尚未被构造)。但是,在构建列表时简单地构造Param和Var将是不够的,因为其他操作不会发生,稍后您只会碰到一个不同的错误(当LP编写器在第一次遍历模型层次结构时遇到一个Var时,下一个错误将是一个很明显的错误)。
https://stackoverflow.com/questions/63958827
复制相似问题