Search code examples
pyomo

Error with xfrm.apply_to(model) in GDP, can't clone model with Set initialized


I'm trying to solve a GDP in Pyomo, when I use the command xfrm.apply_to(model) I get the following error

ERROR: Unable to clone Pyomo component attribute. Component 'Agrupacion'
contains an uncopyable field '_init_values' (<class
'pyomo.core.base.set.TuplizeValuesInitializer'>).  Setting field to `None`
on new object

File "C:\Users\Samuel\anaconda3\lib\site-packages\pyomo\core\base\var.py", line 455, in ub
ub = ub()
TypeError: 'list' object is not callable

My Agrupacion component is a Set that is initialized with the keys of a dictionary.

model.Agrupacion = Set(initialize = Agrupacion.keys())

I need this set to be initialised with these values.

Is there any way to solve this problem?

The error message says: Setting field to 'None' on new object

But I don't quite understand what it means. Does it mean that I should build an additional Set without initial values and relate it somehow to the other one, or does it simply mean that I should not set initial values to my Set Agrupacion?

Thank you for your help


Solution

  • First, your question would be significant;y easier to answer if it included a (minimal) complete example of the problem. In particular, apply_to() should be an in-place transformation and not require duplicating (cloning) the model.

    The error you are seeing is because you are initializing the Set with dict.keys(). That (Python) method returns a dict_keys object that is not deepcopyable (this is a known issue: https://github.com/Pyomo/pyomo/issues/1510). Since cloning a model is a specialized form of deepcopy, the clone() would usually fail. However, Pyomo includes special "second chance" handling when a model fails to deepcopy cleanly where it will perform the deepcopy more manually and will remove component attributes that fail, replacing them with None. The error you are seeing is warning you what just happened and giving you a hint where to look to resolve it.

    The workaround is to initialize your Set() with a list instead of a dict_keys object, e.g.:

    model.I = Set(initialize=list(a_dict.keys()))
    

    That said, the error about cloning and _init_values very likely unrelated to the exception about 'list' object is not callable. That is likely because you are somehow initializing a Var bounds to a list instead of a value, but it is really impossible to diagnose without a complete example.