62 lines
2.7 KiB
Python
62 lines
2.7 KiB
Python
"""Offline numerical comparison; timings are local measurements, not API latency."""
|
|
|
|
from dataclasses import replace
|
|
import json
|
|
import math
|
|
from pathlib import Path
|
|
from statistics import median
|
|
import sys
|
|
from time import perf_counter
|
|
|
|
from mcm26b.geometry import (Measurement, solve, smallest_enclosing_circle,
|
|
first_bearing_candidate_disk)
|
|
from mcm26b.geometry.localization import _enclosing_circle_reference
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
def timed(function, points, repeats):
|
|
durations = []
|
|
for _ in range(repeats):
|
|
start = perf_counter()
|
|
result = function(points)
|
|
durations.append(perf_counter()-start)
|
|
return result, median(durations)*1000
|
|
|
|
|
|
def main():
|
|
timings = []
|
|
for size in [4, 20, 60]:
|
|
points = [(20*math.cos(i*math.tau/size), 20*math.sin(i*math.tau/size)) for i in range(size)]
|
|
old, old_ms = timed(_enclosing_circle_reference, points, 3)
|
|
new, new_ms = timed(smallest_enclosing_circle, points, 11)
|
|
timings.append(dict(vertices=size, reference_ms=old_ms, incremental_ms=new_ms,
|
|
speedup=old_ms/new_ms, radius_difference_m=abs(old[1]-new[1])))
|
|
source = next((ROOT/'output/q1/practice').glob('*_observations.json'))
|
|
rows = json.loads(source.read_text(encoding='utf-8'))['measurements']
|
|
observations = [Measurement(**m) for m in rows]
|
|
sensitivity = []
|
|
for margin in [0, 0.005]:
|
|
ms = [replace(m, half_angle_deg=m.half_angle_deg+margin) for m in observations]
|
|
result, duration = timed(solve, ms, 31)
|
|
cert = result['clearance_certificate']
|
|
sensitivity.append(dict(additional_half_angle_deg=margin, solve_ms=duration,
|
|
diameter_m=result['diameter_m'],
|
|
mec_radius_m=result['minimum_enclosing_circle']['radius_m'],
|
|
diameter_circle_excess_m=result['diameter_circle']['max_excess_m'],
|
|
clearance_margin_m=cert['remaining_margin_m']))
|
|
report = dict(
|
|
python=sys.version.split()[0],
|
|
timing_method='median perf_counter; warm local process',
|
|
timing_scope='MEC only; not whole solver speedup or simulator/network performance',
|
|
circle_benchmarks=timings, practice_sensitivity=sensitivity,
|
|
q2_first_bearing_certificate=first_bearing_candidate_disk(Measurement(0, 0, 0, 1.005)))
|
|
output = ROOT/'output/q1/optimization_report.json'
|
|
output.write_text(
|
|
json.dumps(report, ensure_ascii=False, indent=2, allow_nan=False)+'\n', encoding='utf-8')
|
|
print(json.dumps(report, ensure_ascii=False, indent=2))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|