在使用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时,下一个错误将是一个很明显的错误)。
发布于 2020-09-18 17:53:34
也许这会有帮助。我不确定为什么您的示例失败了,只说pyomo
是一种建模语言,它将结构化的数学问题传递给求解者,并且需要对集合进行离散定义,而不是在对象列表中。也许其他人可以把它解释得更清楚。
在您的建模中,您似乎希望为x[i,j]
构建某种粗糙的集,其中j
的范围可以根据i
而变化。您通常希望为I
和J
设置集合,以支持各种约束结构。然后,您可以为任何模型组件创建“有效”(i,j)元组的子集,这些组件需要通过这个粗糙的集合进行索引。您可以使用这个子集作为迭代的基础,或者使用它来检查成员资格,如果您正在动态地构建事物。
下面是一个使用list N的示例:
import pyomo.environ as pyo
N = [1, 4, 3]
m = pyo.ConcreteModel()
m.I = pyo.Set(initialize=range(len(N)))
m.J = pyo.Set(initialize=range(max(N)))
m.IJ = pyo.Set(within=m.I * m.J, initialize =
[(i, j) for i in range(len(N)) for j in range(N[i])])
m.x = pyo.Var(m.IJ, domain=pyo.NonNegativeReals)
def _obj(model):
return sum(m.x[t] for t in m.IJ)
m.obj = pyo.Objective(rule=_obj)
def constrain_x2(model):
return sum(m.x[2, j] for j in m.J if (2, j) in m.IJ) >=1
m.c1 = pyo.Constraint(rule=constrain_x2)
m.pprint()
产量:
4 Set Declarations
I : Dim=0, Dimen=1, Size=3, Domain=None, Ordered=False, Bounds=(0, 2)
[0, 1, 2]
IJ : Dim=0, Dimen=2, Size=8, Domain=IJ_domain, Ordered=False, Bounds=None
[(0, 0), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2)]
IJ_domain : Dim=0, Dimen=2, Size=12, Domain=None, Ordered=False, Bounds=None
Virtual
J : Dim=0, Dimen=1, Size=4, Domain=None, Ordered=False, Bounds=(0, 3)
[0, 1, 2, 3]
1 Var Declarations
x : Size=8, Index=IJ
Key : Lower : Value : Upper : Fixed : Stale : Domain
(0, 0) : 0 : None : None : False : True : NonNegativeReals
(1, 0) : 0 : None : None : False : True : NonNegativeReals
(1, 1) : 0 : None : None : False : True : NonNegativeReals
(1, 2) : 0 : None : None : False : True : NonNegativeReals
(1, 3) : 0 : None : None : False : True : NonNegativeReals
(2, 0) : 0 : None : None : False : True : NonNegativeReals
(2, 1) : 0 : None : None : False : True : NonNegativeReals
(2, 2) : 0 : None : None : False : True : NonNegativeReals
1 Objective Declarations
obj : Size=1, Index=None, Active=True
Key : Active : Sense : Expression
None : True : minimize : x[0,0] + x[1,0] + x[1,1] + x[1,2] + x[1,3] + x[2,0] + x[2,1] + x[2,2]
1 Constraint Declarations
c1 : Size=1, Index=None, Active=True
Key : Lower : Body : Upper : Active
None : 1.0 : x[2,0] + x[2,1] + x[2,2] : +Inf : True
7 Declarations: I J IJ_domain IJ x obj c1
https://stackoverflow.com/questions/63958827
复制相似问题