68 lines
2.8 KiB
Python
68 lines
2.8 KiB
Python
"""问题二近似最优参考:在保证接收盘内做稠密网格枚举。
|
||
|
||
目标函数与生产实现一致(最坏后验包围半径 + 移动时间同分决胜),但候选点
|
||
取自**均匀网格**而非环形采样族,因此可用来检验生产采样是否接近该目标下的
|
||
网格最优。注意这是"同一目标下的网格参考",不是连续问题的严格全局最优。
|
||
"""
|
||
|
||
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,
|
||
}
|