def test_with_adjacent(self): assert P.closed(1, 2) | P.closed(2, 3) == P.closed(1, 3) assert P.closed(1, 2) | P.open(2, 3) == P.closedopen(1, 3) assert P.open(1, 2) | P.closed(2, 3) == P.openclosed(1, 3) assert P.open(1, 3) | P.open(2, 4) == P.open(1, 4) assert P.closedopen(1, 2) | P.closed(2, 3) == P.closed(1, 3) assert P.open(1, 2) | P.closed(2, 4) == P.openclosed(1, 4)
def test_combine_nonempty(self): add = lambda x, y: x + y d1 = P.IntervalDict([(P.closed(1, 3) | P.closed(5, 7), 1)]) d2 = P.IntervalDict([(P.closed(2, 4) | P.closed(6, 8), 2)]) assert d1.combine(d2, add) == d2.combine(d1, add) assert d1.combine(d2, add) == P.IntervalDict([ (P.closedopen(1, 2) | P.closedopen(5, 6), 1), (P.closed(2, 3) | P.closed(6, 7), 3), (P.openclosed(3, 4) | P.openclosed(7, 8), 2), ]) d1 = P.IntervalDict({ P.closed(0, 1): 2, P.closed(3, 4): 2 }) d2 = P.IntervalDict({ P.closed(1, 3): 3, P.closed(4, 5): 1 }) assert d1.combine(d2, add) == d2.combine(d1, add) assert d1.combine(d2, add) == P.IntervalDict({ P.closedopen(0, 1): 2, P.singleton(1): 5, P.open(1, 3): 3, P.singleton(3): 5, P.open(3, 4): 2, P.singleton(4): 3, P.openclosed(4, 5): 1, })
def test_nonatomic_interval(self): assert (P.closed(0, 1) | P.closed(2, 3)).adjacent(P.open(1, 2)) assert P.open(1, 2).adjacent(P.closed(0, 1) | P.closed(2, 3)) assert not (P.closed(0, 1) | P.closed(2, 3)).adjacent(P.closed(1, 2)) assert (P.closedopen(0, 1) | P.openclosed( 2, 3)).adjacent(P.open(-1, 0) | P.closed(1, 2) | P.openclosed(3, 4))
def test_parameters(self): i1, i2, i3, i4 = P.closed(0, 1), P.openclosed(0, 1), P.closedopen(0, 1), P.open(0, 1) params = { 'disj': ' or ', 'sep': '-', 'left_open': '<!', 'left_closed': '<', 'right_open': '!>', 'right_closed': '>', 'conv': lambda s: '"{}"'.format(s), 'pinf': '+oo', 'ninf': '-oo', } assert P.to_string(i1, **params) == '<"0"-"1">' assert P.to_string(i2, **params) == '<!"0"-"1">' assert P.to_string(i3, **params) == '<"0"-"1"!>' assert P.to_string(i4, **params) == '<!"0"-"1"!>' assert P.to_string(P.empty(), **params) == '<!!>' assert P.to_string(P.singleton(1), **params) == '<"1">' assert P.to_string(P.openclosed(-P.inf, 1), **params) == '<!-oo-"1">' assert P.to_string(P.closedopen(1, P.inf), **params) == '<"1"-+oo!>' assert P.to_string(P.closed(0, 1) | P.closed(2, 3), **params) == '<"0"-"1"> or <"2"-"3">'
def test_parameters(self): i1, i2, i3, i4 = '<"0"-"1">', '<!"0"-"1">', '<"0"-"1"!>', '<!"0"-"1"!>' params = { 'conv': lambda s: int(s[1:-1]), 'disj': ' or ', 'sep': '-', 'left_open': '<!', 'left_closed': '<', 'right_open': '!>', 'right_closed': '>', 'pinf': r'\+oo', 'ninf': '-oo', } assert P.from_string(i1, **params) == P.closed(0, 1) assert P.from_string(i2, **params) == P.openclosed(0, 1) assert P.from_string(i3, **params) == P.closedopen(0, 1) assert P.from_string(i4, **params) == P.open(0, 1) assert P.from_string('<!!>', **params) == P.empty() assert P.from_string('<"1">', **params) == P.singleton(1) assert P.from_string('<!-oo-"1">', **params) == P.openclosed(-P.inf, 1) assert P.from_string('<"1"-+oo!>', **params) == P.closedopen(1, P.inf) assert P.from_string('<"0"-"1"> or <"2"-"3">', **params) == P.closed(0, 1) | P.closed(2, 3)
def step(mover: int, pivot: int, stick_rate: float): # find available places around pivot nears = calc_near(pivot) available = portion.openclosed(-np.pi, np.pi) for near in nears: if near != mover: dist = distance(circles[pivot], circles[near]) angl = angle(circles[pivot], circles[near]) var = np.arccos(dist / 2) left = angl - var right = angl + var if left <= -np.pi: occupied = portion.open(-np.pi, right) | portion.openclosed( left + 2 * np.pi, np.pi) elif right > np.pi: occupied = portion.openclosed(left, np.pi) | portion.open( -np.pi, right - 2 * np.pi) else: occupied = portion.open(left, right) available -= occupied if available.empty: print("Void step. No available space next to the pivot.") return circles[mover] # stick: move mover to a place sticking to an obstacle. Notice when only 1 circle around pivot stick is not doable. if np.random.rand() < stick_rate: stick_angles = [] for interval in available._intervals: stick_angles.append(interval.lower) stick_angles.append(interval.upper) if available.enclosure == portion.openclosed(-np.pi, np.pi): stick_angles.remove(-np.pi) stick_angles.remove(np.pi) if len(stick_angles) == 0: print("Not doable.") return circles[mover] stick_angle = stick_angles[np.random.randint(len(stick_angles))] return circles[pivot][0] + np.cos( stick_angle), circles[pivot][1] + np.sin(stick_angle) # non-stick: uniformly pick angle from all available angle intervals else: # available is 1 interval if available.atomic: stick_angle = available.lower + np.random.rand() * ( available.upper - available.lower) return circles[pivot][0] + np.cos( stick_angle), circles[pivot][1] + np.sin(stick_angle) # available is union of 2 intervals else: stick_angle = available.lower + np.random.rand() * \ (available._intervals[0].upper - available._intervals[0].lower + available._intervals[1].upper - available._intervals[1].lower) if stick_angle > available._intervals[0].upper: stick_angle += (available._intervals[1].lower - available._intervals[0].upper) return circles[pivot][0] + np.cos( stick_angle), circles[pivot][1] + np.sin(stick_angle) pass
def test_with_smaller(self): assert P.closed(0, 4) - P.closed(2, 3) == P.closedopen( 0, 2) | P.openclosed(3, 4) assert P.closed(1, 4) - P.closed(1, 3) == P.openclosed(3, 4) assert P.closed(1, 4) - P.closed(2, 4) == P.closedopen(1, 2) assert P.closed(0, 4) - P.open(1, 2) == P.closed(0, 1) | P.closed(2, 4) assert P.closed(0, 2) - P.open(0, 2) == P.singleton(0) | P.singleton(2)
def test_pop_interval(self): d = P.IntervalDict([(P.closed(0, 3), 0)]) t = d.pop(P.closed(0, 1)) assert t.as_dict() == {P.closed(0, 1): 0} assert d.as_dict() == {P.openclosed(1, 3): 0} t = d.pop(P.closed(0, 2), 1) assert t.as_dict() == {P.closed(0, 1): 1, P.openclosed(1, 2): 0} assert d.as_dict() == {P.openclosed(2, 3): 0}
def test_pop_interval(self): d = P.IntervalDict([(P.closed(0, 3), 0)]) t = d.pop(P.closed(0, 1)) assert t.items() == [(P.closed(0, 1), 0)] assert d.items() == [(P.openclosed(1, 3), 0)] t = d.pop(P.closed(0, 2), 1) assert t.items() == [(P.closed(0, 1), 1), (P.openclosed(1, 2), 0)] assert d.items() == [(P.openclosed(2, 3), 0)]
def test_overlaps_with_edge_cases(self): assert not P.closed(0, 1).overlaps(P.open(1, 2)) assert not P.closed(0, 1).overlaps(P.openclosed(1, 2)) assert not P.closedopen(0, 1).overlaps(P.closed(1, 2)) assert not P.closedopen(0, 1).overlaps(P.closedopen(1, 2)) assert not P.closedopen(0, 1).overlaps(P.openclosed(1, 2)) assert not P.closedopen(0, 1).overlaps(P.open(1, 2)) assert not P.open(0, 1).overlaps(P.open(1, 2)) assert P.open(0, 2).overlaps(P.open(0, 1)) assert P.open(0, 1).overlaps(P.open(0, 2))
def test_overlapping(self): assert not P.openclosed(0, 2).adjacent(P.closedopen(2, 3)) assert not P.closed(0, 2).adjacent(P.closedopen(2, 3)) assert not P.closed(0, 2).adjacent(P.closed(2, 3)) assert not P.open(0, 2).adjacent(P.open(2, 3)) assert not P.closedopen(2, 3).adjacent(P.openclosed(0, 2)) assert not P.closedopen(2, 3).adjacent(P.closed(0, 2)) assert not P.closed(2, 3).adjacent(P.closed(0, 2)) assert not P.open(2, 3).adjacent(P.open(0, 2))
def test_replace_with_union(self): i = P.closed(0, 1) | P.open(2, 3) assert i.replace() == i assert i.replace(P.OPEN, -1, 4, P.OPEN) == P.openclosed(-1, 1) | P.open(2, 4) assert i.replace(lower=2) == P.closedopen(2, 3) assert i.replace(upper=1) == P.closedopen(0, 1) assert i.replace(lower=5) == P.empty() assert i.replace(upper=-5) == P.empty() assert i.replace( left=lambda v: ~v, lower=lambda v: v - 1, upper=lambda v: v + 1, right=lambda v: ~v) == P.openclosed(-1, 1) | P.openclosed(2, 4)
def I_mid(X): i = l_m j = 2*l_m I = list(p.iterate(p.openclosed(X[i], X[j]), step=step)) while j == dt is False: i = 2*i j = 2*j I = I.append(list(p.iterate(p.openclosed(X[i], X[j]), step=step))) else: pass return I
def test_contained(self): assert not P.closed(0, 4).adjacent(P.closed(0, 2)) assert not P.closed(0, 4).adjacent(P.closed(2, 4)) assert not P.closed(0, 4).adjacent(P.open(0, 2)) assert not P.closed(0, 4).adjacent(P.open(2, 4)) assert not P.closed(0, 2).adjacent(P.closed(0, 4)) assert not P.closed(2, 4).adjacent(P.closed(0, 4)) assert not P.closed(0, 2).adjacent(P.open(0, 4)) assert not P.closed(2, 4).adjacent(P.open(0, 4)) assert not P.closed(0, 2).adjacent(P.closed(0, 2)) assert not P.open(0, 2).adjacent(P.open(0, 2)) assert not P.openclosed(0, 2).adjacent(P.openclosed(0, 2)) assert not P.closedopen(0, 2).adjacent(P.closedopen(0, 2))
class TestIntervalComplement: def test_singleton(self): assert ~P.singleton(0) == P.open(-P.inf, 0) | P.open(0, P.inf) assert ~(P.open(-P.inf, 0) | P.open(0, P.inf)) == P.singleton(0) def test_nonempty(self): assert ~P.closed(1, 2) == P.open(-P.inf, 1) | P.open(2, P.inf) assert ~P.open(1, 2) == P.openclosed(-P.inf, 1) | P.closedopen(2, P.inf) def test_union(self): assert ~(P.singleton(0) | P.singleton(5) | P.singleton(10)) == P.open(-P.inf, 0) | P.open(0, 5) | P.open(5, 10) | P.open(10, P.inf) assert ~(P.open(0, 1) | P.closed(2, 3) | P.open(4, 5)) == P.openclosed(-P.inf, 0) | P.closedopen(1, 2) | P.openclosed(3, 4) | P.closedopen(5, P.inf) @pytest.mark.parametrize('i', [P.closed(0, 1), P.open(0, 1), P.openclosed(0, 1), P.closedopen(0, 1)]) def test_identity(self, i): for interval in i: assert ~(~interval) == interval def test_empty(self): assert ~P.open(1, 1) == P.open(-P.inf, P.inf) assert (~P.closed(-P.inf, P.inf)).empty assert ~P.empty() == P.open(-P.inf, P.inf) def test_proxy_method(self): i1, i2 = P.closed(0, 1), P.closed(2, 3) assert ~i1 == i1.complement() assert ~i2 == i2.complement()
def test_is_empty(self): assert P.openclosed(1, 1).empty assert P.closedopen(1, 1).empty assert P.open(1, 1).empty assert not P.closed(1, 1).empty assert P.Interval().empty assert P.empty().empty
def check_state(self): # print("CHECK_STATE") all_ancestry = [] num_nodes = len(self.A_head) for j in range(num_nodes): head = self.A_head[j] tail = self.A_tail[j] if head is None: assert tail is None else: x = head while x.next is not None: assert x.right <= x.next.left x = x.next assert x == tail x = head while x is not None: assert x.left < x.right all_ancestry.append(portion.openclosed(x.left, x.right)) if x.next is not None: assert x.right <= x.next.left # We should also not have any squashable segments. if x.right == x.next.left: assert x.node != x.next.node x = x.next # Make sure we haven't lost ancestry. if len(all_ancestry) > 0: union = all_ancestry[0] for interval in all_ancestry[1:]: union = union.union(interval) assert union.atomic assert union.lower == 0 assert union.upper == self.sequence_length
def test_identity(self): i1, i2, i3, i4 = P.closed(0, 1), P.openclosed(0, 1), P.closedopen(0, 1), P.open(0, 1) assert P.from_data(P.to_data(i2)) == i2 assert P.from_data(P.to_data(i3)) == i3 assert P.from_data(P.to_data(i4)) == i4 assert P.from_data(P.to_data(i1)) == i1
def test_open_intervals(self): assert P.from_data([(P.OPEN, float('-inf'), float('inf'), P.OPEN) ]) == P.open(-P.inf, P.inf) assert P.from_data([(P.OPEN, float('-inf'), 0, P.CLOSED) ]) == P.openclosed(-P.inf, 0) assert P.from_data([(P.CLOSED, 0, float('inf'), P.OPEN) ]) == P.closedopen(0, P.inf)
def test_identity(self): i1, i2, i3, i4 = P.closed(0, 1), P.openclosed(0, 1), P.closedopen(0, 1), P.open(0, 1) assert P.from_string(P.to_string(i1), int) == i1 assert P.from_string(P.to_string(i2), int) == i2 assert P.from_string(P.to_string(i3), int) == i3 assert P.from_string(P.to_string(i4), int) == i4
def test_open_intervals(self): assert P.to_data(P.open(-P.inf, P.inf)) == [(False, float('-inf'), float('inf'), False)] assert P.to_data(P.openclosed(-P.inf, 0)) == [(False, float('-inf'), 0, True)] assert P.to_data(P.closedopen(0, P.inf)) == [(True, 0, float('inf'), False)]
def test_reversed_iteration_with_open_intervals(self): with pytest.raises(ValueError): list(P.iterate(P.closedopen(0, P.inf), step=-1, reverse=True)) gen = P.iterate(P.openclosed(-P.inf, 0), step=-1, reverse=True) assert next(gen) == 0 assert next(gen) == -1 assert next(gen) == -2 # and so on
def test_open_intervals(self): with pytest.raises(ValueError): list(P.iterate(P.openclosed(-P.inf, 2), step=1)) gen = P.iterate(P.closedopen(0, P.inf), step=1) assert next(gen) == 0 assert next(gen) == 1 assert next(gen) == 2 # and so on
def test_bounds(self): assert P.closed(0, 1) == P.Interval.from_atomic(P.CLOSED, 0, 1, P.CLOSED) assert P.open(0, 1) == P.Interval.from_atomic(P.OPEN, 0, 1, P.OPEN) assert P.openclosed(0, 1) == P.Interval.from_atomic( P.OPEN, 0, 1, P.CLOSED) assert P.closedopen(0, 1) == P.Interval.from_atomic( P.CLOSED, 0, 1, P.OPEN) assert P.singleton(2) == P.closed(2, 2)
def test_issue_13(self): # https://github.com/AlexandreDecan/python-intervals/issues/13 assert P.closed(1, 1) | P.openclosed(1, 2) == P.closed(1, 2) assert P.openclosed(1, 2) | P.closed(1, 1) == P.closed(1, 2) assert P.closed(0, 1) | P.openclosed(1, 2) == P.closed(0, 2) assert P.openclosed(1, 2) | P.closed(0, 1) == P.closed(0, 2) assert P.openclosed(1, 2) | P.closed(1, 1) == P.closed(1, 2) assert P.closed(1, 1) | P.openclosed(1, 2) == P.closed(1, 2) assert P.openclosed(1, 2) | P.closed(0, 1) == P.closed(0, 2) assert P.closed(0, 1) | P.openclosed(1, 2) == P.closed(0, 2)
def test_empty(self): assert P.empty() == P.Interval.from_atomic(P.OPEN, P.inf, -P.inf, P.open) assert P.closed(3, -3) == P.empty() assert P.openclosed(0, 0) == P.empty() assert P.closedopen(0, 0) == P.empty() assert P.open(0, 0) == P.empty() assert P.closed(0, 0) != P.empty() assert P.singleton(P.inf) == P.empty() assert P.singleton(-P.inf) == P.empty()
def test_hash_with_hashable(self): assert hash(P.closed(0, 1)) is not None assert hash(P.closed(0, 1)) != hash(P.closed(1, 2)) assert hash(P.openclosed(-P.inf, 0)) is not None assert hash(P.closedopen(0, P.inf)) is not None assert hash(P.empty()) is not None assert hash(P.closed(0, 1) | P.closed(3, 4)) is not None assert hash(P.closed(0, 1) | P.closed(3, 4)) != hash(P.closed(0, 1)) assert hash(P.closed(0, 1) | P.closed(3, 4)) != hash(P.closed(3, 4))
def test_with_unions(self): assert P.closed(0, 1) | P.closed(2, 3) in P.closed(0, 4) assert P.closed(0, 1) | P.closed(2, 3) in P.closed(0, 1) | P.closed( 2, 3) assert P.closed(0, 1) | P.closed(2, 3) in P.closed(0, 0) | P.closed( 0, 1) | P.closed(2, 3) assert P.closed(0, 1) | P.closed(2, 3) not in P.closed(0, 2) assert P.closed(0, 1) | P.closed(2, 3) not in P.closed( 0, 1) | P.closedopen(2, 3) assert P.closed(0, 1) | P.closed(2, 3) not in P.closed( 0, 1) | P.closedopen(2, 3) | P.openclosed(3, 4)
def test_copy_and_update(self): d = P.IntervalDict({P.closed(0, 2): 0, P.closed(4, 5): 1}) assert d == P.IntervalDict([(P.closed(0, 2), 0), (P.closed(4, 5), 1)]) a, b = d.copy(), d.copy() a.update({P.closed(-1, 1): 2}) b.update([[P.closed(-1, 1), 2]]) assert a != d assert a == b assert a != 1 assert a.as_dict() == {P.closed(-1, 1): 2, P.openclosed(1, 2): 0, P.closed(4, 5): 1} assert P.IntervalDict([(0, 0), (1, 1)]) == P.IntervalDict([(1, 1), (0, 0)])
def comparator_interval(op, version): if op == '=': return I.singleton(version) if op == '<': return I.closedopen(Version.FIRST, version) if op == '<=': return I.closed(Version.FIRST, version) if op == '>': return I.open(version, I.inf) if op == '>=': return I.closedopen(version, I.inf) if op == '!=': return I.closedopen(Version.FIRST, version) | I.openclosed( version, I.inf)