60 lines
2.3 KiB
Python
60 lines
2.3 KiB
Python
"""问题一最优实现:复用生产几何内核 ``mcm26b.geometry.localization.solve``。
|
|
|
|
算法(已由 ``tests/test_geometry.py`` / ``tests/test_geometry_certificates.py``
|
|
固化,本模块只做输入输出适配,不重写):
|
|
|
|
1. 每条带 ±δ 误差的示向度写成前向角域的三条半平面约束(含 0°/360° 跨界);
|
|
2. 枚举全部边界直线交点,保留满足全部约束者,单调链求凸包;
|
|
3. 检查是否存在非零衰退方向判定无界;否则枚举凸包顶点对取精确直径;
|
|
4. 用直径两端点中点圆检验覆盖,并给出圆外顶点、最大超出距离等反例见证;
|
|
5. Welzl 增量法求最小包围圆,给出 20 m 清除余量证书。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from time import perf_counter
|
|
|
|
from mcm26b.geometry.localization import Measurement, solve
|
|
|
|
from project.common import Method
|
|
|
|
METHOD = Method(
|
|
key="optimal",
|
|
name="精确半平面交 + 顶点对直径 + MEC",
|
|
kind="optimal",
|
|
note="生产内核 mcm26b.geometry.localization.solve",
|
|
)
|
|
|
|
|
|
def solve_case(case: dict) -> dict:
|
|
"""输入 case["measurements"],输出归一化结果。"""
|
|
measurements = [Measurement(row["x"], row["y"], row["bearing_deg"],
|
|
row.get("half_angle_deg", 1.0))
|
|
for row in case["measurements"]]
|
|
start = perf_counter()
|
|
result = solve(measurements)
|
|
elapsed_ms = (perf_counter() - start) * 1000.0
|
|
return normalize(result, elapsed_ms)
|
|
|
|
|
|
def normalize(result: dict, elapsed_ms: float) -> dict:
|
|
status = result["status"]
|
|
diameter = result.get("diameter_m")
|
|
circle = result.get("diameter_circle") or {}
|
|
mec = result.get("minimum_enclosing_circle") or {}
|
|
covers = circle.get("covers") if status in ("point", "segment", "polygon") else None
|
|
return {
|
|
"method": METHOD.key,
|
|
"status": status,
|
|
"diameter_m": diameter,
|
|
"diameter_infinite": result.get("diameter_infinite"),
|
|
"covers": covers,
|
|
"mec_radius_m": mec.get("radius_m"),
|
|
"max_excess_m": circle.get("max_excess_m"),
|
|
"outside_vertex_count": len(circle.get("outside_vertex_indices", []))
|
|
if circle else None,
|
|
"vertex_count": len(result.get("vertices", [])),
|
|
"runtime_ms": round(elapsed_ms, 4),
|
|
"algorithm": METHOD.name,
|
|
}
|