首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Pyomo:在列表中未构造的Param和Var

Pyomo:在列表中未构造的Param和Var
EN

Stack Overflow用户
提问于 2020-09-18 15:41:45
回答 2查看 556关注 0票数 0

在使用pyomo建模优化问题时,我注意到在使用list of VarParam时有一种奇怪的行为:我总是得到以下错误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)完全按照预期运行:

代码语言:javascript
运行
复制
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.xmodel.c中设置list时,程序在创建目标函数时崩溃:

代码语言:javascript
运行
复制
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)

是什么导致了这个错误?这是因为我不明白的原因而想要的行为,还是一个错误?无论如何,如何在问题中使用Params和Vars的列表?我知道,理论上我可以将所有参数和变量都压缩到一个IndexedVarIndexedParam中,并自己处理新的索引,但这会很繁琐,因为我的xc的第3和第4索引的范围取决于第1和第2索引,因此,如果我可以使用lists,代码中就会清楚得多。

更确切地说:我有一个类似于这样的代码(尽管我仍然对了解上面的MWE不工作的原因感兴趣):

代码语言:javascript
运行
复制
# 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)
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-09-18 22:57:09

你的最小例子

代码语言:javascript
运行
复制
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)

生成以下错误:

代码语言:javascript
运行
复制
ValueError: Evaluating the numeric value of parameter 'SimpleParam' before
        the Param has been constructed (there is currently no value to return).

原因是没有将生成的VarParam直接附加到模型。当将Pyomo建模组件附加到Block (ConcreteModel对象是构造的块的实例)时,会发生很多事情:

组件被分配了一个名称(与块属性名称匹配),组件被插入到层次结构中(基本上,设置了指针,以便方法可以在模型hierarchy)

  • The组件上走和下走,这样编写器、求解器和转换可以在以后的

  • (如果块已经构建)中找到,组件就自动constructed.

)。

通过将组件放置在列表中,您实际上是在对Pyomo“隐藏”它的存在。第一个错误与最后一个项目有关( Param尚未被构造)。但是,在构建列表时简单地构造Param和Var将是不够的,因为其他操作不会发生,稍后您只会碰到一个不同的错误(当LP编写器在第一次遍历模型层次结构时遇到一个Var时,下一个错误将是一个很明显的错误)。

票数 1
EN

Stack Overflow用户

发布于 2020-09-18 17:53:34

也许这会有帮助。我不确定为什么您的示例失败了,只说pyomo是一种建模语言,它将结构化的数学问题传递给求解者,并且需要对集合进行离散定义,而不是在对象列表中。也许其他人可以把它解释得更清楚。

在您的建模中,您似乎希望为x[i,j]构建某种粗糙的集,其中j的范围可以根据i而变化。您通常希望为IJ设置集合,以支持各种约束结构。然后,您可以为任何模型组件创建“有效”(i,j)元组的子集,这些组件需要通过这个粗糙的集合进行索引。您可以使用这个子集作为迭代的基础,或者使用它来检查成员资格,如果您正在动态地构建事物。

下面是一个使用list N的示例:

代码语言:javascript
运行
复制
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()

产量:

代码语言:javascript
运行
复制
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
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63958827

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档