BerGeo/h2/tmptest.py

238 lines
9.1 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",
"calc 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",
"find farthest point",
)
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)
results = {"graham_scan": {"times": {"sorting points": 0.039986371994018555, "calc sidedness": 0.20061016082763672, "iterating points": 0.1414051055908203, "graham_scan": 0.48474693298339844, "other": 0.10274529457092285}, "total": 0.48474693298339844, "total_profiled": 0.3820016384124756, "unaccounted": 0.10274529457092285}, "quick_hull": {"times": {"partitioning set": 0.1488804817199707, "find farthest point": 0.0767507553100586, "quick_hull": 0.24364948272705078, "other": 0.018018245697021484}, "total": 0.24364948272705078, "total_profiled": 0.2256312370300293, "unaccounted": 0.018018245697021484}, "mbc": {"times": {"finding median": 0.008962392807006836, "partitioning set": 0.08010172843933105, "building constraints": 0.14875221252441406, "shuffling constraints": 0.08788180351257324, "solving LP": 0.14783930778503418, "finding bridge points": 0.06223654747009277, "pruning between line points": 0.05157780647277832, "mbc": 0.625605583190918, "other": 0.0382537841796875}, "total": 0.625605583190918, "total_profiled": 0.5873517990112305, "unaccounted": 0.0382537841796875}, "mbc_no_shuffle": {"times": {"finding median": 0.007230997085571289, "partitioning set": 0.06375980377197266, "building constraints": 0.12821173667907715, "solving LP": 0.06401801109313965, "finding bridge points": 0.05544614791870117, "pruning between line points": 0.042369842529296875, "mbc_no_shuffle": 0.3726029396057129, "other": 0.011566400527954102}, "total": 0.3726029396057129, "total_profiled": 0.3610365390777588, "unaccounted": 0.011566400527954102}, "mbc2": {"times": {"extra pruning step": 0.15880751609802246, "finding median": 0.0018236637115478516, "partitioning set": 0.022843599319458008, "building constraints": 0.04632830619812012, "shuffling constraints": 0.02962517738342285, "solving LP": 0.05501532554626465, "finding bridge points": 0.02581334114074707, "pruning between line points": 0.015393733978271484, "mbc2": 0.36753416061401367, "other": 0.01188349723815918}, "total": 0.36753416061401367, "total_profiled": 0.3556506633758545, "unaccounted": 0.01188349723815918}, "mbc2_no_shuffle": {"times": {"extra pruning step": 0.15827727317810059, "finding median": 0.0018894672393798828, "partitioning set": 0.0220644474029541, "building constraints": 0.04755878448486328, "solving LP": 0.026836633682250977, "finding bridge points": 0.023386240005493164, "pruning between line points": 0.01653766632080078, "mbc2_no_shuffle": 0.30204010009765625, "other": 0.0054895877838134766}, "total": 0.30204010009765625, "total_profiled": 0.2965505123138428, "unaccounted": 0.0054895877838134766}}
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)