Files
mcm-26-b/scripts/benchmark_q1.py
2026-09-12 01:56:34 +08:00

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()