- particles.py: 网格幸存集滤波,Voronoi 裕量保证真源保留(缺席证明/网格清除证书/跳测规则)
- planner/bayes_loop.py: 统一任务循环(站点/定位/清除滚动 2-opt 排序)、期望后验半径选点
- planner/seven.py: 七点覆盖策略族提升为库代码
- cli: mcm26b run --strategy {grid,seven,bayes}
- BayesConfig 参数组;tests +24 项(真源保留/证书/端到端),129 全绿
5.8 KiB
目标
在新分支 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 加交叉引用。
执行顺序
git checkout -b q3-bayes- BayesConfig → particles.py(含单测)→ seven.py 提升
- bayes_loop.py + CLI 接入 → pytest 全绿
- 跑配对消融基准
- Optuna 调参 → 回填参数复跑基准
- 若达标(全清 100% 且配对均值更优):
mcm26b run默认切 bayes + 文档更新 - 分支上分阶段 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 裕量定理 + 随机化真源保留性测试兜底