1. Interval¶
Basic interval arithmetic.
1.1. Usage¶
1.1.1. Creating intervals¶
The class Interval
is used to create intervals, i. e. subsets of a
set of values, by defining a lower and an upper endpoint.
The simplest way is calling Interval
without arguments, resulting in
both endpoints to be infinite:
>>> ival = Interval()
>>> ival
Interval()
>>> str(ival)
'(-inf .. +inf)'
For getting a more useful interval, it’s neccessary to specify atleast one endpoint:
>>> ival = Interval(LowerClosedLimit(0))
>>> ival
Interval(lower_limit=Limit(True, 0, True))
>>> str(ival)
'[0 .. +inf)'
>>> ival = Interval(upper_limit=UpperClosedLimit(100.))
>>> ival
Interval(upper_limit=Limit(False, 100.0, True))
>>> str(ival)
'(-inf .. 100.0]'
>>> ival = Interval(LowerClosedLimit(0), UpperOpenLimit(27))
>>> ival
Interval(lower_limit=Limit(True, 0, True), upper_limit=Limit(False, 27, False))
>>> str(ival)
'[0 .. 27)'
Any type which defines a total ordering can be used for the limits:
>>> ClosedInterval('a', 'zzz')
Interval(lower_limit=Limit(True, 'a', True), upper_limit=Limit(False, 'zzz', True))
Several factory functions can be used as shortcut. For example:
>>> LowerClosedInterval(30)
Interval(lower_limit=Limit(True, 30, True))
>>> UpperOpenInterval(0)
Interval(upper_limit=Limit(False, 0, False))
>>> ClosedInterval(1, 3)
Interval(lower_limit=Limit(True, 1, True), upper_limit=Limit(False, 3, True))
>>> ChainableInterval(0, 5)
Interval(lower_limit=Limit(True, 0, True), upper_limit=Limit(False, 5, False))
1.1.2. Operations on intervals¶
The limits of an interval can be retrieved via properties:
>>> ival = ClosedInterval(0, 100)
>>> ival.lower_limit
Limit(True, 0, True)
>>> ival.upper_limit
Limit(False, 100, True)
>>> ival.limits
(Limit(True, 0, True), Limit(False, 100, True))
Several methods can be used to test for specifics of an interval. For example:
>>> ival.is_bounded()
True
>>> ival.is_finite()
True
>>> ival.is_left_open()
False
Intervals can be tested for including a value:
>>> 74 in ival
True
>>> -4 in ival
False
Intervals can be compared:
>>> ival2 = LowerOpenInterval(100)
>>> ival3 = LowerClosedInterval(100)
>>> ival < ival2
True
>>> ival < ival3
True
>>> ival2 < ival3
False
>>> ival2 == ival3
False
>>> ival3 < ival2
True
>>> ival2.is_adjacent(ival3)
False
>>> ival3.is_adjacent(ival2)
False
>>> ival4 = UpperClosedInterval(100)
>>> ival4.is_adjacent(ival2)
True
>>> ival.is_overlapping(ival3)
True
>>> ival.is_subset(ival4)
True
1.2. Classes¶
-
class
ivalutils.interval.
Limit
(lower, value, closed=True)¶ Lower / upper limit of an Interval.
Parameters: - lower (bool) – specifies which endpoint of an interval this limit defines: True -> lower endpoint, False -> upper endpoint
- value (<total ordering>) – limiting value (can be of any type that defines a total ordering)
- closed (bool) – specifies whether value itself is the endpoint or not: True -> the interval that has this limit includes value, False -> the interval that has this limit does not includes value
Returns: instance of
Limit
Raises: AssertionError
– lower is not instance of boolAssertionError
– value is NoneAssertionError
– closed is not instance of bool
-
__eq__
(other)¶ self == other
-
__ge__
(other)¶ self >= other
-
__gt__
(other)¶ self > other
-
__hash__
()¶ hash(self)
-
__le__
(other)¶ self <= other
-
__lt__
(other)¶ self < other
-
adjacent_limit
()¶ Return the limit adjacent to self.
-
class
ivalutils.interval.
Interval
(lower_limit=None, upper_limit=None)¶ An Interval defines a subset of a set of values by optionally giving a lower and / or an upper limit.
The base set of values - and therefore the given limits - must have a common base type which defines a total order on the values.
If both limits are given, the interval is said to be bounded or finite, if only one or neither of them is given, the interval is said to be unbounded or infinite.
If only the lower limit is given, the interval is called lower bounded or left bounded (maybe also upper unbounded, upper infinite, right unbounded or right infinite). Correspondingly, if only the upper limit is given, the interval is called upper bounded or right bounded (maybe also lower unbounded, lower infinite, left unbounded or left infinite).
For both limits (aka endpoints) must be specified whether the given value is included in the interval or not. In the first case the limit is called closed, otherwise open.
Parameters: Returns: instance of
Interval
If None is given as lower_limit, the resulting interval is lower infinite. If None is given as upper_limit, the resulting interval is upper infinite.
Raises: InvalidInterval
– lower_limit is not a lower limitInvalidInterval
– upper_limit is not a upper limitInvalidInterval
– lower_limit > upper_limitIncompatibleLimits
– values of lower_limit and upper_limit are not comparable
-
__and__
(other)¶ self & other
-
__contains__
(value)¶ True if value does not exceed the limits of self.
-
__copy__
()¶ Return self (Interval instances are immutable).
-
__eq__
(other)¶ self == other.
True if all elements contained in self are also contained in other and all elements contained in other are also contained in self.
This is exactly the case if self.limits == other.limits.
-
__ge__
(other)¶ self >= other.
-
__gt__
(other)¶ self > other.
True if there is an element in self which is greater than all elements in other or there is an element in other which is smaller than all elements in self.
This is exactly the case if self.limits > other.limits.
-
__hash__
()¶ hash(self)
-
__le__
(other)¶ self <= other.
-
__lt__
(other)¶ self < other.
True if there is an element in self which is smaller than all elements in other or there is an element in other which is greater than all elements in self.
This is exactly the case if self.limits < other.limits.
-
__or__
(other)¶ self | other
-
__sub__
(other)¶ self - other
-
is_adjacent
(other)¶ True if self.is_lower_adjacent(other) or self.is_upper_adjacent(other).
-
is_disjoint
(other)¶ True if self contains no elements in common with other.
-
is_lower_adjacent
(other)¶ True if self.upper_limit.is_lower_adjacent(other.lower_limit).
-
is_overlapping
(other)¶ True if there is a common element in self and other.
-
is_subset
(other)¶ True if self defines a proper subset of other, i.e. all elements contained in self are also contained in other, but not the other way round.
-
is_upper_adjacent
(other)¶ True if self.lower_limit.is_upper_adjacent(other.upper_limit).
-
limits
¶ Lower and upper limit as tuple.
-
lower_limit
¶ Lower limit (LowerInfiniteLimit, if no lower limit was given.)
-
upper_limit
¶ Upper limit (UpperInfiniteLimit, if no upper limit was given.)
1.3. Factoryfunctions¶
-
ivalutils.interval.
LowerLimit
(value, closed=True)¶ Create a lower limit.
Parameters: - value (<total ordering>) – limiting value (can be of any type that defines a total ordering)
- closed (bool) – specifies whether value itself is the endpoint or not: True -> the interval that has this limit includes value, False -> the interval that has this limit does not includes value
Returns: instance of
Limit
Raises: AssertionError
– value is NoneAssertionError
– closed is not instance of bool
-
ivalutils.interval.
LowerInfiniteLimit
()¶ Create a lower infinite limit (a singleton).
-
ivalutils.interval.
UpperLimit
(value, closed=True)¶ Create an upper limit.
Parameters: - value (<total ordering>) – limiting value (can be of any type that defines a total ordering)
- closed (bool) – specifies whether value itself is the endpoint or not: True -> the interval that has this limit includes value, False -> the interval that has this limit does not includes value
Returns: instance of
Limit
Raises: AssertionError
– value is NoneAssertionError
– closed is not instance of bool
-
ivalutils.interval.
UpperInfiniteLimit
()¶ Create an upper infinite limit (a singleton).
-
ivalutils.interval.
LowerClosedLimit
(value)¶ Create a lower closed limit.
Parameters: value (<total ordering>) – limiting value (can be of any type that defines a total ordering) Returns: instance of Limit
Raises: AssertionError
– value is None
-
ivalutils.interval.
LowerOpenLimit
(value)¶ Create a lower open limit.
Parameters: value (<total ordering>) – limiting value (can be of any type that defines a total ordering) Returns: instance of Limit
Raises: AssertionError
– value is None
-
ivalutils.interval.
UpperClosedLimit
(value)¶ Create an upper closed limit.
Parameters: value (<total ordering>) – limiting value (can be of any type that defines a total ordering) Returns: instance of Limit
Raises: AssertionError
– value is None
-
ivalutils.interval.
UpperOpenLimit
(value)¶ Create an upper open limit.
Parameters: value (<total ordering>) – limiting value (can be of any type that defines a total ordering) Returns: instance of Limit
Raises: AssertionError
– value is None
-
ivalutils.interval.
ChainableInterval
(lower_value, upper_value, lower_closed=True)¶ Create Interval with one closed and one open endpoint.
-
ivalutils.interval.
ClosedInterval
(lower_value, upper_value)¶ Create Interval with closed endpoints.
-
ivalutils.interval.
LowerClosedInterval
(lower_value)¶ Create Interval with closed lower and infinite upper endpoint.
-
ivalutils.interval.
LowerOpenInterval
(lower_value)¶ Create Interval with open lower and infinite upper endpoint.
-
ivalutils.interval.
OpenBoundedInterval
(lower_value, upper_value)¶ Create Interval with open endpoints.
-
ivalutils.interval.
OpenFiniteInterval
(lower_value, upper_value)¶ Create Interval with open endpoints.
-
ivalutils.interval.
UpperClosedInterval
(upper_value)¶ Create Interval with infinite lower and closed upper endpoint.
-
ivalutils.interval.
UpperOpenInterval
(upper_value)¶ Create Interval with infinite lower and open upper endpoint.
2. IntervalChain¶
Sequences of adjacent intervals.
2.1. Usage¶
2.1.1. Creating interval chains¶
The class IntervalChain
is used to create sequences of adjacent
intervals:
>>> ic = IntervalChain(('a', 'd', 'g', 'z'))
>>> ic
IntervalChain(('a', 'd', 'g', 'z'))
The default is to create an interval sequence which is lower-bound and upper-infinite and containing lower-closed intervals:
>>> str(ic)
"[['a' .. 'd'), ['d' .. 'g'), ['g' .. 'z'), ['z' .. +inf)]"
By specifying additional parameters, you can determine which endpoints will be closed and whether a lower and / or upper infinite endpoint will be added:
>>> ic = IntervalChain(('a', 'd', 'g', 'z'), lower_closed = False, add_lower_inf=True, add_upper_inf=False)
>>> str(ic)
"[(-inf .. 'a'], ('a' .. 'd'], ('d' .. 'g'], ('g' .. 'z']]"
2.1.2. Operations on interval chains¶
Interval chains can be indexed and iterated like lists ...:
>>> ic[2]
Interval(lower_limit=Limit(True, 'd', False), upper_limit=Limit(False, 'g', True))
>>> [ival.upper_limit.value for ival in ic]
['a', 'd', 'g', 'z']
... and can be searched for the index of the interval holding a specified value:
>>> ic.map2idx('b')
1
>>> ic.map2idx('a')
0
>>> ic.map2idx('aa')
1
2.2. Classes¶
-
class
ivalutils.interval_chain.
IntervalChain
(limits, lower_closed=True, add_lower_inf=False, add_upper_inf=True)¶ An IntervalChain is a list of adjacent intervals.
It is constructed from a list of limiting values.
Parameters: - limits (Iterable) – an iterable of the limiting values, must be ordered from smallest to greatest
- lower_closed (boolean) – defines which endpoint of the contained intervals will be closed: if True, lower endpoint closed, upper open (default), if False, lower endpoint open, upper closed
- add_lower_inf (boolean) – defines whether a lower infinite interval will be added as first interval: if True, infinite interval as lowest interval, if False, no infinite interval as lowest interval (default)
- add_upper_inf (boolean) – defines whether an upper infinite interval will be added as last interval: if True, infinite interval as last interval (default), if False, no infinite interval as last interval
Returns: instance of
IntervalChain
Raises: EmptyIntervalChain
– given limits do not define any intervalInvalidInterval
– given limits do not define a sequence of adjacent intervalsIncompatibleLimits
– given limits are not comparable
-
__copy__
()¶ Return self (IntervalChain instances are immutable).
-
__eq__
(other)¶ self == other
-
__getitem__
(idx)¶ self[idx]
-
__iter__
()¶ iter(self)
-
__len__
()¶ len(self)
-
__repr__
()¶ repr(self)
-
__str__
()¶ str(self)
-
is_lower_infinite
()¶ True if first interval is lower infinite.
-
is_upper_infinite
()¶ True if last interval is upper infinite.
-
map2idx
(value)¶ Return the index of the interval which contains value.
Raises ValueError if value is not contained in any of the intervals in self.
-
limits
¶ The limiting values.
-
total_interval
¶ Returns the interval between lower endpoint of first interval in self and upper endpoint of last interval in self.
3. IntervalMapping¶
Mappings on intervals
3.1. Usage¶
3.1.1. Creating interval mappings¶
The class IntervalMapping
is used to create a mapping from intervals
to arbitrary values.
Instances can be created by giving an IntervalChain and a sequence of associated values ...:
>>> im1 = IntervalMapping(IntervalChain((0, 300, 500, 1000)), (0., .10, .15, .20))
... or a sequence of limiting values and a sequence of associated values ...:
>>> im2 = IntervalMapping((0, 300, 500, 1000), (0., .10, .15, .20))
... or a sequence of tuples, each holding a limiting value and an associated value:
>>> im3 = IntervalMapping(((0, 0.), (300, .10), (500, .15), (1000, .20)))
>>> im1 == im2 == im3
True
3.1.2. Operations on IntervalMappings¶
Interval mappings behave like ordinary mappings:
>>> list(im3.keys())
[Interval(lower_limit=Limit(True, 0, True), upper_limit=Limit(False, 300, False)),
Interval(lower_limit=Limit(True, 300, True), upper_limit=Limit(False, 500, False)),
Interval(lower_limit=Limit(True, 500, True), upper_limit=Limit(False, 1000, False)),
Interval(lower_limit=Limit(True, 1000, True))]
>>> list(im3.values())
[0.0, 0.1, 0.15, 0.2]
>>> im3[Interval(lower_limit=Limit(True, 300, True), upper_limit=Limit(False, 500, False))]
0.1
In addition they can be looked-up for the value associated with the interval which contains a given value:
>>> im3.map(583)
0.15
As a short-cut, the interval mapping can be used like a function:
>>> im3(412)
0.1
Use cases for interval mappings are for example:
- determine the discount to be applied depending on an order value,
- rating customers depending on their sales turnover,
- classifying cities based on the number of inhabitants,
- mapping booking dates to accounting periods,
- grouping of measured values in discrete ranges.
3.2. Classes¶
-
class
ivalutils.interval_map.
IntervalMapping
(*args)¶ An IntervalMapping is a container of associated interval / value pairs.
- It is constructed from either
- an IntervalChain and a sequence of associated values,
- a sequence of limiting values and a sequence of associated values,
- a sequence of tuples, each holding a limiting value and an associated value.
1. Form
Parameters: - arg0 (
IntervalChain
) – sequence of intervals to be mapped - arg1 (Sequence) – sequence of associated values
2. Form
Parameters: - arg0 (Sequence) – sequence of values limiting the intervals to be mapped
- arg1 (Sequence) – sequence of associated values
3. Form
Parameters: arg0 (Sequence) – sequence of tuples containing a limiting value and an associated value If no IntervalChain is given, the given limiting values must be comparable and must be given in ascending order.
Returns: instance of
IntervalMapping
Raises: AssertionError
– given sequences do not have the same lengthAssertionError
– given sequences of limiting values is emptyInvalidInterval
– given limits do not define a sequence of adjacent intervalsIncompatibleLimits
– given limits are not comparableTypeError
– given sequence is not a sequence of 2-tuplesTypeError
– wrong number of arguments
-
__call__
(val)¶ Return the value associated with interval which contains val.
-
__copy__
()¶ Return self (IntervalMapping instances are immutable).
-
__eq__
(other)¶ self == other
-
__getitem__
(key)¶ self[key]
-
__iter__
()¶ iter(self)
-
__len__
()¶ len(self)
-
map
(val)¶ Return the value associated with interval which contains val.