Pyomo索引约束仅Lambda规则生效,替换为函数时报错求助
问题:Pyomo中自定义约束函数报错排查
在Pyomo中将索引约束的Lambda表达式替换为自定义函数时出现报错,以下是详细场景:
可正常运行的代码示例
import pyomo.environ as pyomo model = pyomo.ConcreteModel() model.time_set = pyomo.Set(initialize=range(1, 3)) model.thermal_set = pyomo.Set(initialize=range(1, 3)) model.thermal_generation = pyomo.Var(model.time_set, model.thermal_set) model.thermal_operation = pyomo.Var(model.time_set, model.thermal_set, bounds=(0, 1)) model.thermal_reserve = pyomo.Var( model.time_set, model.thermal_set, domain=pyomo.NonNegativeReals ) model.NGC = pyomo.Param(model.thermal_set, initialize={1: 0.6, 2: 0.3}) model.thermal_MSG = pyomo.Constraint( model.time_set, model.thermal_set, rule=lambda model, t, i: model.thermal_generation[t, i] + model.thermal_reserve[t, i] <= model.NGC[i] * model.thermal_operation[t, i], )
改写后报错的代码
def thermal_NGC_constraint(model, t, i): thermal_NGC_constraint = ( model.thermal_generation[t, i] + model.thermal_reserve[t, i] <= model.NGC[i] * model.thermal_operation[t, i], ) return thermal_NGC_constraint model.thermal_MSG = pyomo.Constraint( model.time_set, model.thermal_set, rule=thermal_NGC_constraint, )
报错信息
Constraint 'thermal_MSG[1,1]' does not have a proper value. Found a tuple of length 1. Expecting a tuple of length 2 or 3: Equality: (left, right) Inequality: (lower, expression, upper)
问题原因与解决方法
问题出在自定义函数的赋值语句里,表达式末尾多了一个逗号,导致返回的是长度为1的元组,而Pyomo约束规则不接受这种格式。
Lambda表达式中直接返回不等式表达式,没有额外逗号,所以能正常运行;但自定义函数里的逗号让Python把表达式包装成了单元素元组,不符合Pyomo对约束返回值的要求——Pyomo期望约束规则返回以下类型之一:
- 单个等式/不等式表达式(如
a <= b) - 长度为2的元组(表示等式约束:
(left_expr, right_expr)) - 长度为3的元组(表示区间约束:
(lower_bound, expr, upper_bound))
修正后的代码
去掉表达式末尾的逗号即可:
def thermal_NGC_constraint(model, t, i): thermal_NGC_constraint = ( model.thermal_generation[t, i] + model.thermal_reserve[t, i] <= model.NGC[i] * model.thermal_operation[t, i] ) return thermal_NGC_constraint model.thermal_MSG = pyomo.Constraint( model.time_set, model.thermal_set, rule=thermal_NGC_constraint, )
或者更简洁的写法,直接返回表达式:
def thermal_NGC_constraint(model, t, i): return model.thermal_generation[t, i] + model.thermal_reserve[t, i] <= model.NGC[i] * model.thermal_operation[t, i]
内容的提问来源于stack exchange,提问作者Christoph Neumann
相关产品推荐
相关产品推荐

