Tom Roth
Tom Roth

Reputation: 2074

Change constraints based on variable value in Pyomo

Is there a way of changing the values of a constraint as the solver is running?

Basically, I have a constraint that depends on the value of a variable. The problem is that the constraint is evaluated based on the initial value of the variable, but isn't updated as the variable changes.

Here's a simple example:

from pyomo.environ import *
from pyomo.opt import SolverFactory
import numpy as np

# Setup
model = ConcreteModel()
model.A = Set(initialize = [0,1,2])
model.B = Set(initialize = [0,1,2])
model.x = Var(model.A, model.B, initialize=0)

# A constraint that I'd like to keep updating, based on the value of x
def changing_constraint_rule(model, a):
    x_values = list((model.x[a, b].value for b in model.B))
    if np.max(x_values) == 0:
        return Constraint.Skip
    else:
        # Not really important what goes here, just as long as it updates the constraint list
        if a == 1 : return sum(model.x[a,b] for b in model.B) == 0
        else:       return sum(model.x[a,b] for b in model.B) == 1
model.changing_constraint = Constraint(model.A, rule = changing_constraint_rule)

# Another constraint that changes the value of x
def bounding_constraint_rule(model, a):
    return sum(model.x[a, b] for b in model.B) == 1
model.bounding_constraint = Constraint(
    model.A,
    rule = bounding_constraint_rule)

# Some objective function
def obj_rule(model):
    return(sum(model.x[a,b] for a in model.A for b in model.B))
model.objective = Objective(rule=obj_rule)

# Results
opt = SolverFactory("glpk")
results = opt.solve(model)
results.write()
model.x.display()

If I run model.changing_constraint.pprint() I can see that no constraints have been made, since the initial value of the variable model.x was set to 0.

If it's not possible to change the constraint values while solving, how could I formulate this problem differently to achieve what I'm looking for? I've read this other post but couldn't figure it out from the instructions.

Upvotes: 0

Views: 1891

Answers (1)

oakca
oakca

Reputation: 1568

I am giving you the same answer in the other question by @Gabe:

Any if-logic you use inside of rules should not involve the values of variables (unless it is based on the initial value of a variable, in which case you would wrap the variable in value() wherever you use it outside of the main expression that is returned).

for example: model.x[a, b].value should be model.x[a, b].value()

But still this might not give you the solution what you are looking for.

Upvotes: 2

Related Questions