Skip to content

Commit

Permalink
Merge branch 'main' into mbigm-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
emma58 authored Dec 21, 2023
2 parents 4f0cc01 + d5b53d5 commit 663b913
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 48 deletions.
18 changes: 11 additions & 7 deletions pyomo/core/base/range.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def __contains__(self, value):
return False

if self.step:
_dir = math.copysign(1, self.step)
_dir = int(math.copysign(1, self.step))
_from_start = value - self.start
return (
0 <= _dir * _from_start <= _dir * (self.end - self.start)
Expand Down Expand Up @@ -411,14 +411,13 @@ def _split_ranges(cnr, new_step):

assert new_step >= abs(cnr.step)
assert new_step % cnr.step == 0
_dir = math.copysign(1, cnr.step)
_dir = int(math.copysign(1, cnr.step))
_subranges = []
for i in range(int(abs(new_step // cnr.step))):
if _dir * (cnr.start + i * cnr.step) > _dir * cnr.end:
# Once we walk past the end of the range, we are done
# (all remaining offsets will be farther past the end)
break

_subranges.append(
NumericRange(cnr.start + i * cnr.step, cnr.end, _dir * new_step)
)
Expand Down Expand Up @@ -458,7 +457,7 @@ def _step_lcm(self, other_ranges):
else:
# one of the steps was 0: add to preserve the non-zero step
a += b
return abs(a)
return int(abs(a))

def _push_to_discrete_element(self, val, push_to_next_larger_value):
if not self.step or val in _infinite:
Expand Down Expand Up @@ -557,9 +556,14 @@ def range_difference(self, other_ranges):
NumericRange(t.start, start, 0, (t.closed[0], False))
)
if s.step: # i.e., not a single point
for i in range(int(start // s.step), int(end // s.step)):
for i in range(int((end - start) // s.step)):
_new_subranges.append(
NumericRange(i * s.step, (i + 1) * s.step, 0, '()')
NumericRange(
start + i * s.step,
start + (i + 1) * s.step,
0,
'()',
)
)
if t.end > end:
_new_subranges.append(
Expand Down Expand Up @@ -605,7 +609,7 @@ def range_difference(self, other_ranges):
)
elif t_max == s_max and t_c[1] and not s_c[1]:
_new_subranges.append(NumericRange(t_max, t_max, 0))
_this = _new_subranges
_this = _new_subranges
return _this

def range_intersection(self, other_ranges):
Expand Down
58 changes: 28 additions & 30 deletions pyomo/core/base/set.py
Original file line number Diff line number Diff line change
Expand Up @@ -1584,28 +1584,26 @@ def _to_0_based_index(self, item):
# implementation does not guarantee that the index is valid (it
# could be outside of abs(i) <= len(self)).
try:
if item != int(item):
raise IndexError(
"%s indices must be integers, not %s"
% (self.name, type(item).__name__)
)
item = int(item)
_item = int(item)
if item != _item:
raise IndexError()
except:
raise IndexError(
"%s indices must be integers, not %s" % (self.name, type(item).__name__)
)

if item >= 1:
return item - 1
elif item < 0:
item += len(self)
if item < 0:
raise IndexError("%s index out of range" % (self.name,))
return item
f"Set '{self.name}' positional indices must be integers, "
f"not {type(item).__name__}"
) from None

if _item >= 1:
return _item - 1
elif _item < 0:
_item += len(self)
if _item < 0:
raise IndexError(f"{self.name} index out of range")
return _item
else:
raise IndexError(
"Pyomo Sets are 1-indexed: valid index values for Sets are "
"[1 .. len(Set)] or [-1 .. -len(Set)]"
"Accessing Pyomo Sets by position is 1-based: valid Set positional "
"index values are [1 .. len(Set)] or [-1 .. -len(Set)]"
)


Expand Down Expand Up @@ -1683,7 +1681,7 @@ def at(self, index):
try:
return self._ordered_values[i]
except IndexError:
raise IndexError("%s index out of range" % (self.name))
raise IndexError(f"{self.name} index out of range") from None

def ord(self, item):
"""
Expand Down Expand Up @@ -2023,7 +2021,7 @@ def __init__(
filter=None,
validate=None,
name=None,
doc=None
doc=None,
):
...

Expand Down Expand Up @@ -2545,7 +2543,7 @@ def at(self, index):
try:
return self._ref[i]
except IndexError:
raise IndexError("%s index out of range" % (self.name))
raise IndexError(f"{self.name} index out of range") from None

def ord(self, item):
# The bulk of single-value set members are stored as scalars.
Expand Down Expand Up @@ -2686,7 +2684,7 @@ def at(self, index):
if not idx:
return ans
idx -= 1
raise IndexError("%s index out of range" % (self.name,))
raise IndexError(f"{self.name} index out of range")

def ord(self, item):
if len(self._ranges) == 1:
Expand Down Expand Up @@ -2861,7 +2859,7 @@ def __init__(
filter=None,
validate=None,
name=None,
doc=None
doc=None,
):
...

Expand All @@ -2878,7 +2876,7 @@ def __init__(
filter=None,
validate=None,
name=None,
doc=None
doc=None,
):
...

Expand All @@ -2892,7 +2890,7 @@ def __init__(
filter=None,
validate=None,
name=None,
doc=None
doc=None,
):
...

Expand Down Expand Up @@ -3505,7 +3503,7 @@ def at(self, index):
if val not in self._sets[0]:
idx -= 1
except StopIteration:
raise IndexError("%s index out of range" % (self.name,))
raise IndexError(f"{self.name} index out of range") from None
return val

def ord(self, item):
Expand Down Expand Up @@ -3642,7 +3640,7 @@ def at(self, index):
idx -= 1
return next(_iter)
except StopIteration:
raise IndexError("%s index out of range" % (self.name,))
raise IndexError(f"{self.name} index out of range") from None

def ord(self, item):
"""
Expand Down Expand Up @@ -3736,7 +3734,7 @@ def at(self, index):
idx -= 1
return next(_iter)
except StopIteration:
raise IndexError("%s index out of range" % (self.name,))
raise IndexError(f"{self.name} index out of range") from None

def ord(self, item):
"""
Expand Down Expand Up @@ -3846,7 +3844,7 @@ def at(self, index):
idx -= 1
return next(_iter)
except StopIteration:
raise IndexError("%s index out of range" % (self.name,))
raise IndexError(f"{self.name} index out of range") from None

def ord(self, item):
"""
Expand Down Expand Up @@ -4128,7 +4126,7 @@ def at(self, index):
i -= 1
_ord[i], _idx = _idx % _ord[i], _idx // _ord[i]
if _idx:
raise IndexError("%s index out of range" % (self.name,))
raise IndexError(f"{self.name} index out of range")
ans = tuple(s.at(i + 1) for s, i in zip(self._sets, _ord))
if FLATTEN_CROSS_PRODUCT and normalize_index.flatten and self.dimen != len(ans):
return self._flatten_product(ans)
Expand Down
50 changes: 40 additions & 10 deletions pyomo/core/tests/unit/test_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -1530,8 +1530,8 @@ def test_ordered_setof(self):
self.assertEqual(i[-1], 0)
with self.assertRaisesRegex(
IndexError,
"valid index values for Sets are "
r"\[1 .. len\(Set\)\] or \[-1 .. -len\(Set\)\]",
"Accessing Pyomo Sets by position is 1-based: valid Set positional "
r"index values are \[1 .. len\(Set\)\] or \[-1 .. -len\(Set\)\]",
):
i[0]
with self.assertRaisesRegex(IndexError, "OrderedSetOf index out of range"):
Expand Down Expand Up @@ -1589,8 +1589,8 @@ def test_ordered_setof(self):
self.assertEqual(i[-1], 0)
with self.assertRaisesRegex(
IndexError,
"valid index values for Sets are "
r"\[1 .. len\(Set\)\] or \[-1 .. -len\(Set\)\]",
"Accessing Pyomo Sets by position is 1-based: valid Set positional "
r"index values are \[1 .. len\(Set\)\] or \[-1 .. -len\(Set\)\]",
):
i[0]
with self.assertRaisesRegex(IndexError, "OrderedSetOf index out of range"):
Expand Down Expand Up @@ -1752,8 +1752,8 @@ def test_ord_index(self):
self.assertEqual(r[i + 1], v)
with self.assertRaisesRegex(
IndexError,
"valid index values for Sets are "
r"\[1 .. len\(Set\)\] or \[-1 .. -len\(Set\)\]",
"Accessing Pyomo Sets by position is 1-based: valid Set positional "
r"index values are \[1 .. len\(Set\)\] or \[-1 .. -len\(Set\)\]",
):
r[0]
with self.assertRaisesRegex(
Expand All @@ -1769,8 +1769,8 @@ def test_ord_index(self):
self.assertEqual(r[i + 1], v)
with self.assertRaisesRegex(
IndexError,
"valid index values for Sets are "
r"\[1 .. len\(Set\)\] or \[-1 .. -len\(Set\)\]",
"Accessing Pyomo Sets by position is 1-based: valid Set positional "
r"index values are \[1 .. len\(Set\)\] or \[-1 .. -len\(Set\)\]",
):
r[0]
with self.assertRaisesRegex(
Expand Down Expand Up @@ -2647,6 +2647,34 @@ def test_infinite_setdifference(self):
list(RangeSet(ranges=[NR(0, 2, 0, (True, False))]).ranges()),
)

x = RangeSet(0, 6, 0) - RangeSet(1, 5, 2)
self.assertIs(type(x), SetDifference_InfiniteSet)
self.assertFalse(x.isfinite())
self.assertFalse(x.isordered())

self.assertIn(0, x)
self.assertNotIn(1, x)
self.assertIn(2, x)
self.assertNotIn(3, x)
self.assertIn(4, x)
self.assertNotIn(5, x)
self.assertIn(6, x)
self.assertNotIn(7, x)

self.assertEqual(
list(x.ranges()),
list(
RangeSet(
ranges=[
NR(0, 1, 0, (True, False)),
NR(1, 3, 0, (False, False)),
NR(3, 5, 0, (False, False)),
NR(5, 6, 0, (False, True)),
]
).ranges()
),
)


class TestSetSymmetricDifference(unittest.TestCase):
def test_pickle(self):
Expand Down Expand Up @@ -4191,10 +4219,12 @@ def test_indexing(self):
m.I = [1, 3, 2]
self.assertEqual(m.I[2], 3)
with self.assertRaisesRegex(
IndexError, "I indices must be integers, not float"
IndexError, "Set 'I' positional indices must be integers, not float"
):
m.I[2.5]
with self.assertRaisesRegex(IndexError, "I indices must be integers, not str"):
with self.assertRaisesRegex(
IndexError, "Set 'I' positional indices must be integers, not str"
):
m.I['a']

def test_add_filter_validate(self):
Expand Down
4 changes: 3 additions & 1 deletion pyomo/core/tests/unit/test_sets.py
Original file line number Diff line number Diff line change
Expand Up @@ -3395,7 +3395,9 @@ def test_getitem(self):
with self.assertRaisesRegex(RuntimeError, ".*before it has been constructed"):
a[0]
a.construct()
with self.assertRaisesRegex(IndexError, "Pyomo Sets are 1-indexed"):
with self.assertRaisesRegex(
IndexError, "Accessing Pyomo Sets by position is 1-based"
):
a[0]
self.assertEqual(a[1], 2)

Expand Down

0 comments on commit 663b913

Please sign in to comment.