Andrewfreestuff
Andrewfreestuff

Reputation: 173

Best way to change the value of an indexed parameter

I am new to Pyomo, and am wanting to know how to change the value of an already existing model parameter that has one or more index.

I have seen some examples for scalar parameters, i.e. no index. For example:

model5 = ConcreteModel()
model5.data2 = Param(initialize=10.0, mutable=True)
print("print data2 before")
model5.data2.pprint()
model5.data2 = 999
print("print data2 after")
model5.data2.pprint()

This produces the output:

print data2 before
data2 : Size=1, Index=None, Domain=Any, Default=None, Mutable=True
    Key  : Value
    None :  10.0
print data2 after
data2 : Size=1, Index=None, Domain=Any, Default=None, Mutable=True
    Key  : Value
    None :   999

But if I try and do it with a parameter that has an index I get an error. The following code fails, but probably no surprise because I am trying to assign a Python object to a Pyomo object. What is the correct way to update a parameter with an index (or more than one index)?

model5 = ConcreteModel()
# Make a small set
myList = ['i1', 'i2', 'i3', 'i4']
model5.i = Set(dimen=1, initialize=myList)
# Make a dict for each element in the set and give it the value 10
dataDict = {}
for  element in myList:
  dataDict[element] = 10
print("print dataDict")
print(dataDict)
# Make the data into a model Param
model5.data = Param(model5.i, initialize=dataDict, mutable=True)
print("print data parameter")
model5.data.pprint()
# Change a values for each element to 999
for  element in myList:
  dataDict[element] = 999
# Try and update the Param
model5.data = dataDict # THIS FAILS <-- how do I do this?

Upvotes: 3

Views: 2822

Answers (1)

Giorgio Balestrieri
Giorgio Balestrieri

Reputation: 1062

tl,dr: use the reconstruct method of the (mutable!) parameter you want to update.

First, my suggestion is to put the procedure to initialize your model into a function, so that you can call it from different places and reuse it.

from pyomo import environ as pe

def create_model(d: dict) -> pe.ConcreteModel:
    """Create Pyomo Concrete Model.

    Parameters
    ----------
    d : Dictionary with keys corresponding to components names.
    """
    model = pe.ConcreteModel()
    model.I = pe.Set(initialize=d['I'])
    model.data = pe.Param(model.I, mutable=True, initialize=d['data'])
    return model

Then you can initialize the model with whatever data you want:

d = {}
d['I'] = ['i1', 'i2', 'i3', 'i4']
d['data'] = {i : 10 for i in d['I']}

model = create_model(d)
​
model.data.pprint()

data : Size=4, Index=I, Domain=Any, Default=None, Mutable=True
    Key : Value
     i1 :    10
     i2 :    10
     i3 :    10
     i4 :    10

Now update the values using reconstruct:

new_values = {i: 5 for i in d['I']} # 5 here is arbitrary, you
model.data.reconstruct(new_values) 
​
model.data.pprint()
data : Size=4, Index=I, Domain=Any, Default=None, Mutable=True
    Key : Value
     i1 :     5
     i2 :     5
     i3 :     5
     i4 :     5

As a side note, data is a really confusing name for a parameter, you should find something more specific.

Upvotes: 4

Related Questions