Search code examples
pyomo

Pyomo: Cannot apply a Set operator to an indexed Set component


I'm a new Pyomo user, i try to convert an ampl model to pyomo and i found it's too hard to do this work.

When i create the var x with the set lev witch is indexed by a another set A, i get this error warning: Cannot apply a Set operator to an indexed Set component (lev).

Thanks in advance.

Ampl model and pyomo code is shown below

Ampl

set T=1..7; #set of epochs
set A ordered; #set of appliances
set L; # set of energy consumption levels 
set Lev {A} within L; #set of energy consumption levels of appliance A

var x{a in A, l in Lev[a], t in T}, binary;     #1 if appliance a operates at consumption level l at epoch t 

Pyomo

model=pyo.AbstractModel()
model.T = pyo.RangeSet(1,48)
model.A=pyo.Set(ordered=True)
model.L=pyo.Set()
model.lev=pyo.Set(model.A,within=model.L)

model.y=pyo.Var(model.A,model.T,domain=pyo.Binary)
model.x=pyo.Var(model.A,model.lev,model.T,domain=pyo.Binary)

error warning

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-74-f8fe2ec9e77d> in <module>()
     10 
     11 model.y=pyo.Var(model.A,model.T,domain=pyo.Binary)
---> 12 model.x=pyo.Var(model.A,model.lev,model.T,domain=pyo.Binary)

C:\Users\HaichengLing\anaconda3\envs\nilmtk-env\lib\site-packages\pyomo\core\base\var.py in __init__(self, *args, **kwd)
    522         #
    523         kwd.setdefault('ctype', Var)
--> 524         IndexedComponent.__init__(self, *args, **kwd)
    525         #
    526         # Determine if the domain argument is a functor or other object

C:\Users\HaichengLing\anaconda3\envs\nilmtk-env\lib\site-packages\pyomo\core\base\indexed_component.py in __init__(self, *args, **kwds)
    215             # "transferred" to the model).
    216             #
--> 217             tmp = [process_setarg(x) for x in args]
    218             self._implicit_subsets = tmp
    219             self._index = tmp[0].cross(*tmp[1:])

C:\Users\HaichengLing\anaconda3\envs\nilmtk-env\lib\site-packages\pyomo\core\base\indexed_component.py in <listcomp>(.0)
    215             # "transferred" to the model).
    216             #
--> 217             tmp = [process_setarg(x) for x in args]
    218             self._implicit_subsets = tmp
    219             self._index = tmp[0].cross(*tmp[1:])

C:\Users\HaichengLing\anaconda3\envs\nilmtk-env\lib\site-packages\pyomo\core\base\set.py in process_setarg(arg)
    118         raise TypeError("Cannot apply a Set operator to an "
    119                         "indexed %s component (%s)"
--> 120                         % (arg.ctype.__name__, arg.name,))
    121     elif isinstance(arg, Component):
    122         raise TypeError("Cannot apply a Set operator to a non-Set "

TypeError: Cannot apply a Set operator to an indexed Set component (lev)

Solution

  • The easiest way to do this is to use an intermediate set:

    model.A=pyo.Set(ordered=True)
    model.L=pyo.Set()
    model.lev=pyo.Set(model.A, within=model.L)
    
    def AL_rule(m):
        return [(a,l) for a in m.A for l in m.lev[a]]
    model.AL = Set(within=model.A*model.L, initialize=AL_rule)
    
    model.x=pyo.Var(model.AL, model.T, domain=pyo.Binary)