简体   繁体   English

在 pyomo 中定义一组约束的结果是错误的

[英]The outcome of defining a set of constraints in pyomo is wrong

I create an optimization model in pyomo, and I have a list of tuples as a parameter “par”.我在 pyomo 中创建了一个优化 model,我有一个元组列表作为参数“par”。

import pyomo.environ as pe
model = pe.ConcreteModel()
p_set = [(1,2), (2,3), (4,5)]
model.par = pe.Param(initialize=p_set, mutable= True)
def var_fix(model, i, j ):
    if (i,j) in model.par:
        constraint = (model.v[i,j] == 1)      # v is a binary variable
    else:
        constraint = (model.v[i,j] == 0) 
    return constraint
model.var_fix = pe.Constraint(model.edges, rule=var_fix)  

But, after printing “var_fix” constraint, all of them are equall to zero:但是,在打印“var_fix”约束后,它们都等于零:

Key       : Lower : Body     : Upper : Active
(1, 2)   :   0.0     :   v[1,2] :   0.0     :   True
(2, 3)   :   0.0     :   v[2,3] :   0.0     :   True
(4, 5)   :   0.0     :   v[4,5] :   0.0     :   True

I define the parameter and constraint in this way since I want to iteratively change this parameter “par” with a new one which may have different number of tuples, then solve the problem.我以这种方式定义参数和约束,因为我想用一个可能有不同数量元组的新参数迭代地更改这个参数“par”,然后解决问题。 In each iteration I will do:在每次迭代中我会做:

# generating par_new based on some random processes 
par_new = [(5,10), (2,3), (4,5), (11,8), (10,6)]
model.par = par_new
# solve the problem again

The crux of your problem is that you are defining a single ScalarParam that holds a list of tuples.问题的症结在于您正在定义一个包含元组列表的 ScalarParam 。 Scalar objects in Pyomo are special cases of their Indexed counderparts that use an implicit index of None . Pyomo 中的标量对象是使用隐式索引None的索引对象的特例。 This is done so that code working with Pyomo models can treat all components as if they were indexed (which prevents code from being littered with if comp.is_indexed(): tests).这样做是为了使使用 Pyomo 模型的代码可以将所有组件视为已被索引(这可以防止代码被if comp.is_indexed():测试弄得乱七八糟)。 The __contains__ test that you are doing ( if (i,j) in model.par ) is testing if the tuple is in the Param's indexing set , and not in the Param's value .您正在执行的__contains__测试( if (i,j) in model.par )正在测试元组是否在 Param 的索引集中,而不是在 Param 的中。

The simplest change is to change the test to check the Param's value:最简单的更改是更改测试以检查参数的值:

>>> from pyomo.environ import *
>>> m = ConcreteModel()
>>> m.p = Param(initialize=[(1,2),(3,4)], mutable=True, domain=Any)
>>> (1,2) in m.p
False
>>> (1,2) in m.p.value
True

However, if you intend on updating the model iteratively (without rebuilding it), I would recommend making the param hold the RHS of the constraint.但是,如果您打算迭代更新 model(不重建它),我建议让参数保留约束的 RHS。 That is, something more like:也就是说,更像是:

model = pe.ConcreteModel()

p_set = [(1,2), (2,3), (4,5)]
def par(m, i, j):
    return 1 if (i,j) in p_set else 0
model.par = pe.Param(model.edges, initialize=par, mutable=True)

def var_fix(model, i, j ):
    return model.v[i,j] == model.par[i,j]
model.var_fix = pe.Constraint(model.edges, rule=var_fix)  

This is because construction rules are not callbacks : they are called only when initially constructing the component and not during the solve.这是因为构造规则不是回调:它们仅在最初构造组件时被调用,而不是在求解期间被调用。 Updating the Params would then look more like:更新参数看起来更像是:

model.par.set_values(0)
for i,j in par_new:
    model.par[i,j] = 1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM