-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinterval-partitioning.py
More file actions
67 lines (54 loc) · 1.95 KB
/
interval-partitioning.py
File metadata and controls
67 lines (54 loc) · 1.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
"""Greedy interval partitioning (coloring an interval graph).
Given a set of intervals with start time s and finish time f, assign each
interval to a "color" (or resource) so that no two overlapping intervals
share the same color. Equivalently, partition the intervals into the minimum
number of non-overlapping subsets.
The algorithm processes all start/end events in increasing time order. When
an interval ends, its color becomes available again; when an interval starts,
it is assigned any available color. This is optimal and uses exactly the
maximum number of simultaneously active intervals.
Runs in O(n log n) time due to sorting of event times.
Returns a mapping: color -> list of intervals.
"""
from random import randint as R
from collections import namedtuple as T
from collections import defaultdict as D
Interval = T("Interval", "s f")
def rand_interval():
a = R(1, 50)
b = R(3, 30)
return Interval(a, a + b)
def length(iv):
return iv.f - iv.s
def schedule_all(intervals):
start = D(list)
end = D(list)
timesteps = []
for iv in intervals:
start[iv.s].append(iv)
end[iv.f].append(iv)
timesteps += [iv.s, iv.f]
timesteps = sorted(set(timesteps)) # makes unique
colors = list(reversed(range(len(intervals))))
coloring = D(list)
interval_color = {}
for t in timesteps:
for iv in end[t]:
color = interval_color[iv]
colors.append(color)
for iv in start[t]:
color = colors.pop()
coloring[color].append(iv)
interval_color[iv] = color
return coloring
I = [rand_interval() for _ in range(20)]
print(I)
coloring = schedule_all(I)
for x in sorted(coloring):
ivs = sorted(coloring[x])
s = [" " * ivs[0].s]
for i in range(len(ivs) - 1):
s += "(" + "-" * (length(ivs[i]) - 2) + ")"
s += " " * (ivs[i + 1].s - ivs[i].f)
s += "(" + "-" * (length(ivs[-1]) - 2) + ")"
print(x, " ".join(s))