Skip to content

Commit

Permalink
Merge pull request #2765 from jsiirola/index-with-lists
Browse files Browse the repository at this point in the history
Bugfix: component indexes specified as lists
  • Loading branch information
blnicho authored Mar 9, 2023
2 parents a47fa92 + bdbc14e commit 87295e4
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 5 deletions.
8 changes: 3 additions & 5 deletions pyomo/core/base/indexed_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -802,10 +802,10 @@ def _processUnhashableIndex(self, idx):
# Iterate through the index and look for slices and constant
# components
#
orig_idx = idx
fixed = {}
sliced = {}
ellipsis = None
_found_numeric = False
#
# Setup the slice template (in fixed)
#
Expand Down Expand Up @@ -844,8 +844,6 @@ def _processUnhashableIndex(self, idx):
# should raise a TemplateExpressionError
try:
val = EXPR.evaluate_expression(val, constant=True)
_found_numeric = True

except TemplateExpressionError:
#
# The index is a template expression, so return the
Expand Down Expand Up @@ -937,15 +935,15 @@ def _processUnhashableIndex(self, idx):
IndexedComponent_slice._getitem_args_to_str(list(idx)),
self.name, set_dim, slice_dim))
return IndexedComponent_slice(self, fixed, sliced, ellipsis)
elif _found_numeric:
elif len(idx) == len(fixed):
if len(idx) == 1:
return fixed[0]
else:
return tuple( fixed[i] for i in range(len(idx)) )
else:
raise DeveloperError(
"Unknown problem encountered when trying to retrieve "
"index for component %s" % (self.name,) )
f"index '{orig_idx}' for component '{self.name}'")

def _getitem_when_not_present(self, index):
"""Returns/initializes a value when the index is not in the _data dict.
Expand Down
17 changes: 17 additions & 0 deletions pyomo/core/tests/unit/test_indexed.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,26 @@ def test_index_var_by_tuple_with_variables(self):
def test_index_by_unhashable_type(self):
m = ConcreteModel()
m.x = Var([1,2,3], initialize=lambda m,x: 2*x)
# Indexing by a dict raises an error
self.assertRaisesRegex(
TypeError, '.*',
m.x.__getitem__, {})
# Indexing by lists works...
# ... scalar
self.assertIs(m.x[[1]], m.x[1])
# ... "tuple"
m.y = Var([(1, 1), (1, 2)])
self.assertIs(m.y[[1, 1]], m.y[1, 1])
m.y[[1, 2]] = 5
y12 = m.y[[1, 2]]
self.assertEqual(y12.value, 5)
m.y[[1, 2]] = 15
self.assertIs(y12, m.y[[1, 2]])
self.assertEqual(y12.value, 15)
with self.assertRaisesRegex(
KeyError, r"Index '\(2, 2\)' is not valid for indexed component 'y'"):
m.y[[2, 2]] = 5


def test_ordered_keys(self):
m = ConcreteModel()
Expand Down

0 comments on commit 87295e4

Please sign in to comment.