BerGeo/h2/tmptest.py

237 lines
6.6 KiB
Python

import json
import random
from time import time
from collections import namedtuple
import util
from gift_wrapper import rapper
from graham import graham_scan
from mbc import mbc, mbc_no_shuffle, mbc2_no_shuffle, mbc2
from profile import Profiler
from quick_hull import quick_hull
import os.path
import matplotlib.pyplot as plt
#random.seed(1337_420)
TimedResult = namedtuple("TimedResult", "algorithm points running_time")
def time_it(f: callable, args: tuple = ()):
start = time()
f(*args)
return str(time() - start)
def initiate_file(file):
with open(file, "w+") as tmp:
tmp.write("algorithm\t\tpoints\t\ttime")
def write_to_log(file, data):
if not os.path.isfile(file):
initiate_file(file)
tmp = []
for res in data:
line = str.join("\t\t", res)
print(line)
tmp.append(line)
write_string = "\n" + str.join("\n", tmp)
with open(file, "a+") as open_file:
open_file.write(write_string)
def calculate_hulls(number_of_points, points):
return [TimedResult("graham", number_of_points, time_it(graham_scan, args=(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,)))]
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)
def do_circular_tests(number_of_points):
points_circular = {util.gen_point(0, 100) for _ in range(number_of_points)}
results = calculate_hulls(number_of_points, points_circular)
write_to_log("circular_tests.log", results)
def do_triangular_tests(number_of_points):
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(number_of_points)}
results = calculate_hulls(number_of_points, points)
write_to_log("triangular_tests.log", results)
def do_quadratic_tests(number_of_points):
points = {util.gen_weird_point(-10, 10) for _ in range(number_of_points)}
results = calculate_hulls(number_of_points, points)
write_to_log("quadratic_tests.log", results)
def sanity_check():
points = {util.gen_point(1, 50) for i in range(100)}
graham = set(graham_scan(points))
gift = set(rapper(points))
quick = quick_hull(points)
mbch = set.union(mbc(points))
mbch2 = set.union(mbc2(points))
assert gift == graham == quick == mbch == mbch2
def do_one_profile(num_points):
print(f"==================================== PROFILE ({num_points}) ====================================")
random.seed(6)
points = {util.gen_point(0, 100) for _ in range(num_points)}
tests = [
("graham_scan", graham_scan),
#("gift_wrapper", rapper),
("quick_hull", quick_hull),
("mbc", mbc),
("mbc_no_shuffle", mbc_no_shuffle),
("mbc2", mbc2),
("mbc2_no_shuffle", mbc2_no_shuffle),
]
results = {}
for algorithm, func in tests:
Profiler.reset()
func(points)
times = dict(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)
unaccounted = total - sum_profiled
print("Unaccounted:", unaccounted)
times["other"] = unaccounted
results[algorithm] = {
"times": times,
"total": total,
"total_profiled": sum_profiled,
"unaccounted": unaccounted,
}
return results
def plot_mbc(results, ax):
algorithms = list(results.keys())
steps = (
"other",
"finding median",
"partitioning set",
"building constraints",
"solving LP",
"finding bridge points",
"pruning between line points",
"shuffling constraints",
"extra pruning step",
)
util.stacked_bar(ax=ax,
data=[[result["times"].get(step, 0) * 1000 for result in results.values()] for step in steps],
series_labels=steps,
category_labels=algorithms,
value_format="{:.1f}")
def plot_graham(result, ax):
steps = (
"other",
"sorting points",
"iterating points",
"calculating sidedness",
)
util.stacked_bar(ax=ax,
data=[[result["times"][step] * 1000] for step in steps],
series_labels=steps,
category_labels=["graham scan"],
value_format="{:.1f}")
def plot_gift(result, ax):
steps = (
"other",
"calculating angle",
"calculating vector",
)
util.stacked_bar(ax=ax,
data=[[result["times"][step] * 1000] for step in steps],
series_labels=steps,
category_labels=["gift wrapper"],
value_format="{:.1f}")
def plot_quick(result, ax):
steps = (
"other",
"partitioning set",
"finding farthest point from line",
)
util.stacked_bar(ax=ax,
data=[[result["times"][step] * 1000] for step in steps],
series_labels=steps,
category_labels=["quickhull"],
value_format="{:.1f}")
def do_profile():
num_points = 60_000
results = do_one_profile(num_points)
print("================== RESULTS ==================")
print(json.dumps(results))
fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, sharex=False, sharey=True, gridspec_kw={"width_ratios": (1, 1, 4)})
fig.add_subplot(111, frameon=False)
plt.tick_params(labelcolor='none', top='off', bottom='off', left='off', right='off')
plt.ylabel("time (ms)")
plt.subplots_adjust(wspace=0)
plot_graham(results["graham_scan"], ax1)
#plot_gift(results["gift_wrapper"], ax2)
plot_quick(results["quick_hull"], ax2)
plot_mbc({alg: data
for alg, data in results.items()
if alg.startswith("mbc")},
ax3)
plt.show()
if __name__ == '__main__':
sanity_check()
do_profile()
exit()
for i in range(50, 1000, 50):
do_square_tests(i)