|
|
@@ -58,18 +58,11 @@ class Interval: |
|
|
|
raise IntervalError("not a subset") |
|
|
|
return Interval(start, end) |
|
|
|
|
|
|
|
def set_difference(a, b): |
|
|
|
""" |
|
|
|
Compute the difference (a \\ b) between the intervals in 'a' and |
|
|
|
the intervals in 'b'; i.e., the ranges that are present in 'self' |
|
|
|
but not 'other'. |
|
|
|
|
|
|
|
'a' and 'b' must both be iterables. |
|
|
|
|
|
|
|
Returns a generator that yields each interval in turn. |
|
|
|
Output intervals are built as subsets of the intervals in the |
|
|
|
first argument (a). |
|
|
|
""" |
|
|
|
def _interval_math_helper(a, b, op, subset = True): |
|
|
|
"""Helper for set_difference, intersection functions, |
|
|
|
to compute interval subsets based on a math operator on ranges |
|
|
|
present in A and B. Subsets are computed from A, or new intervals |
|
|
|
are generated if subset = False.""" |
|
|
|
# Iterate through all starts and ends in sorted order. Add a |
|
|
|
# tag to the iterator so that we can figure out which one they |
|
|
|
# were, after sorting. |
|
|
@@ -84,31 +77,57 @@ def set_difference(a, b): |
|
|
|
# At each point, evaluate which type of end it is, to determine |
|
|
|
# how to build up the output intervals. |
|
|
|
a_interval = None |
|
|
|
b_interval = None |
|
|
|
in_a = False |
|
|
|
in_b = False |
|
|
|
out_start = None |
|
|
|
for (ts, k, i) in nilmdb.utils.iterator.imerge(a_iter, b_iter): |
|
|
|
if k == 0: |
|
|
|
# start a interval |
|
|
|
a_interval = i |
|
|
|
if b_interval is None: |
|
|
|
out_start = ts |
|
|
|
in_a = True |
|
|
|
elif k == 1: |
|
|
|
# start b interval |
|
|
|
b_interval = i |
|
|
|
if out_start is not None and out_start != ts: |
|
|
|
yield a_interval.subset(out_start, ts) |
|
|
|
out_start = None |
|
|
|
in_b = True |
|
|
|
elif k == 2: |
|
|
|
# end a interval |
|
|
|
in_a = False |
|
|
|
elif k == 3: |
|
|
|
in_b = False |
|
|
|
include = op(in_a, in_b) |
|
|
|
if include and out_start is None: |
|
|
|
out_start = ts |
|
|
|
elif not include: |
|
|
|
if out_start is not None and out_start != ts: |
|
|
|
yield a_interval.subset(out_start, ts) |
|
|
|
if subset: |
|
|
|
yield a_interval.subset(out_start, ts) |
|
|
|
else: |
|
|
|
yield Interval(out_start, ts) |
|
|
|
out_start = None |
|
|
|
a_interval = None |
|
|
|
elif k == 3: |
|
|
|
# end b interval |
|
|
|
b_interval = None |
|
|
|
if a_interval: |
|
|
|
out_start = ts |
|
|
|
|
|
|
|
def set_difference(a, b): |
|
|
|
""" |
|
|
|
Compute the difference (a \\ b) between the intervals in 'a' and |
|
|
|
the intervals in 'b'; i.e., the ranges that are present in 'self' |
|
|
|
but not 'other'. |
|
|
|
|
|
|
|
'a' and 'b' must both be iterables. |
|
|
|
|
|
|
|
Returns a generator that yields each interval in turn. |
|
|
|
Output intervals are built as subsets of the intervals in the |
|
|
|
first argument (a). |
|
|
|
""" |
|
|
|
return _interval_math_helper(a, b, (lambda a, b: a and not b)) |
|
|
|
|
|
|
|
def intersection(a, b): |
|
|
|
""" |
|
|
|
Compute the intersection between the intervals in 'a' and the |
|
|
|
intervals in 'b'; i.e., the ranges that are present in both 'a' |
|
|
|
and 'b'. |
|
|
|
|
|
|
|
'a' and 'b' must both be iterables. |
|
|
|
|
|
|
|
Returns a generator that yields each interval in turn. |
|
|
|
Output intervals are built as subsets of the intervals in the |
|
|
|
first argument (a). |
|
|
|
""" |
|
|
|
return _interval_math_helper(a, b, (lambda a, b: a and b)) |
|
|
|
|
|
|
|
def optimize(it): |
|
|
|
""" |
|
|
|