Skip to content

Commit

Permalink
Merge pull request #3063 from jsiirola/fix-range-diff
Browse files Browse the repository at this point in the history
Fix `range_difference` for Sets with nonzero anchor points
  • Loading branch information
blnicho authored Dec 19, 2023
2 parents dbff7d1 + da8da5a commit d5b53d5
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 7 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
28 changes: 28 additions & 0 deletions pyomo/core/tests/unit/test_set.py
Original file line number Diff line number Diff line change
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

0 comments on commit d5b53d5

Please sign in to comment.