Build Pyomo Sets into a Python dictionnary

733 views Asked by At

For example, I want to create a dictionnary of Pyomo Sets from a Python dictionnary of lists named dictOfList. dictOfList is built as follow:

dictOfList= {}
dictOfList[1] = [10,11,12]
dictOfList[2] = [20,21]
dictOfList[3] = [31,32,33,34]

Now, I would like the values [10,11,12], [20,21], and [31,32,33,34] to be put in a Python dictionnary of Pyomo Sets named dictOfSets as follow:

model.dictOfSets = {}
for el in dictOfList:
    model.dictOfSets[el] = Set(initialize=dictOfList[el])

Then, if I display the values of the Sets using another simple for loop:

for el in dictOfList:
    model.dictOfSets[el].display()

It seems like the Sets are not properly built, since it shows this in the running console:

_unknown_ : Dim=0, Dimen=1, Size=0, Domain=None, Ordered=False, Bounds=None
    Not constructed
_unknown_ : Dim=0, Dimen=1, Size=0, Domain=None, Ordered=False, Bounds=None
    Not constructed
_unknown_ : Dim=0, Dimen=1, Size=0, Domain=None, Ordered=False, Bounds=None
    Not constructed

Is there a way to build a Pyomo Set inside a Python dictionnary? Right now, I have used normal Python lists, but it caused me very long processing time in larger models, and I know that it is better to use Pyomo Sets for faster performances in building constraints.

1

There are 1 answers

3
jsiirola On BEST ANSWER

The Sets are not being fully constructed because they are never being assigned to a Block or model object. While not exactly what you are asking for (you don't actually end up with a dict of Sets on your model), the easiest thing to do to get the effect you want is to actually create an indexed Set:

dictOfList= {}
dictOfList[1] = [10,11,12]
dictOfList[2] = [20,21]
dictOfList[3] = [31,32,33,34]
model.S = Set(dictOfList.keys(), initialize=dictOfList)

If you print the model (model.pprint()), you will get:

2 Set Declarations
    S : Dim=1, Dimen=1, Size=9, Domain=None, ArraySize=3, Ordered=False, Bounds=None
        Key : Members
          1 : [10, 11, 12]
          2 : [20, 21]
          3 : [31, 32, 33, 34]
    S_index : Dim=0, Dimen=1, Size=3, Domain=None, Ordered=False, Bounds=(1, 3)
        [1, 2, 3]

To actually create a Python dict of Sets you would also need to assign each individual Set to the model so that it gets properly constructed. Something like this could work:

model.dictOfSets = {}
for el in dictOfList:
    model.dictOfSets[el] = Set(initialize=dictOfList[el])
    setattr(model, 'dictOfSets_member_%s' % (el,), model.dictOfSets[el])
for el in dictOfList:
    model.dictOfSets[el].display()

gives

dictOfSets_member_1 : Dim=0, Dimen=1, Size=3, Domain=None, Ordered=False, Bounds=(10, 12)
    [10, 11, 12]
dictOfSets_member_2 : Dim=0, Dimen=1, Size=2, Domain=None, Ordered=False, Bounds=(20, 21)
    [20, 21]
dictOfSets_member_3 : Dim=0, Dimen=1, Size=4, Domain=None, Ordered=False, Bounds=(31, 34)
    [31, 32, 33, 34]

EDIT: You can have more complicated indexing if you explicitly create the indexed Set's index. That is:

model.S_IDX = Set(initialize=dictOfList.keys())
model.S = Set(model.S_IDX, initialize=dictOfList)

By explicitly creating the set, you can have arbitrarily complicated keys. Note that in some cases you may have to explicitly set the "dimension" of the index Set using the dimen= keyword:

dictOfList = { (1,2): [10,11,12],
               (2,3): [20,21],
               (1,3): [31,32,33,34],
}
model.S_IDX = Set(initialize=dictOfList.keys(), dimen=2)
model.S = Set(model.S_IDX, initialize=dictOfList)

This is especially true if you want the tuples to have different lengths:

dictOfList = { (1,): [10,11,12],
               (2,3): [20,21],
               (1,3,4): [31,32,33,34],
}
model.S_IDX = Set(initialize=dictOfList.keys(), dimen=None)
model.S = Set(model.S_IDX, initialize=dictOfList)

Where model.pprint() gives:

2 Set Declarations
    S : Dim=None, Dimen=1, Size=9, Domain=None, ArraySize=3, Ordered=False, Bounds=None
        Key       : Members
             (1,) : [10, 11, 12]
        (1, 3, 4) : [31, 32, 33, 34]
           (2, 3) : [20, 21]
    S_IDX : Dim=0, Dimen=None, Size=3, Domain=None, Ordered=False, Bounds=None
        [(1,), (1, 3, 4), (2, 3)]