Profiling.
This commit is contained in:
parent
54c97fc832
commit
776412995c
|
@ -1,9 +1,11 @@
|
||||||
# Use atan2 instead of acos to calc angle; atan2(x,y) of the point we potentially want to add
|
# Use atan2 instead of acos to calc angle; atan2(x,y) of the point we potentially want to add
|
||||||
from math import acos, sqrt
|
from math import acos, sqrt
|
||||||
|
|
||||||
|
from profile import Profiler
|
||||||
from util import Vector, Point, gen_point
|
from util import Vector, Point, gen_point
|
||||||
|
|
||||||
|
|
||||||
|
@Profiler("calculating angle")
|
||||||
def calc_angle(v1: Vector, v2: Vector) -> float:
|
def calc_angle(v1: Vector, v2: Vector) -> float:
|
||||||
dot = (v1.x * v2.x) + (v1.y * v2.y)
|
dot = (v1.x * v2.x) + (v1.y * v2.y)
|
||||||
len_1 = sqrt(v1.x**2 + v1.y**2)
|
len_1 = sqrt(v1.x**2 + v1.y**2)
|
||||||
|
@ -13,18 +15,21 @@ def calc_angle(v1: Vector, v2: Vector) -> float:
|
||||||
return acos(max(min(tmp, 1), -1)) # acos is only defined in [-1,1]
|
return acos(max(min(tmp, 1), -1)) # acos is only defined in [-1,1]
|
||||||
|
|
||||||
|
|
||||||
|
@Profiler("calculating vector")
|
||||||
def calc_vector(p1: Point, p2: Point) -> Vector:
|
def calc_vector(p1: Point, p2: Point) -> Vector:
|
||||||
return Vector((p2.x - p1.x), (p2. y - p1.y))
|
return Vector((p2.x - p1.x), (p2. y - p1.y))
|
||||||
|
|
||||||
|
|
||||||
|
@Profiler("gift_wrapper")
|
||||||
def rapper(points: set):
|
def rapper(points: set):
|
||||||
min_pt = min(points)
|
min_pt = min(points)
|
||||||
hull = [min_pt]
|
hull = [min_pt]
|
||||||
comp_vec = Vector(0, 1)
|
comp_vec = Vector(0, 1)
|
||||||
|
with Profiler("iterating points", excluded=("calculating angle", "calculating vector")):
|
||||||
while True:
|
while True:
|
||||||
hull.append(min(points - {hull[-1]},
|
hull.append(min(points - {hull[-1]},
|
||||||
key=lambda p: calc_angle(comp_vec,
|
key=lambda p: calc_angle(comp_vec, calc_vector(hull[-1], p))))
|
||||||
calc_vector(hull[-1], p))))
|
|
||||||
comp_vec = calc_vector(hull[-2], hull[-1])
|
comp_vec = calc_vector(hull[-2], hull[-1])
|
||||||
|
|
||||||
if hull[-1] == min_pt:
|
if hull[-1] == min_pt:
|
||||||
|
|
23
h2/graham.py
23
h2/graham.py
|
@ -1,8 +1,10 @@
|
||||||
from util import gen_point, Side, Point, display
|
from profile import Profiler
|
||||||
|
|
||||||
|
from util import gen_point, Side, display
|
||||||
|
|
||||||
|
|
||||||
|
@Profiler("calculating sidedness")
|
||||||
def sidedness(p1, p2, p3, eps=0.0000001):
|
def sidedness(p1, p2, p3, eps=0.0000001):
|
||||||
|
|
||||||
# Find line from p1 to p2, ask where p3 is in relation to this
|
# Find line from p1 to p2, ask where p3 is in relation to this
|
||||||
|
|
||||||
y = p3.y * (p2.x - p1.x)
|
y = p3.y * (p2.x - p1.x)
|
||||||
|
@ -18,33 +20,26 @@ def sidedness(p1, p2, p3, eps=0.0000001):
|
||||||
return Side.BELOW
|
return Side.BELOW
|
||||||
|
|
||||||
|
|
||||||
# test
|
@Profiler("graham_scan")
|
||||||
|
|
||||||
|
|
||||||
p1 = Point(4, 4)
|
|
||||||
p2 = Point(0, 0)
|
|
||||||
p3 = Point(5, 2)
|
|
||||||
|
|
||||||
|
|
||||||
# print(sidedness(p1, p2, p3))
|
|
||||||
|
|
||||||
|
|
||||||
def graham_scan(points):
|
def graham_scan(points):
|
||||||
# A funky issue where both a and b become negative in the sidedness test causes us to have to use
|
# A funky issue where both a and b become negative in the sidedness test causes us to have to use
|
||||||
# Side.ABOVE for both tests, regardless of UH or LH.
|
# Side.ABOVE for both tests, regardless of UH or LH.
|
||||||
|
with Profiler("sorting points"):
|
||||||
sorted_points = sorted(points)
|
sorted_points = sorted(points)
|
||||||
|
|
||||||
UH = sorted_points[:2]
|
UH = sorted_points[:2]
|
||||||
|
with Profiler("iterating upper hull", excluded=("calculating sidedness",)):
|
||||||
for s in sorted_points[2:]:
|
for s in sorted_points[2:]:
|
||||||
while len(UH) > 1 and (sidedness(UH[-2], UH[-1], s) != Side.ABOVE):
|
while len(UH) > 1 and (sidedness(UH[-2], UH[-1], s) != Side.ABOVE):
|
||||||
del UH[-1]
|
del UH[-1]
|
||||||
UH.append(s)
|
UH.append(s)
|
||||||
|
|
||||||
|
with Profiler("reversing list"):
|
||||||
reversed_list = list(reversed(sorted_points))
|
reversed_list = list(reversed(sorted_points))
|
||||||
reversed_list.append(UH[0])
|
reversed_list.append(UH[0])
|
||||||
LH = reversed_list[:2]
|
LH = reversed_list[:2]
|
||||||
|
|
||||||
|
with Profiler("iterating lower hull", excluded=("calculating sidedness",)):
|
||||||
for s in reversed_list[2:]:
|
for s in reversed_list[2:]:
|
||||||
while len(LH) > 1 and (sidedness(LH[-2], LH[-1], s) != Side.ABOVE):
|
while len(LH) > 1 and (sidedness(LH[-2], LH[-1], s) != Side.ABOVE):
|
||||||
del LH[-1]
|
del LH[-1]
|
||||||
|
|
69
h2/mbc.py
69
h2/mbc.py
|
@ -1,8 +1,8 @@
|
||||||
import random
|
import random
|
||||||
from math import sqrt
|
|
||||||
from typing import Set
|
from typing import Set
|
||||||
|
|
||||||
from util import Side, Point, gen_point, display, gen_circular_point, gen_triangular_point
|
from profile import Profiler
|
||||||
|
from util import Side, Point, gen_point, display, gen_circular_point
|
||||||
|
|
||||||
|
|
||||||
def sidedness(slope: float, intersection: float, p3: Point, flipper: callable, eps=0.0000001) -> Side:
|
def sidedness(slope: float, intersection: float, p3: Point, flipper: callable, eps=0.0000001) -> Side:
|
||||||
|
@ -14,6 +14,7 @@ def sidedness(slope: float, intersection: float, p3: Point, flipper: callable, e
|
||||||
return Side.BELOW
|
return Side.BELOW
|
||||||
|
|
||||||
|
|
||||||
|
@Profiler("solving 1D LP")
|
||||||
def solve_1dlp(c, constraints):
|
def solve_1dlp(c, constraints):
|
||||||
c1, c2 = c
|
c1, c2 = c
|
||||||
((a1, a2), b) = constraints[-1]
|
((a1, a2), b) = constraints[-1]
|
||||||
|
@ -22,7 +23,6 @@ def solve_1dlp(c, constraints):
|
||||||
interval = [-10_000, 10_000]
|
interval = [-10_000, 10_000]
|
||||||
|
|
||||||
for (lel_a1, lel_a2), lel_b in constraints:
|
for (lel_a1, lel_a2), lel_b in constraints:
|
||||||
|
|
||||||
bj, aj = (lel_b - lel_a2 * q), (lel_a1 - lel_a2 * p)
|
bj, aj = (lel_b - lel_a2 * q), (lel_a1 - lel_a2 * p)
|
||||||
if aj < 0 and bj / aj > interval[0]:
|
if aj < 0 and bj / aj > interval[0]:
|
||||||
interval[0] = bj / aj
|
interval[0] = bj / aj
|
||||||
|
@ -36,6 +36,7 @@ def solve_1dlp(c, constraints):
|
||||||
return interval[1], q - (p * interval[1])
|
return interval[1], q - (p * interval[1])
|
||||||
|
|
||||||
|
|
||||||
|
@Profiler("solving 2D LP")
|
||||||
def solve_2dlp(c, constraints):
|
def solve_2dlp(c, constraints):
|
||||||
c1, c2 = c
|
c1, c2 = c
|
||||||
x1 = -10_000 if c1 > 0 else 10_000
|
x1 = -10_000 if c1 > 0 else 10_000
|
||||||
|
@ -47,6 +48,7 @@ def solve_2dlp(c, constraints):
|
||||||
return x1, x2
|
return x1, x2
|
||||||
|
|
||||||
|
|
||||||
|
@Profiler("finding median")
|
||||||
def find_median(points):
|
def find_median(points):
|
||||||
num_candidates = min(5, len(points))
|
num_candidates = min(5, len(points))
|
||||||
candidates = random.sample(points, num_candidates)
|
candidates = random.sample(points, num_candidates)
|
||||||
|
@ -59,40 +61,77 @@ def find_median(points):
|
||||||
return median[0]
|
return median[0]
|
||||||
|
|
||||||
|
|
||||||
def mbc_ch(points: Set[Point], flipper: callable) -> Set[Point]:
|
def is_left(a: Point, b: Point, c: Point):
|
||||||
|
return ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)) > 0
|
||||||
|
|
||||||
|
|
||||||
|
def mbc_ch(points: Set[Point], flipper: callable, extra_prune=False, shuffle=True) -> Set[Point]:
|
||||||
if len(points) < 2:
|
if len(points) < 2:
|
||||||
return points
|
return points
|
||||||
|
|
||||||
|
# Extra pruning step
|
||||||
|
if extra_prune:
|
||||||
|
with Profiler("extra pruning step"):
|
||||||
|
left_point = min(points, key=lambda p: (p.x, -p.y))
|
||||||
|
right_point = max(points, key=lambda p: (p.x, -p.y))
|
||||||
|
if flipper(1) == 1:
|
||||||
|
points = {p for p in points if is_left(left_point, right_point, p)}.union({left_point, right_point})
|
||||||
|
else:
|
||||||
|
points = {p for p in points if not is_left(left_point, right_point, p)}.union({left_point, right_point})
|
||||||
|
|
||||||
# Find the point with median x-coordinate, and partition the points on this point
|
# Find the point with median x-coordinate, and partition the points on this point
|
||||||
med_x = find_median(points)
|
med_x = find_median(points)
|
||||||
|
|
||||||
# Find left and right points in regards to median
|
# Find left and right points in regards to median
|
||||||
|
with Profiler("partitioning set"):
|
||||||
pl = {p for p in points if p.x < med_x}
|
pl = {p for p in points if p.x < med_x}
|
||||||
pr = {p for p in points if p.x >= med_x}
|
pr = {p for p in points if p.x >= med_x}
|
||||||
|
|
||||||
|
# Shuffle
|
||||||
|
constraints = [((flipper(-p.x), flipper(-1)), flipper(-p.y)) for p in points]
|
||||||
|
if shuffle:
|
||||||
|
with Profiler("shuffling constraints"):
|
||||||
|
random.shuffle(constraints)
|
||||||
|
|
||||||
# Find the bridge over the vertical line in pm
|
# Find the bridge over the vertical line in pm
|
||||||
slope, intercept = solve_2dlp((flipper(med_x), flipper(1)),
|
slope, intercept = solve_2dlp((flipper(med_x), flipper(1)), constraints)
|
||||||
[((flipper(-p.x), flipper(-1)), flipper(-p.y)) for p in points])
|
|
||||||
|
|
||||||
|
|
||||||
|
with Profiler("finding bridge points"):
|
||||||
left_point = next(p for p in pl if sidedness(slope, intercept, p, flipper) == Side.ON)
|
left_point = next(p for p in pl if sidedness(slope, intercept, p, flipper) == Side.ON)
|
||||||
right_point = next(p for p in pr if sidedness(slope, intercept, p, flipper) == Side.ON)
|
right_point = next(p for p in pr if sidedness(slope, intercept, p, flipper) == Side.ON)
|
||||||
|
|
||||||
|
|
||||||
# Find the two points which are on the line
|
|
||||||
#dist_to_line = lambda p: abs(intercept + slope * p.x - p.y)/sqrt(1 + slope**2)
|
|
||||||
#left_point = min(pl, key=dist_to_line)
|
|
||||||
#right_point = min(pr, key=dist_to_line)
|
|
||||||
|
|
||||||
# Prune the points between the two line points
|
# Prune the points between the two line points
|
||||||
|
with Profiler("pruning between line points"):
|
||||||
pl = {p for p in pl if p.x <= left_point.x}
|
pl = {p for p in pl if p.x <= left_point.x}
|
||||||
pr = {p for p in pr if p.x >= right_point.x}
|
pr = {p for p in pr if p.x >= right_point.x}
|
||||||
|
|
||||||
return set.union(mbc_ch(pl, flipper), {left_point, right_point}, mbc_ch(pr, flipper))
|
return set.union(mbc_ch(pl, flipper, extra_prune=extra_prune, shuffle=shuffle),
|
||||||
|
{left_point, right_point},
|
||||||
|
mbc_ch(pr, flipper, extra_prune=extra_prune, shuffle=shuffle))
|
||||||
|
|
||||||
|
|
||||||
|
@Profiler("mbc")
|
||||||
def mbc(points: Set[Point]) -> Set[Point]:
|
def mbc(points: Set[Point]) -> Set[Point]:
|
||||||
return set.union(mbc_ch(points, lambda x: x), mbc_ch(points, lambda x: -x))
|
return set.union(mbc_ch(points, lambda x: x, extra_prune=False, shuffle=True),
|
||||||
|
mbc_ch(points, lambda x: -x, extra_prune=False, shuffle=True))
|
||||||
|
|
||||||
|
|
||||||
|
@Profiler("mbc2")
|
||||||
|
def mbc2(points: Set[Point]) -> Set[Point]:
|
||||||
|
return set.union(mbc_ch(points, lambda x: x, extra_prune=True, shuffle=True),
|
||||||
|
mbc_ch(points, lambda x: -x, extra_prune=True, shuffle=True))
|
||||||
|
|
||||||
|
|
||||||
|
@Profiler("mbc_no_shuffle")
|
||||||
|
def mbc_no_shuffle(points: Set[Point]) -> Set[Point]:
|
||||||
|
return set.union(mbc_ch(points, lambda x: x, extra_prune=False, shuffle=False),
|
||||||
|
mbc_ch(points, lambda x: -x, extra_prune=False, shuffle=False))
|
||||||
|
|
||||||
|
|
||||||
|
@Profiler("mbc2_no_shuffle")
|
||||||
|
def mbc2_no_shuffle(points: Set[Point]) -> Set[Point]:
|
||||||
|
return set.union(mbc_ch(points, lambda x: x, extra_prune=True, shuffle=False),
|
||||||
|
mbc_ch(points, lambda x: -x, extra_prune=True, shuffle=False))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
26
h2/profile.py
Normal file
26
h2/profile.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import time
|
||||||
|
from collections import defaultdict
|
||||||
|
from contextlib import ContextDecorator
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
|
||||||
|
class Profiler(ContextDecorator):
|
||||||
|
results = defaultdict(float)
|
||||||
|
|
||||||
|
def __init__(self, name: str, excluded: Tuple = None) -> None:
|
||||||
|
self.name = name
|
||||||
|
self.excluded = excluded or ()
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
self.start = time.time()
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, *exc):
|
||||||
|
stop = time.time()
|
||||||
|
excluded = sum(self.results[e] for e in self.excluded)
|
||||||
|
self.results[self.name] += stop - self.start - excluded
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reset(cls):
|
||||||
|
cls.results.clear()
|
|
@ -1,6 +1,7 @@
|
||||||
from math import sqrt
|
from math import sqrt
|
||||||
from typing import Set
|
from typing import Set
|
||||||
|
|
||||||
|
from profile import Profiler
|
||||||
from util import Point, gen_point, display
|
from util import Point, gen_point, display
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,6 +15,7 @@ def is_left(a: Point, b: Point, c: Point):
|
||||||
return ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)) > 0
|
return ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)) > 0
|
||||||
|
|
||||||
|
|
||||||
|
@Profiler("quick_hull")
|
||||||
def quick_hull(points: Set[Point]):
|
def quick_hull(points: Set[Point]):
|
||||||
left = min(points)
|
left = min(points)
|
||||||
right = max(points)
|
right = max(points)
|
||||||
|
@ -21,12 +23,16 @@ def quick_hull(points: Set[Point]):
|
||||||
hull = {left, right}
|
hull = {left, right}
|
||||||
points = points - hull
|
points = points - hull
|
||||||
|
|
||||||
find_hull({p for p in points if not is_left(left, right, p)},
|
with Profiler("partitioning set"):
|
||||||
|
partition = {p for p in points if not is_left(left, right, p)}
|
||||||
|
find_hull(partition,
|
||||||
left,
|
left,
|
||||||
right,
|
right,
|
||||||
hull)
|
hull)
|
||||||
|
|
||||||
find_hull({p for p in points if not is_left(right, left, p)},
|
with Profiler("partitioning set"):
|
||||||
|
partition = {p for p in points if not is_left(right, left, p)}
|
||||||
|
find_hull(partition,
|
||||||
right,
|
right,
|
||||||
left,
|
left,
|
||||||
hull)
|
hull)
|
||||||
|
@ -38,16 +44,21 @@ def find_hull(points: Set[Point], p: Point, q: Point, hull: Set[Point]):
|
||||||
if not points:
|
if not points:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
with Profiler("finding farthest point from line"):
|
||||||
farthest = max(points, key=lambda point: abs(distance(p, q, point)))
|
farthest = max(points, key=lambda point: abs(distance(p, q, point)))
|
||||||
hull.add(farthest)
|
hull.add(farthest)
|
||||||
points.remove(farthest)
|
points.remove(farthest)
|
||||||
|
|
||||||
find_hull({po for po in points if not is_left(p, farthest, po)},
|
with Profiler("partitioning set"):
|
||||||
|
partition = {po for po in points if not is_left(p, farthest, po)}
|
||||||
|
find_hull(partition,
|
||||||
p,
|
p,
|
||||||
farthest,
|
farthest,
|
||||||
hull)
|
hull)
|
||||||
|
|
||||||
find_hull({po for po in points if not is_left(farthest, q, po)},
|
with Profiler("partitioning set"):
|
||||||
|
partition = {po for po in points if not is_left(farthest, q, po)}
|
||||||
|
find_hull(partition,
|
||||||
farthest,
|
farthest,
|
||||||
q,
|
q,
|
||||||
hull)
|
hull)
|
||||||
|
|
|
@ -4,7 +4,8 @@ from collections import namedtuple
|
||||||
import util
|
import util
|
||||||
from gift_wrapper import rapper
|
from gift_wrapper import rapper
|
||||||
from graham import graham_scan
|
from graham import graham_scan
|
||||||
from mbc import mbc
|
from mbc import mbc, mbc_no_shuffle, mbc2_no_shuffle, mbc2
|
||||||
|
from profile import Profiler
|
||||||
from quick_hull import quick_hull
|
from quick_hull import quick_hull
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
|
@ -13,9 +14,8 @@ import os.path
|
||||||
TimedResult = namedtuple("TimedResult", "algorithm points running_time")
|
TimedResult = namedtuple("TimedResult", "algorithm points running_time")
|
||||||
|
|
||||||
|
|
||||||
def time_it(f: callable, args: tuple = (), iterations=1):
|
def time_it(f: callable, args: tuple = ()):
|
||||||
start = time()
|
start = time()
|
||||||
for i in range(iterations):
|
|
||||||
f(*args)
|
f(*args)
|
||||||
return str(time() - start)
|
return str(time() - start)
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ def initiate_file(file):
|
||||||
|
|
||||||
|
|
||||||
def write_to_log(file, data):
|
def write_to_log(file, data):
|
||||||
|
|
||||||
if not os.path.isfile(file):
|
if not os.path.isfile(file):
|
||||||
initiate_file(file)
|
initiate_file(file)
|
||||||
|
|
||||||
|
@ -42,49 +41,41 @@ def write_to_log(file, data):
|
||||||
open_file.write(write_string)
|
open_file.write(write_string)
|
||||||
|
|
||||||
|
|
||||||
def do_square_tests(amount_of_points):
|
def calculate_hulls(number_of_points, points):
|
||||||
points_square = {util.gen_point(0, 100) for _ in range(amount_of_points)}
|
return [TimedResult("graham", number_of_points, time_it(graham_scan, args=(points,))),
|
||||||
amount_of_points = str(amount_of_points)
|
TimedResult("gift", number_of_points, time_it(rapper, args=(points,))),
|
||||||
|
TimedResult("quick", number_of_points, time_it(quick_hull, args=(points,))),
|
||||||
|
TimedResult("mbch", number_of_points, time_it(mbc, args=(points,))),
|
||||||
|
TimedResult("mbch2", number_of_points, time_it(mbc2, args=(points,)))]
|
||||||
|
|
||||||
results = [TimedResult("graham", amount_of_points, time_it(graham_scan, args=(points_square,))),
|
|
||||||
TimedResult("gift", amount_of_points, time_it(rapper, args=(points_square,))),
|
|
||||||
TimedResult("quick", amount_of_points, time_it(quick_hull, args=(points_square,))),
|
|
||||||
TimedResult("mbch", amount_of_points, time_it(mbc, args=(points_square,)))]
|
|
||||||
|
|
||||||
|
def do_square_tests(number_of_points):
|
||||||
|
points_square = {util.gen_point(0, 100) for _ in range(number_of_points)}
|
||||||
|
number_of_points = str(number_of_points)
|
||||||
|
|
||||||
|
results = calculate_hulls(number_of_points, points_square)
|
||||||
write_to_log("square_tests.log", results)
|
write_to_log("square_tests.log", results)
|
||||||
|
|
||||||
|
|
||||||
def do_circular_tests(amount_of_points):
|
def do_circular_tests(number_of_points):
|
||||||
points_circular = {util.gen_point(0, 100) for _ in range(amount_of_points)}
|
points_circular = {util.gen_point(0, 100) for _ in range(number_of_points)}
|
||||||
|
|
||||||
results = [TimedResult("graham", amount_of_points, time_it(graham_scan, args=(points_circular,))),
|
|
||||||
TimedResult("gift", amount_of_points, time_it(rapper, args=(points_circular,))),
|
|
||||||
TimedResult("quick", amount_of_points, time_it(quick_hull, args=(points_circular,))),
|
|
||||||
TimedResult("mbc", amount_of_points, time_it(mbc, args=(points_circular,)))]
|
|
||||||
|
|
||||||
|
results = calculate_hulls(number_of_points, points_circular)
|
||||||
write_to_log("circular_tests.log", results)
|
write_to_log("circular_tests.log", results)
|
||||||
|
|
||||||
|
|
||||||
def do_triangular_tests(amount_of_points):
|
def do_triangular_tests(number_of_points):
|
||||||
left, right, top = util.Point(1,1), util.Point(51,1), util.Point(26,40)
|
left, right, top = util.Point(1,1), util.Point(51,1), util.Point(26,40)
|
||||||
points = {util.gen_triangular_point(left, right, top) for _ in range(amount_of_points)}
|
points = {util.gen_triangular_point(left, right, top) for _ in range(number_of_points)}
|
||||||
|
|
||||||
results = [TimedResult("graham", amount_of_points, time_it(graham_scan, args=(points,))),
|
|
||||||
TimedResult("gift", amount_of_points, time_it(rapper, args=(points,))),
|
|
||||||
TimedResult("quick", amount_of_points, time_it(quick_hull, args=(points,))),
|
|
||||||
TimedResult("mbc", amount_of_points, time_it(mbc, args=(points,)))]
|
|
||||||
|
|
||||||
|
results = calculate_hulls(number_of_points, points)
|
||||||
write_to_log("triangular_tests.log", results)
|
write_to_log("triangular_tests.log", results)
|
||||||
|
|
||||||
|
|
||||||
def do_quadratic_tests(amount_of_points):
|
def do_quadratic_tests(number_of_points):
|
||||||
points = {util.gen_weird_point(-10, 10) for _ in range(amount_of_points)}
|
points = {util.gen_weird_point(-10, 10) for _ in range(number_of_points)}
|
||||||
|
|
||||||
results = [TimedResult("graham", amount_of_points, time_it(graham_scan, args=(points,))),
|
|
||||||
TimedResult("gift", amount_of_points, time_it(rapper, args=(points,))),
|
|
||||||
TimedResult("quick", amount_of_points, time_it(quick_hull, args=(points,))),
|
|
||||||
TimedResult("mbc", amount_of_points, time_it(mbc, args=(points,)))]
|
|
||||||
|
|
||||||
|
results = calculate_hulls(number_of_points, points)
|
||||||
write_to_log("quadratic_tests.log", results)
|
write_to_log("quadratic_tests.log", results)
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,10 +85,46 @@ def sanity_check():
|
||||||
gift = set(rapper(points))
|
gift = set(rapper(points))
|
||||||
quick = quick_hull(points)
|
quick = quick_hull(points)
|
||||||
mbch = set.union(mbc(points))
|
mbch = set.union(mbc(points))
|
||||||
assert gift == graham == quick == mbch
|
mbch2 = set.union(mbc2(points))
|
||||||
|
assert gift == graham == quick == mbch == mbch2
|
||||||
|
|
||||||
|
|
||||||
|
def do_profile():
|
||||||
|
print("==================================== PROFILE RESULTS ====================================")
|
||||||
|
random.seed(6)
|
||||||
|
points = {util.gen_point(0, 100) for _ in range(60_000)}
|
||||||
|
|
||||||
|
tests = [
|
||||||
|
("graham_scan", graham_scan),
|
||||||
|
("gift_wrapper", rapper),
|
||||||
|
("quick_hull", quick_hull),
|
||||||
|
("mbc", mbc),
|
||||||
|
("mbc2", mbc2),
|
||||||
|
("mbc_no_shuffle", mbc_no_shuffle),
|
||||||
|
("mbc2_no_shuffle", mbc2_no_shuffle),
|
||||||
|
]
|
||||||
|
|
||||||
|
for algorithm, func in tests:
|
||||||
|
Profiler.reset()
|
||||||
|
func(points)
|
||||||
|
|
||||||
|
times = Profiler.results
|
||||||
|
|
||||||
|
print(f"-------------- {algorithm} --------------")
|
||||||
|
print("Times:", times)
|
||||||
|
|
||||||
|
total = times[algorithm]
|
||||||
|
print("Total:", total)
|
||||||
|
|
||||||
|
sum_profiled = sum(times.values()) - total
|
||||||
|
print("Total Profiled:", sum_profiled)
|
||||||
|
|
||||||
|
print("Unaccounted:", total - sum_profiled)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
sanity_check()
|
sanity_check()
|
||||||
|
do_profile()
|
||||||
|
exit()
|
||||||
for i in range(50, 1000, 50):
|
for i in range(50, 1000, 50):
|
||||||
do_square_tests(i)
|
do_square_tests(i)
|
||||||
|
|
|
@ -72,6 +72,7 @@ def gen_graph(data):
|
||||||
graham = data['graham']
|
graham = data['graham']
|
||||||
quick = data['quick']
|
quick = data['quick']
|
||||||
mbch = data['mbch']
|
mbch = data['mbch']
|
||||||
|
mbch2 = data['mbch2']
|
||||||
gift = data['gift']
|
gift = data['gift']
|
||||||
|
|
||||||
graham_x = [p[0] for p in graham]
|
graham_x = [p[0] for p in graham]
|
||||||
|
@ -83,15 +84,19 @@ def gen_graph(data):
|
||||||
mbch_x = [p[0] for p in mbch]
|
mbch_x = [p[0] for p in mbch]
|
||||||
mbch_y = [p[1] for p in mbch]
|
mbch_y = [p[1] for p in mbch]
|
||||||
|
|
||||||
|
mbch2_x = [p[0] for p in mbch2]
|
||||||
|
mbch2_y = [p[1] for p in mbch2]
|
||||||
|
|
||||||
gift_x = [p[0] for p in gift]
|
gift_x = [p[0] for p in gift]
|
||||||
gift_y = [p[1] for p in gift]
|
gift_y = [p[1] for p in gift]
|
||||||
|
|
||||||
plt.plot(graham_x, graham_y)
|
plt.plot(graham_x, graham_y)
|
||||||
plt.plot(quick_x, quick_y)
|
plt.plot(quick_x, quick_y)
|
||||||
plt.plot(mbch_x, mbch_y)
|
plt.plot(mbch_x, mbch_y)
|
||||||
|
plt.plot(mbch2_x, mbch2_y)
|
||||||
plt.plot(gift_x, gift_y)
|
plt.plot(gift_x, gift_y)
|
||||||
|
|
||||||
plt.legend(['graham', 'quick', 'mbch', 'gift'], loc='upper left')
|
plt.legend(['graham', 'quick', 'mbch', 'mbch2', 'gift'], loc='upper left')
|
||||||
|
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user