Files
mcm-26-b/.zcode/plans/plan-sess_f2eec9cb-6a04-41a3-9d72-ce6ab4455a52.md
T
Horldsence e0665c73fb feat(q3): 贝叶斯网格粒子滤波闭环(PF负观测+信息增益选点+2-opt调度)
- particles.py: 网格幸存集滤波,Voronoi 裕量保证真源保留(缺席证明/网格清除证书/跳测规则)
- planner/bayes_loop.py: 统一任务循环(站点/定位/清除滚动 2-opt 排序)、期望后验半径选点
- planner/seven.py: 七点覆盖策略族提升为库代码
- cli: mcm26b run --strategy {grid,seven,bayes}
- BayesConfig 参数组;tests +24 项(真源保留/证书/端到端),129 全绿
2026-09-11 09:02:28 +08:00

80 lines
5.8 KiB
Markdown
Raw 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.
# 目标
在新分支 **`q3-bayes`**(基于当前 `gpt`)实现第三问新算法:**网格化贝叶斯粒子滤波(含负观测更新)+ 信息增益选点 + 开放路径 2-opt 任务排序 + 七点覆盖兜底 + Optuna 离线调参**。评分口径 = 虚拟总时间(A2 基线:官方演练 12 源 5232s、109 次检测);硬性要求全清率 100%、缺席证明正确、零异常。
# 关键设计
## 1. 粒子滤波 `src/mcm26b/particles.py`(新建)
与用户方案的差异点:本项目要求清除证书/缺席证明**严格**(A2 靠保守几何证书做到 100% 清除率),软核概率 PF 有删掉真源的风险。因此采用**网格幸存集滤波**(= 硬似然 PF + Voronoi 裕量,与用户"|θ̂−θ|>1° 权重置零"的设定一致但更严格):
- 每频道一组 Ω 上间距 h≈30m 的网格粒子(约 1.1 万格,alive 用整数索引集合;空间哈希加速邻域查询)
- 保守 kill 判定(margin = h·√2/2,保证真源所在格必活):
- `no_signal`@s:kill dist(g,s) ≤ 1000 − margin(题面 r_eff ≥ 1000 ⟹ 可严格排除该盘)
- `direction`@s 读数 θ:kill 角向偏差超出 δ_eff=1.005°(含余量)或 dist > 1500 + margin 的格
- `near`@s:kill dist(g,s) > 5 + margin
- 证书全部由此推导:清除证书 = MEC(alive).R + margin ≤ 20 − clear_margin;**缺席证明 = alive 为空集**(无需额外像素覆盖检查);跳测规则 = min dist(alive, s) > 1500 + margin ⟹ 必 no_signal,跳过省 6s/次
- 信息增益:对候选点用子采样(≤500 粒子)× K 个代表假设做 MC 期望熵减估计;复用 `smallest_enclosing_circle`(Welzl) 求 MEC
## 2. 新策略 `BayesLoop(OmnidirectionalLoop)`(`src/mcm26b/planner/bayes_loop.py`)
复用基类 run() 骨架、异常收尾、summary、anomaly、预算机制,重写阶段逻辑:
- **发现阶段**:原点起扫(频道排序省换频)→ 站点 = 七点环 ∪ PF 高价值点,按"期望发现数 − λ·移动时间"贪心选站;每站批量扫频时跳过"PF 判定必 no_signal"的 (站,频道) 对与已证缺席频道;每站扫完即服务已发现频道(SevenBatch 风格)
- **定位服务**:选点 = 保证接收盘内候选环采样 + 信息增益评分(ΔH − λ·移动 − μ·检测),有证书即清除;步数上限沿用 `max_localize_steps`
- **清除调度**:待服务任务(定位+清除 ≤20 节点)开放路径最近邻 + 2-opt,纯标准库,每个决策点滚动重排
- **收尾**:全部 CLEARED/ABSENT → all_resolved;清满 16 提前停;persistent_search 沿用现有配置语义(实现时对照 `run_q3_seven_practice.py` 保持官方演练停止行为一致)
## 3. 配置 `config.py`
新增 `BayesConfig` frozen dataclass([工程]):particle_spacing_m、λ/μ 权重、MC 代表数/子采样、skip_margin、站点环半径、2-opt 开关/迭代数等;挂到 `ProblemConfig.bayes`。默认值不改变现有策略行为。
## 4. 七点覆盖提升为库代码 `src/mcm26b/planner/seven.py`
把 `scripts/benchmark_q3_search.py` 的 `seven_points()/SevenImmediate/SevenBatch` 移入 src(旧脚本改 import,消融结果可复现),供 CLI 与新基准复用。
## 5. CLI `cli.py`
`mcm26b run --strategy {grid,seven,bayes}`,默认 grid;**若基准通过则默认改为 bayes**(用户已确认)。
## 6. 基准 `scripts/benchmark_q3_bayes.py`
配对消融 {seven_batch, bayes} ×(seeds 0..5 × 10/16 源 + 边界源 + 0 源纯缺席场景),复用现有 run_case/LocalSimulator 模式;输出 `output/q3/bayes-ablation/`(benchmark.json + report.md):全清率、correct_absence、异常、accounted/total 虚拟时间、配对降幅、实机 compute_wall_s。
## 7. Optuna 调参 `scripts/tune_q3_bayes.py`
- `uv add --group dev optuna`(仅调参脚本用,生产零新增依赖)
- TPE,目标 = 场景子集平均虚拟时间 + 10⁶×失败惩罚;场景与 error_seed 多样化防过拟合
- 搜索空间:h、λ/μ、skip margin、候选环、2-opt 开关等
- optuna 不可用时自动退化为随机搜索;最优参数写 JSON,复跑基准确认后合入 config.py 默认值
## 8. 测试
- `tests/test_particles.py`:真源保留性(随机场景 × LocalSimulator 误差场,任意更新序列后真源邻域格必活);证书正确性(alive=∅ ⟺ 真缺席;MEC 证书清除必成功);跳测规则永不漏检
- `tests/test_bayes_loop_q3.py`:端到端 LocalSimulator(10/16/0 源、边界源、预算耗尽、故障注入):全清 + 缺席正确 + 无异常 + 正常退出
- 现有 105 项测试保持绿
## 9. 文档
`docs/algo-3-bayes.md`(Voronoi 裕量严格性论证、信息增益与调度设计、与 A2 对比数据);README 策略表加行;`docs/algo-3.md` 加交叉引用。
# 执行顺序
1. `git checkout -b q3-bayes`
2. BayesConfig → particles.py(含单测)→ seven.py 提升
3. bayes_loop.py + CLI 接入 → pytest 全绿
4. 跑配对消融基准
5. Optuna 调参 → 回填参数复跑基准
6. 若达标(全清 100% 且配对均值更优):`mcm26b run` 默认切 bayes + 文档更新
7. 分支上分阶段 commit(不 push)
# 验收标准
- 基准全部场景:all_cleared 100%、correct_absence 100%、anomalies 空、normal_exit、单局实机计算 < 60s
- 配对平均虚拟时间优于 seven_batch(目标降幅 ≥5%;参考量级 A2=5232s/12 源)
- `uv run pytest` 全绿;`mcm26b run --self-test --problem 3` 通过
# 风险与对策
- PF 实机计算耗时 → 空间哈希 + MC 子采样,基准记录 compute_wall_s,超预算先降 MC 规模(实机预算 1200s,A2 仅用 3.4s,余量巨大)
- LocalSimulator 误差场确定性 → 调参与基准用多 error_seed
- 负观测删点的正确性 → Voronoi 裕量定理 + 随机化真源保留性测试兜底