Skip to content

Commit

Permalink
Merge 3551354 into c5f8afe
Browse files Browse the repository at this point in the history
  • Loading branch information
RyanStonebraker committed Feb 4, 2020
2 parents c5f8afe + 3551354 commit cf4caa5
Show file tree
Hide file tree
Showing 6 changed files with 2,133 additions and 96 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ __pycache__/
.coverage
mieda.egg-info
htmlcov
build
build
.ipynb_checkpoints
77 changes: 77 additions & 0 deletions comparisons/iterative.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
def createInterval(start, finish, keys, key):
new_interval = {}
new_interval["start"] = start
new_interval["finish"] = finish
new_interval[key] = keys.copy()
return new_interval


def getMainPermutations(intervals, key):
conflicts = False
new_intervals = []
for start_interval in intervals:
for compare_interval in intervals:
if start_interval["start"] >= compare_interval["finish"] or start_interval["finish"] <= compare_interval["start"]:
continue
conflicts = True

first_finish = start_interval["start"]
if start_interval["start"] != compare_interval["start"]:
first_start = min(start_interval["start"], compare_interval["start"])
first_finish = max(start_interval["start"], compare_interval["start"])
keys = start_interval[key] if start_interval["start"] < compare_interval["start"] else compare_interval[key]
new_interval = createInterval(first_start, first_finish, keys, key)
if new_interval not in new_intervals:
new_intervals.append(new_interval)

last_start = start_interval["finish"]
if start_interval["finish"] != compare_interval["finish"]:
last_start = min(start_interval["finish"], compare_interval["finish"])
last_finish = max(start_interval["finish"], compare_interval["finish"])
keys = start_interval[key] if start_interval["finish"] > compare_interval["finish"] else compare_interval[key]
new_interval = createInterval(last_start, last_finish, keys, key)
if new_interval not in new_intervals:
new_intervals.append(new_interval)

new_interval = createInterval(first_finish, last_start, start_interval[key].union(compare_interval[key]), key)
if new_interval not in new_intervals:
new_intervals.append(new_interval)
return conflicts, new_intervals


def resolveConflicts(intervals, key):
resolved_intervals = []
skip = {}
unresolved = False
for i, start_interval in enumerate(intervals):
if (start_interval["start"], start_interval["finish"]) in skip:
continue

conflict = False
for j, compare_interval in enumerate(intervals):
if start_interval["start"] == compare_interval["start"] and start_interval["finish"] > compare_interval["finish"]:
compare_interval[key] = compare_interval[key].union(start_interval[key])
conflict = True
break

if start_interval["start"] < compare_interval["start"] < start_interval["finish"]:
unresolved = True

elif (start_interval["start"], start_interval["finish"]) == (compare_interval["start"], compare_interval["finish"]):
start_interval[key] = start_interval[key].union(compare_interval[key])
skip[(start_interval["start"], start_interval["finish"])] = True

if not conflict:
resolved_intervals.append(start_interval)
return unresolved, resolved_intervals

class Merge:
@staticmethod
def union(intervals: list, key: str = "set_items"):
while True:
conflict, intervals = getMainPermutations(intervals, key)
unresolved, intervals = resolveConflicts(intervals, key) if conflict else (False, intervals)
if not unresolved:
break

return intervals
110 changes: 110 additions & 0 deletions comparisons/iterative_optimized.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
from operator import itemgetter


def create_interval(start, finish, keys, key):
new_interval = {}
new_interval["start"] = start
new_interval["finish"] = finish
new_interval[key] = keys.copy()
return new_interval


def get_max_list_intervals(min_start, max_list, key):
intervals = []
max_list = sorted(max_list, key=lambda x: x["point"])
for i, end in enumerate(max_list):
if i == 0 or min_start["point"] == end["point"]:
if len(max_list) == 1:
intervals.append(create_interval(min_start["point"], end["point"], end["keys"], key))
min_start["keys"] = min_start["keys"].union(end["keys"])
continue

keys = set()
if min_start["label"] == "start":
keys = min_start["keys"].union(intervals[-1][key]) if len(intervals) > 0 else min_start["keys"]
elif end["label"] == "finish":
if i + 1 < len(max_list):
if max_list[i+1]["label"] == "start" and intervals:
keys = intervals[-1][key].difference(max_list[i-1]["keys"])
else:
keys = end["keys"].union(max_list[i+1]["keys"])
else:
keys = end["keys"]
else:
keys = intervals[-1][key].difference(min_start["keys"]).difference(end["keys"])

intervals.append(create_interval(min_start["point"], end["point"], keys, key))
min_start = end
return intervals


def merge_same_intervals(intervals, key):
new_intervals = []
last_interval = intervals[0]
for interval in intervals[1:]:
if (last_interval["start"], last_interval["finish"]) == (interval["start"], interval["finish"]):
last_interval[key] = last_interval[key].union(interval[key])
else:
new_intervals.append(last_interval)
last_interval = interval
if not new_intervals or new_intervals[-1] != last_interval:
new_intervals.append(last_interval)
return new_intervals


def create_vertex(interval, label, key):
vertex = {"point": interval[label], "keys": interval[key], "label": label}
return vertex


def get_main_permutations(intervals, key):
conflicts = False
new_intervals = []
intervals = sorted(intervals, key=itemgetter("start", "finish"))
intervals = merge_same_intervals(intervals, key)

min_start = create_vertex(intervals[0], "start", key)
max_end = intervals[0]["finish"]
max_list = [create_vertex(intervals[0], "start", key), create_vertex(intervals[0], "finish", key)]
for interval in intervals[1:]:
if min_start["point"] < interval["start"] < max_end:
max_list.append(create_vertex(interval, "start", key))
max_list.append(create_vertex(interval, "finish", key))
max_end = max(max_end, interval["finish"])
elif min_start["point"] < interval["finish"] < max_end:
max_list.append(create_vertex(interval, "finish", key))
elif min_start["point"] == interval["start"] and interval["finish"] > max_end:
min_start["keys"] = min_start["keys"].union(interval[key])
max_list.append(create_vertex(interval, "finish", key))
max_end = interval["finish"]

if interval["start"] >= max_end:
new_intervals += get_max_list_intervals(min_start, max_list, key)
min_start = create_vertex(interval, "start", key)
max_list = [create_vertex(interval, "finish", key)]
new_intervals += get_max_list_intervals(min_start, max_list, key)

return conflicts, new_intervals


def resolve_conflicts(intervals, key):
resolved_intervals = []
current_interval = intervals[0]
for interval in intervals[1:]:
if interval["start"] > current_interval["start"]:
resolved_intervals.append(current_interval)
current_interval = interval
else:
current_interval[key] = current_interval[key].union(interval[key])
resolved_intervals.append(current_interval)
return resolved_intervals


class Merge:
@staticmethod
def union(intervals: list, key: str = "set_items"):
conflict, intervals = get_main_permutations(intervals, key)
if conflict:
intervals = sorted(intervals, key=itemgetter("start", "finish"))
intervals = resolve_conflicts(intervals, key)
return intervals

0 comments on commit cf4caa5

Please sign in to comment.