6.7 KiB
6.7 KiB
修复计划:7 项 P2 问题 + 3 项规划调整
已核实:7 个问题的定位与审核报告一致;另确认关联缺陷 planner/__init__.py:392 用 > 判断遮挡预算(实际放行 5 个被遮挡探点,注释口径为 4)。用户已确认:环探保留启发式+重写依据;误差场采用逐点白噪声哈希。
修改一:模拟器固定误差场(问题1)
文件 src/mcm26b/sim/simulator.py:
- 新增
_bearing_error(channel, pos):sha256(f"{error_seed}|{channel}|{round(x,6)}|{round(y,6)}")前 8 字节映射到[-error_half_deg, +error_half_deg)。同一(源频道, 位置)读数恒定,不同点独立。 _observe(L193)改为调用它;删除顺序随机流self._rng(构造参数error_seed保留)。- 模块 docstring 更新:同位置误差固定;分布仍是测试假设。
- 新增测试:同位置重复测量(不同 request_id)svd_deg 相同;同种子两次构造结果一致。
修改二:Q4 对跖探点公式(问题2)
文件 src/mcm26b/planner/__init__.py(L440-447):
- L447:
dx / norm * scale→dx * scale(dy 同理),使偏移模长 =min(norm, safe)。圆心为原点、原探点 (200,0)、safe≥200 时返回 (-200,0)。 - L444 退化分支:
min(safe, 1.0)→safe(方向 +x),不再钳到 1m。 - 新增单测:对跖点坐标(safe≥norm 与 safe<norm 两种)。
修改三:环探依据重写 + 预算一致(问题3,保留启发式)
planner/__init__.py模块 docstring、DirectionalExtensiondocstring、_next_probedocstring(L428-431):删除"≥180° 弧"声称,改为诚实表述:源位于环上且朝向沿外切线时可见弧可退化为单点,固定 45° 步进无最坏命中保证;梯子只提高提前命中率,完备性完全由后备清除兜底。docs/协议规则表与状态机.md§7(L166-172)同步重写。- L392
>→>=,config.py:85注释与文档同步为"4 个被遮挡探点(选点/对跖/环探×2)"。 - 新增
scripts/benchmark_q4.py:批量种子扫描(--problem 4,可配源数/定向数/种子范围/输出路径),逐局记录 measures、clears、后备清除格数与 attempts、virtual_time、completed,落盘output/q4/benchmark.json并打印汇总表——用于验证修复后的后备清除成本(审核"验证后备成本"要求),同时为论文问题4结果表提供可复现数字。
修改四:通信失败可靠收尾(问题4)
文件 planner/__init__.py run()(L195-205):
client.enter()纳入 try;except 顺序:DeadlineExceeded→(TransportError, ProtocolError, InconsistentBelief)→Exception兜底;stop_reason 分别记real_budget_exhausted/transport_failure/protocol_error/inconsistent_belief/unexpected_error,summary 增abort_detail(异常类型+消息,截断)。/exit改为尽力而为:client.exit()失败不再中断收尾;_summary接受info=None(exit_reason="exit_unreachable",virtual_time 取client.state.virtual_time_s)。- summary 增
channel_status快照(每频道状态 + 候选 MEC 半径,约 20 条)——即"保存未完成状态";--log的 JSONL 本就有全过程留痕。 - cli.py 无需改(
completed=false已映射退出码 1)。 - 新增测试:注入连续三次传输失败(若
ScriptedFaultTransport不支持持久失败则扩展其故障类型),断言run()正常返回 summary 不抛异常、有 /exit 尝试留痕、退出码路径为 1。
修改五:Q1 近平行退化情形(问题5)
文件 src/mcm26b/geometry/localization.py(L216-226):
- 衰退方向判定改为对浮点平面系数的精确有理数运算(
Fraction):候选方向仍枚举各平面法线的垂直方向(b,-a)/(-b,a);先用浮点快速预筛(max > 1e-9 直接排除,浮点误差远小于该阈值),近零候选再用 Fraction 精确检验∀(d,e,f): d·dir_x + e·dir_y ≤ 0。平面系数本身是 float(精确有理数),故结论对量化输入精确,消除 2e-14 阈值与顶点过滤 eps=1e-9 的口径错配导致的漏判。 - 顶点枚举与
PARALLEL_EPS预筛保持现状。 - 回归测试:审核复现输入
[(0,0,1°), (0,0.01,358.99999999999°)]→status=unbounded、diameter_infinite=true、不给清除保证;scripts/benchmark_q1.py两档结果不回归。
修改六:默认舍入裕量统一(问题6)
config.py:75:bearing_rounding_margin_deg默认0.0→0.005,注释改为"覆盖服务器两位小数舍入偏差(≤0.005°);库默认与 CLI 默认一致"。q1子命令与geometry/__main__.py的--rounding-margin-deg默认保持 0(离线敏感性分析语义不变,审核未要求改)。- 新增断言
SearchConfig().bearing_rounding_margin_deg == 0.005,并用默认配置复跑"边缘读数保留真源"场景;检查显式传参的现有测试不受影响;README 如有默认值描述一并更新。
修改七:后验评分补 near 分支(问题7)
文件 planner/__init__.py _worst_posterior_radius(L93-110):
- 增加 near 分支:
probe.clip_disk(q, field.near_radius_m, search.polygon_sides),多边形非空则纳入 max;direction 端点分支保留,docstring 说明 safe 盘内 no_signal 不可能故不枚举。 - 调用点(粗评/加密复评两处)传入
near_radius_m与polygon_sides。 - 新增测试:候选集
[(-4,0),(4,0)](两点退化区域)、q=原点 → 最坏后验 ≈ 4m(修复前报 2m);test_loop_q3/q4场景回归(选点可能变化,但断言均为清除状态类,预期无碍)。
规划调整落地
- A(第二问定位):
docs/algo-2.md§13(L231 附近)明确交付为"安全选点的启发式基线":解析安全盘证书已实现并证明;§10 区间上界未实现,采样最大值仅作粗筛,不得称严格最坏上界。 - B(第三问):无代码改动;顺序约束(先修改一/四,再官方演练)在
docs/B题建模分析与实施计划.md演练清单处注明。 - C(第四问预算口径):
_summary增total_requests(measures+clears);DirectionalExtension._summary增fallback_clear_attempts(Σ attempts);docs/协议规则表与状态机.md§7 后备清除段注明"后备 /clear 请求计入总请求与现实预算"。
测试与验收
- 每项修改配单测(新增约 10-12 项),全套 pytest 通过(95 → ~107 项)。
- 冒烟:
uv run mcm26b sim-check;uv run mcm26b run --problem 3/4 --self-test若干种子。 - 运行
scripts/benchmark_q4.py记录修复后后备成本,输出落盘。
执行顺序
修改一(模拟器)→ 修改四(收尾)→ 修改六 → 修改七 → 修改二 → 修改三 → 修改五 → 文档同步 → 全量回归。