Search code examples
pythonoptimizationpyomo

Initialize to iterate over set in abstract pyomo model?


I am trying to debug an abstract pyomo model (of electric investment/dispatch), and can't get past the following error:

"Cannot iterate over AbstractOrderedSimpleSet 'gen_type' before it has been constructed (initialized)."

Any idea what I am doing wrong? It seems to be suggesting that I haven't correctly identified the set data, is there something wrong with my data file?

Note that I am very new to using pyomo, so I'm sure there are plenty of other issues with the code (particularly with indexing transmission lines between two locations and defining intermediary variables to build to the objective function) but I can't move forward without addressing this error first (though, if you have thoughts on indexing transmission and intermediary variables, I would appreciate any suggestions).

The relevant portion of code is as follows:

from pyomo.environ import *

model = AbstractModel()

### sets, parameters, and variables

#time, locations, generation types
model.tim=Set()
model.loc=Set()
model.gen_type=Set()

#generation capital and variable cost, transmission capital cost
model.gen_capcost=Param(model.gen_type)
model.gen_varcost=Param(model.gen_type)
model.trans_capcost=Param()

#generation capacity, electricity generated, transmission capacity, electricity transmitted
model.gen_cap=Var(model.gen_type,model.loc,within=NonNegativeReals)
model.elec_gen=Var(model.gen_type,model.tim,model.loc,within=NonNegativeReals)
model.trans_cap=Var(model.loc,model.loc,within=NonNegativeReals)
model.elec_trans=Var(model.tim,model.loc,model.loc,within=NonNegativeReals)

###objective

gen_cost= sum(model.gen_cap[g,l]*model.gen_capcost[g]+model.elec_gen[g,t,l]*model.gen_varcost[g] for g in model.gen_type for t in model.tim for l in model.loc)

trans_cost= sum(model.trans_cap[l,k]*model.trans_capcost for l in model.loc for k in model.loc)

def obj_rule(model):
    return gen_cost+trans_cost
model.obj=Objective(rule=obj_rule)

###constraints

def max_gen_cap_rule(model,g,t,l):
    return model.elec_gen[g,t,l]<=model.gen_cap[g,l]
model.max_gen_cap=Constraint(model.gen_type,model.tim,model.loc,rule=max_gen_cap_rule)

def max_trans_cap_rule(model,t,l,k):
    return model.elec_trans[t,l,k]<=model.trans_cap[l,k]
model.max_trans_cap=Constraint(model.tim,model.loc,model.loc,rule=max_trans_cap_rule)

And the relevant portion of the data file is as follows:

set tim := 1 2 3 4 ;

set loc := A B ;

set gen_type := solar wind hydro nuclear fossil ;

param gen_capcost :=
solar 100
wind 200
hydro 300
nuclear 400
fossil 250;

param gen_varcost :=
solar 1
wind 1
hydro 3
nuclear 5 
fossil 12;

param trans_capcost := 20 ;

Thank you!


Solution

  • The issue here is not with your data. Python (not pyomo) is trying to execute your gen_cost and trans_cost statements and the sets are (obviously) not initialized. You can shield these statements from being executed until pyomo calls them with data by being consistent with your def-rule pattern in pyomo. Restructure your objective to this, and I think you'll be on your way...

    ###objective
    
    def obj_rule(model):
        gen_cost= sum(model.gen_cap[g,l]*model.gen_capcost[g]+model.elec_gen[g,t,l]*model.gen_varcost[g] for g in model.gen_type for t in model.tim for l in model.loc)
        trans_cost= sum(model.trans_cap[l,k]*model.trans_capcost for l in model.loc for k in model.loc)
        return gen_cost + trans_cost
    
    model.obj=Objective(rule=obj_rule)