Search code examples
parametersmodelmutablepyomo

Pyomo: How to update constraint definition for existing model instance?


I'm being stuck on a problem, for which I'm sure there is an answer (probably a single line of code).

I have the following minimal model (which mathematically is nonsensical, but it describes my problem):

from pyomo.environ import *

model=AbstractModel()
m=model
m.name="Example model"

#Sets
m.mySet=Set(doc="my set")

m.myVar = Var(m.mySet, name="my variable", initialize=0, within=NonNegativeReals)
m.mutableParameter = Param(m.mySet, name="some mutable parameter", default=0, mutable=True)

m.someDefaultValue = 10
m.someOtherValue = 20
def changingConstraint_rule(m, n):
    if m.mutableParameter[n] == 0:
        return m.myVar[n] == m.someDefaultValue
    else:
        return m.myVar[n] == m.someOtherValue/m.mutableParameter[n]
m.changingConstraint = Constraint(m.mySet, rule=changingConstraint_rule)

#Objective function
def myObj(m):
    return sum([m.myVar[n] for n in m.mySet])
m.myObjective = Objective(rule=myObj, sense=minimize)

As you can see, the behavoir of the changingConstraint depends on the value that the mutableParameter is having.

Now when I create an instance of this model with m.create_instance('mydata.dat'), Pyomo automatically decides which part of the if-clause to use, based on the value the mutableParameter has the moment the instance is being created.

But when I update my mutableParameter now (to a non-zero value) and run the model again, Pyomo does not update its usage of the if-clause in the constraint, and still goes with the original interpretation:

from pyomo import *
from pyomo.environ import *

from minimalModel import m

instance = m.create_instance('datafile.dat')

# Run model once with standard values
solver = 'ipopt'
opt = SolverFactory(solver)
results = opt.solve(instance)

# Change the mutableParameter and run the model again
for t in instance.mySet:
    instance.mutableParameter[t] = 99

# --> This is where I seem to be missing some call to update the instance. I've tried instance.preprocess(), that didn't work <--
results = opt.solve(instance)

What do I have to do to tell Pyomo "re-read the model file and re-assess all if-clauses, based on the new values of the mutableParameters"?

I have a dummy way of doing it: Writing a new .dat-File with the new parameters, and making a completely new instance via another create_instance() call. But that requires me to write a new .dat file for every alteration in any of my mutable parameters. I'm sure there is a smarter way of doing this.

I'd be thankful for any hints. Thanks!


Solution

  • I've figured it out, credit goes to Qi Chen for pointing me the right way.

    What needs to be done, is to reconstruct the constraint before evaluating the model again, but not the entire model.

    Beforehand, I was trying

    instance.reconstruct()
    

    before calling the opt.solve() again. That did not work. What actually needs to be done is reconstruct the constraint itself via

    instance.changingConstraint.reconstruct()
    

    which then re-evaluates the if-clause in the constraint, based on the new values of the mutable parameter.