Search code examples
pyomocreateinstance

Pyomo Cannot iterate over abstract Set before it has been constructed


I constructed an abstract model in Pyomo and it worked well.

However, when I try to use a dictionary to instantiate the abstract model, I got the following errors "ERROR: Rule failed when generating expression for objective value: RuntimeError: Cannot iterate over abstract Set 'I' before it has been constructed (initialized)."

To be specific, here's the issue:

    from pyomo.environ import *

    model = AbstractModel()
    model.D = Set()      
    model.I = Set()                            
    model.w = Param(model.D)                   
    model.S_0 = Param(model.D) 
    model.x = Var(real_model.I, model.D) 

    def sum_cubic(m):
        return sum(w[j]*(m.x[i][j]-m.S_0[j])**3 for i in model.I for j in model.D)
    
    model.value = Objective(rule = sum_cubic, sense = maximize)
    model.pprint()

The above code runs just fine. But errors are given when I add the following codes right after it where names and S_0 are predefined dictionaries:

    data = {None:{
    'D':{None: names},
    'I':{None: list(range(1,4))},
    'w':[0.3,0.3,0.4],
    'S_0':S_0,
    }
    }
    real_model = model.create_instance(data) 

ERROR: Rule failed when generating expression for objective value: RuntimeError: Cannot iterate over abstract Set 'I' before it has been constructed (initialized). ERROR: Constructing component 'value' from data=None failed: RuntimeError: Cannot iterate over abstract Set 'I' before it has been constructed (initialized).

Could anyone help me with that? Thanks.


Solution

  • You have a couple things biting you here...

    • you are mixing m. and model. in your function, where you should be using m. because that is the self-referencing parameter of your function signature
    • you are indexing m.x incorrectly. It should be tuple-indexed (see mine)
    • your data dictionary is not set up right for the parameters. (see mine)

    Good luck!


    from pyomo.environ import *
    
    model = AbstractModel()
    model.D = Set()      
    model.I = Set()                            
    model.w = Param(model.D)                   
    model.S_0 = Param(model.D) 
    model.x = Var(model.I, model.D) 
    
    def sum_cubic(m):
        return sum(m.w[j]*(m.x[i, j]-m.S_0[j])**3 for i in m.I for j in m.D)
    
    model.value = Objective(rule = sum_cubic, sense = maximize)
    model.pprint()
    
    names=['a', 'b', 'c']
    data = {    None:{
        'D':    {None:  names},
        'I':    {None:  [1, 2, 3]},
        'w':    {'a': 0.4, 'b': 0.3, 'c': 0.2},
        'S_0':  {'a': 1.0, 'b': 2.0, 'c': 3.0} }
        }
        
    real_model = model.create_instance(data)