Christoph Neumann
Christoph Neumann

Reputation: 115

Pyomo indexed constraint works with lambda-rule only

I am puzzled by a pyomo error that I obtained when replacing a lambda-expression by a function.

Consider the following working example:

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],
)

Replacing the last line by

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,
)

results in the error

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) 

Rewriting other constraints like this worked. What am I doing wrong here?

Upvotes: 0

Views: 243

Answers (1)

AirSquid
AirSquid

Reputation: 11883

You have a stray comma that is biting you. Inside your function, you are assigning the expression to a malformed tuple unintentionally in this statement:

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

It is essentially saying this:

my_expression = (some vars <= other vars, ___)

which simplifies to:

my_expression = (<a pyomo expression>, )

which is a tuple type, not an expression. I believe you can express expressions as tuples as the error kinda suggests, but that is not what you are trying to do here. Remove the comma and all is well. In fact, I've been bitten by this before and I recommend you do not put the expression in parens to prevent this from happening also.

Upvotes: 1

Related Questions