提问者:小点点

为什么Pyomo行为改变时传递参数约束函数?


此代码工作正常。

def m(model, i):
    return model.fd_amt[i] <= getattr(model, 'br_sa_ind')[i] * global_m

setattr(model, ind+"_m",Constraint(model.br_standalone_I, rule=m))

但是这个

def m(model, i, ind_name):
    return model.fd_amt[i] <= getattr(model, ind_name)[i] * global_m

setattr(model, ind+"_m",Constraint(rule=m(model,model.model.br_standalone_I, 'br_sa_ind') ))

导致此错误:

错误:计算表达式:未初始化的数值对象fd_amt[br_standalone_I]没有值(表达式:fd_amt[br_standalone_I]

Pyomo约束对显式参数的行为方式有什么原因吗?


共2个答案

匿名用户

通过将rule=替换为expr=,可以实现所需的行为:

setattr(model, ind+"_m",Constraint(model.br_standalone_I))
for i in model.br_standalone_I:
    getattr(model, ind+"_m")[i].set_value(expr=m(model, i, 'br_sa_ind'))

规则的目的是使用通用规则构造索引约束表达式。如果有单例约束,可以使用expr指定表达式。

匿名用户

您的代码无法工作,因为您使用了函数调用rule=m(…)而不是函数引用rule=m

虽然此解决方案可能无法直接解决您的问题,但它可能会提供一个解决方案。我仍然不知道Pyomo是否允许您的请求(将参数传递给规则)。

使用要作为唯一元素传递的参数创建一个新集。如果您能够充分处理规则函数中的参数,您可以在以后添加更多元素。为了简单起见,让我们只从一个元素开始。

model.S = Set(initialize=['br_sa_ind'])

然后使用这个集合作为规则的参数。这就像使用一个for all符号,只有一个元素。(对于集合S和集合br_standalone_I中的所有元素,应用规则m)。您应该使用

Constraint(model.br_standalone_I, model.S, rule=m)

所以你的整个代码看起来像

def m(model, i, ind_name):
    return model.fd_amt[i] <= getattr(model, ind_name)[i] * global_m

setattr(model, ind+"_m",Constraint(model.br_standalone_I, model.S, rule=m))

这并不完全优雅,但应该行得通。我还想知道您是否可以在创建约束时为规则指定参数。