Python Intervals Arithmetic
Project description
Interval arithmetic for Python
Provide interval arithmetic for Python 3.4+.
Features
- Support intervals of any (comparable) objects.
- Closed or open, finite or infinite intervals.
- Union of intervals out of the box.
- Automatic simplification of (union of) intervals.
- Support iteration, comparison, intersection, union, complement, difference and containment.
Installation
You can use pip
to install this library:
pip install python-intervals
This will install the latest available version from pypi branch. Prereleases are available from the master branch.
Usage
Assuming this library is imported using import intervals as I
, intervals can be easily created using one of the following functions:
I.open(1, 2)
corresponds to(1,2)
;I.closed(1, 2)
corresponds to[1,2]
;I.openclosed(1, 2)
corresponds to(1,2]
;I.closedopen(1, 2)
corresponds to[1,2)
;I.singleton(1)
corresponds to[1,1]
;I.empty()
corresponds to the empty interval()
.
>>> I.closed(0, 3)
[0,3]
>>> I.openclosed('a', 'z')
('a','z']
>>> I.singleton(2.5)
[2.5]
>>> I.empty()
()
Infinite and semi-infinite intervals are supported using I.inf
and -I.inf
as upper or lower bounds. These two objects support comparison with any other object.
>>> I.openclosed(-I.inf, 0)
(-inf,0]
>>> I.closed(-I.inf, I.inf) # Automatically converted
(-inf,+inf)
>>> I.inf > 'a', I.inf > 0, I.inf > True
(True, True, True)
Intervals created with this library are Interval
instances.
An Interval
object is a disjunction of AtomicInterval
.
An AtomicInterval
represents a single interval (e.g. [1,2])
while an Interval
represents union of intervals (e.g. [1,2] | [3,4]
).
For convenience, Interval
are automatically simplified:
>>> I.closed(0, 2) | I.closed(2, 4)
[0,4]
>>> I.closed(1, 2) | I.closed(3, 4) | I.closed(2, 3)
[1,4]
>>> I.closed(1, 2) | I.openclosed(2, 3) | I.closedopen(5, 5)
[1,3]
Both classes support interval arithmetic:
x.intersection(other)
orx & other
returns the intersection of two intervals.>>> I.closed(0, 2) & I.closed(1, 3) [1,2] >>> I.closed(0, 4) & I.open(2, 3) (2,3) >>> I.closed(0, 2) & I.closed(2, 3) [2] >>> I.closed(0, 2) & I.closed(3, 4) ()
x.union(other)
orx | other
returns the union of two intervals.>>> I.closed(0, 1) | I.closed(1, 2) [0,2] >>> I.closed(0, 1) | I.closed(2, 3) [0,1] | [2,3]
x.complement(other)
or~x
returns the complement of the interval.>>> ~I.closed(0, 1) (-inf,0) | (1,+inf) >>> ~(I.open(-I.inf, 0) | I.open(1, I.inf)) [0,1] >>> ~I.open(-I.inf, I.inf) ()
x.difference(other)
orx - other
returns the difference betweenx
andother
.>>> I.closed(0,2) - I.closed(1,2) [0,1) >>> I.closed(0, 4) - I.closed(1, 2) [0,1) | (2,4]
x == other
checks for interval equality.>>> I.closed(0, 2) == I.closed(0, 1) | I.closed(1, 2) True
x.is_empty()
tests if the interval is empty.>>> I.closed(0, 1).is_empty() False >>> I.closed(0, 0).is_empty() False >>> I.openclosed(0, 0).is_empty() True >>> I.empty().is_empty() True
x.overlaps(other)
test if there is an overlap between two intervals. This method accepts apermissive
parameter which defaults toFalse
. IfTrue
, it considers that [1, 2) and [2, 3] have an overlap on 2 (but not [1, 2) and (2, 3]).>>> I.closed(1, 2).overlaps(I.closed(2, 3)) True >>> I.closed(1, 2).overlaps(I.open(2, 3)) False >>> I.closed(1, 2).overlaps(I.open(2, 3), permissive=True) True
x.contains(other)
orother in x
returns True if given item is contained in the interval. SupportInterval
,AtomicInterval
and arbitrary comparable values.>>> 2 in I.closed(0, 2) True >>> 2 in I.open(0, 2) False >> I.open(0, 1) in I.closed(0, 2) True
Moreover, both Interval
and AtomicInterval
are comparable using >
or <
.
The comparison is based on the interval, not only on one bound or the other.
For instance, assuming a
and b
are intervals, a < b
holds iff a
is entirely lower than b
.
>>> I.closed(0, 2) < I.closed(3, 4)
True
>>> I.closed(0, 2) < I.closed(2, 3)
False
While less meaningful, <=
and >=
are supported too and correspond exactly to < or ==
(resp. > or ==
).
Consequently, comparisons between partially overlapping intervals will always evaluate to False
.
>>> I.closed(0, 2) <= I.closed(2, 3)
False
>>> I.closed(0, 2) < I.closed(0, 2)
False
>>> I.closed(0, 2) | I.closed(5, 6) <= I.closed(3, 4)
False
>>> I.closed(0, 2) <= I.closed(0, 2)
True
Additionally, an Interval
provides:
x.enclosure()
returns the smallest interval that includes the current one.>>> (I.closed(0, 1) | I.closed(2, 3)).enclosure() [0,3]
x.is_atomic()
evaluates toTrue
if interval is the union of a single (possibly empty) atomic interval.>>> I.closed(0, 2).is_atomic(), (I.closed(0, 1) | I.closed(2, 3)).is_atomic() (True, False)
x.to_atomic()
returns the smallestAtomicInterval
that contains the interval(s). Is equivalent tox.enclosure()
but returns anAtomicInterval
instead of anInterval
object.
Intervals can be iterated to access the underlying set of AtomicInterval
, sorted by their lower bounds.
As intervals are automatically simplified, this implies their upper bounds are also sorted.
>>> list(I.open(2, 3) | I.closed(0, 1) | I.closed(21, 24))
[[0,1], (2,3), [21,24]]
The AtomicInterval
of an Interval
can also be accessed using their index.
>>> (I.open(2, 3) | I.closed(0, 1) | I.closed(21, 24))[-2]
(2,3)
The left and right boundaries, and the lower and upper bound of an AtomicInterval
can be respectively accessed
with its left
, right
, lower
and upper
attribute.
>>> [(i.left, i.lower, i.upper, i.right) for i in I.open(2, 3) | I.closed(0, 1)]
[(True, 0, 1, True), (False, 2, 3, False)]
Contributions
Contributions are very welcome! Feel free to report bugs or suggest new features using GitHub issues and/or pull requests.
This library was inspired by pyinter.
Licence
LGPLv3 - GNU Lesser General Public License, version 3
Changelog
1.2.0 (2018-04-04)
Interval
support indexing, to retrieve the underlyingAtomicInterval
.
1.1.0 (2018-04-04)
- Both
AtomicInterval
andInterval
are fully comparable. - Add
singleton(x)
to create a singleton interval [x]. - Add
empty()
to create an empty interval. - Add
Interval.enclosure()
that returns the smallest interval that includes the current one. - Interval simplification is in O(n) instead of O(n*m).
AtomicInterval
in anInterval
are sorted by lower bound.
1.0.4 (2018-04-03)
- All operations of
AtomicInterval
(except overlaps) acceptInterval
. - Raise
TypeError
instead ofValueError
if type is not supported (coherent withNotImplemented
).
1.0.3 (2018-04-03)
- Initial working release on PyPi.
1.0.0 (2018-04-03)
- Initial release.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for python_intervals-1.2.0-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 918280bc5abe5f6c208edebeaf8cb239f5817f6cc8f414646d4596bb8afef874 |
|
MD5 | 662179d3f7282a6a736db196bfcb7068 |
|
BLAKE2b-256 | 9db470b07f54ed7bece26e58fab5ae164effab3da058a0e05a5328e5b2002d2f |