Files
mcm-26-b/project/q2/reference.py
2026-09-12 16:58:25 +08:00

68 lines
2.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""问题二近似最优参考:在保证接收盘内做稠密网格枚举。
目标函数与生产实现一致(最坏后验包围半径 + 移动时间同分决胜),但候选点
取自**均匀网格**而非环形采样族,因此可用来检验生产采样是否接近该目标下的
网格最优。注意这是"同一目标下的网格参考",不是连续问题的严格全局最优。
"""
from __future__ import annotations
import math
from mcm26b.config import ProblemConfig
from mcm26b.planner import (_worst_posterior_radius, safe_disk_radius)
from project.common import Method, problem_config
from project.q2.region import first_bearing_region
METHOD = Method(
key="reference",
name="保证接收盘内网格枚举",
kind="reference",
note="同一目标下的稠密网格参考,非连续全局最优",
)
GRID_SIDES = 9
WITNESS_SPACING_M = 150.0
def candidate(case: dict, config: ProblemConfig | None = None) -> dict:
config = config or problem_config()
region = first_bearing_region(case, config)
station = (case["station"][0], case["station"][1])
center = region.mec()[0]
safe = safe_disk_radius(region, config)
if safe < 0:
return _payload(center, region, config, station, "无保证接收盘:退回 MEC 圆心")
field, search = config.field, config.search
half_angle = field.bearing_error_half_deg + search.bearing_rounding_margin_deg
witnesses = region.witnesses(WITNESS_SPACING_M)
step = 2.0 * safe / (GRID_SIDES - 1)
best_key, best_point, best_worst = None, center, None
for i in range(GRID_SIDES):
for j in range(GRID_SIDES):
point = (center[0] - safe + i * step, center[1] - safe + j * step)
if math.dist(point, center) > safe + 1e-9:
continue
worst = _worst_posterior_radius(region, point, witnesses, half_angle,
field.near_radius_m, search.polygon_sides)
move = math.dist(station, point) / config.cost.speed_mps
key = (round(worst, 6), round(move, 6))
if best_key is None or key < best_key:
best_key, best_point, best_worst = key, point, worst
return _payload(best_point, region, config, station,
f"安全盘网格 {GRID_SIDES}×{GRID_SIDES} 取最坏后验最小",
worst_value=best_worst)
def _payload(point, region, config, station, reason, worst_value=None) -> dict:
return {
"method": METHOD.key,
"position": [round(point[0], 4), round(point[1], 4)],
"worst_posterior_radius_m": worst_value,
"move_cost_s": math.dist(station, point) / config.cost.speed_mps,
"safe_disk_radius_m": safe_disk_radius(region, config),
"initial_radius_m": region.mec()[1],
"reason": reason,
}