Gabriel Yin
Gabriel Yin

Reputation: 53

How to map different indices in Pyomo?

I am a new Pyomo/Python user. Now I need to formulate one set of constraints with index 'n', where all of the 3 components are with different indices but correlate with index 'n'. I am just curious that how I can map the relationship between these sets.

In my case, I read csv files in which their indices are related to 'n' to generate my set. For example: a1.n1, a2.n3, a3.n5 /// b1.n2, b2.n4, b3.n6, b4.n7 /// c1.n1, c2.n2, c3.n4, c4.n6 ///. The constraint expression of index n1 and n2 is the follows for example:

for n1: P(a1.n1) + L(c1.n1) == D(n1)
for n2: - F(b1.n2) + L(c2.n2) == D(n2)

Now let's go the coding. The set creating codes are as follow, they are within a class:

import pyomo
import pandas
import pyomo.opt
import pyomo.environ as pe

class MyModel:

    def __init__(self, Afile, Bfile, Cfile):
        self.A_data = pandas.read_csv(Afile)
        self.A_data.set_index(['a'], inplace = True)
        self.A_data.sort_index(inplace = True) 
        self.A_set = self.A_data.index.unique()

        ... ...

Then I tried to map the relationship in the constraint construction like follows:

    def createModel(self):

        self.m = pe.ConcreteModel()

        self.m.A_set = pe.Set( initialize = self.A_set )

        def obj_rule(m):
            return ...
        self.m.OBJ = pe.Objective(rule = obj_rule, sense = pe.minimize)

        def constr(m, n)
            As = self.A_data.reset_index()
            Amap = As[ As['n'] == n ]['a']
            Bs = self.B_data.reset_index()
            Bmap = Bs[ Bs['n'] == n ]['b']
            Cs = self.C_data.reset_index()
            Cmap = Cs[ Cs['n'] == n ]['c']

            return sum(m.P[(p,n)] for p in Amap) - sum(m.F[(s,n)] for s in Bmap) + sum(m.L[(r,n)] for r in Cmap) == self.D_data.ix[n, 'D']
        self.m.cons = pe.Constraint(self.m.D_set, rule = constr)

    def solve(self):
        ... ...

Finally, the error raises when I run this:

KeyError: "Index '(1, 1)' is not valid for indexed component 'P'"

I know it is the wrong way, so I am wondering if there is a good way to map their relationships. Thanks in advance!

Gabriel

Upvotes: 0

Views: 443

Answers (1)

Gabriel Yin
Gabriel Yin

Reputation: 53

I just forgot to post my answer to my own question when I solved this one week ago. The key thing towards this problem is setting up a map index.

Let me just modify the code in the question. Firstly, we need to modify the dataframe to include the information of the mapped indices. Then, the set for the mapped index can be constructed, taking 2 mapped indices as example:

self.m.A_set = pe.Set( initialize = self.A_set, dimen = 2 )

The names of the two mapped indices are 'alpha' and 'beta' respectively. Then the constraint can be formulated, based on the variables declared at the beginning:

def constr(m, n)
    Amap = self.A_data[ self.A_data['alpha'] == n ]['beta']
    Bmap = self.B_data[ self.B_data['alpha'] == n ]['beta']
    return sum(m.P[(i,n)] for i in Amap) + sum(m.L[(r,n)] for r in Bmap) == D.loc[n, 'D']
m.TravelingBal = pe.Constraint(m.A_set, rule = constr)

The summation groups all associated B to A with a mapped index set.

Upvotes: 2

Related Questions