- particles.py: 网格幸存集滤波,Voronoi 裕量保证真源保留(缺席证明/网格清除证书/跳测规则)
- planner/bayes_loop.py: 统一任务循环(站点/定位/清除滚动 2-opt 排序)、期望后验半径选点
- planner/seven.py: 七点覆盖策略族提升为库代码
- cli: mcm26b run --strategy {grid,seven,bayes}
- BayesConfig 参数组;tests +24 项(真源保留/证书/端到端),129 全绿
80 lines
5.8 KiB
Markdown
80 lines
5.8 KiB
Markdown
# 目标
|
||
|
||
在新分支 **`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 裕量定理 + 随机化真源保留性测试兜底 |