Search code examples
mathematical-optimizationpyomo

Pyomo Error: Cannot apply a Set operator to a non-Set ConcreteModel component (unknown)


I am trying to write some model in Pyomo. My code looks like this:

#model definition
model = ConcreteModel()

#Sets and indices
model.O = RangeSet(len(data))  #Set of representative operating conditions
model.D = RangeSet(len(data)) #Demand profile for the operating conditions
model.G = RangeSet(1)   #set of existing generators
model.C = RangeSet(1)   #set of candidate generators
 

#Parameters
model.Cg= Param(initialize=35, within=NonNegativeReals, mutable=True) #Opex of existing generators
model.Cc= Param(initialize=25, within=NonNegativeReals, mutable=True) #Opex of candidate generators
model.Ic= Param(initialize=70000, within=NonNegativeReals, mutable=True) #Annualized investment cost

#Decision Variables
model.pg = Var(model.O, model.G, bounds=(0, 400), initialize=0, within=NonNegativeReals)
model.pc = Var(model.O, model.C, bounds =(0, 500), initialize=0, within=NonNegativeReals)
model.pc_max = Var(model.C, bounds=(0, 500), initialize=0, within=NonNegativeIntegers)


#Objective function

def objective_rule(model, O):
    return sum(data.loc[O-1, 'w']*(sum(model.Cg*model.pg[O,G] for G in model.G))+\
               data.loc[O-1, 'w']*(sum(model.Cc*model.pc[O,C] for C in model.C)) for O in model.O)+\
                sum(model.Ic*model.pc_max[C] for C in model.C)

model.objective = Objective(model, rule=objective_rule, sense=minimize)
#Constraints
#1. sign restrictions already provided for in the definition of decision variables

def con1_limit_candidate_units(model, O, C):
    return model.pc[O,C] <= model.pc_max[C]

model.con1 = Constraint(model.O, model.C, rule=con1_limit_candidate_units)

def con2_power_balance(model, O, G):
    return sum(model.pg[O, G] for G in model.G) + sum(model.pc[O, C] for C in model.C) == data.loc[O-1, 'd']

model.con2 = Constraint(model.O, model.G, rule = con2_power_balance)

opt = SolverFactory('cplex')
instance = model.create_instance()
results = opt.solve(instance) # solves and updates instance
print('Objective value=',value(instance.objective))

When I try running it I find this error so many times.

TypeError                                 Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_5960/507444092.py in <module>
     36                 sum(model.Ic*model.pc_max[C] for C in model.C)
     37 
---> 38 model.objective = Objective(model, rule=objective_rule, sense=minimize)
     39 #Constraints
     40 #1. sign restrictions already provided for in the definition of decision variables

~\anaconda3\lib\site-packages\pyomo\core\base\objective.py in __init__(self, *args, **kwargs)
    279 
    280         kwargs.setdefault('ctype', Objective)
--> 281         ActiveIndexedComponent.__init__(self, *args, **kwargs)
    282 
    283         self.rule = Initializer(_init)

~\anaconda3\lib\site-packages\pyomo\core\base\indexed_component.py in __init__(self, *args, **kwds)
   1046 
   1047     def __init__(self, *args, **kwds):
-> 1048         IndexedComponent.__init__(self, *args, **kwds)
   1049         # Replicate the ActiveComponent.__init__() here.  We don't want
   1050         # to use super, because that will run afoul of certain

~\anaconda3\lib\site-packages\pyomo\core\base\indexed_component.py in __init__(self, *args, **kwds)
    289             #
    290             self._implicit_subsets = None
--> 291             self._index = process_setarg(args[0])
    292         else:
    293             #

~\anaconda3\lib\site-packages\pyomo\core\base\set.py in process_setarg(arg)
    118                             % (arg.ctype.__name__, arg.name,))
    119         if isinstance(arg, Component):
--> 120             raise TypeError("Cannot apply a Set operator to a non-Set "
    121                             "%s component (%s)"
    122                             % (arg.__class__.__name__, arg.name,))

TypeError: Cannot apply a Set operator to a non-Set ConcreteModel component (unknown)

What could be the issue and how can it be solved?

It seems the issue is in the portion: sum(model.Ic*model.pc_max[C] for C in model.C). I have tried removing the "for C in model.C" part but it still doesn't work). For this case, the set C only contains 1 element.


Solution

  • You shouldn't pass the model to the Objective constructor. Component constructors assume all non-keyword arguments are indexing sets. So, instead of

    model.objective = Objective(model, rule=objective_rule, sense=minimize)
    

    You should do

    model.objective = Objective(rule=objective_rule, sense=minimize)