Repository: Pyomo/pyomo

Issue:
Indexing error
Hi, when trying to add an extra constraint I get the following error:
raise DeveloperError(
pyomo.common.errors.DeveloperError: Internal Pyomo implementation error:
        'Unknown problem encountered when trying to retrieve index for component assign_to_open_cstr'
        Please report this to the Pyomo Developers.

This happens due to the following code:
m.travel_pairs = pyo.Set(initialize=[(i, j) for i in m.set1 for j in m.set2])
m.assign_to_open_cstr = pyo.Constraint(m.pairs, rule=assign_to_open_cstr)
And then later I try to add constraints: 
for (i,j) in new_pairs:
        m.assign_to_open_cstr.add(expr=assign_to_open_cstr(m,i,j), index=[i,j])

I think the way I format the index might just be wrong, but since the error told me to report this, this what I am doing. 


Discussion:

Resolving patch:
diff --git a/pyomo/core/base/indexed_component.py b/pyomo/core/base/indexed_component.py
--- a/pyomo/core/base/indexed_component.py
+++ b/pyomo/core/base/indexed_component.py
@@ -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)
         #
@@ -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
@@ -937,7 +935,7 @@ 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:
@@ -945,7 +943,7 @@ def _processUnhashableIndex(self, 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.


Test patch:
diff --git a/pyomo/core/tests/unit/test_indexed.py b/pyomo/core/tests/unit/test_indexed.py
--- a/pyomo/core/tests/unit/test_indexed.py
+++ b/pyomo/core/tests/unit/test_indexed.py
@@ -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()