Intervals¶
[1]:
from part import Interval, Atomic
Construction¶
An interval can be created using:
the constructor
static methods
[2]:
print(Interval[int](lower_value=10, upper_value=20))
[10;20)
[3]:
print(Interval[str](lower_value="abc", upper_value="def", upper_closed=True))
['abc';'def']
[4]:
print(Interval[int](lower_closed=None, lower_value=10, upper_value=20))
(10;20)
[5]:
print(Interval[int]())
(-inf;+inf)
[6]:
print(Atomic[int].from_tuple((10, 20)))
[10;20)
[7]:
print(Atomic[int].from_tuple((10, 20, None)))
(10;20)
[8]:
print(Atomic[int].from_tuple((10, 20, None, True)))
(10;20]
[9]:
print(Atomic[int].from_value(10))
[10;10]
[10]:
print(Interval[int].lower_limit(value=10))
[10;+inf)
[11]:
print(Interval[int].lower_limit(value=10, closed=None))
(10;+inf)
[12]:
print(Interval[int].upper_limit(value=10))
(-inf;10)
[13]:
print(Interval[int].upper_limit(value=10, closed=True))
(-inf;10]
Properties¶
Properties can be easily accessed.
[14]:
a = Atomic[int].from_tuple((10, 20, None))
print(a.lower)
print(a.lower_value)
print(a.lower_closed)
print(a.upper)
print(a.upper_value)
print(a.upper_closed)
10+
10
None
20-
20
None
Comparison¶
Intervals can be compared using Allen’s algebra:
[15]:
a = Atomic[int].from_tuple((10, 20, None))
[16]:
a.meets(Atomic[int].from_tuple((20, 30)))
[16]:
False
[17]:
a.meets(Atomic[int].from_tuple((20, 30)), strict=False)
[17]:
True
[18]:
a.overlaps(Atomic[int].from_tuple((15, 30)))
[18]:
True
[19]:
a.starts(Atomic[int].from_tuple((20, 40, None)))
[19]:
False
[20]:
a.starts(Atomic[int].from_tuple((10, 40, None)), strict=False)
[20]:
True
[21]:
a.during(Atomic[int].from_tuple((0, 30)))
[21]:
True
[22]:
a.finishes(Atomic[int].from_tuple((0, 20)))
[22]:
True
Operations¶
Intervals support set operation: union, intersection and complement. These operations produce instance of FrozenSetInterval
.
[23]:
a = Atomic[int].from_tuple((10, 20, None))
b = Atomic[int].from_tuple((15, 30))
c = Atomic[int].from_tuple((30, 40))
[24]:
print(a | b)
print(a | c)
print(a & b)
print(a & c)
print(a - b)
print(a ^ b)
print(~a)
(10;30)
(10;20) | [30;40)
[15;20)
(10;15)
(10;15) | [20;30)
(-inf;10] | [20;+inf)
Interval sets¶
There exists two versions of interval sets:
FrozenIntervalSet
MutableIntervalSet
FrozenIntervalSet
is slightly more efficient than MutableIntervalSet
.
Frozen Interval Set¶
[25]:
from part import FrozenIntervalSet
Construction¶
A frozen interval set can be constructed using an iterable of interval-like values.
[26]:
a = FrozenIntervalSet[int]([2, (6, 7), (8, 9, None), (10, 11, True, True)])
[27]:
print(a)
[2;2] | [6;7) | (8;9) | [10;11]
Properties¶
the number of intervals can be known using the standard function
len
;iteration over a set of intervals is obtained by using the standard function
iter
;the intervals are accessible using their indices.
[28]:
print(len(a))
print([str(interval) for interval in a])
print(a[0])
print(a[2])
print(a[1:3])
4
['[2;2]', '[6;7)', '(8;9)', '[10;11]']
[2;2]
(8;9)
[6;7) | (8;9)
Comparison¶
Interval set can be compared using the set comparison operators.
[29]:
a = FrozenIntervalSet[int]([2, (6, 7), (8, 9, None), (10, 11, True, True)])
b = FrozenIntervalSet[int]([(0, 7), (8, 13)])
print(a)
print(b)
[2;2] | [6;7) | (8;9) | [10;11]
[0;7) | [8;13)
[30]:
a <= b
[30]:
True
[31]:
a < b
[31]:
True
[32]:
a == b
[32]:
False
[33]:
a >= b
[33]:
False
[34]:
a > b
[34]:
False
Operations¶
Classical set operations are defined.
[35]:
a = FrozenIntervalSet[int]([(2, 8), (10, 11, True, True)])
b = FrozenIntervalSet[int]([(0, 7), (8, 13)])
print(a)
print(b)
[2;8) | [10;11]
[0;7) | [8;13)
[36]:
print((10,13) in a)
print((10,13) in b)
print(a | b)
print(a.union(b))
print(a & b)
print(a.intersection(b))
False
True
[0;13)
[0;13)
[2;7) | [10;11]
[2;7) | [10;11]
[37]:
print(~a)
(-inf;2) | [8;10) | (11;+inf)
[38]:
print(a - b)
print(a.difference(b))
print(a ^ b)
print(a.symmetric_difference(b))
[7;8)
[7;8)
[0;2) | [7;10) | (11;13)
[0;2) | [7;10) | (11;13)
Selection¶
[39]:
a = FrozenIntervalSet[int]([2, (6, 7), (8, 10, None), (11, 13, True, True)])
[40]:
print([str(interval) for interval in a.select((5, 9))])
['[6;7)']
[41]:
print([str(interval) for interval in a.select((2, 9))])
['[2;2]', '[6;7)']
[42]:
print([str(interval) for interval in a.select((2, 9), strict=False)])
['[2;2]', '[6;7)', '(8;10)']
Mutable Interval Set¶
In addition to frozen interval set operations, the mutable interval set implements method that can modify the set.
[43]:
from part import MutableIntervalSet
Element operations¶
[44]:
a = MutableIntervalSet[int]([2, (6, 7), (8, 10, None), (11, 13, True, True)])
print(a)
a.add((2, 6))
print(a)
[2;2] | [6;7) | (8;10) | [11;13]
[2;7) | (8;10) | [11;13]
[45]:
a = MutableIntervalSet[int]([2, (6, 7), (8, 10, None), (11, 13, True, True)])
print(a)
a.discard((2, 8))
print(a)
[2;2] | [6;7) | (8;10) | [11;13]
(8;10) | [11;13]
[46]:
a = MutableIntervalSet[int]([2, (6, 7), (8, 10, None), (11, 13, True, True)])
print(a)
try:
a.remove((2, 8))
except KeyError as e:
print(e)
[2;2] | [6;7) | (8;10) | [11;13]
'(2, 8)'
[47]:
a = MutableIntervalSet[int]([2, (6, 7), (8, 10, None), (11, 13, True, True)])
print(a)
print(a.pop())
print(a)
[2;2] | [6;7) | (8;10) | [11;13]
[2;2]
[6;7) | (8;10) | [11;13]
[48]:
a = MutableIntervalSet[int]([2, (6, 7), (8, 10, None), (11, 13, True, True)])
print(a)
a.clear()
print(a)
[2;2] | [6;7) | (8;10) | [11;13]
Set operations¶
[49]:
a = MutableIntervalSet[int]([2, (6, 7), (8, 10, None), (11, 13, True, True)])
b = MutableIntervalSet[int]([(0, 7), (8, 12)])
print(a)
print(b)
a.update(b)
print(a)
a |= MutableIntervalSet[int]([(7, 8)])
print(a)
[2;2] | [6;7) | (8;10) | [11;13]
[0;7) | [8;12)
[0;7) | [8;13]
[0;13]
[50]:
a = MutableIntervalSet[int]([2, (6, 7), (8, 10, None), (11, 13, True, True)])
b = MutableIntervalSet[int]([(0, 7), (8, 12)])
print(a)
print(b)
a.intersection_update(b)
print(a)
a &= MutableIntervalSet[int]([(6, 11)])
print(a)
[2;2] | [6;7) | (8;10) | [11;13]
[0;7) | [8;12)
[2;2] | [6;7) | (8;10) | [11;12)
[6;7) | (8;10)
[51]:
a = MutableIntervalSet[int]([2, (6, 7), (8, 10, None), (11, 13, True, True)])
b = MutableIntervalSet[int]([(0, 7), (8, 12)])
print(a)
print(b)
a.difference_update(b)
print(a)
a -= MutableIntervalSet[int]([12])
print(a)
[2;2] | [6;7) | (8;10) | [11;13]
[0;7) | [8;12)
[12;13]
(12;13]
[52]:
a = MutableIntervalSet[int]([2, (6, 7), (8, 10, None), (11, 13, True, True)])
b = MutableIntervalSet[int]([(0, 7), (8, 12)])
print(a)
print(b)
a.symmetric_difference_update(b)
print(a)
a ^= MutableIntervalSet[int]([(8,12)])
print(a)
[2;2] | [6;7) | (8;10) | [11;13]
[0;7) | [8;12)
[0;2) | (2;6) | [8;8] | [10;11) | [12;13]
[0;2) | (2;6) | (8;10) | [11;13]
Interval dicts¶
There exists two versions of interval dicts:
FrozenIntervalDict
MutableIntervalDict
FrozenIntervalDict
is slightly more efficient than MutableIntervalDict
.
Frozen Interval Dict¶
[53]:
from part import FrozenIntervalDict
Construction¶
A frozen interval dict can be constructed using an iterable.
[54]:
print(FrozenIntervalDict[int, int]({(10, 15): 1, (20, 25): 2, (30, 35): 3}))
{'[10;15)': 1, '[20;25)': 2, '[30;35)': 3}
[55]:
print(FrozenIntervalDict[int, int]([((10, 15), 1), ((20, 25), 2), ((30, 35), 3)]))
{'[10;15)': 1, '[20;25)': 2, '[30;35)': 3}
Properties¶
the number of intervals can be known using the standard function
len
;iteration over a dict of intervals is obtained by using the standard function
iter
;the values are accessible using their intervals;
new dict can be created using the slice notation.
[56]:
a = FrozenIntervalDict[int, int]({(10, 15): 1, (20, 25): 2, (30, 35): 3})
print(len(a))
print([str(interval) for interval in a])
print(a[(10, 15)])
print(a[(11, 12)])
print((11, 12) in a)
print((12, 17) in a)
try:
print(a[(12, 17)])
except KeyError as e:
print(e)
print(a[12:32])
3
['[10;15)', '[20;25)', '[30;35)']
1
1
True
False
'(12, 17)'
{'[12;15)': 1, '[20;25)': 2, '[30;32)': 3}
Iteration¶
As for classical python dictionaries, methods keys
, values
and items
are available.
[57]:
a = FrozenIntervalDict[int, int]({(10, 15): 1, (20, 25): 2, (30, 35): 3})
print([str(interval) for interval in a.keys()])
print([str(value) for value in a.values()])
print([f"{interval}:{value}" for interval, value in a.items()])
['[10;15)', '[20;25)', '[30;35)']
['1', '2', '3']
['[10;15):1', '[20;25):2', '[30;35):3']
Selection¶
[58]:
a = FrozenIntervalDict[int, int]({(10, 15): 1, (20, 25): 2, (30, 35): 3})
print([str(interval) for interval in a.select((12, 26))])
print([str(interval) for interval in a.select((12, 22), strict=False)])
['[20;25)']
['[10;15)', '[20;25)']
Compression¶
[59]:
a = FrozenIntervalDict[int, int]({(10, 15): 1, (14, 25): 1, (30, 35): 2, (33, 45): 2})
print(a)
print(a.compress())
{'[10;14)': 1, '[14;25)': 1, '[30;33)': 2, '[33;45)': 2}
{'[10;25)': 1, '[30;45)': 2}
Mutable Interval Dict¶
[60]:
from part import MutableIntervalDict
Modify items¶
[61]:
a = MutableIntervalDict[int, int]({(10, 15): 1, (20, 25): 2, (30, 35): 3})
print(a)
a[12] = 4
print(a)
a[14:22] = 5
print(a)
del a[12:22]
print(a)
{'[10;15)': 1, '[20;25)': 2, '[30;35)': 3}
{'[10;12)': 1, '[12;12]': 4, '(12;15)': 1, '[20;25)': 2, '[30;35)': 3}
{'[10;12)': 1, '[12;12]': 4, '(12;14)': 1, '[14;22)': 5, '[22;25)': 2, '[30;35)': 3}
{'[10;12)': 1, '[22;25)': 2, '[30;35)': 3}
Update¶
[62]:
a = MutableIntervalDict[int, int](
{(10, 15): 1, (20, 25): 2, (30, 35): 3},
operator=lambda x, y: x + y
)
a |= MutableIntervalDict[int, int]({(14, 21): 2})
print(a)
{'[10;14)': 1, '[14;15)': 3, '[15;20)': 2, '[20;21)': 4, '[21;25)': 2, '[30;35)': 3}
[63]:
a = MutableIntervalDict[float, set](
operator=lambda x, y: x | y,
strict=False,
)
print(a)
a |= MutableIntervalDict[float, set]({(1.2, 3.6): {1}, (3.8, 4.5) : {2}})
print(a)
a |= MutableIntervalDict[float, set]({(2, 4): {3}})
print(a)
{}
{'[1.2;3.6)': {1}, '[3.8;4.5)': {2}}
{'[1.2;2)': {1}, '[2;3.6)': {1, 3}, '[3.6;3.8)': {3}, '[3.8;4)': {2, 3}, '[4;4.5)': {2}}
Clear¶
[64]:
a = MutableIntervalDict[int, int]({(10, 15): 1, (20, 25): 2, (30, 35): 3})
print(a)
a.clear()
print(a)
{'[10;15)': 1, '[20;25)': 2, '[30;35)': 3}
{}