"""问题二基线实现:两个朴素但常见的对照。 - ``candidate_perp``:沿首次示向度垂直方向、距检测点约 1000 m 取点。 这是"尽量把交会角做成 90°"的教科书启发式,**但它忽略接收距离保证**: 真源可能落在首次角域的远端(≤1500 m),此时第二点距离可超过 1000 m, 第二次测量直接 ``no_signal``,几何收益落空。 - ``candidate_mec``:退到候选集最小包围圆圆心。它确实落在保证接收盘内 (ρ≤1000 时),但交会角可能接近 0°、后验几乎不收缩,代表"最保守"一端。 """ from __future__ import annotations import math from mcm26b.config import ProblemConfig from mcm26b.planner import safe_disk_radius from project.common import Method, problem_config from project.q2.region import first_bearing_region PERP = Method( key="baseline_perp", name="垂直 1000 m 最大交会角", kind="baseline", note="忽略接收保证的几何启发式", ) MEC = Method( key="baseline_mec", name="候选集 MEC 圆心", kind="baseline", note="保证接收但交会角最差的保守基线", ) METHODS = (PERP, MEC) def _region(case: dict, config: ProblemConfig): return first_bearing_region(case, config) def candidate_perp(case: dict, config: ProblemConfig | None = None) -> dict: config = config or problem_config() region = _region(case, config) station = (case["station"][0], case["station"][1]) theta = math.radians(case["bearing_deg"] + 90.0) distance = config.field.r_eff_min_m position = (station[0] + distance * math.cos(theta), station[1] + distance * math.sin(theta)) return { "method": PERP.key, "position": [round(position[0], 4), round(position[1], 4)], "worst_posterior_radius_m": None, # 由 compare 统一评估 "move_cost_s": None, "safe_disk_radius_m": safe_disk_radius(region, config), "initial_radius_m": region.mec()[1], "reason": "沿首次示向度法向 1000 m 取 90° 交会点", } def candidate_mec(case: dict, config: ProblemConfig | None = None) -> dict: config = config or problem_config() region = _region(case, config) center, radius = region.mec() return { "method": MEC.key, "position": [round(center[0], 4), round(center[1], 4)], "worst_posterior_radius_m": None, "move_cost_s": None, "safe_disk_radius_m": safe_disk_radius(region, config), "initial_radius_m": radius, "reason": "取候选集最小包围圆圆心,保证接收但交会角可能最差", }