pyomo
pyomo copied to clipboard
IndexedSet objects can no longer be used with the within argument in pyomo 6.7.3
Summary
Pyomo Set objects allow users to define their supersets for validation via the within argument. This used to be possible with indexed set too (objects (e.g., pyomo 6.6) but is no longer possible.
Steps to reproduce the issue
The following script can be used to reproduce the issue. I adapted the example from the website (https://pyomo.readthedocs.io/en/stable/pyomo_modeling_components/Sets.html).
import pyomo.environ as pyo
from pyomo.opt import check_available_solvers
use_within_argument = False # change to True to trigger the error
model = pyo.AbstractModel()
# non-indexed sets not using the within argument
model.Nodes = pyo.Set()
model.Arcs = pyo.Set(dimen=2)
# non-indexed sets using within argument
model.SubsetNodes = pyo.Set(within=model.Nodes)
model.SubsetArcs = pyo.Set(within=model.Arcs, dimen=2)
# indexed sets not using the within argument
model.ThingsOfArcs = pyo.Set(model.Arcs)
model.ThingsOfNodes = pyo.Set(model.Nodes)
# indexed sets using the within/not using the argument
if not use_within_argument:
# okay
model.SubsetThingsOfNodes = pyo.Set(model.Nodes)
model.SubsetThingsOfArcs = pyo.Set(model.Arcs)
else:
# fail
model.SubsetThingsOfNodes = pyo.Set(model.Nodes, within=model.ThingsOfNodes)
model.SubsetThingsOfArcs = pyo.Set(model.Arcs, within=model.ThingsOfArcs)
def NodesOut_init(m, node):
for i, j in m.Arcs:
if i == node:
yield j
model.NodesOut = pyo.Set(model.Nodes, initialize=NodesOut_init)
def NodesIn_init(m, node):
for i, j in m.Arcs:
if j == node:
yield i
model.NodesIn = pyo.Set(model.Nodes, initialize=NodesIn_init)
model.Flow = pyo.Var(model.Arcs, domain=pyo.NonNegativeReals)
model.FlowCost = pyo.Param(model.Arcs)
model.Demand = pyo.Param(model.Nodes)
model.Supply = pyo.Param(model.Nodes)
def Obj_rule(m):
return pyo.summation(m.FlowCost, m.Flow)
model.Obj = pyo.Objective(rule=Obj_rule, sense=pyo.minimize)
def FlowBalance_rule(m, node):
return m.Supply[node] \
+ sum(m.Flow[i, node] for i in m.NodesIn[node]) \
- m.Demand[node] \
- sum(m.Flow[node, j] for j in m.NodesOut[node]) \
== 0
model.FlowBalance = pyo.Constraint(model.Nodes, rule=FlowBalance_rule)
data_dict = {
None: {
'Arcs': {None: [("CityA","CityB"), ("CityA", "CityC"), ("CityC", "CityB")]},
'Nodes': {None: ["CityA", "CityB", "CityC"]},
'FlowCost': {("CityA","CityB"): 1.4, ("CityA", "CityC"): 2.7, ("CityC", "CityB"): 1.6},
'Demand': {"CityA":0, "CityB": 1, "CityC": 1},
'Supply': {"CityA": 2, "CityB": 0, "CityC": 0},
# new data
'SubsetNodes': {None: ["CityC"]},
'SubsetArcs': {None: [("CityA","CityB"),("CityC", "CityB")]},
'ThingsOfNodes': {"CityA": ['a','b','c'], "CityB": ['d', 'e', 'f'], "CityC": ['a','d']},
'ThingsOfArcs': {("CityA","CityB"): ['m','h'], ("CityA", "CityC"): ['t','g'], ("CityC", "CityB"): ['r']},
'SubsetThingsOfNodes': {"CityA": ['a','c'], "CityB": ['f'], "CityC": ['d']},
'SubsetThingsOfArcs': {("CityA","CityB"): ['h'], ("CityA", "CityC"): ['t'], ("CityC", "CityB"): ['r']},
}
}
solver_name = 'cbc'
solver_available = bool(check_available_solvers(solver_name))
if solver_available:
opt = pyo.SolverFactory(solver_name)
problem = model.create_instance(data=data_dict)
opt.solve(problem, tee=True)
Error Message
$ ERROR: Constructing component 'SubsetThingsOfNodes' from data={'CityA': ['a',
'c'], 'CityB': ['f'], 'CityC': ['d']} failed:
AttributeError: 'InsertionOrderSetData' object has no attribute
'construct'
Traceback (most recent call last):
File ~\Documents\Trabalho\Python\pyvenv\lib\site-packages\spyder_kernels\py3compat.py:356 in compat_exec
exec(code, globals, locals)
File c:\users\mend_pd\documents\trabalho\example\ptomo_sparse_set.py:112
problem = model.create_instance(data=data_dict)
File ~\Documents\Trabalho\Python\pyvenv\lib\site-packages\pyomo\core\base\PyomoModel.py:731 in create_instance
instance.load(data, namespaces=_namespaces, profile_memory=profile_memory)
File ~\Documents\Trabalho\Python\pyvenv\lib\site-packages\pyomo\core\base\PyomoModel.py:768 in load
self._load_model_data(dp, namespaces, profile_memory=profile_memory)
File ~\Documents\Trabalho\Python\pyvenv\lib\site-packages\pyomo\core\base\PyomoModel.py:820 in _load_model_data
self._initialize_component(
File ~\Documents\Trabalho\Python\pyvenv\lib\site-packages\pyomo\core\base\PyomoModel.py:868 in _initialize_component
declaration.construct(data)
File ~\Documents\Trabalho\Python\pyvenv\lib\site-packages\pyomo\core\base\set.py:2181 in construct
IndexedComponent.__getitem__(self, index)
File ~\Documents\Trabalho\Python\pyvenv\lib\site-packages\pyomo\core\base\indexed_component.py:658 in __getitem__
return self._getitem_when_not_present(index)
File ~\Documents\Trabalho\Python\pyvenv\lib\site-packages\pyomo\core\base\set.py:2221 in _getitem_when_not_present
domain.construct()
AttributeError: 'InsertionOrderSetData' object has no attribute 'construct'
Information on your system
Pyomo version: 6.7.3 Python version: 3.10.6 Operating system: Windows 10 How Pyomo was installed (PyPI, conda, source): pip Solver (if applicable): cbc, scip, etc
Additional information
I ran into this error when I upgraded to pyomo 6.7.3. The error should not be obtained with pyomo 6.6.x and earlier versions.