[英]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.