Repository: Pyomo/pyomo

Issue:
Multiplying Virtual Sets causes the original Set to be modified
Multiplying a Virtual Set by itself produces the desired resulting set, but also causes the original Set to become crossed with itself.

In the following example, note that the Virtual Set `m.IJ` goes from 9 to 81 elements, and that the members are 4-tuples instead of 2-tuples (even though the Set `Dimen` flag is not updated).

```python
>>> from pyomo.environ import *
>>> m = ConcreteModel()
>>> m.I = Set(initialize=[1,2,3])
>>> m.J = Set(initialize=[4,5,6])
>>> m.IJ = m.I * m.J
>>> m.IJ.display()
IJ : Dim=0, Dimen=2, Size=9, Domain=None, Ordered=False, Bounds=None
    Virtual
>>> m.IJ2 = m.IJ * m.IJ
>>> m.IJ.display()
IJ : Dim=0, Dimen=2, Size=81, Domain=None, Ordered=False, Bounds=None
    Virtual
>>> m.IJ2.display()
IJ2 : Dim=0, Dimen=4, Size=81, Domain=None, Ordered=False, Bounds=None
    Virtual
>>> [x for x in m.IJ]
[(1, 4, 1, 4), (1, 4, 1, 5), (1, 4, 1, 6), (1, 4, 2, 4), (1, 4, 2, 5), (1, 4, 2, 6), (1, 4, 3, 4), (1, 4, 3, 5), (1, 4, 3, 6), (1, 5, 1, 4), (1, 5, 1, 5), (1, 5, 1, 6), (1, 5, 2, 4), (1, 5, 2, 5), (1, 5, 2, 6), (1, 5, 3, 4), (1, 5, 3, 5), (1, 5, 3, 6), (1, 6, 1, 4), (1, 6, 1, 5), (1, 6, 1, 6), (1, 6, 2, 4), (1, 6, 2, 5), (1, 6, 2, 6), (1, 6, 3, 4), (1, 6, 3, 5), (1, 6, 3, 6), (2, 4, 1, 4), (2, 4, 1, 5), (2, 4, 1, 6), (2, 4, 2, 4), (2, 4, 2, 5), (2, 4, 2, 6), (2, 4, 3, 4), (2, 4, 3, 5), (2, 4, 3, 6), (2, 5, 1, 4), (2, 5, 1, 5), (2, 5, 1, 6), (2, 5, 2, 4), (2, 5, 2, 5), (2, 5, 2, 6), (2, 5, 3, 4), (2, 5, 3, 5), (2, 5, 3, 6), (2, 6, 1, 4), (2, 6, 1, 5), (2, 6, 1, 6), (2, 6, 2, 4), (2, 6, 2, 5), (2, 6, 2, 6), (2, 6, 3, 4), (2, 6, 3, 5), (2, 6, 3, 6), (3, 4, 1, 4), (3, 4, 1, 5), (3, 4, 1, 6), (3, 4, 2, 4), (3, 4, 2, 5), (3, 4, 2, 6), (3, 4, 3, 4), (3, 4, 3, 5), (3, 4, 3, 6), (3, 5, 1, 4), (3, 5, 1, 5), (3, 5, 1, 6), (3, 5, 2, 4), (3, 5, 2, 5), (3, 5, 2, 6), (3, 5, 3, 4), (3, 5, 3, 5), (3, 5, 3, 6), (3, 6, 1, 4), (3, 6, 1, 5), (3, 6, 1, 6), (3, 6, 2, 4), (3, 6, 2, 5), (3, 6, 2, 6), (3, 6, 3, 4), (3, 6, 3, 5), (3, 6, 3, 6)]
```

This bug was reported on the [pyomo-forum](https://groups.google.com/d/msg/pyomo-forum/RSBD6QNV8n4/ZqT2_CIWAwAJ)
Multiplying Virtual Sets causes the original Set to be modified
Multiplying a Virtual Set by itself produces the desired resulting set, but also causes the original Set to become crossed with itself.

In the following example, note that the Virtual Set `m.IJ` goes from 9 to 81 elements, and that the members are 4-tuples instead of 2-tuples (even though the Set `Dimen` flag is not updated).

```python
>>> from pyomo.environ import *
>>> m = ConcreteModel()
>>> m.I = Set(initialize=[1,2,3])
>>> m.J = Set(initialize=[4,5,6])
>>> m.IJ = m.I * m.J
>>> m.IJ.display()
IJ : Dim=0, Dimen=2, Size=9, Domain=None, Ordered=False, Bounds=None
    Virtual
>>> m.IJ2 = m.IJ * m.IJ
>>> m.IJ.display()
IJ : Dim=0, Dimen=2, Size=81, Domain=None, Ordered=False, Bounds=None
    Virtual
>>> m.IJ2.display()
IJ2 : Dim=0, Dimen=4, Size=81, Domain=None, Ordered=False, Bounds=None
    Virtual
>>> [x for x in m.IJ]
[(1, 4, 1, 4), (1, 4, 1, 5), (1, 4, 1, 6), (1, 4, 2, 4), (1, 4, 2, 5), (1, 4, 2, 6), (1, 4, 3, 4), (1, 4, 3, 5), (1, 4, 3, 6), (1, 5, 1, 4), (1, 5, 1, 5), (1, 5, 1, 6), (1, 5, 2, 4), (1, 5, 2, 5), (1, 5, 2, 6), (1, 5, 3, 4), (1, 5, 3, 5), (1, 5, 3, 6), (1, 6, 1, 4), (1, 6, 1, 5), (1, 6, 1, 6), (1, 6, 2, 4), (1, 6, 2, 5), (1, 6, 2, 6), (1, 6, 3, 4), (1, 6, 3, 5), (1, 6, 3, 6), (2, 4, 1, 4), (2, 4, 1, 5), (2, 4, 1, 6), (2, 4, 2, 4), (2, 4, 2, 5), (2, 4, 2, 6), (2, 4, 3, 4), (2, 4, 3, 5), (2, 4, 3, 6), (2, 5, 1, 4), (2, 5, 1, 5), (2, 5, 1, 6), (2, 5, 2, 4), (2, 5, 2, 5), (2, 5, 2, 6), (2, 5, 3, 4), (2, 5, 3, 5), (2, 5, 3, 6), (2, 6, 1, 4), (2, 6, 1, 5), (2, 6, 1, 6), (2, 6, 2, 4), (2, 6, 2, 5), (2, 6, 2, 6), (2, 6, 3, 4), (2, 6, 3, 5), (2, 6, 3, 6), (3, 4, 1, 4), (3, 4, 1, 5), (3, 4, 1, 6), (3, 4, 2, 4), (3, 4, 2, 5), (3, 4, 2, 6), (3, 4, 3, 4), (3, 4, 3, 5), (3, 4, 3, 6), (3, 5, 1, 4), (3, 5, 1, 5), (3, 5, 1, 6), (3, 5, 2, 4), (3, 5, 2, 5), (3, 5, 2, 6), (3, 5, 3, 4), (3, 5, 3, 5), (3, 5, 3, 6), (3, 6, 1, 4), (3, 6, 1, 5), (3, 6, 1, 6), (3, 6, 2, 4), (3, 6, 2, 5), (3, 6, 2, 6), (3, 6, 3, 4), (3, 6, 3, 5), (3, 6, 3, 6)]
```

This bug was reported on the [pyomo-forum](https://groups.google.com/d/msg/pyomo-forum/RSBD6QNV8n4/ZqT2_CIWAwAJ)


Discussion:

Resolving patch:
diff --git a/pyomo/core/base/sets.py b/pyomo/core/base/sets.py
--- a/pyomo/core/base/sets.py
+++ b/pyomo/core/base/sets.py
@@ -1544,7 +1544,7 @@ def __init__(self, *args, **kwd):
         _SetOperator.__init__(self, *args, **kwd)
         # the individual index sets definining the product set.
         if isinstance(self._setA,_SetProduct):
-            self.set_tuple = self._setA.set_tuple
+            self.set_tuple = list(self._setA.set_tuple)
         else:
             self.set_tuple = [self._setA]
         if isinstance(self._setB,_SetProduct):


Test patch: