2
$\begingroup$

I am trying to implement a delayed column generation approach in pyomo. However, I cannot find a way to add a variable to a constraint. I can add variables to the objective function, simply by adding to the objective expression, but that does not seem to work with constraints. So my question is "can you add a variable to an existing constraint in pyomo"? To illustrate what I want to do, here is small example (which does not work):

import pyomo.environ as pyomo
# Create model and variable
model = pyomo.ConcreteModel()
model.x = pyomo.Var(within=pyomo.NonNegativeReals)
# Create simple initial model
model.obj = pyomo.Objective(expr=model.x, sense=pyomo.minimize)
model.cst = pyomo.Constraint(expr=model.x >= 2)
# Solve the model
solver = pyomo.SolverFactory('gurobi')
solver.solve(model, tee=True)
# Create new variable
model.y = pyomo.Var(within=pyomo.NonNegativeReals)
# Add a new variable to the objective and to the constraint
model.obj.expr += model.y
model.cst.body += model.y # This does not work!
$\endgroup$

1 Answer 1

2
$\begingroup$

You can do this using an Expression object to hold the part of the constraint you want to modify:

import pyomo.environ as pyomo

# Create model and variable
model = pyomo.ConcreteModel()
model.x = pyomo.Var(within=pyomo.NonNegativeReals)

# Create simple initial model
model.obj = pyomo.Objective(expr=model.x, sense=pyomo.minimize)
model.lhs_expr = pyomo.Expression(expr=model.x)
model.cst = pyomo.Constraint(expr=model.lhs_expr >= 2)

# Solve the model
solver = pyomo.SolverFactory('gurobi')
solver.solve(model, tee=True)

# Create new variable
model.y = pyomo.Var(within=pyomo.NonNegativeReals)

# Add a new variable to the objective and to the constraint
model.obj.expr += model.y
model.lhs_expr += model.y 
$\endgroup$
3
  • $\begingroup$ Thanks! This is certainly a step forward (after banging my head against this for too long)! Next problem seems to be that Pyomo isn't providing an "ExpressionList" as is the case for VarList and ConstraintList. And simply storing the expressions in a python list, seems to make pyomo angry again. Do you known a way around this? Say I have 100 constraints, where I want to be able to access the lhs_expr for each of them. $\endgroup$
    – Sune
    Nov 3, 2022 at 9:52
  • 1
    $\begingroup$ One way is to index the Expression by the Pyomo set Any. This gives you the behavior of something like an "ExpressionList" but you have more control of the indexing sets. For example: model.lhs_expr = pyomo.Expression(pyomo.Any), model.lhs_expr[1] = model.x, model.lhs_expr[2] = model.x**2, model.lhs_expr.pprint() # Will print only indices that have been defined $\endgroup$ Nov 3, 2022 at 15:10
  • 1
    $\begingroup$ Just make sure you're using the latest Pyomo version (6.4.2) when using the += operator with Expression components. There was a bug with this operation prior to that release (see: github.com/Pyomo/pyomo/pull/2493) $\endgroup$ Nov 3, 2022 at 15:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.