Compare commits

Author SHA1 Message Date
sloray 14b0ebb7fb 改写 2026-09-13 19:59:33 +08:00
sloray b7aadaa400 改一点标题 2026-09-13 19:37:19 +08:00
sloray 2cb3dd6602 AIGC 合规 .gitignore 2026-09-13 19:16:47 +08:00
sloray 662d17e21a AIGC 合规说明 2026-09-13 19:14:06 +08:00
sloray 599eea40d6 去敏感提交 2026-09-13 18:43:25 +08:00
sloray 89021eb9f8 论文完成 2026-09-13 18:05:59 +08:00
sloray 9fb15f53f5 图表换正式数据 2026-09-13 14:38:31 +08:00
sloray 705c4c9b6a 行文优化 2026-09-13 13:23:10 +08:00
Horldsence 257d1a9bd7 46 2026-09-13 11:45:01 +08:00
sloray fb0325f67f Merge branch 'q3-bayes-no-ml' of git.simba-robotics.com:HelixCopex/mcm-26-b into q3-bayes-no-ml 2026-09-13 10:55:45 +08:00
sloray 4f836fe123 重写tex 2026-09-13 10:53:22 +08:00
Horldsence 78e4420a3e iuh 2026-09-13 10:52:28 +08:00
sloray 2c63610f12 论文更改与图更改
Co-authored-by: Pengheng <Horldsence@users.noreply.github.com>
2026-09-13 10:30:05 +08:00
Horldsence 82311a47cc 123 2026-09-13 10:27:09 +08:00
Horldsence b810ec7777 1134 2026-09-13 10:27:04 +08:00
Horldsence 0a2d30702d 12 2026-09-13 08:54:06 +08:00
323 changed files with 42754 additions and 48149 deletions
Vendored
BIN
View File
Binary file not shown.
+57 -12
View File
@@ -1,18 +1,42 @@
# Python-generated files
# ============================================================
# 2026 B 题:无线电干扰源自动定位清除 —— 版本控制忽略清单
# 原则:只跟踪"可复现结果所需的最小集合"。
# - 源码、自建模拟器、六份正式日志、测试、复现脚本与说明文档:纳入版本控制;
# - 编译产物、运行期采集目录、缓存与本机工作区:一律忽略。
# ============================================================
# ---------- Python ----------
__pycache__/
*.py[oc]
*.py[cod]
*.egg-info/
.venv/
.piptmp/
.pytest_cache/
.mypy_cache/
.ruff_cache/
.ipynb_checkpoints/
# 构建与打包产物
build/
dist/
wheels/
*.egg-info
# Virtual environments
.venv
# Sim
# ---------- 运行期产生:不进版本控制 ----------
# 官方模拟器本体与判题留档(体积大且需官方环境)
Jammers*/
# 官方演练采集产物(问题一观测、回放归档、评测机日志)
output/
# 本机临时工作区:历史留档、截图、中间草稿等
tmp/
# LaTeX build artifacts
# 构建 Python 包时使用的临时目录
.piptmp/
uv-temp/
pip-temp/
# referee-data/ 是论文正文数据的来源,纳入版本控制(含演练与正式日志)。
# 其中登录标识已统一为中性占位符,不包含参赛队号。
# ---------- LaTeX 编译产物 ----------
docs/paper/build/
docs/paper/*.aux
docs/paper/*.log
@@ -21,9 +45,30 @@ docs/paper/*.fls
docs/paper/*.fdb_latexmk
docs/paper/*.xdv
docs/paper/*.synctex.gz
# 支撑包是脚本产物(scripts/build_paper_support.py --package),不入库
docs/paper/support-materials.zip
# pytest
.pytest_cache/
# ---------- 编辑器 / 操作系统 ----------
.vscode/*
!.vscode/settings.json
.idea/
.zcode/
.DS_Store
Thumbs.db
# 1
output/
# ---------- 字体:体积过大,不进版本控制 ----------
# docs/paper/fonts/ 共约 150 MB(HeitiSC / SongtiSC / Times New Roman),
# 远超支撑材料合理体积。cls 已内置系统字体回退方案,缺字体时按
# docs/paper/mcm26b-paper.cls 中的「若未携带 fonts/ 目录」注释改用系统字体即可。
docs/paper/fonts/
# AIGC 报告构建产物
docs/build/
docs/*.aux
docs/*.log
docs/*.toc
docs/*.out
docs/*.fls
docs/*.fdb_latexmk
docs/*.xdv
docs/*.synctex.gz
+67 -19
View File
@@ -1,37 +1,85 @@
{
// LaTeX Workshop 配方 —— 与 docs/paper/README.md 记录的口令一致:
// latexmk -xelatex -interaction=nonstopmode -halt-on-error main.tex
// 论文需要多遍编译(交叉引用、目录与长表格),且必须用 XeLaTeX(ctex + fontspec),
// 因此默认配方取 latexmk,而不是单遍 xelatex。
"latex-workshop.latex.workingDirectory": "%DIR%",
"latex-workshop.latex.tools": [
{
"name": "xelatex",
// 默认配方使用的工具:%DOCFILE% 与 %DIR% 配合,
// 切换工作目录后传给 latexmk 的仍是纯文件名,避免绝对路径与 \input 相对路径冲突。
"name": "latexmk (xelatex, paper)",
"command": "latexmk",
"args": [
"-synctex=1",
"-interaction=nonstopmode",
"-halt-on-error",
"-file-line-error",
"-xelatex",
"%DOCFILE%"
],
"env": {}
},
{
// 备选:产物集中到 build/ 子目录,源码目录更干净;
// 需要清理时删除 docs/paper/build 即可(该目录已在 .gitignore 中)。
"name": "latexmk (xelatex, outdir=build)",
"command": "latexmk",
"args": [
"-synctex=1",
"-interaction=nonstopmode",
"-halt-on-error",
"-file-line-error",
"-xelatex",
"-outdir=build",
"%DOCFILE%"
],
"env": {}
},
{
// 单遍 xelatex 只用于排查单个文件的语法错误,交叉引用会显示为 ??
"name": "xelatex (单遍,调试用)",
"command": "xelatex",
"args": [
"-synctex=1",
"-interaction=nonstopmode",
"-file-line-error",
"%DOC%"
]
},
{
"name": "latexmk (xelatex)",
"command": "latexmk",
"args": [
"-synctex=1",
"-interaction=nonstopmode",
"-file-line-error",
"-xelatex",
"%DOC%"
]
"%DOCFILE%"
],
"env": {}
}
],
"latex-workshop.latex.recipes": [
{
"name": "xelatex",
"tools": ["xelatex"]
"name": "latexmk (xelatex, paper)",
"tools": ["latexmk (xelatex, paper)"]
},
{
"name": "latexmk (xelatex)",
"tools": ["latexmk (xelatex)"]
"name": "latexmk (xelatex, outdir=build)",
"tools": ["latexmk (xelatex, outdir=build)"]
},
{
"name": "xelatex (单遍,调试用)",
"tools": ["xelatex (单遍,调试用)"]
}
],
"latex-workshop.latex.recipe.default": "first"
// 默认配方:本项目的实际编译口令(多遍 + XeLaTeX + 遇错即停)。
//
// 产物写入 build/ 而不是就地写 docs/paper/main.pdf:就地编译时若 PDF 预览
// 仍打开发着 main.pdf,Windows 会锁住该文件,xdvipdfmx 随即报
// "gave an error" 且不产出 PDF,表现为"编译没反应"。
// 写到 build/ 后,预览读的是 docs/paper/build/main.pdf,不再与源码目录的
// main.pdf 抢占,保存即编译也就稳定了。
// 需要就地产出时,把下面这行改为 "latexmk (xelatex, paper)",并先关闭 PDF 预览。
"latex-workshop.latex.recipe.default": "latexmk (xelatex, outdir=build)",
// 预览与 build/ 配方保持一致
"latex-workshop.latex.outDir": "build",
// 保存即编译:单次编译约十秒,开启后可直接看 PDF 预览;
// 只想手动触发时把下一行改为 "never"。
"latex-workshop.latex.autoBuild.run": "onSave",
"latex-workshop.latex.autoClean.run": "onBuilt",
"latex-workshop.latex.clean.subfolder.enabled": true,
"latex-workshop.view.pdf.viewer": "tab",
// 禁止 LaTeX Workshop 用启发式自动切换工具,始终按上面的配方执行
"latex-workshop.latex.build.forceRecipeUsage": true
}
@@ -1,60 +0,0 @@
# 修复计划: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、`DirectionalExtension` docstring、`_next_probe` docstring(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` 记录修复后后备成本,输出落盘。
## 执行顺序
修改一(模拟器)→ 修改四(收尾)→ 修改六 → 修改七 → 修改二 → 修改三 → 修改五 → 文档同步 → 全量回归。
@@ -1,80 +0,0 @@
# 目标
在新分支 **`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 裕量定理 + 随机化真源保留性测试兜底
+160 -165
View File
@@ -1,202 +1,197 @@
# mcm26b — CUMCM 2026 B题:无线电干扰源的快速自动定位与清除
# mcm26b — CUMCM 2026 B 题:无线电干扰源的快速自动定位与清除
统一框架:有界误差几何定位、主动选点、带覆盖证明的搜索、按真实动作耗时调度。
分析依据 `issue/B题.pdf`、附件1《模拟器使用说明》、附件2《通信接口说明及编程指南》。
本仓库为参赛论文(`docs/paper/main.tex`)的可复现支撑材料:
提供四问的完整可运行程序、自建模拟器、论文全部数据与插图的生成脚本。
算法本身的推导、证明与结果分析见论文,本文件只说明**怎么跑、怎么复现**。
**文档总入口:[docs/README.md](docs/README.md)**(分类索引、阅读顺序与口径登记)。
---
- [总体思路与流程图(四问主线、端到端流程图、执行时间速查)](docs/总体思路与流程图.md)
- [执行时间与执行步骤(计时模型、状态机、附件示例推演、实测分解)](docs/执行时间与执行步骤.md)
- [几何计算示意图册(逐图说明:角域交会、覆盖、最小命中集)](docs/几何计算示意图册.md)
- [论文插图清单与复现方式](docs/figures/README.md)(`uv run python scripts/make_figures.py`)
- [四问建模分析与 P0–P7 实施计划](docs/B题建模分析与实施计划.md)
- [协议规则表、字段表与状态机(P0 交付)](docs/协议规则表与状态机.md)
- [问题一完整解答](docs/问题一解答.md)
- [问题一算法说明(当前实现口径)](docs/algo-1.md)
- [问题二算法说明(保证接收的第二点选择)](docs/algo-2.md)
- [问题三算法说明(七点覆盖证明、贝叶斯闭环与滚动调度)](docs/algo-3.md)
- [问题四算法说明(定向覆盖最小命中集、联合信念与后备清除)](docs/algo-4.md)
- [第三、四问系统性架构优化与运行提速方案(运行历史复核、最小命中集、联合信念)](docs/第三四问架构优化与运行提速方案.md)
- [第三、四问图论与动态规划优化方案(定点实测、路由 gap、定向定位 DP、证书硬化)](docs/第三四问图论与动态规划优化方案.md)
- [1-4 问最优与基线实现对比框架](project/README.md)(`uv run python -m project.run`,结果在 `project/results/`)
- [最优与基线实现对比(论文口径说明)](docs/最优与基线实现对比.md)
- [论文](docs/paper/main.tex)
## 1. 环境
## 项目结构
- Python ≥ 3.10;运行时依赖仅 `requests`,测试与自检另需 `pytest`、`numpy`。
- 自建模拟器 `referee/` 为零第三方依赖的独立包,`uv sync` 时作为开发依赖一并挂载。
- 复现论文 PDF 另需 TeX Live(XeLaTeX、ctex、TikZ)。论文用字体在 `docs/paper/fonts/`,
该目录约 150 MB、**已在 `.gitignore` 中排除、不入库**;缺失时按
`docs/paper/mcm26b-paper.cls` 中的「若未携带 fonts/ 目录」注释改用系统字体即可编译。
```
referee/ # 独立评测机包(mcm26b-referee):模拟器引擎+机器狗接口+WebUI,
# 零第三方依赖、不依赖本队代码;题意符合性对照见 referee/README.md
src/mcm26b/
├── config.py # 参数中心:题面常量[题面] + 工程参数[工程],唯一字面量来源
├── protocol/ # P0/P1 字段表、计时模型、状态机、串行幂等客户端(已完工)
├── geometry/ # P2 角域交会、直径、MEC、问题二安全候选盘证书(已完工)
├── belief/ # P3 逐频道候选集合 K_c:保守外包多边形 + 半平面裁剪(已完工)
├── coverage/ # P4 49点覆盖账本(网格生成 + 逐频道记录)
├── planner/ # P3 保证接收盘选点器 / P4 全向闭环 / P5 混合源定向闭环(已完工)
├── routing.py # 图论/DP 工具箱:Held-Karp 精确开放路径、2-opt/Or-opt、MST 下界、路由度量
├── evaluation/ # 日志复算与统计(已完工)
└── harness/ # 测试侧适配:评测机<->Transport 内存回环、故障注入、回放、场景
tests/ # pytest(含解耦守卫:运行时零导入 referee + 规则表不漂移)
project/ # 1-4 问"最优实现 / 基线实现"对比框架:逐问 optimal+baseline
# +独立参考,冻结基准集配对出数;见 project/README.md
scripts/ # 采集、基准、可视化与校核脚本(含问题四批量仿真 benchmark_q4.py、
# 运行历史计时分解 analyze_run_timing.py、第四问覆盖证书 verify_q4_cover.py、
# 论文插图 make_figures.py、日志归档 archive_replay_logs.py)
docs/figures/ # 论文插图(PNG)+ manifest.json(数据来源与 sha256)+ 图清单
output/ examples/ # 演练证据、算例与生成产物
```bash
uv sync # 安装主包与 referee(可编辑挂载)
```
## 独立评测机与 WebUI(referee/)
---
评测机已抽成独立包:`referee/`(uv workspace 成员,`uv sync` 自动挂载为 dev 依赖)。
参赛队运行时代码**零导入** referee,双方仅通过附件2 的 HTTP 协议耦合——
评测机可独立服务任何客户端,参赛队代码对接官方模拟器无需任何改动。
## 2. 运行程序(问题三 / 问题四闭环)
**队号不在代码中固化**:登录标识属身份信息,一律在运行时通过 `--robot-id` 传入,
代码、测试、示例与日志中只出现与赛事无关的中性占位符(如 `TEAM-0001`)。
```bash
# 对接官方模拟器(先在界面确认测试已开始、接口就绪)
uv run python -m mcm26b.cli run --robot-id <队号> --problem 3
uv run python -m mcm26b.cli run --robot-id <队号> --problem 4
# 一键本地评测:自动起自建模拟器 → 开一局演练 → 跑完整闭环 → 汇总
uv run python -m mcm26b.cli run --robot-id <队号> --problem 3 --local-judge
# 不连任何模拟器的自检(随机场景,内存回环)
uv run python -m mcm26b.cli run --robot-id SELFCHECK --problem 3 --self-test
# 复现附件计时示例(期望 105/111/194/199 秒)
uv run python -m mcm26b.cli sim-check
```
主要开关:`--strategy {bayes,seven,grid}`(仅问题三,默认 `bayes`)、
`--base-url`、`--log <路径>`、`--real-budget-s`(仅自检生效)。
### 问题一 / 问题二
```bash
uv run python -m mcm26b.cli q1 examples/q1/normal.json -o output/q1/result.json
uv run python -m mcm26b.geometry examples/q1/triangle.json
```
`examples/q1/` 下的五个算例分别覆盖正常多边形、劣交会、零误差线段、不相容观测与直径圆反例。
仓库根的 `main.py` 只是转发到同一 CLI 的薄壳(`python main.py <子命令>`),
等价于 `python -m mcm26b.cli <子命令>`。
---
## 3. 自建模拟器(`referee/`)
按题面附件 1《模拟器使用说明》与附件 2《通信接口说明》实现,与参赛队代码零耦合,
只通过 HTTP 协议对接;论文正文的演练数据即由它产生。
```bash
uv run python -m referee # WebUI http://127.0.0.1:8026,接口 :2026
uv run python -m referee --port 2026 --ui-port 8026 --data-dir referee-data
uv run mcm26b run --robot-id 2026001 --local-judge # 一键:起评测机→开演练局→闭环→汇总
uv run python -m referee --data-dir referee-data
```
- **WebUI 完全按附件1 §4 复现官方界面语义**:四个测试模块(演练不限次/正式各3次、
启动即占用、正式前再次确认)、确认开始→数据准备→5秒倒计时→25分钟窗口开放接口、
"指令与反馈"默认最新1000条(100..5000 可调)、中止测试两次确认、结束原因显示、
案例编码、演练结束显示 总数/全向/定向(正式任何界面不显示真值)、行为日志导出
(2MB 上限告警)、空闲时可改端口、只监听本机回环。
- **回放器**("回放"Tab):以本局行为日志 JSONL 驱动,在 Ω 圆上动画复现运动与
扫描过程——移动按 5m/s 展开、检测以雷达扫描动画呈现(direction 附实测示向度
射线)、清除先光学定位再清除;支持播放/暂停、逐步±、1×~300× 倍速快进、
滚轮缩放/拖拽平移、带动作刻度的进度条任意定位;兼容 CSV 式逐事件信息面板。
**支持手动选定 JSONL 回放**:点击"选择 JSONL 文件"或直接拖拽导入任意行为日志
(评测机日志含真值;参赛队客户端会话日志取 accepted 事件,无真值),纯前端解析。
- 引擎与协议:`referee.simulator`(观测判定/幂等/并发409/微秒计时/截止断连)、
`referee.interface`(附件2 §5 完整语法边界,HTTP 服务器与内存直连共用),
一致性由 `referee/tests` 90 项测试与真实 HTTP 测试固化。
- 自建差异(题面未规定)均在 referee/README.md 声明:联网登录/官方校时/17:30
截止/加密上传属官方服务器侧策略,本地不实现;示向度误差场与场景分布是测试假设。
- WebUI 复现官方测试流程:四个模块(演练不限次 / 正式各 3 次)、确认→5 秒倒计时→
25 分钟窗口、指令与反馈流、中止需两次确认、结束原因、行为日志导出;
- "回放"页可用本局行为日志动画复现运动与扫描过程,也支持手动导入任意 JSONL;
- 自建差异(联网登录、官方校时、加密上传属官方服务器侧,本地不实现;
误差场与场景分布为测试假设)见 `referee/README.md`。
## 快速开始
---
Python ≥ 3.10,运行时依赖仅 `requests`;测试/自检另需 `pytest` 与独立评测机
包(`uv sync` 一并安装)。
## 4. 复现论文数据(`referee-data/` → 宏与表格)
`referee-data/sessions/` 收录论文正文引用的 44 局演练日志(问题三 15 局、问题四 29 局),
`referee-data/rejected-sessions/` 保留同批采集中被判定为无效的 11 局以便复核。
```bash
uv sync # 安装(可编辑挂载本包与 referee)
uv run pytest # 全部测试(含 referee 90 项 + 解耦守卫)
uv run python -m referee # 起本地评测机(可选,配合 WebUI 回放)
uv run mcm26b sim-check # P0 自检:复现附件计时示例 105/111/194/199
uv run mcm26b run --robot-id 2026001 --self-test # 问题3自检:随机全向场景闭环(不连官方)
uv run mcm26b run --robot-id 2026001 --self-test --problem 4 # 问题4自检:混合定向源场景
# 自检默认:源数按题面 10~16 随机;实机预算 30 分钟(--real-budget-s 可改,仅自检生效);
# 找全后持续复扫未清除频道直到限时(--config 关闭 persistent_search 可回到"找全即退")
uv run mcm26b run --robot-id <队号> --log output/run/session.jsonl # 对接模拟器正式/演练
uv run mcm26b run --robot-id <队号> --base-url http://127.0.0.1:2026 # 对接本地 referee
uv run mcm26b run --robot-id 2026001 --local-judge # 一键本地评测:自动起 referee+开演练局
# 端口被占时主动询问换端口(非交互自动改空闲端口);WebUI 可实时观战并在"回放"Tab
# 逐步回看;结束自动汇总结束原因/真值统计/全清校验(--judge-no-ui 可关闭界面)
uv run mcm26b q1 examples/q1/normal.json # 问题一求解(等价 python -m mcm26b.geometry ...)
uv run python main.py examples/q1/triangle.json --rounding-margin-deg 0.005
python scripts/build_practice_data.py # 复算演练局 → 宏、整表、CSV/JSON 快照
python scripts/audit_paper_formal.py --snapshot docs/paper/data/formal-results.json
python scripts/build_paper_support.py # 附录正式数据表与支撑包
```
## 问题一(P2,已完工)
- 第一条按题面计时模型逐动作复算,输出 `docs/paper/data/practice-*.tex` 与
`practice-results.{json,csv}`;复算值与评测机记录的最大偏差应为 **0.000000 s**。
运行结束会打印局数、全清局数与平均虚拟时间,可直接与论文数字对照。
- 第二条校验官方六份正式导出包与统计快照的对应关系(来源匹配需原电脑的官方统计队列)。
- 第三条生成附录表格与 `support-materials.zip`(`--package`)。
给定同频道多个检测点及 ±1° 误差示向度,计算前向角域交集(半平面交)、
定位区域直径、直径圆覆盖判断(含反例顶点与超出距离)与最小包围圆、20m 清除余量。
### 需要重新采集演练局时
```bash
uv run mcm26b q1 examples/q1/normal.json -o output/q1/result.json
uv run python scripts/build_q1_demo.py # 重建离线交互可视化 output/q1/question1.html
uv run python scripts/benchmark_q1.py # MEC 基准与舍入敏感性
uv run python scripts/run_practice_episodes.py --problem 3 --robot-id <队号> \
--counts 10,13,16 --seeds 300-314
uv run python scripts/run_practice_episodes.py --problem 4 --robot-id <队号> \
--counts 10,13,16 --directional-cycle 3,6,8 --seeds 400-439
```
离线交互页:`output/q1/question1.html`。可选 PNG 重绘需要 Pillow 与 Windows
雅黑字体:`python scripts/render_q1_figures.py`;事件校核需要 Node.js:
`node scripts/verify_visualization.cjs`。二者仅为图形校核,非求解依赖。
脚本启动评测机并调用生产策略对接接口,真值与行为日志由评测机写入
`referee-data/sessions/`。判定标准为
`清完全部源 ∧ 无缺席误判 ∧ 主动退出 ∧ 零异常 ∧ 零失败清除`;
只看"是否清完"会放过"清完了但中途大量 `/clear` 打空"的无效局。
## 协议基线(P0/P1,已完工)
---
- `protocol.rules`:四条指令的字段表、结果码与错误语义(可执行表格);
- `protocol.timing`:纯计时模型,逐步复现附件示例 105/111/194/199;
- `protocol.state.RobotState`:位置/频道/虚拟时刻状态机;accepted=false 不更新,
`/clear` 不切频道,虚拟时刻以 accepted 响应为准;
- `protocol.client.SimulatorClient`:串行发送、幂等重试(同 ID 同内容原样重发)、
连接/读超时、基于 `remaining_real_duration_s` 的本地截止时钟与退出预留、JSONL 会话日志;
- 独立包 `referee`:按附件语义复现评测机(观测门限、定向覆盖角、幂等回放、
整数微秒计时、现实/虚拟截止、并发409和请求校验),真值只对评测机/测试端开放;
`harness.LocalSimTransport` 内存回环挂载(与 referee HTTP 服务器共用同一边界),
`harness.ScriptedFaultTransport` 注入断连/超时/500,`harness.PlaybackTransport`
回放官方演练日志。
## 5. 复现论文插图
本地模拟器默认执行至多1200秒程序预算、1500秒接口开放窗口,截止后通过
`SimulatorClosed` 模拟连接关闭,已登记动作可以完成。可注入 `clock`、`wall_clock`
和 `window_started_at` 测试迟到与超时。CLI `--self-test` 显式使用 `stress_mode=True`,
保留默认1800秒压力预算并扩展窗口;这不是官方演练时限。
内存传输不实现TCP连接限流、UI或日志上传;场景均匀分布及逐点哈希误差仍是测试假设。
```python
from mcm26b.protocol import SimulatorClient
client = SimulatorClient("参赛队号") # 默认 http://127.0.0.1:2026
client.enter()
outcome = client.measure((300, 400), 1) # MeasureOutcome(result, svd_deg, ...)
client.exit()
```bash
uv run python scripts/plot_paper_figures.py # 生成 docs/figures/*.png
```
## 阶段状态(对照 P0–P6 计划)
脚本只读 `docs/paper/data/` 下的复算结果与第四问覆盖计划,不手抄任何数字;
图内文字与图注数据均来自同一次复算。插图清单、数据来源与生成命令见
[`docs/figures/README.md`](docs/figures/README.md) 与 `docs/figures/manifest.json`。
| 阶段 | 状态 |
---
## 6. 编译论文
```bash
cd docs/paper
latexmk -xelatex -interaction=nonstopmode -halt-on-error -outdir=build main.tex # 产物 build/main.pdf
latexmk -xelatex -interaction=nonstopmode -halt-on-error main.tex # 产物 main.pdf
```
两条口令都完成交叉引用所需的多遍编译。VS Code 的 LaTeX Workshop 配置见
`.vscode/settings.json`(默认配方为前者)。细节与注意事项见
[`docs/paper/README.md`](docs/paper/README.md)。
---
## 7. 单文件核心代码与测试
```bash
uv run pytest # 全部测试(本包 + referee)
python scripts/build_core_notebook.py # 由 src/mcm26b 生成单文件核心代码
python scripts/run_notebook_cells.py # 顺序执行 notebook 全部代码单元(零依赖自检)
```
[`mcm26b-核心代码.ipynb`](mcm26b-核心代码.ipynb) 是四问生产实现的单文件版本
(约 5000 行),不含评测机、命令行外壳、采集/绘图脚本与测试;
`src/mcm26b/` 保留与之逐字对应的模块化版本。
---
## 8. AIGC 使用合规记录
竞赛要求如实记录 AI 使用情况。本项目使用的 AI 编程助手(ChatGPT/Codex 桌面版、
DeepSeek Harness)在本目录内的全部会话,已从本机客户端存储中提取并汇编为一份合规记录:
| 文件 | 说明 |
| --- | --- |
| P0 规则固定(规则表/状态机/字段表,示例逐步 105/111/194/199) | ✅ 完成 |
| P1 协议基线(客户端 + 自建回放/故障注入测试) | ✅ 完成 |
| P2 几何内核(角域交、直径、MEC、证书) | ✅ 完成(迁入 `mcm26b.geometry`) |
| P3 问题二选点(K1、候选区域 Q、采样评估) | ✅ 完成(belief + 选点器,测试固化) |
| P4 问题3全向闭环(49点覆盖、定位队列、清除、停止) | ✅ 官方问题3演练单案例通过(10/10全清,[验证报告](output/q3/practice/20260911-port2026/report.md)) |
| P5 问题4定向扩展(联合约束、后备清除、预算) | ✅ 自建完成(官方演练待执行;[算法说明](docs/algo-4.md)) |
| P6 加速与消融 | ✅ 七点批量(`--strategy seven`,官方演练 12/12)+ 贝叶斯闭环(`--strategy bayes` 默认,自建消融 −30.0%,[算法说明](docs/algo-3.md)、[设计细节](docs/algo-3-bayes.md)) |
| P7 图论/动态规划优化(S1–S5) | ✅ 已落地([实测回填](docs/第三四问图论与动态规划优化方案.md#8-本轮实测回填2026-09-12-实施结果)):路由度量入库、覆盖证书硬化(15 m/72 缺口 566→0)、Q4 后备盲清 125.7→4.3 次/局;同时修复联合信念 `no_signal` 朝向规则反向缺陷 |
| [`docs/aigc-compliance-record.tex`](docs/aigc-compliance-record.tex) | LaTeX 源文件(58 页):编制说明、使用总览、环境与权限配置、逐会话逐轮次详细记录、合规性说明、附录 |
| [`docs/aigc-compliance-record.pdf`](docs/aigc-compliance-record.pdf) | 编译成品 |
### 图论/DP 轮(2026-09-12,S1–S5)要点
记录覆盖 **11 个会话 / 34 个工作轮次 / 31 条人工提示词 / 1508 次工具调用**,
跨 2026-09-10 20:52 至 2026-09-13 18:51(UTC+8)。每条目给出该轮次的
**发生时间、执行环境与上下文(含提示词全文)、大模型实际操作概要**(工具调用分类、
写入文件、代表性命令、模型对外结论)。
- **S1 度量**:`scripts/run_suite.py` 逐局新增 `route_gap_vs_offline`、
`route_lower_bound_s`(MST 下界)、`distinct_service_points`、
`coverage_actual_visited`、`probe_no_signal_ratio`、`plan_verify_wall_s`;
图算法在 `src/mcm26b/routing.py`(Held-Karp 精确 / 2-opt / Or-opt / Prim)。
- **S2 证书**:`q4_mincover_v2`(31 点,`r_design=965 m` + 前向角裕量 5°,
15 m/72 档 325.6 万 (p,h) 缺口 0,最坏命中 990 m),取代粗采样过拟合的
`q4_mincover_v1`(25 m/48 档 125 缺口)。
- **S3 探点**:默认口径改为"可见候选里移动最省"(`probe_score_mode=nearest_visible`);
后备盲清 125.7 → 4.3 次/局,Q4 core 均值 8676 → 8602 s、最坏 10891 → 9630 s。
- **S4/S5 负面结论**:后备清除 Or-opt、Held-Karp 精确任务序、路线感知探点
在本模拟器上均为净负收益,默认关闭,代码与开关保留(见方案 §8.6)。
- **正确性修复**:`belief/joint.py` 的 `no_signal` 朝向裁剪原先规则反向且漏计格内
角裕量,会删掉真源朝向档;已修复并由 `tests/test_joint_belief.py` 的随机观测
序列保留性测试固化。
## 采集与正式测试约束
改进版 A2(七点覆盖+本站批量扫频)已通过官方案例 `J4ER-Y9EP-Q379-UPFA`:
12/12源全清,109次检测,虚拟耗时5232.132109秒,现实耗时3.406秒。
[本局报告与运行方法](output/q3/practice/20260911-seven-batch-01/report.md)。
独立入口为 `scripts/run_q3_seven_practice.py`。
贝叶斯闭环 `bayes`(网格粒子滤波+负观测更新+信息增益选点+滚动 2-opt
调度,参数经 Optuna 回填)在自建模拟器配对消融中相对 SevenBatch 平均
虚拟时间再降 30.0%(14/14 场景全清零异常),算法与数据见
[algo-3-bayes.md](docs/algo-3-bayes.md),已是 `mcm26b run` 默认策略。
虚拟时间即成绩口径:找全证明后立即 `/exit`(`--persistent` 可显式开启
"扫到限时"的复扫保险模式)。
2026-09-11 已通过本机 2026 端口完成一次官方问题3演练:案例
`DHFK-PHD2-SR2P-FXK9`,10/10 源全清,540 次检测、10 次清除,现实耗时
7.629 秒。原始请求响应、官方产物及离线审计见上述验证报告。原计时复算的
541 处微秒精度误报也已记录;按官方整数微秒累计规则独立复算后,552 个
响应时刻全部吻合。生产计时复算函数保持原样。
编译(需 ctex / longtable / booktabs):
```bash
uv run python scripts/verify_q3_practice.py output/q3/practice/20260911-port2026
cd docs
latexmk -xelatex -interaction=nonstopmode aigc-compliance-record.tex
```
本项目只使用官方**演练**采集观测,从未使用正式测试。`scripts/capture_practice.py`
不会启动测试:必须先在界面确认“问题3演练”、接口已就绪,再提供
`--practice-confirmed` 与本局案例编码。正式测试由团队按计划另行安排;
加密日志上传上限 2MB,程序避免异常高频循环。
> 记录由审计脚本从 `~/.codex/sessions/`、`~/.codex/state_5.sqlite`、`~/.dsh/sessions/`
> 中**工作目录等于本仓库**的会话自动提取生成,原始记录未经改写;提取与统计脚本
> 存于 `tmp/aigc/`(该目录按 `.gitignore` 不入库)。会话如何归属本项目、
> 哪些存储被核查后排除,见记录第 1 节与附录 A.4。
---
## 9. 目录结构
```
src/mcm26b/ 四问求解实现:config / protocol / geometry / belief / coverage /
guarantee / planner / particles / routing / evaluation / harness
referee/ 自建模拟器(独立包,零第三方依赖,不依赖本队代码)
referee-data/ 论文数据来源:演练日志(sessions / rejected-sessions)、正式统计快照
tests/ 本包测试(含运行时零导入 referee 的解耦守卫)
docs/paper/ 论文 LaTeX 源、数据与宏、编译说明
docs/figures/ 论文插图(PNG)与来源清单
docs/ AIGC 使用合规记录(aigc-compliance-record.tex / .pdf)与本目录索引
examples/ 问题一算例与回放归档
scripts/ 复现脚本:数据复算、插图绘制、正式数据核对、采集与基准
project/ 四问"最优实现 / 基线实现"配对对比框架(论文对比表的来源)
issue/ 赛题、附件与格式规范(原始材料)
```
`docs/paper/REWRITE_NOTES.md` 记录论文各轮修订与验证过程(含数据重采与问题修复)。
-237
View File
@@ -1,237 +0,0 @@
# B 题建模分析与实施计划
根据你们对工程实践和物理模型的熟悉程度,确定研究 B 题“无线电干扰源的快速自动定位与清除”。推荐采用**有界误差几何定位、主动选点、具有覆盖证明的搜索、按实际动作耗时调度**的统一框架。AI 辅助推导、实现与实验分析,策略只依赖题目允许的观测。
本文件已结合本次评审修订。问题一的几何内核、离线可视化和官方演练观测回放已经完成;问题二新增了安全候选圆盘证书,但主动选点优化器、问题三和四的全清闭环尚未完成。文中的覆盖结论是根据题设推导的,耗时估算不是演练成绩。当前工作仅离线复算既有演练记录,不使用正式测试。
依据:`issue/B题.pdf` 全文、`issue/附件/附件1.docx`《模拟器使用说明》、`issue/附件/附件2.docx`《模拟器通信接口说明及编程指南》。文档中的登录、测试和日志要求在这里作为交付约束分析,不作为自动执行正式测试的指令。
## 本次建议的取舍
| 建议 | 处理结论 |
| --- | --- |
| 四问复用几何内核、有界误差、覆盖证明、严格停止、幂等协议 | 保留,作为主线与验收条件 |
| 问题二的候选集合加入 $\Omega$ 和 1500 米上界 | 采纳,但仅加入在线候选集合 $K$,不改变问题一纯角域多边形 $P$ |
| 问题二首次测向后安全区域可能为空 | 对一般 $K$ 成立;本题首次窄角域可直接证明非空,见下文 |
| $Q$ 为空就去最小包围圆圆心并结合交会角 | 仅是一般情形的探索退化;$\rho>1000$ 时不保证接收,不能冒充保底方案 |
| 枚举所有直径对判断直径圆 | 简化为任意一组最远点对检查一次;失败时给出圆外顶点 |
| 定向无信号不直接删位置、失去信号后覆盖清除 | 采纳;执行前必须计算覆盖格数、路径和现实请求预算 |
| 现实20分钟优先控制请求数 | 采纳为硬约束;全部清除后仍按题目虚拟时间优化 |
| P0–P7分期与尽早正式测试 | 采纳分期;演练不限定3次,正式问题3/4各3次由团队另行安排 |
| `/detect` | 修正为附件规定的 `/measure` |
## 1. 四问应当串成一条实现主线
| 问题 | 要回答的实质问题 | 推荐抽象 | 必须交付的结果 |
| --- | --- | --- | --- |
| 1 | 带误差的多个方位如何形成定位区域,其直径如何计算,直径圆是否覆盖区域 | 扇形角域的半平面交、凸多边形直径、最小包围圆 | 算法、边界情形、覆盖判断及反例 |
| 2 | 仅有一次测向时,下一步去哪里更有利 | 在未知目标位置条件下进行主动测量设计 | 明确的候选区域、选点目标和比较实验 |
| 3 | 数量未知的全向源如何全部找到并尽快清除 | 全域覆盖、逐频道候选区域、局部定位与路径调度 | 演练统计、3 次正式结果、原名正式日志 |
| 4 | 有未知朝向的定向源时,如何避免遗漏 | 加入朝向不确定性的观测模型、半平面覆盖、失去信号后的处理 | 演练统计、另外 3 次正式结果、正式日志 |
第 1 问的定位区域和包围圆直接服务第 2 问选点与第 3、4 问清除;第 3 问的工程框架延伸到第 4 问。模型不必为每问重新搭建。
## 2. 用题面明确的观测能力约束物理抽象
目标区域为 $\Omega=\{(x,y):x^2+y^2\le 1800^2\}$。每个频道最多有一个源,源总数为 10–16,频道为 1–20。对一个存在的源 $c$,用未知位置 $g_c$、接收半径 $R_c\in[1000,1500]$、类型和定向朝向描述;全向源不需要朝向参数。
机器狗状态只需要位置 $p$、当前测向频道 $k$、虚拟时间、现实剩余时间、各频道的观测历史和处理状态。每个频道维护:未知/已发现待定位/可清除/已清除/已证明不存在,以及尚可能包含源的集合 $K_c$。
| 规则 | 数学或程序含义 | 容易出现的错误 |
| --- | --- | --- |
| 只返回 no_signal、near、direction;direction 附带示向度 | 这是带距离可见性门限的方位观测问题 | 构造接口并未提供的 RSSI、距离或场强数据 |
| 同地点误差固定,幅度不超过 $1^\circ$ | 用有界误差集合,保留空间相关性 | 原地重复测量取平均,假定可消除误差 |
| 示向度保留两位小数 | 题设模型取 $\pm 1^\circ$;实现可另设 $\pm 1.005^\circ$ 保守裕量 | 把额外舍入裕量写成题面规定 |
| 定向源覆盖朝向两侧各 $90^\circ$,包含边界 | 检测点须处于以源为界的发射半平面内 | 把无信号直接判定为没有源 |
| 可到目标圆域外检测与清除 | 目标位置受 $\Omega$ 限制,机器狗正常搜索不受 $\Omega$ 限制 | 所有搜索点强制留在圆域内,遗漏朝外发射的边界源 |
| 清除半径 20 米,不受定向朝向限制 | 清除可成为失去信号时的可靠后备手段 | 认为背面接收不到信号就无法清除 |
| /clear 不切换测向频道 | 保存独立的当前测向频道状态 | 清除后错误更新频道,算错下一次检测耗时 |
不需要重新拟合电磁传播衰减公式:接口只暴露接收门限与方位,额外物理参数无法由题目观测充分辨识。工程经验主要用于设计可见性分析、测向几何和闭环决策。
精确的虚拟时间目标是:
$$
T=\frac{L}{5}+N_{\mathrm{switch}}+5N_{\mathrm{measure}}
+5N_{\mathrm{clear,success}}+3N_{\mathrm{clear,fail}}.
$$
$L$ 包括检测和清除引发的所有移动,切换次数只由被接受的检测动作决定。先满足全部清除,再减少 $T$;不能通过少清几个源来改善平均时间。程序运行时间是另一个硬约束,不能把虚拟检测的 5 秒实现为现实 `sleep(5)`。
## 3. 定位与选点的统一几何标准
在 $s_i$ 测到 $\theta_i$ 后,定义 $W_i$ 为从 $s_i$ 出发、方向范围 $[\theta_i-\delta,\theta_i+\delta]$ 的前向角域。它由两条线性半平面约束表示,必须正确处理 $0^\circ/360^\circ$ 跨界。
第 1 问的定位多边形 $P$ 为这些角域的交。求各边界直线交点并筛选可行点、排序成凸多边形后,小规模下直接枚举顶点对即可计算直径:
$$
D(P)=\max_{i,j}\lVert v_i-v_j\rVert.
$$
先用简单可靠的顶点对枚举作基准,规模确有需要时再换旋转卡壳。算法必须区分空集、单点、线段、有限多边形和无界区域;不能靠任意大方框截断后声称得到无界区域的真实直径。旋转卡壳的背景可参考 [McGill 计算几何研究页面](https://www-cgrl.cs.mcgill.ca/~godfried/research/calipers.html)。
**直径为 $D$ 的圆不一定覆盖直径为 $D$ 的区域。**例如边长为 $D$ 的等边三角形,最小包围圆半径为 $D/\sqrt{3}$,大于 $D/2$。后续保证清除应使用:
$$
\rho(K)=\min_z\max_{g\in K}\lVert g-z\rVert\le 20.
$$
到最小包围圆圆心清除是充分选择,并非唯一选择。所有可保证清除的位置组成 $C_{20}(K)=\bigcap_{g\in K}B(g,20)$;只要该集合非空,就可进一步选择距离机器狗最近的可行点来节省移动。$D\le 40$ 只是必要条件,不是充分条件。最小包围圆是已有标准计算几何问题,可参考 [CGAL Min_circle_2 文档](https://doc.cgal.org/latest/Bounding_volumes/classCGAL_1_1Min__circle__2.html)。实现时给 20 米阈值保留数值余量;数值阈值附近返回谨慎判断,不把浮点容差当作精确算术证明。
直径圆覆盖只需任意一组最远顶点 $A,B$:包含距离为 $D$ 的两点且半径为 $D/2$ 的圆,其圆心只能是 $(A+B)/2$。因此检查一次全部顶点即可;若失败,换另一组直径对也不可能产生覆盖圆。问题一实现现输出最坏超出距离、圆外顶点索引和一个具体反例顶点。
在线定位还可用 $\Omega$ 和“收到信号意味着距离 $\le 1500$”约束 $K$。圆盘交角域可能包含曲线边界;若用多边形近似,必须构造外包近似,才能维持“不丢失真源”的保证。用圆周采样点连成的内接多边形不能直接作为保守外包。
第 2 问建议先明确“较好的定位效果”:以新观测后的最坏包围圆半径为主要几何指标,再考虑移动和检测成本。交会角大、面积小可作为候选点筛选指标,但不是对所有未知位置都最优的证明。
第一次收到 `direction` 后,明确取 $K_1=\Omega\cap W(s_1,\theta_1\pm\delta)\cap B(s_1,1500)$。保留整个距离圆盘是保守处理,忽略 `direction` 还隐含的近距离排除不会丢失真源。对全向源,第二检测点的安全候选区域为:
$$
\mathcal{Q}=\left\{q:\max_{g\in K_1}\lVert q-g\rVert\le 1000\right\}.
$$
在这里测量,不论实际目标位于 $K_1$ 何处,接收距离都满足题目最小接收半径;可能返回 `direction`,也可能返回 `near`。若已知外包圆 $K_1\subseteq B(c,r)$,且 $r\le 1000$,则 $B(c,1000-r)$ 是充分候选区域,等号时是单点。不要误写成“距第一次检测点不超过 1000 米”。宽松外包圆的 $r>1000$ 不能证明真实 $\mathcal{Q}$ 为空。
本题还有比“检查 $\mathcal{Q}$ 是否为空”更强的解析结论。令 $R=1500$,$u$ 为第一次示向方向,$\delta\le 45^\circ$,定义
$$
a=\frac{R}{2\cos\delta},\qquad c=s_1+au.
$$
整个截断角域 $W\cap B(s_1,R)$ 包含在 $B(c,a)$ 内。证明:任意候选 $g=s_1+tu_\varphi$ 满足 $0\le t\le R$、$|\varphi-\theta_1|\le\delta$,因此
$$
\lVert g-c\rVert^2=t^2+a^2-2at\cos(\varphi-\theta_1).
$$
该式关于 $t$ 是凸函数,最大值在 $0$ 或 $R$ 取得;两端都不超过 $a^2$。于是 $K_1\subseteq B(c,a)$,从而 $B(c,1000-a)\subseteq\mathcal{Q}$。$\delta=1.005^\circ$ 时,$a\approx 750.115391$ 米,安全圆盘半径约 $249.884609$ 米,严格为正;题设 $\delta=1^\circ$ 同样成立。即使检测点或 $c$ 在 $\Omega$ 外也合法,因为机器狗不受源位置圆域限制。实现见 `geometry/planning.py::first_bearing_candidate_disk`。
因此,在本题一致的首次测向条件下无需依赖“$\mathcal{Q}$ 空集退化”。对后续更一般的非空紧集 $K$,$\mathcal{Q}$ 非空当且仅当 $\rho(K)\le 1000$;若确实 $\rho>1000$,去 MEC 圆心只是最小化最坏接收距离的探索动作,必须允许 `no_signal`。若 $K$ 为空,应先核查频道、数据、误差界与几何计算,不给空集编造中心。上述证书只保证距离;不能直接用于定向源的朝向可见性保证。
在上述安全圆盘内,围绕测向轴两侧取候选点,计算后验包围半径与动作代价。最坏情形目标可写为 $\sup_{\theta'}\rho\bigl(K_1\cap W(q,\theta')\bigr)$,其中 $\theta'$ 遍历与 $K_1$ 和误差界一致的读数;实现先用目标位置与误差区间端点采样,并加密检查。若返回 `near`,则候选源位于当前点 5 米以内,可直接在当前位置尝试清除该频道。交会角仅作筛选或同分择优,不为改善交会角越出已证明安全的候选区域。采样是启发式,不能称为严格最坏情形最优解;圆弧先验如需离散,使用外包切线多边形并记录逼近误差。
## 4. 搜索完整性和停止条件要有可验证的依据
第 3 问中,在 $s$ 对尚未清除频道测得 `no_signal`,可以排除以 $s$ 为中心、半径 1000 米的圆盘内存在该全向源。超过 1000 米仍可能存在接收半径较小的源,不能一律排除到 1500 米。
第 4 问中,同样的 `no_signal` 约束的是“位置、半径、朝向”的联合假设。若位置和朝向暂不联合维护,最简单的可靠基线就是不利用这一观测直接删除空间候选点,只记录覆盖检测已完成。后续加速版本再维护朝向可行集合。
可以先构造一个对全向、定向均适用的完整发现基线:
$$
S=\{(700i,700j):i,j=-3,-2,\ldots,3\},\quad |S|=49.
$$
这些点覆盖 $[-2100,2100]^2$,包含目标圆域,并允许到圆域外访问。对于位于一个网格单元内部的源 $g$,该单元 4 个顶点到 $g$ 的距离都不超过 $700\sqrt{2}\approx 989.95$ 米。$g$ 在这些顶点的凸包内部,所以经过 $g$ 的任意发射半平面总包含至少一个顶点。该顶点满足接收距离与发射角条件。源恰在网格边或顶点时,取相邻单元的顶点;由于目标圆域与外框有余量,两侧相邻点都存在,仍可选择距离合格、且不与源重合的可见点。
因此,对每个尚未解决的频道完成这些点的测量,能够保证发现该频道存在的源。实际实现可跳过已经清除或已经具有有效定位任务的频道,但必须保存逐频道的覆盖记录,不能把“路过某点”当作“测过所有频道”。
作为规模检查,49点全部扫描20频道最多需要980次检测。若从原点去网格一角,再按逐行折返路线扫完,纯扫描路程约36569.85米;每点检测成本上界120秒,纯扫描虚拟总耗时上界约13193.97秒,即3.665小时。**该估算不含定位、清除及其绕行,也不保证满足现实20分钟窗口。**它说明覆盖基线在100小时虚拟上限内有设计空间,现实可行性仍要测接口延迟、总请求数和日志大小。
发现源后,先通过主动测向缩小候选集合。若定向源再次失去信号,可对已知有界候选集合构造半径小于 20 米的有限圆盘覆盖,逐点调用 `/clear`,作为不依赖朝向的后备清除方法。边长 20 米方格中心距格内任何点不超过 $10\sqrt{2}$ 米;保留与候选集合相交的格子即可保守覆盖。格子按统一半开区间索引,源恰在网格线上时至少归入一个格子;若相交判定数值不确定则保留格子。
有限不等于现实预算可行。设候选外包框宽为 $w$、高为 $h$,使用全局 20 米网格枚举时,上界可取 $N\le(\lceil w/20\rceil+2)(\lceil h/20\rceil+2)$,再以实际相交格子列表得到精确请求上限。生成路径长度 $L$ 后,单源全失败清除耗时为 $L/5+3N$;若最后一次成功则为 $L/5+3(N-1)+5$。现实代价用 $N$ 乘实测单请求高分位耗时加本地计算时间估计。不满足剩余预算时应继续有希望的定位、选择其它任务或按预算退出,不能声称后备清除保证 20 分钟内成功。即使已知源落在半径 1500 米圆盘,按外包框枚举仍有约 $2.3$ 万个格子的量级,故宽候选集合不能直接盲扫。
停止成功的依据为以下任一项:
- 已成功清除16个不同频道的源,达到题设数量上界。
- 每个频道都已有清除成功记录,或通过完整覆盖证明不存在;所有已发现源均已处理完毕。
发现10个源、连续若干次无信号、候选采样点恰好为空,都不是充分停止条件。现实预算不足而退出应记为未证明完成,不能与成功退出混记。
## 5. 在可靠基线之上增加加速策略
先做“发现一个、定位清除一个”的简单闭环,保证功能可运行;再增加以下独立可开关的策略,以便消融比较:
| 策略 | 所解决的问题 | 需要验证的收益 |
| --- | --- | --- |
| 共享检测位置 | 一次移动后顺便测多个未知频道 | 是否减少总移动时间,而非仅减少单目标测量数 |
| 目标队列和短路径排序 | 多个已发现源处理顺序不佳 | 路程减少是否抵消局部定位变差 |
| 第二点主动选取 | 共线或小交会角导致候选区域狭长 | 同等观测预算下包围圆半径、清除耗时改善 |
| 自适应覆盖 | 固定49点有冗余 | 跳点之后每个频道的覆盖证明是否仍成立 |
| 朝向可行集合 | 第4问盲区导致反复失去信号 | 是否减少无效检测,同时不误删真源 |
| 提前尝试清除 | 再测一次可能不如直接尝试便宜 | 失败的3秒和绕行是否值得;保留失败后的正确更新 |
调度可以先采用“预期信息改善/增量虚拟耗时”之类的启发式,但要记录每项含义和参数,性能结论来自演练。不预设目标均匀分布,不假定测向误差独立或均匀分布。若研究统计模型,明确它是实验场景假设。
AI 的适合用法是把这些模块逐一变成可测试程序、生成边界案例、分析消融结果,以及在自建环境中搜索策略参数。先形成可解释基线,再判断学习方法是否有额外收益;避免把未建立的奖励与训练分布直接用于正式测试。
## 6. 抽象标准和验收标准
采用“来源—输入—状态—动作—观测—约束—代价—输出—验证”的统一模块记录格式。它是本项目建议的工程标准,不是竞赛另行规定的官方评分标准。每个假设注明是题面事实、保守近似还是实验启发式;每条结论注明是数学证明还是演练观察。
| 模块 | 最小接口职责 | 验收标准 |
| --- | --- | --- |
| 协议与状态 | 串行发送动作,更新位置、频道、两类时间 | 附件计时示例逐步得到105、111、194、199秒 |
| 观测与几何 | 根据 direction、near、clear结果更新候选集合 | 自建已知真值案例中真源始终保留;跨角度边界不出错 |
| 直径与包围圆 | 给出直径、圆心、包围半径 | 与顶点对枚举对照;等边三角形反例通过 |
| 主动选点 | 输出下一测量位置及选择依据 | 实际可见性、最坏误差与移动成本均有记录 |
| 覆盖与停止 | 管理每频道的覆盖记录和成功依据 | 边界朝外源不漏搜;10源和16源场景都能正确退出 |
| 后备清除 | 对有界候选集合建立20米以内圆盘覆盖 | 覆盖无空洞、每次失败后能继续、预算有上界估计 |
| 演练统计 | 从自身动作日志与演练结束真值统计结果 | 清除比例、平均时间、总时间与分项耗时可独立复算 |
| 正式交付 | 绑定案例编码、程序版本、统计与官方原始日志 | 问题3和4各3次;日志原名保留,核查上传与导出 |
协议必须同时检查 HTTP 状态和 accepted。accepted=false 时不得更新状态,返回的 virtual_time_s=0 不能重置本地虚拟时钟。网络超时重试同一动作必须复用原 request_id 和完全相同的内容;处理重试响应也不能重复累加本地成功数与费用。新动作使用新ID,不并发调用不同动作。
用/enter返回的remaining_real_duration_s建立本地单调时钟截止时间;后续响应若提供剩余时间则校准,不能把首次剩余时间当成永远不变。记录每次请求的现实往返耗时,预留退出与故障恢复余量。例如先预留60秒,再由演练高分位延迟调节;60秒是初始工程参数,不是官方规定。估计剩余请求数时同时计入测量、失败重试、清除和退出,禁止并发动作。
980次检测在单次0.5–1秒的假设下占490–980秒(约8.17–16.33分钟),还没有定位清除余量。这个延迟范围不是实测结论;本地接口和模拟器计算的实际耗时应测量。当前14个动作的单次短演练不足以估计高分位延迟或全程稳定性。已清除频道跳过,已发现频道暂停覆盖并进入定位队列,移动到同一点后共享频道测量;自适应跳点必须保留逐频道覆盖证据。根据附件,正式上传日志不超过2MB,需监测官方日志体积;自建JSON大小不能冒充加密日志的大小。
基准实验至少覆盖:全向与混合源;数量 10 和 16;接收半径 1000 和 1500 米;目标贴近圆域边界且朝外;测向接近 $0^\circ/360^\circ$;误差取界值;检测点距离 5 米及清除距离 20 米的边界;重复请求、拒绝动作及短暂断连。样例数量按剩余时间和运行成本安排,不把有限样例通过等同于数学保证。
比较策略时先看是否全清,再比较同一批场景的总虚拟时间、平均每源时间、中位数与高分位耗时、程序时间、请求数。自建环境可用固定场景做配对比较;官方案例随机且不能重读真值,演练成绩单独记录,不声称是在完全相同的隐藏案例上比较。
## 7. 建议实施次序与阶段交付
下面按P0–P7列出可执行交付与当前状态。排期以验收门槛推进,避免把“几何代码完成”误认为“全清策略完成”。
| 阶段 | 交付与执行任务 | 验收门槛 | 当前状态 |
| --- | --- | --- | --- |
| P0 规则固定 | 规则表、状态机、四类API字段与成本 | 示例逐步105/111/194/199秒;clear不切换频道 | 已完成:`protocol/rules+timing+state` 工程化,`sim-check` 与 `tests/test_protocol_timing.py` 固化 |
| P1 协议基线 | enter/measure/clear/exit客户端;串行、幂等、截止时间 | accepted=false和超时重试不污染状态;主动退出;故障注入回放 | 已完成:`protocol/client`,`ScriptedFaultTransport`/`PlaybackTransport` 回放,`tests/test_protocol_client.py` 全过 |
| P2 几何内核 | 问题一解答、区域分类、直径圆证据、MEC、清除余量 | 跨界、退化、无界、解析反例、独立算法对照 | 已实现并优化,20项自动化测试通过 |
| P3 问题二选点 | $K_1$ 先验、安全候选盘、后验半径采样与 `near` 分支 | 距离证书有效;采样加密;不把探索当接收保证 | 已实现:`belief` 保守候选集 + `planner` 保证接收盘选点器(worst-posterior 采样、1/4 间距加密复核);策略对比实验待做 |
| P4 全向闭环 | 49点覆盖记录、定位队列、清除、停止、日志统计 | 10/16源、边界源和错误响应案例;官方演练全清并正常退出 | 自建闭环已完成:`planner.OmnidirectionalLoop`(10/16/0 源、近边界源、预算耗尽、故障注入测试通过);官方演练全清待团队执行 |
| P5 定向扩展 | no_signal联合约束、覆盖发现、有限清除后备与预算 | 朝外边界源不漏;真源不误删;格数与退出预算检查 | 已实现:`planner.DirectionalExtension`(49点覆盖对定向源成立、保证接收盘内 no_signal 记为观测到定向、对跖+环探梯子、`fallback_clear_cells` 有限圆盘覆盖后备清除带格数/预算双硬顶);`tests/test_loop_q4.py` 全过;官方混合源演练待执行 |
| P6 加速消融 | 共享测点、自适应覆盖、目标排序、提前清除 | 配对案例全清不退化,时间/请求数改善可复算 | 可删减;闭环基线数据已可用于消融对照 |
| P7 正式与论文 | 固定版本、论文表1、日志原名、上传核查 | 问题3/4各3份正式记录与程序版本对应 | 团队后续安排;本任务不执行正式测试 |
按2026年9月10日起的剩余时间,建议10日补齐P1并衔接P3,11日完成P4自建边界案例与全向演练,12日完成P5及混合源演练;未达验收就删减P6并优先修正闭环。演练不限3次,正式机会为问题3和4各3次。团队在版本稳定后自行安排正式记录,留出失败恢复和论文整理时间。附件建议9月13日15:30前完成正式测试,17:30后不能启动新的演练或正式测试;已进入上传队列的日志仍会继续上传。此处引用所给附件安排,运行前核对模拟器界面公告;这份排期不改变当前禁止使用正式测试的限制。
若时间不足,优先删减加速策略,保留可解释定位、覆盖证明、可靠协议和完整日志。开发组织可按几何算法、工程接口、实验论文分工,具体人员由团队安排。
建议后续代码划分为 protocol、geometry、belief、coverage、planner、local_simulator、evaluation 七个模块。官方客户端与自建环境使用同一动作接口;自建真值只对测试端开放,策略端只能看到观测,防止评估时意外使用隐藏答案。
## 8. 当前已落实的结论与下一步
已完成题面与附件核对、49点覆盖推导及扫描成本复算;此前497160个位置与朝向组合的辅助数值校核未发现覆盖遗漏,但采样不代替证明。问题一已通过官方演练三点观测离线验证;该次只有enter、measure、exit,没有清除动作,不能当作全清策略成绩。
本次将 MEC 从全支撑点枚举改为带固定随机种子的 Welzl 增量算法,保留原枚举法作独立对照;对外输出增加直径圆反例顶点、超出距离和 20 米清除余量。CLI 可显式追加 $0.005^\circ$ 舍入裕量。真实演练默认 $\delta=1^\circ$ 时 $D=23.996723$ 米、$\rho=12.068583$ 米;$\delta=1.005^\circ$ 时 $D=24.119088$ 米、$\rho=12.130377$ 米,两种口径下直径圆都不覆盖,但 MEC 半径都小于 20 米。原始演练记录未改写。
可复现报告见 `output/q1/optimization_report.json`,问题一证明、输入输出及数值限制见 `docs/问题一解答.md`。局部MEC基准只反映本地几何计算,不能据此宣称请求延迟、完整策略或官方成绩得到同样提升。
P0–P5(自建部分)与 P2 均已交付:协议层(串行幂等客户端、状态机、预算截止、
故障回放)、几何内核、belief 保守候选集、保证接收盘选点器、`OmnidirectionalLoop`
全向闭环与 `DirectionalExtension` 混合源定向闭环(49 点覆盖对定向源同样成立、
no_signal 联合约束基线不删候选、对跖+环探遮挡梯子、`fallback_clear_cells`
有限圆盘覆盖后备清除,格数与现实预算双硬顶下不盲扫)。自建验收:
`uv run pytest`(105 项)与 `uv run mcm26b sim-check`;随机场景自检:
`uv run mcm26b run --robot-id <队号> --self-test`(问题4加 `--problem 4`)。
评审修订(2026-09-11):本地模拟器改为逐点固定误差场(同一"源×位置"读数
恒定,与官方演练实测一致);对跖复核探点公式修正(此前塌缩到 MEC 圆心 1m
内,浪费探点预算并推高后备清除);环探"≥180° 可见弧"依据删除(最坏可见弧
可退化为单点,梯子只是启发式,完备性由后备清除兜底);断连/协议错误中断后
仍尽力 /exit 并产出未完成 summary;库默认舍入裕量统一为 0.005°;后验评分
补 near 分支;问题一近平行细长区域保留远端顶点。后备清除成本用
`scripts/benchmark_q4.py` 批量种子扫描量化(结果落盘 `output/q4/`)。
下一步优先把两个闭环接入官方演练(问题3用全向、问题4用混合,先实测单请求
延迟与总请求数,核对 1200s 现实预算与 2MB 日志体积),再做 P6 消融对照。
顺序约束:上述模拟器与故障收尾修复先行合入,官方演练在修复后的版本上执行;
总请求口径必须计入后备清除(summary 的 `total_requests` 与
`fallback_clear_attempts`),仅统计检测次数会低估现实耗时。
基线量级供参照:10 源场景约 550–630 次检测、虚拟总时 1.4–1.7 万秒;16 源
场景约 200–320 次检测即触发数量上界停止。该数字说明共享测点与跳点策略
(P6)有明确改进空间。不要重复开发几何内核或提前堆叠学习算法;以官方演练
的实际请求、日志和耗时决定 P6 加速投入。
-191
View File
@@ -1,191 +0,0 @@
# 2026 高教社杯 B 题(无线电干扰源快速自动定位与清除)问题 3、4 相关论文列表
> 排序原则:与问题 3/4 直接应用方案越相关,排名越靠前。
> 标注:【Q3】主要支撑问题 3(全向干扰源:搜索→交会定位→逼近清除的整体策略);【Q4】主要支撑问题 4(定向干扰源、方向未知);【Q3·Q4】两者通用。
---
## 一、无线电信号源的移动机器人搜索与定位(与赛题任务框架最直接对应)
1. **Simultaneous Localization of Multiple Unknown and Transient Radio Sources Using a Mobile Robot** 【Q3】
D. Song, C. Y. Kim, J. Yi. *IEEE Transactions on Robotics*, 2012(被引 75)
移动机器人沿路径采集 RSS,在线同时定位**多个未知无线电源**——与问题 3“干扰源个数未知、机器狗边走边测”的设定几乎同构,可直接借鉴其多源数据关联与定位框架。
https://ieeexplore.ieee.org/abstract/document/6145760/ | [PDF](http://coewww.rutgers.edu/~jgyi/pdfs/IEEE_TRO_2012.pdf)
2. **Cooperative Search of Multiple Unknown Transient Radio Sources Using Multiple Paired Mobile Robots** 【Q3】
C. Y. Kim, D. Song, Y. Xu, J. Yi, X. Wu. *IEEE Transactions on Robotics*, 2014(被引 67)
上文的协同多机器人版本:成对机器人搜索多个未知瞬态无线电源,含**源匿名(信号不可区分)**处理——对应本题不同频道区分信号的思路对照。
https://ieeexplore.ieee.org/abstract/document/6857360/ | [PDF](https://jingangyi.rutgers.edu/pdfs/IEEE_TRO_2014.pdf)
3. **RSS Gradient-Assisted Frontier Exploration and Radio Source Localization** 【Q3·Q4】
J. N. Twigg, J. R. Fink, L. Y. Paul, B. M. Sadler. *ICRA*, 2012(被引 77)
用 RSS 梯度引导前沿探索(frontier exploration),让机器人高效逼近信号源而避免盲目遍历——可直接支撑问题 3/4 中“初探→逼近”的两阶段搜索策略设计。
https://ieeexplore.ieee.org/abstract/document/6225059/
4. **Radio Source Localization Using Sparse Signal Measurements from Uncrewed Ground Vehicles** 【Q3】
A. Perera, V. P. Tran, S. Anavatti, K. Kasmarik, et al. *arXiv:2312.03493*, 2023
地面无人车(与机器狗同类平台)在室外区域以稀疏采样定位无线电源,含完整仿真评估流程——与用模拟器演练测试的实验设计直接可参照。
https://arxiv.org/abs/2312.03493 | [PDF](https://arxiv.org/pdf/2312.03493)
5. **Particle Filter Based Localization of Access Points Using Direction of Arrival on Mobile Robots** 【Q3·Q4】
R. Parashar, R. Parasuraman. *IEEE VTC*, 2020(被引 13)
移动机器人利用**到达方向(DOA,即示向度)**+ 粒子滤波递推定位无线电源——对应本题“多次测向→逐步缩小定位区域”的序贯定位算法。
https://ieeexplore.ieee.org/abstract/document/9348813/
6. **Online Methods for Radio Signal Mapping with Mobile Robots** 【Q3】
J. Fink, V. Kumar. *ICRA*, 2010(被引 166)
移动机器人边走边在线构建信号场强地图并估计源位置,可支撑本题“场强仅随距离衰减”假设下的快速粗定位与路径在线修正。
https://ieeexplore.ieee.org/abstract/document/5509574/
7. **Distributed Algorithms for Stochastic Source Seeking with Mobile Robot Networks** 【Q3】
N. A. Atanasov, J. Le Ny, et al. *ASME JDSMC*, 2015(被引 117)
随机源搜索的分布式算法,以无线电源定位为应用背景,理论保证强,可作为逼近清除阶段的收敛性依据。
https://arxiv.org/pdf/1402.0051
8. **Cooperative Multi-Robot Estimation and Control for Radio Source Localization** 【Q3】
B. Charrow, N. Michael, V. Kumar. *IJRR*, 2014(被引 84)
仅测距射频下的多机器人协同估计与控制,信息论驱动( mutual information )选择测量动作——可迁移为“选哪个频道、去哪测”的决策准则。
https://journals.sagepub.com/doi/abs/10.1177/0278364913500542
9. **A Review of Radio Frequency Based Localisation for Aerial and Ground Robots with 5G Future Perspectives** 【Q3·Q4】
M. Kabiri, C. Cimarelli, H. Bavle, et al. *Sensors*, 2022(被引 48)
综述:RSS/AOA 等 RF 定位手段在空地机器人上的比较,适合写论文的“研究现状”部分并帮助选型。
https://www.mdpi.com/1424-8220/23/1/188
---
## 二、测向(Bearing-only/AOA)交会定位与观测点优化(第二检测点选择、定位区域收缩)
10. **Gathering Bearing Data for Target Localization** 【Q3】
H. Bayram, J. Vander Hook, V. Isler. *IEEE Robotics and Automation Letters*, 2016(被引 38)
给定若干潜在目标区域与不确定度要求,规划采集方位数据的机器人路径,归结为 **TSP with Neighborhoods 的信息路径规划**——与问题 3“多个待清除目标 + 逐个交会定位 + 总时间最短”的任务排序高度吻合。
https://ieeexplore.ieee.org/abstract/document/7390217/ | [PDF](https://conservancy.umn.edu/bitstreams/ff2d34bf-0056-4a29-be84-eb7355b527e4/download)
11. **Relationship Between Error Ellipse and Error Quadrilateral in Bearing-Only Localization** 【Q3·Q4】
B. Wang, Y. Hu, C. Yu, et al. *IEEE Access*, 2026
直接研究双站测向定位的**误差四边形**(即题目中的“定位区域”)与误差椭圆的关系,论证几何构型与精度的关系——与问题 1 的定位区域、问题 2/3 的测点选择理论完全对口。
https://ieeexplore.ieee.org/abstract/document/11677056/
12. **Bearing-Only Active Target Localization Strategies for a System of Two Communicating Mobile Robots** 【Q3】
J. Vander Hook, P. Tokekar. 技术报告, 2013
主动测向定位:规划“去哪测”以最优压缩目标位置不确定性,给出最优双机器人测量构型——第二检测点选择策略的系统性理论。
https://conservancy.umn.edu/items/38693c39-7a3b-400b-8926-f9aa194a8824
13. **Multi-UAV Trajectory Optimization for Bearing-Only Localization in GPS Denied Environments** 【Q3】
A. Sciacchitano, L. Mudrik, S. Kragelund, et al. *arXiv:2602.11116*, 2026
面向测向定位的轨迹优化,在视场等约束下优化测量构型——可借鉴其代价函数与滚动优化框架设计机器狗的测点序列。
https://arxiv.org/abs/2602.11116 | [PDF](https://arxiv.org/pdf/2602.11116)
14. **Optimal Sensor Placement for Multi-Source AOA Localisation with Distance-Dependent Noise Model** 【Q3·Q4】
M. Hamdollahzadeh, R. Amiri, et al. *IET Radar, Sonar & Navigation*, 2019(被引 37)
**多源** AOA 定位的最优布点,含递推 CRLB 表示——支撑多干扰源场景下测点位置的全局优化。
https://ietresearch.onlinelibrary.wiley.com/doi/abs/10.1049/iet-rsn.2018.5426
15. **Optimal Sensor Placement for Target Localization Using Hybrid RSS, AOA and TOA Measurements** 【Q3】
S. Xu, et al. *IEEE Communications Letters*, 2020(被引 110)
混合量测下最小化 tr(CRLB) 的最优传感器-目标几何,可用于论证“交会角接近 90°”等构型结论的严谨性。
https://ieeexplore.ieee.org/abstract/document/9097832/
16. **Geometry Influence on GDOP in TOA and AOA Positioning Systems** 【Q3·Q4】
X. Lv, K. Liu, P. Hu. *ICNSC*, 2010(被引 58)
基于 CRLB 分析新增观测点对 GDOP 的影响——回答“再加一个检测点值不值、放在哪”的定量依据。
https://ieeexplore.ieee.org/abstract/document/5480336/
17. **定向交叉定位配站问题与定位精度分析**(中文)【Q3·Q4】
张艳花. 《电讯技术》, 2008(被引 2)
中文文献,专门讨论测向交叉定位的配站(交会角)与精度关系,便于直接引用“交会角 90° 最优、30°~150° 可用”类结论。
(《电讯技术》2008 年刊,可通过知网/万方检索全文)
18. **Trajectory Planning for Multiple Robots in Bearing-Only Target Localisation** 【Q3】
C. Leung, S. Huang, G. Dissanayake, et al. *IROS*, 2005(被引 16)
早期经典:以定位精度为目标做测向机器人轨迹规划,适合作为主动定位问题的建模起点引用。
https://ieeexplore.ieee.org/abstract/document/1545322/
19. **Observer Path Planning for Bearings-Only Localization Considering Limited Field of View** 【Q3】
A. Nayebi Astaneh, N. Pariz, M. O. Naghibi Sistani. *Journal of Control*, 2014
考虑传感器视场约束的观测者实时路径规划——对应测向机需旋转天线搜索示向度的过程约束。
https://joc.kntu.ac.ir/browse.php?a_id=37&sid=1&slc_lang=en&ftxt=1
---
## 三、多目标搜索理论与任务规划(10–16 个未知目标的区域搜索框架)
20. **Multi-Vehicle Bayesian Search for Multiple Lost Targets** 【Q3·Q4】
E. M. Wong, F. Bourgault, T. Furukawa. *ICRA*, 2005(被引 193)
多目标贝叶斯搜索经典:概率图 + 贝叶斯更新 + 搜索资源分配——问题 3“干扰源个数未知、需确保全部清除”的终止判据与覆盖率论证可由此构建。
https://ieeexplore.ieee.org/abstract/document/1570598/
21. **MPC-Based Cooperative Multiagent Search for Multiple Targets Using a Bayesian Framework** 【Q3】
H. Xiao, R. Cui, D. Xu, Y. Li. *Journal of Field Robotics*, 2024(被引 9)
模型预测控制 + 贝叶斯框架的多目标搜索路径规划,滚动时域决策——适合借鉴为本题“边测边重规划”的在线策略。
https://onlinelibrary.wiley.com/doi/abs/10.1002/rob.22382
22. **Multi-Agent Informed Path Planning Using the Probability Hypothesis Density** 【Q3·Q4】
J. Olofsson, G. Hendeby, T. R. Lauknes, T. A. Johansen. *Autonomous Robots*, 2020(被引 27)
用 PHD(随机有限集)表示**目标个数与位置均未知**的场景并做信息路径规划——与“干扰源总数 10–16 但具体未知”的设定直接对应。
https://link.springer.com/article/10.1007/s10514-020-09904-1 | [PDF](https://torarnj.folk.ntnu.no/AURO2020a.pdf)
23. **Probabilistic Search for Tracking Targets: Theory and Modern Applications** 【Q3·Q4】
E. Kagan, I. Ben-Gal. Wiley, 2013(被引 27)
搜索论专著:最优搜索策略、马尔可夫决策模型,为搜索策略提供理论根基(Stone 最优搜索理论的应用版)。
https://onlinelibrary.wiley.com/doi/abs/10.1002/9781118596593
24. **Efficient Multi-Robot Search for a Moving Target** 【Q3】
G. Hollinger, S. Singh, J. Djugash, A. Kehagias. *IJRR*, 2009(被引 254)
多机器人高效搜索路径规划(ESPP)并提出可证明性能的近似算法;本题目标虽静止,其“最大化截获概率”的建模与保证思路可迁移。
https://journals.sagepub.com/doi/abs/10.1177/0278364908099853
---
## 四、定向干扰源定位(问题 4 特有:覆盖角 180°、方向未知)
25. **UAV-Based Efficient Joint Estimation of Directional Emitter Position and Transmission Orientation** 【Q4】
T. Ruan, Y. Huang, L. Zhou, Q. Wu, et al. *IEEE Wireless Communications Letters*, 2024(被引 2)
**联合估计定向发射源的位置与发射方向**(RSS-AOA 混合量测)——问题 4“定向方向未知”的最直接对应文献。
https://ieeexplore.ieee.org/abstract/document/10802920/
26. **Efficient Localization of Directional Emitters via Joint Beampattern Estimation** 【Q4】
F. Williams, A. Pemasiri, D. Jayalath, T. Martin, et al. *arXiv:2411.04364*, 2024
联合波束方向图估计实现定向发射源高效定位,并分析波束宽度/朝向对定位的灵敏度(CRLB)——可支撑定向源需从侧向多点探测的策略设计。
https://arxiv.org/abs/2411.04364 | [PDF](https://arxiv.org/pdf/2411.04364)
27. **Location Errors of Directional Emitters in AOA System for Non-Line-of-Sight Conditions** 【Q4】
J. M. Kelner, C. Ziółkowski, et al. *SPIE*, 2019
分析发射天线朝向对 AOA 示向度误差的影响——定向干扰源场景下误差建模的参考。
https://www.spiedigitallibrary.org/conference-proceedings-of-spie/11055/110551G/Location-errors-of-directional-emitters-in-AOA-system-for-non/10.1117/12.2525060.short
28. **ALRD: AoA Localization with RSSI Differences of Directional Antennas for Wireless Sensor Networks** 【Q4】
J. R. Jiang, C. M. Lin, F. Y. Lin, et al. *Int. J. of Distributed Sensor Networks*, 2013(被引 133)
利用定向天线朝向差分的 RSSI 做定位,对“信号只在 180° 覆盖角内可被接收”的探测盲区分析与补盲路径设计有参考价值。
https://journals.sagepub.com/doi/abs/10.1155/2013/529489
---
## 五、信息路径规划方法与综述(通用方法库)
29. **Information-Driven Path Planning** 【Q3·Q4】
S. Bai, T. Shan, F. Chen, L. Liu, B. Englot. *Current Robotics Reports*, 2021(被引 53)
信息驱动路径规划综述,梳理目标函数(信息增益、熵减)与平台约束,适合搭建问题 3 的总体算法框架。
https://link.springer.com/article/10.1007/s43154-021-00045-6
30. **Adaptive Informative Path Planning in Metric Spaces** 【Q3】
Z. W. Lim, D. Hsu, W. S. Lee. *IJRR*, 2016(被引 101)
带自适应性的信息路径规划,具次模性与近似保证——为“总时间越短越好”的目标函数设计提供理论工具。
https://journals.sagepub.com/doi/abs/10.1177/0278364915596378
31. **Informative Path Planning for Active Field Mapping Under Localization Uncertainty** 【Q3】
M. Popović, T. Vidal-Calleja, J. J. Chung, et al. *ICRA*, 2020(被引 62)
不确定性感知的信息路径规划,平衡探索与精度——对应本题“检测耗时 vs 路径耗时”的权衡。
https://ieeexplore.ieee.org/abstract/document/9197034/
32. **基于深度强化学习的短波自主检测与定位方法**(中文)【Q3】
冯祺玥, 唐涛, 张昀普, 王鼎, 吴志东. 《通信学报》, 2026
中文文献:多站测角交会定位 + 深度强化学习自主检测定位,提供国内无线电监测定位的表述与流程范式。
https://www.joconline.com.cn/rc-pub/front/front-article/download/155129217/lowqualitypdf/%E5%9F%BA%E4%BA%8E%E6%B7%B1%E5%BA%A6%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0%E7%9A%84%E7%9F%AD%E6%B3%A2%E8%87%AA%E4%B8%BB%E6%A3%80%E6%B5%8B%E4%B8%8E%E5%AE%9A%E4%BD%8D%E6%96%B9%E6%B3%95.pdf
---
### 使用建议
- **问题 3 算法主线**:以 1、3、10、20、22 为核心——贝叶斯概率图搜索(20/22)确定探测顺序与终止条件,DOA 序贯定位(5)+ 交会几何优化(10/11/15/17)选测点,RSS 梯度逼近(3)完成 20 m 内清除前逼近。
- **问题 4 增量**:在问题 3 框架上叠加 25/26 的“位置 + 方向”联合估计,并用 28 的思路设计覆盖角盲区的补测路径。
- **论文写作**:现状综述引用 9、29、32;精度理论引用 11、14、15、16。
+24 -63
View File
@@ -1,71 +1,32 @@
# docs 索引
仓库文档分四类:**总览与流程**、**逐问算法**、**验证与对比**、**论文与插图**。
阅读顺序建议按下面的表格从上到下。
论文本身已完整给出四问的模型、推导与结果分析,因此本目录不再保留算法说明文档,
只留下复现所需的说明与材料。
## 总览与流程
| 文档 | 内容 |
| 入口 | 内容 |
| --- | --- |
| [`总体思路与流程图.md`](总体思路与流程图.md) | 四问主线、端到端流程图(mermaid)、执行步骤与执行时间速查、交付物与验收锚点 |
| [`执行时间与执行步骤.md`](执行时间与执行步骤.md) | 计时模型、会话状态机与动作回合、附件示例逐步推演、实测日志分解、时间预算与安全阀 |
| [`B题建模分析与实施计划.md`](B题建模分析与实施计划.md) | 四问建模取舍与 P0–P7 实施计划(最早的设计文档) |
| [`协议规则表与状态机.md`](协议规则表与状态机.md) | 指令字段表、结果码、计时模型、状态机(P0 交付) |
| [`../README.md`](../README.md) | **总入口**:环境、运行程序、复现论文数据与插图、编译论文 |
| [`aigc-compliance-record.tex`](aigc-compliance-record.tex) | **AIGC 使用合规记录**:本机 AI 客户端会话的完整审计留痕(58 页) |
| [`aigc-compliance-record.pdf`](aigc-compliance-record.pdf) | 上述记录的编译成品 |
| [`paper/README.md`](paper/README.md) | 论文工程说明:数据分工、重算与编译步骤、VS Code 配方 |
| [`paper/REWRITE_NOTES.md`](paper/REWRITE_NOTES.md) | 论文各轮修订与验证记录(含演练数据重采与问题修复) |
| [`paper/main.tex`](paper/main.tex) | 论文 LaTeX 源文件(正文与附录) |
| [`paper/data/`](paper/data) | 论文引用的全部数据、宏与整表(由脚本生成) |
| [`figures/README.md`](figures/README.md) | 论文插图清单:每张图的数据来源与生成命令 |
| [`figures/manifest.json`](figures/manifest.json) | 插图来源清单(可机读) |
## 逐问算法
`docs/paper/fonts/` 存放论文编译用字体(约 150 MB),已在 `.gitignore` 中排除、不入库;
缺失时按 `paper/mcm26b-paper.cls` 内的注释改用系统字体。
| 文档 | 内容 |
| --- | --- |
| [`algo-1.md`](algo-1.md) | 问题一实现口径:半平面交、顶点对直径、直径圆充要判定、MEC 清除证书 |
| [`问题一解答.md`](问题一解答.md) | 问题一论文式解答:模型边界、算法可复现步骤、反例构造、演练验证 |
| [`algo-2.md`](algo-2.md) | 问题二:候选集 K1、保证接收盘、安全盘 B(c, 1000−a)、最坏后验选点 |
| [`algo-3.md`](algo-3.md) | 问题三:三层在线架构、七点解析覆盖、覆盖账本、任务调度与停止条件 |
| [`algo-3-bayes.md`](algo-3-bayes.md) | 问题三 `bayes` 策略:网格幸存集滤波、信息增益选点、动态 TSP、Optuna 调参 |
| [`algo-4.md`](algo-4.md) | 问题四:`forward_half_disk` 最小命中集、位置×朝向联合信念、后备盲清 |
## 复现顺序
## 优化与验证
```bash
python scripts/build_practice_data.py # 演练局复算 → 宏与表格
python scripts/audit_paper_formal.py --snapshot docs/paper/data/formal-results.json
python scripts/build_paper_support.py # 附录正式数据表(--package 另出支撑包)
uv run python scripts/plot_paper_figures.py
cd docs/paper && latexmk -xelatex -interaction=nonstopmode -halt-on-error -outdir=build main.tex
```
| 文档 | 内容 |
| --- | --- |
| [`第三四问架构优化与运行提速方案.md`](第三四问架构优化与运行提速方案.md) | 运行历史复核、分层目标架构、P0–P2 优化项与实施路线 |
| [`第三四问图论与动态规划优化方案.md`](第三四问图论与动态规划优化方案.md) | 图论/DP 引入方案与实测回填(含未采用的改动与原因) |
| [`算法审核与优化-20260911.md`](算法审核与优化-20260911.md) | 一次外部口径的算法审核记录与结论 |
| [`最优与基线实现对比.md`](最优与基线实现对比.md) | 1–4 问「最优实现 / 基线实现」对比框架与结果(论文口径说明) |
| [`B题问题3-4相关论文列表.md`](B题问题3-4相关论文列表.md) | 题 3、4 相关文献清单 |
## 论文与插图
| 路径 | 内容 |
| --- | --- |
| [`paper/main.tex`](paper/main.tex) | 论文正文(`latexmk -xelatex main.tex`) |
| [`paper/README.md`](paper/README.md) | 论文编译方式、目录结构与待办标记 |
| [`figures/README.md`](figures/README.md) | 插图清单、配色与字体约定、数据来源与复现命令 |
| [`figures/manifest.json`](figures/manifest.json) | 每张图的数据来源与 sha256、生成命令 |
| [`../project/README.md`](../project/README.md) | 对比框架目录结构与运行方式 |
## 口径登记
同一事实在多份文档中出现时,以下列来源为准;发现不一致请先改文档,再复核图。
| 事实 | 权威来源 |
| --- | --- |
| 题面常量(Ω、速度、各动作耗时、源与频道范围) | `src/mcm26b/config.py`(带 `[题面]` / `[工程]` 标注) |
| 指令字段与结果码 | `src/mcm26b/protocol/rules.py` + [`协议规则表与状态机.md`](协议规则表与状态机.md) |
| 问题一数值(D、ρ、E) | `mcm26b.geometry.solve` 的返回,或 [`问题一解答.md`](问题一解答.md) |
| 覆盖计划与证书 | `src/mcm26b/guarantee/plans/*.json`(`q4_mincover_v2.json` 为默认) |
| 实测虚拟时间 | 行为日志 `virtual_time_s` 字段与 `evaluation.recompute_virtual_time` |
| 冻结基准集对比结果 | `project/results/*.md`(由 `uv run python -m project.run` 生成) |
已知的两处需要随环境更新的引用:
1. [`问题一解答.md`](问题一解答.md) 引用的 `output/q1/figures/*.png` 属于早期
离线插图(`output/` 未入库);现行插图在 [`figures/`](figures/README.md)。
2. 多份文档提到的官方演练报告位于 `output/q3/practice/`、`output/q4/`,
同样未入库;需要时用 `scripts/verify_q3_practice.py` 对留档目录复算。
## 写作约定
- 只写结论与依据,不使用比喻、排比与自评式措辞(例如「唯一权威」「关键洞察」)。
- 数字必须能在代码或数据中找到出处;图内不放标题与解释段落,
说明写在正文,图名与清单见 [`figures/README.md`](figures/README.md)。
- 中文引号统一使用「」,避免与代码中的 ASCII 引号混淆。
> `docs/paper/data/*.tex` 由脚本生成,一律使用 LF 换行:CRLF 会让 `\input` 进表格的行
> 在 TeX 缓冲中提前 `\par` 化,触发 booktabs 的 “Misplaced \noalign”。
Binary file not shown.
File diff suppressed because one or more lines are too long
-266
View File
@@ -1,266 +0,0 @@
# 问题一算法说明:有界测向误差下的角域交会、直径与最小包围圆
> 本文按**当前仓库实现**重写,替代早期只描述理论方案的版本。
> 问题一生产入口为 `src/mcm26b/geometry/localization.py::solve`,CLI 为
> `python -m mcm26b.geometry`;问题二至四只复用其中的
> `smallest_enclosing_circle` 与同一套角域半平面语义,并不直接调用
> `solve`(复用与差异见 §7)。
## 1. 问题与实现入口
同一频道的同一静止干扰源,在若干检测点 $s_i=(s_{ix},s_{iy})$ 处得到示向度
$\theta_i$。题设测向误差不超过 $\pm1^\circ$,同一地点重复测量误差不变;
示向度从正东逆时针计量。问题一要求定位区域的直径,并判断“以该直径为
直径的圆”能否覆盖定位区域。
| 层次 | 文件 | 内容 |
| --- | --- | --- |
| 生产内核 | `src/mcm26b/geometry/localization.py` | `Measurement`、`halfplanes`、`convex_hull`、`diameter`、`smallest_enclosing_circle`、`solve` |
| CLI | `src/mcm26b/geometry/__main__.py` | 读 JSON、可加两位小数舍入裕量、输出结果 |
| 统一入口 | `src/mcm26b/cli.py` | `mcm26b q1` |
| 对比框架 | `project/q1/{optimal,baseline,reference,cases,compare}.py` | 生产实现 / 朴素基线 / 独立大框参考解 |
| 回归 | `tests/test_geometry.py`、`tests/test_geometry_certificates.py` | 解析形状、真值保留、随机对拍、证书边界 |
| 结果 | `examples/q1/*.json`、`project/results/q1.md` | 固定解析算例与 40 个随机交会算例的配对结果 |
```bash
.venv/bin/python -m mcm26b.geometry examples/q1/triangle.json
.venv/bin/python -m mcm26b.geometry examples/q1/normal.json --rounding-margin-deg 0.005
```
`--rounding-margin-deg` 默认 $0$;库内在线求解默认把服务器两位小数舍入的
$\le0.005^\circ$ 偏差计入有效半角,这是**实现口径**,不是题面新增误差。
问题一 CLI 只有显式传参才附加该裕量,以便同时报告纯 $1^\circ$ 与
$1.005^\circ$ 两套敏感性结果。
## 2. 模型:把角域写成半平面交
令方向向量 $u(\alpha)=(\cos\alpha,\sin\alpha)$,二维叉积
$[a,b]=a_xb_y-a_yb_x$。设误差半角为 $\delta$(题设主模型 $\delta=1^\circ$),
真实源 $g$ 属于闭前向角域
$$
W(s,\theta,\delta)=\{g:\ [u(\theta-\delta),g-s]\ge0,\
[u(\theta+\delta),g-s]\le0,\ u(\theta)\cdot(g-s)\ge0\}.
$$
对应实现中的三条半平面 $a x+b y\le c$ 为
| 约束 | $a$ | $b$ | $c$ |
| --- | --- | --- | --- |
| 下边界左侧 | $\sin(\theta-\delta)$ | $-\cos(\theta-\delta)$ | $a s_x+b s_y$ |
| 上边界右侧 | $-\sin(\theta+\delta)$ | $\cos(\theta+\delta)$ | $a s_x+b s_y$ |
| 前向 | $-\cos\theta$ | $-\sin\theta$ | $a s_x+b s_y$ |
第三条前向约束在 $0<\delta<90^\circ$ 时冗余,但在 $\delta=0$ 时必须保留,
否则两条边界只确定一条直线而非一条射线。角域顶点按闭集处理;这是保守的
几何含义,不表示边界点仍能返回方向读数。
$P=\bigcap_i W_i$ 是有限条闭半平面之交,因而是闭凸集;可能为空、单点、
线段、有界多边形或无界多边形。实现不做正态、均匀或独立误差假设,
只使用题面给定的有界误差。
## 3. 精确算法流程
`solve(measurements, eps)` 的步骤如下。
### 3.1 坐标归一化与边界交点枚举
先对所有检测点做平移和统一缩放,使数值量级接近单位坐标;结果再换回原坐标。
1. 生成 $k=3n$ 条半平面。
2. 枚举全部边界直线对($\binom{k}{2}$ 对),用行列式
$\Delta=ae-bd$ 求交点;仅在 $\Delta$ 恰为 $0$ 时跳过,近平行对也保留,
因为其交点可能是细长区域的合法远端顶点。
3. 保留满足全部约束的交点;可行性判定使用随坐标量级缩放的位置容差
`eps * max(1, |x|, |y|)`,避免大坐标下绝对残差被误判为不可行。
### 3.2 空集、有界与无界
- 无观测:$P=\mathbb R^2$,返回 `unbounded`。
- 没有任何可行边界交点:返回 `empty`。
- 否则检查衰退锥 $\mathcal R=\{d:Ad\le0\}$ 是否存在非零方向。二维情况下
该锥若非零必含一条与某条有效边界平行的极射线;实现只需检查每条约束的
两个切向 $(b,-a)$、$(-b,a)$ 是否满足全部齐次不等式
$a d_x+b d_y\le 2\times10^{-14}$。阈值取得比位置容差紧得多,避免把
极细长有界区域误判成无界。
- 存在非零衰退方向时返回 `unbounded`,直径为 `null` 且显式置
`diameter_infinite=true`,不伪造有限数值。
### 3.3 凸包与状态分类
将可行交点去重后,用 Andrew 单调链求凸包(逆时针、无重复首尾点)。
按顶点数与维数返回:
| `status` | 含义 | 直径 | 最小包围圆 |
| --- | --- | --- | --- |
| `empty` | 观测不相容 | 未定义(`null`) | 不计算 |
| `unbounded` | 存在非零衰退方向 | $+\infty$(`null` + 标志) | 不计算 |
| `point` | 单点 | 0 | 半径 0 |
| `segment` | 线段 | 两端点距离 | 半径 = 直径 / 2 |
| `polygon` | 二维有界凸多边形 | 见 §3.4 | 见 §3.6 |
### 3.4 直径:只需枚举顶点对(已证明)
**定理 1.** 若 $P=\operatorname{conv}(V)$ 非空有界,则
$D(P)=\max_{v_i,v_j\in V}\lVert v_i-v_j\rVert$。
证明:任一 $x,y\in P$ 写成凸组合后,
$x-y=\sum_{i,j}\lambda_i\mu_j(v_i-v_j)$,由三角不等式有
$\lVert x-y\rVert\le\max_{i,j}\lVert v_i-v_j\rVert$,而最远顶点对本身
属于 $P$,故上界可达。实现直接枚举顶点对,复杂度 $O(m^2)$;单点返回 0,
线段返回端点距离。
### 3.5 直径圆覆盖:唯一候选圆心是直径中点(已证明)
**定理 2.** 取任意一组最远顶点 $a,b$,$D=\lVert a-b\rVert$,
$o=(a+b)/2$。存在直径为 $D$ 的覆盖圆,当且仅当所有顶点 $v_i$ 满足
$\lVert v_i-o\rVert\le D/2$。
证明:若半径 $D/2$ 的圆心 $z$ 同时包含 $a,b$,则
$D\le\lVert a-z\rVert+\lVert z-b\rVert\le D$,两个不等式都必须取等号,
故 $z$ 只能在两点中点。圆盘是凸集,检查全部顶点即检查整个凸包。
实现输出 `diameter_circle`:圆心、半径、全部顶点到圆心的最大距离、
`covers` 布尔值、最大超出量 `max_excess_m`、圆外顶点索引
`outside_vertex_indices` 和反例顶点 `witness_vertex`。`witness_vertex`
是一份可独立复核的覆盖失败证据;`max_excess_m` 不能为负,因为最远顶点
本身在圆周上(精确算术下)。
### 3.6 最小包围圆与 20 m 清除证书
对凸包求最小包围圆 $\rho(P)$。实现采用 Welzl 随机增量算法的显式栈版本:
固定随机种子使结果可复现;三个强制边界点使用外接圆;输出前再对全部
顶点复核一次。内部有 $O(m^4)$ 的 1/2/3 点支撑圆枚举参考实现
(`_enclosing_circle_reference`)用于单测对拍。
在最小包围圆中心 $m$、半径 $\rho$ 处,若
$\rho+\varepsilon_m\le20$,则可直接以 $m$ 为清除点:任意真源
$g\in P\subseteq B(m,\rho)$,到 $m$ 的距离不超过 $\rho$。实现输出
`minimum_enclosing_circle`、`guaranteed_clearable_at_mec_center` 以及
`clearance_certificate`(含数值余量和剩余裕量)。
注意:直径 $D\le40$ 只是“可能一次清除”的必要条件,**不是充分条件**;
三角形反例中 $D=40$ 而 $\rho=23.094>20$。
## 4. 伪代码
```text
solve(measurements):
if measurements 为空: return unbounded
平移/缩放,生成每条读数的三条半平面
V = []
for 每一对边界直线:
求交点 p
if p 满足全部半平面: V.append(p)
if V 为空: return empty
if 存在非零衰退切向 d: return unbounded
H = convex_hull(V)
D, (a,b) = argmax_{v_i,v_j∈H} |v_i-v_j|
o = (a+b)/2
covers = max_{v∈H} |v-o| <= D/2
输出 diameter、diameter_circle、witness
(m,rho) = Welzl_MEC(H)
输出 minimum_enclosing_circle 与 rho+eps<=20 清除证书
```
## 5. 复杂度与数值实现
| 步骤 | 复杂度 |
| --- | --- |
| 生成半平面 | $O(k)$,$k=3n$ |
| 边界交点枚举与可行性判定 | $O(k^3)$ |
| 凸包 | $O(k^2\log k)$ 最坏 |
| 直径 | $O(m^2)$ |
| 直径圆检查 | $O(m)$ |
| Welzl 最小圆 | 随机排列下期望 $O(m)$;固定排列不声称最坏线性 |
主要数值约定:
- 坐标归一化后计算,输出换回原坐标并重新复核包含性;
- 仅对**精确平行**直线对跳过求交;近平行对保留;
- 位置可行性容差随坐标幅值缩放;衰退锥判定使用独立紧阈值;
- `solve` 主动限制最多 100 个检测点,超过时要求改用半平面交算法;
- 所有输出用 `null`/显式标志表示空集和无界,不写非法 JSON 浮点数。
## 6. 已验证算例与结果
固定解析算例(`examples/q1`,当前代码实测):
| 算例 | 状态 | 直径 (m) | MEC 半径 (m) | 直径圆覆盖 | 最大超出 (m) | MEC 可直接清除 |
| --- | --- | ---: | ---: | --- | ---: | --- |
| `normal` 三点交会 | polygon | 26.986 | 13.943 | 否(2 个圆外顶点) | 3.964 | 是 |
| `triangle` 等边三角形反例 | polygon | 40.000 | 23.094 | 否(1 个圆外顶点) | 14.641 | 否 |
| `segment` 零误差退化线段 | segment | 100.000 | 50.000 | 是 | 0.000 | 否 |
| `poor` 近共线检测点 | unbounded | — | — | — | — | — |
| `empty` 不相容观测 | empty | — | — | — | — | — |
`triangle` 的三个顶点是 $(0,0)$、$(40,0)$、$(20,20\sqrt3)$:以直径
$AB$ 为直径的圆圆心 $(20,0)$、半径 20,到 $C$ 的距离为 $20\sqrt3>20$,
故不能覆盖;最小包围圆半径 $40/\sqrt3\approx23.094$,也不能一次清除。
其中 $A=(0,0)$ 坐标是浮点下的 $-6.4\times10^{-13}$,上表按解析值取整。
既有官方演练观测(案例 `U5ZW-P9KN-TCAG-R7ST`,不公开源坐标、未执行清除)
的复算结果:
| 误差半角 | 直径 (m) | MEC 半径 (m) | 直径圆最大超出 (m) |
| --- | ---: | ---: | ---: |
| $1^\circ$ | 23.996723 | 12.068583 | 0.604002 |
| $1.005^\circ$ | 24.119088 | 12.130377 | 0.608486 |
两种口径下直径圆都不覆盖定位区域,MEC 半径都小于 20 m,但该演练没有
真实清除动作,不能据此声称实测定位误差或全清成功率。
`project/q1` 的 40 个随机交会算例(冻结算例与独立参考解对拍):
| 方法 | 状态准确率 | 直径平均绝对误差 | 直径圆覆盖准确率 | 平均耗时 |
| --- | ---: | ---: | ---: | ---: |
| 生产 `solve` | 100% | 0.000 m | 100% | 0.086 ms |
| 朴素基线(网格 + 包围盒对角线) | 100% | 4.583 m | 52.5% | 15.932 ms |
## 7. 与问题二/三/四当前实现的复用关系和差异(核对结果)
问题一给出的几何内核是后续所有几何决策的基础,但**复用方式是“语义 + 最小圆函数”,
不是直接调用 `solve`**。代码层面的核对结果如下。
| 后续问题 | 实际复用了什么 | 实际没有复用 / 做了什么替换 |
| --- | --- | --- |
| 问题二(`planner.select_second_point`) | 同一套角域半平面语义;`smallest_enclosing_circle` 求候选集 MEC;用 MEC 半径构造保证接收盘 | 不调用 `solve`;候选集不是纯角域交,而是 $K_1=\Omega\cap W\cap B(s,1500)$;用 192 边形外包圆盘 + Sutherland–Hodgman 裁剪,而不是枚举直线交点;不计算直径,也不使用“直径中点圆”判据 |
| 问题三(`belief.CandidateRegion`、`planner.bayes_loop`) | 复用 `smallest_enclosing_circle`;角域边界公式与问题一相同;MEC 作为清除证书 | 在线信念是有界凸外包多边形,圆盘边界是外切多边形而非精确曲线;不再判无界;no_signal 的负观测由网格粒子滤波处理(问题一模型里没有负观测);不用直径,而用“MEC 半径 + 外包余量 + 工程余量 $\le20$” |
| 问题四(`planner.DirectionalExtension`、`belief.joint`) | 继续复用问题一的 MEC 与角域语义;(位置 × 朝向)联合信念也建立在同一网格上 | 定向源的 no_signal 不能排除位置,不能沿用问题一/三的纯角度或全向距离解释;覆盖语义改为 `forward_half_disk`(见 `algo-4.md`) |
代码证据:
- `src/mcm26b/belief/__init__.py` 只从 `geometry.localization` 导入
`smallest_enclosing_circle`;
- `src/mcm26b/particles.py` 同样只导入 `smallest_enclosing_circle`;
- `生产/运行代码中 `geometry.localization.solve` 的调用者只有
`geometry/__main__.py` 和 `project/q1/optimal.py`,即问题一 CLI 与其
对比框架;测试文件会直接调用它做解析与随机对拍,不在此列;
- 在线 `clip_wedge` 的半平面系数与问题一 `halfplanes` 一致,但作用在
凸多边形裁剪流程上;`solve` 的“纯角域 + 精确顶点枚举 + 无界判定”
是针对问题一的一站式分析工具,不适合直接嵌入带圆盘、负观测和状态更新
的在线闭环。
**差异一句话总结:** 问题一回答“固定角域观测下源可能在哪里、直径圆能否覆盖”,
是纯几何精确解;问题二至四把其中的角域半平面和最小圆升级为“带距离先验的
保守信念 + 主动动作 + 证据证明”的闭环,问题三再加非凸负观测,问题四再加
朝向维度。
## 8. 结论与适用边界
问题一的当前实现是:三条半平面 → 可行顶点枚举/凸包 → 衰退锥判有界 →
顶点对精确直径 → 任意直径中点唯一候选的覆盖检验 → Welzl 最小包围圆与
20 m 证书。其结论只依赖题面有界误差,不引入误差分布假设。空集、无界、
点、线段和多边形状态都有明确输出。
未解决问题一的数值敏感性时,不应把在线闭环里的外包多边形半径直接当成
问题一的精确直径;两者口径不同。反过来,在线闭环也不能把 `solve` 直接套在
$K_1$ 上,因为 $K_1$ 含圆盘和距离上界,边界可能含圆弧。
## 参考文献
1. 全国大学生数学建模竞赛组委会. 2026 年高教社杯全国大学生数学建模竞赛 B 题:无线电干扰源的快速自动定位与清除[Z]. 2026. 本地题面 `issue/B题.pdf`。
2. BOYD S, VANDENBERGHE L. Convex Optimization[M]. Cambridge University Press, 2004. 凸集、半平面与凸组合背景。
3. WELZL E. Smallest enclosing disks (balls and ellipsoids)[C]//New Results and New Trends in Computer Science, LNCS 555, 1991: 359–370. 随机增量最小包围圆。
4. 本项目. `docs/algo-2.md`(问题二当前实现). 问题二对本文半平面语义与最小圆的复用说明。
5. 本项目. `docs/algo-3.md`、`docs/algo-4.md`. 在线闭环中的保守信念、负观测与联合信念差异。
-312
View File
@@ -1,312 +0,0 @@
# 问题二算法说明:保证接收的第二检测点选择(当前实现)
> 本文按**当前仓库实际运行路径**重写。生产入口是
> `src/mcm26b/planner.select_second_point`,其核心选点器是
> `select_measurement_point`;`src/mcm26b/geometry/planning.py` 中的
> `first_bearing_candidate_disk` 是解析充分证书与独立校核工具,
> 并不在运行时被 `select_second_point` 调用(见 §6 核对结果)。
## 1. 问题、实现入口与交付物
问题二给定一个全向干扰源的首次有效示向度 $(s,\theta)$,要求给出第二个
检测点 $q$ 的选择策略、定位效果与候选区域。两个约束必须同时满足:
1. **接收保证**:$q$ 到所有仍可能为真源的位置都不超过有效接收半径下界
$R_-=1000$ m,否则第二次测量可能返回 `no_signal`,几何收益落空;
2. **定位效果**:在保证接收的候选点中,使第二次测量后的保守位置集合
尽量小。当前实现以“最坏后验最小包围半径”为主指标,以移动耗时为次指标。
| 层次 | 文件 | 内容 |
| --- | --- | --- |
| 在线入口 | `src/mcm26b/planner/__init__.py::select_second_point` | 由首次 `direction` 构造 $K_1$,返回 `SecondPointPlan` |
| 核心选点 | 同文件 `select_measurement_point` | 任意候选集的保证接收盘内选点 |
| 几何证书 | `src/mcm26b/geometry/planning.py::first_bearing_candidate_disk` | 截断角域解析外包圆与安全候选盘 |
| 信念构造 | `src/mcm26b/belief/__init__.py::BeliefState`、`CandidateRegion` | $K_1$ 的保守凸外包与更新 |
| 对比框架 | `project/q2/{optimal,baseline,reference,region,cases,compare}.py` | 生产选点器 / 两种朴素基线 / 保证盘内网格参考 |
| 回归 | `tests/test_planner.py`、`tests/test_geometry_certificates.py`、`tests/test_belief.py` | 接收保证、后验收缩、near 分支、解析证书 |
| 结果 | `project/results/q2.{md,json}` | 30 个随机首次示向度算例配对结果 |
## 2. 首次观测后的候选集 $K_1$
### 2.1 精确定义
记首次检测点为 $s$、首次示向度为 $\theta$、误差半角
$\delta_{\rm eff}=1^\circ+0.005^\circ$(题设误差 + 两位小数舍入裕量),
有效接收半径上界 $R_+=1500$ m,源位置圆域 $\Omega=B(0,1800)$。则
$$
K_1=\Omega\cap W(s,\theta,\delta_{\rm eff})\cap B(s,R_+).
$$
真实源在合法观测下必属于 $K_1$。注意 $B(s,R_+)$ 的半径是**接收半径上界**:
`direction` 读数本身就隐含测得距离不超过 $R_+$;而 $B(s,R_-)$ 不在 $K_1$
之中,因为第二次是否收到信号正是本问要保证的事。
### 2.2 实际保守表示
在线实现不直接处理圆弧边界,而用以下外切多边形表示 $K_1$:
- 先取 $\Omega$ 的 192 边外切正多边形 $P_M(0,1800)$;
- 再与 $B(s,1500)$ 的 192 边外切正多边形求交;
- 最后用 Sutherland–Hodgman 逐半平面裁剪两条测向边界。
设圆盘外切多边形相对圆盘的最大径向超出为 $R(1-\cos(\pi/M))$。实现把每次
圆盘裁剪的该量累加到 `CandidateRegion.slack_m`,因此维护的多边形满足
$K_1\subseteq P_{\rm out}$,且 `slack_m` 是可审计的外包半径余量。
这条路径与问题一的区别:问题一在纯角域上枚举边界直线交点,精确处理
空集/无界;问题二候选集一开始就被 $\Omega$ 和 $B(s,R_+)$ 限成有界集,
因此可以只用凸多边形裁剪。角域系数与问题一 `halfplanes` 完全一致:
$\sin(\theta-\delta)x-\cos(\theta-\delta)y\le c$ 与
$-\sin(\theta+\delta)x+\cos(\theta+\delta)y\le c$。
## 3. 保证接收区域
### 3.1 一般集合形式
对非空紧候选集 $K$,定义
$$
F_K(q)=\max_{g\in K}\lVert q-g\rVert,\qquad
\mathcal Q(K)=\{q:F_K(q)\le R_-\}=\bigcap_{g\in K}B(g,R_-).
$$
$F_K$ 是凸函数且 1-Lipschitz,$\mathcal Q(K)$ 是闭凸集。
**定理 1.** $\mathcal Q(K)\ne\varnothing$ 当且仅当
$\rho(K)=\min_q F_K(q)\le R_-$,其中 $\rho(K)$ 是 $K$ 的最小包围半径。
证明:$\min_q F_K(q)$ 就是最小包围半径;存在 $q$ 使 $F_K(q)\le R_-$ 与
其最小值不超过 $R_-$ 等价。证毕。
### 3.2 多边形外包给出的充分安全盘
设在线维护的多边形 $P_{\rm out}\supseteq K$,其最小包围圆为
$B(m,\rho_{\rm out})$。任取
$$
q\in B(m,\ R_- - \rho_{\rm out}-\eta),\qquad \eta=10^{-3}\ {\rm m},
$$
则对任意真源 $g\in K$:
$$
\lVert q-g\rVert\le\lVert q-m\rVert+\lVert m-g\rVert
\le (R_--\rho_{\rm out}-\eta)+\rho_{\rm out}
=R_--\eta<1000.
$$
实现中 `safe_disk_radius(region)` 直接返回
$R_--\rho_{\rm out}-10^{-3}$;因为 $\rho_{\rm out}$ 已是包含真实候选集
的多边形最小包围半径,这个盘内的点到真实源的三角不等式上界严格小于
1000 m。1 mm 的数值余量避免浮点贴边被 $r_{\rm eff}=1000$ 的源判成
`no_signal`。若该半径 $<0$,说明当前凸外包的 MEC 半径已超过 1000 m:
- 这**不能**证明真实 $\mathcal Q(K)$ 为空,只说明这个充分证书不够紧;
- 实现退化为探索 MEC 圆心,并在 `reason` 中明确标注“可能 `no_signal`”。
### 3.3 首次截断角域的解析候选盘
完全去掉 $\Omega$ 后,完整的截断角域
$S=W(s,\theta,\delta)\cap B(s,R_+)$ 有一个精确最小包围圆:
$$
c=s+a\,u(\theta),\qquad a=\frac{R_+}{2\cos\delta},\qquad
S\subseteq B(c,a),
$$
对 $0\le\delta\le45^\circ$ 成立。简证:设
$g=s+t\,u(\theta+\varphi)$,$0\le t\le R_+$,
$|\varphi|\le\delta$,则
$\lVert g-c\rVert^2=t^2+a^2-2at\cos\varphi$。固定 $\varphi$ 时该式
关于 $t$ 是凸二次函数,最大值在 $t=0$ 或 $t=R_+$ 处:前者为 $a^2$,
后者不超过 $R_+^2+a^2-2aR_+\cos\delta=a^2$(代入
$a=R_+/(2\cos\delta)$),故 $S\subseteq B(c,a)$。最小性由三点
$s$、$s+R_+u(\theta\pm\delta)$ 的加权距离恒等式给出:权重
$\lambda_\pm=1/(4\cos^2\delta)$、
$\lambda_0=1-1/(2\cos^2\delta)$ 非负且和为 1,且
$c=\lambda_0s+\lambda_+p_++\lambda_-p_-$,故任何覆盖这三点的圆半径
至少为 $a$。于是
$$
\mathcal Q_0=B(c,\ R_- - a)
$$
是保证接收的充分候选区域。题设 $\delta_{\rm eff}\le1.005^\circ$ 时:
| 误差半角 | 轴向中心距离 $a$ / m | 安全候选半径 $R_- - a$ / m |
| --- | ---: | ---: |
| $1^\circ$ | 750.114246 | 249.885754 |
| $1.005^\circ$ | 750.115391 | 249.884609 |
该解析盘由 `first_bearing_candidate_disk` 实现并测试。它给出的是
$S$ 的最小圆;由于 $K_1\subseteq S$,$B(c,R_- - a)\subseteq\mathcal Q(K_1)$
是严格充分的。实际在线路径使用比 $S$ 更紧的 $K_1$ 凸外包,因此其安全盘
通常大于该解析下界(例:`q2-4200` 的 $\rho_{\rm out}=674.59$ m,
安全盘半径 325.41 m,而解析下界约 249.89 m)。
## 4. 实际选点算法
### 4.1 入口伪代码
```text
select_second_point(client, s, theta):
region = CandidateRegion.initial(s) # Ω ∩ B(s,1500) 的外包
region.clip_wedge(s, theta, 1.005°) # 交入首次角域
return select_measurement_point(region, client.position)
select_measurement_point(region, from_position):
(m, rho) = region.mec() # Welzl 最小包围圆
safe = 1000 - rho - 1e-3
if safe < 0: return MEC 圆心(探索,可能 no_signal)
候选 = {m} ∪ {m + f*safe*(cos ψ, sin ψ)}
f ∈ {0.4, 0.75, 1.0}, ψ 取 12 个均匀方向
对每个候选 q:
最坏后验 = max( 方向分支、near 分支 )
分数 = (最坏后验, 移动时间)
取分数最小的 q
用 1/4 间距加密复核 q 的最坏后验
return q、最坏后验半径、移动耗时、理由
```
当前 `search.candidate_rings=(0.0,0.4,0.75,1.0)`、`candidate_angles=12`,
去重后实际是 **37 个候选点**(圆心 + 3 环 × 12 方向)。所有点严格属于
保证接收盘,因此第二次测量不会因距离不足返回 `no_signal`。
### 4.2 最坏后验评估
对候选点 $q$,最坏后验半径按以下有限枚举计算:
1. 在候选集边界上以 `witness_spacing_m=60` m 采样见证点
$g$(`region.witnesses`,含全部顶点);
2. 对每个 $g$,真实方位 $\phi=\operatorname{bearing}(q,g)$,枚举允许的
读数区间端点 $\phi\pm\delta_{\rm eff}$;
3. 对每个端点,复制候选多边形并用 `clip_wedge(q, 读数, δ_eff)` 得到后验
凸外包,记录其 MEC 半径;
4. 额外处理 `near` 分支:以 $B(q,5)$ 裁剪候选集,若交集非空,记录其 MEC
半径;它代表“源离第二点不超过 5 m,直接光学定位清除”的分支;
5. 以上全部有效半径取最大值,就是该候选点的评估值。
该评估是**启发式上界近似**:它只对目标边界采样和读数区间端点取值,
没有覆盖连续集合上所有可能读数;但它可在候选点之间做一致比较。
1/4 间距(15 m)的加密复核只提高输出数值的可信度,不改变“采样启发式”
这一事实。定理 1 保证接收,选点最优性没有全局证明。
### 4.3 清除与 `near`
若第二次测量返回 `near`,源在 $q$ 的 5 m 内。由 `clear_certificate`:
候选集 $B(q,5)$ 的 MEC 半径至多略大于 5 m(外包多边形余量很小),
工程余量后仍远小于 20 m,因此可以在当前位置直接 `/clear`,不需要再取
第三个测向读数。若返回 `direction`,则用新角域更新 $K$ 并继续按
问题三/四的定位流程处理;后验半径若仍大于 20 m,**不能**声称两次定位
已经完成。
## 5. 参数与复杂度
| 参数 | 默认值 | 作用 |
| --- | ---: | --- |
| `polygon_sides` | 192 | 圆盘外切多边形边数;$\Omega$ 处径向超出约 0.24 m |
| `bearing_rounding_margin_deg` | 0.005° | 两位小数舍入的显式裕量 |
| `witness_spacing_m` | 60 m | 粗评边界见证间距 |
| `candidate_rings` | (0, 0.4, 0.75, 1.0) | 安全盘内半径比例 |
| `candidate_angles` | 12 | 每环方向数;连同圆心共 37 个候选 |
| `near_radius_m` | 5 m | `near` 分支判定 |
| `clear_margin_m` | 0.5 m | 清除证书的额外工程余量 |
若候选集顶点数为 $m$、候选点数为 $N_q$、边界见证数为 $N_g$,单次选点的
粗评估约为 $O(N_qN_g\cdot{\rm clip}+N_q{\rm MEC})$,`clip` 为
Sutherland–Hodgman 裁剪的 $O(m)$ 代价;再加一次 1/4 间距加密复核。
这是明显可并行/缓存的小规模在线计算,不追求全局最优。
## 6. 实现核对结果:文档旧说法与当前运行路径的差异
早期说明只写到 `geometry/planning.py` 的解析候选盘,容易让人误以为
`select_second_point` 直接调用它。当前代码的实际情况是:
- `select_second_point` 构造 `CandidateRegion`($\Omega\cap B(s,1500)$ 的
192 边形外包)并用 `clip_wedge` 交入首次角域;
- 真正的选点发生在 `select_measurement_point`:它在上述凸外包的 MEC
保证盘内做 37 点候选评估;
- `first_bearing_candidate_disk` 是解析证书函数,用于证明
$B(s+au,1000-a)$ 的充分性,并被
`tests/test_geometry_certificates.py` 以稠密角域采样校核;
- 生产路径不调用 `first_bearing_candidate_disk`,但两者给出同一性质的
保证:选出的点必能收到 `direction`/`near`。生产路径通常比解析盘更紧,
因为它利用了 $K_1$ 完整形状而不是仅用其外包扇区。
因此,问题二的**严格保证**来自“安全盘点到候选集所有点的距离 $\le R_-$”,
解析盘是充分但不唯一的一种实现方式;**最优性**来自有限候选评估,
两者必须在说明中分开陈述。
## 7. 已验证结果
`project/q2` 在 30 个随机首次示向度算例上,用同一 $K_1$、同一评估器
对四种方法配对比较(初始 $\rho$ 均值 681.47 m):
| 方法 | 保证接收率 | 最坏后验均值 | 终值比 $\rho'/\rho$ | 平均移动 | 结论 |
| --- | ---: | ---: | ---: | ---: | --- |
| 生产选点器(保证盘内最小最坏后验) | **100%** | **73.89 m** | **0.104** | 170.4 s | 保证接收且后验最小 |
| 基线① 垂直 1000 m 最大交会角 | **0%** | 80.11 m | 0.116 | 200.0 s | 忽略接收距离,真源在远端必 `no_signal` |
| 基线② 直接取 MEC 圆心 | 100% | 340.75 m | 0.500 | 136.3 s | 保证接收但几乎不收缩 |
| 独立参考:保证盘内 9×9 网格枚举 | 100% | 75.63 m | 0.106 | 170.3 s | 生产采样接近网格最优 |
代表性单例 `q2-4200`:
| 指标 | 数值 |
| --- | ---: |
| $K_1$ MEC 圆心 | (1172.85, −225.68) |
| $K_1$ MEC 半径 $\rho$ | 674.59 m |
| 保证接收盘半径 | 325.41 m |
| 选中第二点 | (1257.07, 88.64) |
| 最坏后验半径 | 54.45 m |
| 移动耗时 | 181.42 s |
## 8. 与问题一及问题三/四的关系(核对结果)
| 对比 | 问题一 | 问题二(本文) | 问题三/四中的去向 |
| --- | --- | --- | --- |
| 信息模型 | 纯角域 $W$ | 角域 $W$ + 距离先验 $K_1=\Omega\cap W\cap B(s,R_+)$ | 问题三在任意后验 $K_c$ 上重复使用;问题四再叠加朝向维度 |
| 求解方式 | 枚举半平面边界交点、凸包、精确直径 | 圆盘外切多边形 + Sutherland–Hodgman 裁剪 | 问题三/四沿用 `CandidateRegion` 凸外包 |
| 决策类型 | 对固定观测做几何分析 | 主动选择下一个测量点 | 问题三是多源闭环;问题四是混合源闭环 |
| 主要输出 | 直径与直径圆覆盖 | `SecondPointPlan`(位置、最坏后验、移动耗时) | 问题三把它推广到定位子过程;问题四把它作为联合信念选点的基础候选之一 |
| 保证口径 | 几何精确(在输入模型内) | 接收严格保证;最坏后验是采样启发式 | 清除证书严格;选点与调度是启发式 |
关键区别:
1. 问题二不直接复用问题一的 `solve`,而是复用其角域语义和
`smallest_enclosing_circle`;候选集多出圆盘和距离上界,不能当作
“纯角域问题一”处理。
2. 问题一的输出是直径和直径圆,问题二的清除判断改用最小包围半径
$\rho\le20$;直径圆本身不参与在线清除。
3. 问题三对同一个 `select_measurement_point` 做任意后验集上的复用,
但同时引入网格粒子滤波处理 $K$ 无法表示的负观测(`no_signal`);
问题二没有负观测更新,因为它假设第二次测量点已在保证接收盘内。
4. 问题四不能直接使用“安全盘内必收到信号”的结论:定向源在安全盘内
也可能因朝向遮挡返回 `no_signal`。问题四保留问题二的安全盘作为
基础候选,但新增(位置 × 朝向)联合信念来判断可见性(见
`algo-4.md`)。
## 9. 结论
问题二的当前实现可以概括为:
- **候选集**:$K_1=\Omega\cap W(s,\theta,\delta_{\rm eff})\cap B(s,R_+)$,
用 192 边形外包圆盘 + 半平面裁剪保守维护;
- **保证接收**:$B(m,R_--\rho_{\rm out}-10^{-3})$ 内的点必不返回
`no_signal`;解析扇区最小圆给出可独立复核的充分候选盘
$B(s+au,1000-a)$,$a=1500/(2\cos\delta)$;
- **选点**:在保证盘内取 37 个候选,以边界见证点 × 读数端点的最坏后验
包围半径为第一指标、移动时间为第二指标,选出后再做 1/4 间距加密复核;
- **清除**:若第二次返回 `near`,直接就地清除;否则把新角域交入后验,
未达到 20 m 证书前继续测量。
严格保证与启发式性能优化在文档和代码中始终分开:接收保证有证明,
全局最优性没有证明;后者依赖自建的有限候选与固定评估口径。
## 参考文献
1. 全国大学生数学建模竞赛组委会. 2026 年高教社杯全国大学生数学建模竞赛 B 题[Z]. 2026. 本地题面 `issue/B题.pdf`。
2. 模拟器配套材料. 附件 2:模拟器通信接口说明及编程指南[Z]. 2026. 本地附件 `issue/附件/附件2.docx`。
3. BOYD S, VANDENBERGHE L. Convex Optimization[M]. Cambridge University Press, 2004. 凸性、最坏情形与鲁棒可行性背景。
4. 本项目. `docs/algo-1.md`(问题一当前实现与复用差异)。
5. 本项目. `docs/algo-3.md`、`docs/algo-4.md`(选点器在后续问题中的推广与边界)。
-144
View File
@@ -1,144 +0,0 @@
# 算法说明:问题3 贝叶斯闭环(`bayes` 策略)
> **历史补充文档.** 当前规范算法、最新默认参数与现行成绩口径见
> [`algo-3.md`](algo-3.md);本文保留 2026-09-11 的设计与消融细节,
> 其中 `lambda_move_s=0.0105`、站点环半径 1200 m 等数字可能已被
> 后续回填(现行默认见 `config.BayesConfig`,λ=0.05、环半径 1159.7 m)。
> 两者冲突时以代码与 `algo-3.md` 为准。
对应实现:`src/mcm26b/particles.py`(感知层)、`src/mcm26b/planner/bayes_loop.py`
(决策层)、`scripts/benchmark_q3_bayes.py`(消融)、`scripts/tune_q3_bayes.py`
(Optuna 调参)。基线对比:`docs/algo-3.md` 的七点批量(`seven`,A2)。
## 1. 建模定位
问题3是部分可观察的在线决策问题:频道数未知(10–16/20)、位置未知、有效
接收半径未知(1000–1500m)、测向误差 ±1°(服务器保留两位小数)。策略层
只能拿到 `/measure` 与 `/clear` 的响应,目标是最小化"发现—定位—清除"的
虚拟总时间。`bayes` 策略把它分解为三层滚动时域闭环:
1. **感知层**:每频道一个贝叶斯后验(网格幸存集),融合全部正/负观测;
2. **决策层**:站点扫频、定位测量、清除三类任务统一建表,开放路径
最近邻 + 2-opt 排序,每个动作后滚动重排(动态 TSP);
3. **选点层**:默认按期望log幸存占比和“到检测点、再接近源”的移动代价评分。
已停靠位置可逐频道补交会观测,真实清除始终由完整角域证书批准。
2026-09-11 当前修订的审核与配对验收见 [三四问算法审核与优化](算法审核与优化-20260911.md)。
本文件第5节是早期版本的历史结果,不应当作当前默认参数的复算结果。
## 2. 网格幸存集滤波与真源保留定理
每频道维护 Ω 上间距 h 的网格(h=14.65m,约 4.7 万格),`alive` 为幸存格
集合。Voronoi 裕量 m = √2/2·h 是格心到格内任一点的最大距离;所有删除
判定都内缩 m,即**仅当整格与可行集不相交时才删格**:
| 观测 | 题面语义 | 删除判定 |
|---|---|---|
| `no_signal`@s | 距离 > r_eff ≥ 1000 | 删格心距 s ≤ 1000 − m 的格 |
| `direction`@s | 距离 ≤ 1500,\|读数−真值\| ≤ δ_eff | 删角向超出 δ_eff + asin(m/(d−m)) 或距 s > 1500 + m 的格 |
| `near`@s | 距离 ≤ 5 | 删格心距 s > 5 + m 的格 |
**定理(真源保留)**:真源 P 满足全部题面约束;P 所在格的格心 g 满足
|g−P| ≤ m,故"整格不相交"判定永不命中该格。因此任意观测序列后 P ∈
幸存格的并集,且:
- **缺席证明**:幸存集为空 ⟹ 可行集为空 ⟹ 该频道无源(严格);
- **清除证书**:MEC(幸存).R + m ≤ 20 − 工程余量 ⟹ 真源距清除点 ≤ 20;
- **跳测规则**:幸存格到测点最小距离 > 1500 + m ⟹ 该测量必 no_signal
且无新排除,可跳过。
性质测试:`tests/test_particles.py`(随机源 × 随机测点 × 随机合法误差,
真源格永不被删;`tests/test_bayes_loop_q3.py` 端到端零异常)。
与 `belief.CandidateRegion`(保守凸外包)的分工:凸表示负责**清除证书**
(精确角域裁剪、收敛后触发),网格负责凸表示做不到的三件事——非凸负
观测挖洞(no_signal 排除盘)、缺席提前证毕、跳测判定。两者同读一套
响应流(`_record_measure`),任何一方证毕即收尾。
## 3. 信息增益选点
候选点集(二选一,按保证接收盘是否非空):
- **保证接收盘** B(MEC_poly 圆心, 1000 − ρ_poly)(盘内必收 direction/near,
几何同 `docs/algo-2.md` 定理1):环形采样(`search.candidate_rings`×12 方向);
- **宽候选集**(ρ_poly > 1000 时):PF MEC 的 1.0/1.5/2.0 倍探索环。
评分(`BayesConfig.score_mode`):
- `radius`(可选):期望后验半径 —— 对 K 个代表假设(幸存格均匀抽样)
各自模拟一次测量的幸存分支,分支半径用幸存子采样的质心最大距离近似,
r_eff~U(1000,1500) 的不确定性解析积分(p_no_signal = (d−1000)/500);
总分 = E[半径] + λ·移动秒数(λ=0.1);
- `entropy`(当前默认,λ=0.0105):期望log幸存占比,加上λ乘以
当前点→候选检测点→候选源中心的移动秒数。来向对称候选补充固定全局方向网格。
这里的均匀先验、零误差代表读数和均匀接收半径是选点评分的工程假设,
不属于题面给定的概率模型;只有完整±1.005°角域与距离界参与安全证明。
λ 与半径同量纲,量级必须小:λ 过大时终局阶段"走 300m"的代价压过
"半径 35m→25m"的收益,选点器原地重测、收敛停滞(消融实测 λ≥0.5 时
单源定位步数翻倍)。
## 4. 统一任务循环(动态 TSP)
每个决策点构建任务表并排序执行首个任务,随后滚动重排:
- **站点任务**:七站(原点 + 当前1159.7m环六点)上的UNKNOWN频道;
构造时验证全向覆盖解析界小于1000m,跳测规则与覆盖账本过滤;
- **定位任务**:DETECTED 且无证书的频道,位置由信息增益选点产生;
- **清除任务**:有证书(凸或网格)的频道,可沿当前位置方向移动证书圆心,
但平移量与原半径之和不得超过清除证书阈值,节省最后一段接近路程。
排序 = 开放路径最近邻打底 + 2-opt 改进(`two_opt_passes` 轮,成本含
移动 + 换频 + 动作耗时;换频按路径顺序逐步传递当前频道,clear保持频道;
终点自由不回起点)。这是 A2"站内最近邻服务
队列"的推广:消融显示距离缩短约 24% 是主要收益来源。
停止条件与基线一致:清满 16(数量上界)或全部频道 CLEARED/ABSENT,
`stop_reason=all_resolved` 即停并 `/exit`——**虚拟时间即评测成绩口径**
[用户决策修订 2026-09-11]。复扫保险模式(`mcm26b run --persistent`,
原默认行为):找全后继续只复扫未清除频道直到清除数达 16、实机预算
耗尽或虚拟安全余量(`search.virtual_reserve_s=10000s`)不足,供需要
"防缺席证明假设偏差"保险的场景显式开启。
## 5. 消融结果(自建模拟器,persistent 关,对齐找全口径)
12 随机场景(6 种子 × 10/16 源)+ 2 边界场景,与 SevenBatch 配对;
bayes 参数为 Optuna 回填后的库默认值:
| 指标 | SevenBatch | bayes |
|---|---|---|
| 有效运行(全清+缺席正确+零异常+正常退出) | 14/14 | **14/14** |
| 平均虚拟时间 | 5352.7s | **3726.2s(−30.0%)** |
| 配对降幅(最差 / 最好) | — | +7% / −41% |
| 平均移动距离 | 23413m | **15050m(−36%)** |
| 平均检测次数 | 102.4 | 110.0 |
| 单局实机计算墙钟 | 1.3s | 1.9s |
复现:`uv run python scripts/benchmark_q3_bayes.py --seeds 0,1,2,3,4,5`
(逐场景数据与场景 JSON 见 `output/q3/bayes-ablation/`)。
## 6. Optuna 调参
`scripts/tune_q3_bayes.py`:TPE(dev 依赖 `optuna`,缺失时自动退化为
随机搜索),目标 = 场景子集平均虚拟时间 + 10⁶×失败惩罚。搜索空间:
λ、代表点数、子采样规模、网格间距、站点环半径、2-opt 轮数、评分模式。
最优组合(entropy 评分、λ=0.0105、h=14.65m、代表点 7、2-opt 4 轮)
已按验收流程回填为 `config.BayesConfig` 默认值:全量基准 3726s/−30.0%
优于回填前的 4277s/−19.5%。两处人工修订:
- `station_ring_radius_m` 保留 1200(Optuna 建议 1159.7 虽再快约 60s,
但七站排除盘对最外圈格心的覆盖差 3.3m,PF 无法独立证明缺席,
只能靠覆盖账本兜底——设计性质优先于 1.7% 的均值差异);
- 评分模式在 entropy(信息增益)与 radius(期望后验半径)之间由调参
数据决定,两者实现均保留(`BayesConfig.score_mode`)。
调参记录见 `output/q3/bayes-tuning/best_params.json`。
## 7. 已知边界
- 检测次数略多于 A2(109.6 vs 102.4):定位收敛多用 1-2 次测量换距离
大幅缩短,净收益为正;跳测规则在 UNKNOWN 阶段(先验全域)暂无收益
面,收益集中在定位与复扫阶段;
- 网格清除证书(h=25m 时阈值 ≤1.8m)极少触发,作为凸证书的补位保险;
- 调参与消融基于自建模拟器(逐点固定 ±1° 误差场),不代表官方误差
分布;真源保留定理只依赖题面界(±1°、r_eff∈[1000,1500]),不依赖
误差分布假设。
-456
View File
@@ -1,456 +0,0 @@
# 问题三算法说明:全向多源搜索的覆盖证明、贝叶斯闭环与任务调度(当前实现)
> 本文汇总当前仓库中问题三的全部实际算法,生产默认策略为
> `src/mcm26b/planner/bayes_loop.py::BayesLoop`(CLI 策略名 `bayes`)。
> `grid`(`OmnidirectionalLoop`,49 点)与 `seven`
> (`SevenBatch`,七点解析覆盖 + 本站批量)保留为可复现对照。
> 问题三当前生产不包含任何机器学习策略;历史 HRL/RL 代码已移除,
> 自建消融中手写基线稳定优于学习策略(见 `docs/第三四问架构优化与运行提速方案.md`)。
## 1. 问题定位与策略族
问题三中每局有 $10\sim16$ 个全向干扰源,位置未知、频道互异(1..20),
源位于 $\Omega=B(0,1800)$ 内;有效接收半径 $r_{\rm eff}$ 未知,但满足
$1000\le r_{\rm eff}\le1500$ m。策略端只能看到协议响应
(`direction` / `near` / `no_signal`),目标是发现、定位并清除全部源,
使虚拟总耗时尽量小,同时给出“不存在漏源”的证明或明确未完成。
| 策略 | 类 | 发现保证 | 定位/决策 | 角色 |
| --- | --- | --- | --- | --- |
| `grid` | `OmnidirectionalLoop` | 700 m 方格 49 点,单元对角 $700\sqrt2\approx989.95\le1000$ | 发现后立即就近定位,无信息增益 | 历史基线 |
| `seven` | `SevenBatch` | 原点 + 半径 1200 m 六等分环,解析覆盖界 968.90 m | 本站先扫频,再按候选集 MEC 圆心最近服务队列 | A2 中间对照 |
| `bayes` | `BayesLoop` | 七站环(默认半径 1159.7 m,界 984.54 m)+ PF 负观测 | 网格粒子滤波 + 信息增益选点 + 滚动任务排序 | **生产默认** |
七站族还有 `SevenImmediate`(A1,发现即离站)与 `SevenSweep`
(A3,先扫完全域再统一服务)。它们的差异只在发现/定位的调度顺序,
七点覆盖证明与距离语义相同。
### 1.1 统一计时模型
忽略微秒量化时,一次动作回合的虚拟耗时为
$$
T=\frac{L}{5}+5N_m+N_s+5N_c^++3N_c^-,
$$
其中 $L$ 为移动距离(速度 5 m/s),$N_m$ 为检测次数,$N_s$ 为换频次数,
$N_c^+$ 为成功清除次数,$N_c^-$ 为失败清除次数。`/clear` 本身不切换
测向频道,`/exit` 不增加虚拟时间,访问顺序是起点固定、终点自由的**开放
路径问题**,不是必须回到原点的 TSP 回路。官方内部按整数微秒累计,项目用
`evaluation.recompute_virtual_time` 逐动作复算并校验。
## 2. 三层在线架构
`BayesLoop` 在 `OmnidirectionalLoop` 的会话/预算/收尾骨架上重构为三层:
1. **保证层**:七点覆盖账本 `CoverageLedger` + 解析覆盖定理;负责
“全测无信号 $\Rightarrow$ 该频道不存在源”。
2. **信念层**:
- 凸候选集 `CandidateRegion`(正观测方向/近距离约束,用于清除证书);
- 网格幸存集 `ChannelParticles`(正/负观测统一更新,用于缺席证明、
跳测与信息增益);
- 两者同读一套响应流,任何一方证毕即结束该频道。
3. **决策层**:统一任务表(站点扫频 / 定位测量 / 清除),开放路径
最近邻 + 2-opt 滚动重排;每执行一个任务后用真实响应重规划。
问题三不复用问题四的(位置 × 朝向)联合信念;`no_signal` 在全向源上
可以排除 $B(s,1000)$。
## 3. 证据层:逐频道候选集与负观测
### 3.1 凸候选集 `CandidateRegion`
对每个已收到过有效信号的频道 $c$ 维护凸多边形 $P_c^{\rm out}$:
- 初始为 $\Omega$ 的 192 边外切正多边形;
- 每次 `direction`:
1. 与 $B(s,1500)$(192 边外切多边形)求交;
2. 与角域 $W(s,\theta,\delta_{\rm eff})$ 求交,$\delta_{\rm eff}=1^\circ+0.005^\circ$;
- `near`:与 $B(s,5)$ 外切多边形求交;
- `no_signal`:**不收缩凸候选集**。对全向源,负观测信息由 `ChannelParticles`
处理;让凸表示保留所有正观测候选,可以避免因模型误差误删真源。
圆盘外切多边形的径向超出逐次累加到 `slack_m`,所有裁剪容差只向
“保留更多候选”的方向倾斜,因此真源始终包含在 $P_c^{\rm out}$ 内。
清除证书使用 $P_c^{\rm out}$ 的最小包围圆 $B(m_c,\rho_c)$:
$$
\rho_c+\text{slack}_c+0.5\le20
\quad\Longrightarrow\quad
\text{在 }m_c\text{ 处一次 `/clear` 必命中真源}.
$$
其中 $0.5$ m 是工程余量,slack 是外包多边形的半径余量;该判据是保守的
充分条件,而不是“必须达到的最优半径”。
### 3.2 网格幸存集 `ChannelParticles`
每个频道维护 $\Omega$ 外扩裕量上的方格网格,间距
$h=14.65$ m,约 4.7 万格;Voronoi 裕量
$$
m=\frac{\sqrt2}{2}h\approx10.359\ {\rm m}
$$
是格心到格内任一点的最大距离。所有删除判定都内缩 $m$:**只有整个格子与
可行集不相交时才删除该格**。
| 观测 | 位置/距离更新 | 实现 |
| --- | --- | --- |
| `no_signal` @ $s$ | 距离 $>r_{\rm eff}\ge1000$,删除格心距 $s\le1000-m$ 的格 | `_kill_disk(s,1000-m)` |
| `direction` @ $s$,读数 $\theta$ | 距离 $\le1500$;角向偏差不超过 $\delta_{\rm eff}$ + 格内角裕量 | 先删距 $s>1500+m$ 的格,再删角向超出的格 |
| `near` @ $s$ | 距离 $\le5$ | 删格心距 $s>5+m$ 的格 |
**定理(真源保留).** 真源 $P$ 所在格的格心 $g$ 满足
$|g-P|\le m$;与真值一致的观测不会让该格与可行集完全不相交,因此
“整格不相交”判定永不删除该格。于是:
- **缺席证明**:幸存集为空 $\Longrightarrow$ 可行集为空
$\Longrightarrow$ 该频道无源;
- **跳测规则**:若某测点到所有幸存格心的最小距离 $>1500+m$,则在该点
测量必为 `no_signal` 且不产生任何新排除,可直接跳过,省 5 秒检测和
1 秒换频;
- **PF 清除证书**:若幸存集 MEC 半径 $\rho_{\rm pf}$ 满足
$\rho_{\rm pf}+m+0.5\le20$,则以该 MEC 圆心清除必命中真源。
`BayesLoop` 在每次测量后同步更新凸候选集与 PF,PF 只在频道尚未
CLEARED/ABSENT 时接收新证据。
### 3.3 数量上界证明
题面给定每局源总数 $10\sim16$ 且每频道至多一个源。若
`DETECTED`/`CLEARED` 的不同频道数达到 16,则所有仍未出现有效信号的
`UNKNOWN` 频道都不可能有源,可直接标记为 `ABSENT`,证据来源记为
`count_bound`。这条规则与位置无关,是严格计数证明,不需要等七站扫完。
`summary.completion_basis` 会区分 `count_cap` 与 `per_channel_proof`,
避免把“达到数量上界”误读成“逐频道缺席证明”。
## 4. 发现保证:七点解析覆盖与覆盖账本
### 4.1 `full_disk` 语义
全向源在测点 $s$ 返回 `no_signal`,意味着真实距离严格大于
$r_{\rm eff}\ge1000$。因此若集合 $S$ 满足
$$
\Omega\subseteq\bigcup_{s\in S}B(s,1000),
$$
则任何合法源必在某个 $s\in S$ 的 1000 m 内,在该点不可能返回
`no_signal`。于是“某频道在全部 $S$ 点都测得 `no_signal`”构成严格的
缺席证明。
`CoverageLedger` 按 `(channel, point_index)` 二维记录,只有所有点都已测
(或显式跳过)才允许 `coverage_complete(channel)=True`;“路过某点”不算
“测过某频道”。
### 4.2 七点构造与解析界
取原点加半径 $a$ 的六等分环:
$$
S(a)=\{(0,0)\}\cup\left\{a(\cos(k\pi/3),\sin(k\pi/3)):\ k=0,\dots,5\right\}.
$$
**定理 1.** 当 $0<a/\sqrt3\le R$ 时,
$$
\max_{g\in\Omega}\min_{s\in S(a)}\lVert g-s\rVert
\le D(a):=
\max\left\{\frac a{\sqrt3},\ \sqrt{R^2+a^2-\sqrt3Ra}\right\},
$$
其中 $R=1800$。证明:任意 $g=(r\cos\varphi,r\sin\varphi)$ 与最近环站的
夹角不超过 $\pi/6$。若 $r\le a/\sqrt3$,选原点;否则选最近环站,由
余弦定理和 $\cos\varphi\ge\cos(\pi/6)=\sqrt3/2$ 得
$\lVert g-s\rVert^2\le r^2+a^2-\sqrt3ar$。右端关于 $r$ 是凸二次函数,
在区间端点取最大值,分别得 $a^2/3$ 和 $R^2+a^2-\sqrt3Ra$。证毕。
代入可验证:$a=1200$ 时 $D=968.901572$ m;当前 `bayes` 默认
`station_ring_radius_m=1159.7` m 时 $D=984.539136$ m;两者都小于 1000,
从站上有 15.5 m 以上的几何余量。$a$ 的可行下界为
$a_{\min}\approx1122.955832$ m(零余量)或 $1125.254906$ m(1 m 余量)。
七点巡回长度 $6a$;$a=1200$ 时纯覆盖路线约 7200 m。
### 4.3 49 点基线
网格 $S=\{(700i,700j):i,j\in[-3,3]\}$ 覆盖 $[-2100,2100]^2\supseteq\Omega$;
每个单元的对角线 $700\sqrt2\approx989.95\le1000$,因此任意源都在某个
网格点的 1000 m 内。该证明不需要朝向信息,对问题三的七点方案是更强的
充分条件,但会发现阶段检测次数多一个数量级(频道 × 49 次);问题四仍
需要它作为 legacy 对照(见 `algo-4.md`)。
### 4.4 计划可验证性
`guarantee/cover.py` 提供两套校核:
- `verify_full_disk(points)`:在 $\Omega$ 内按网格采样,校核
“每个采样位置都在某个点的 1000 m 内”;
- `verify_forward_half_disk(...)`:第四问语义,问题三不使用。
七点计划走解析证明;49 点计划走 `full_disk` 校核。运行期不使用未校核的
点集来宣称“已证明无源”。
## 5. 定位与清除
### 5.1 问题二选点器的推广(基线与安全后备)
`planner.select_measurement_point` 对**任意** `CandidateRegion` 工作:
给定当前后验外包多边形 $P$,令其 MEC 为 $B(m,\rho)$,则安全接收盘为
$$
B\left(m,\ 1000-\rho-10^{-3}\right)
$$
($\rho>1000$ 时退化为探索 MEC 圆心,可能 `no_signal`)。盘内取
37 个候选点(圆心 + 3 环 × 12 方向),以“边界见证点 × 读数区间端点 +
near 分支”的最坏后验 MEC 半径为主指标、移动时间为次指标;选出后再按
1/4 间距加密复核。该函数最初为问题二实现,在问题三中服务于
`SevenBatch`、`OmnidirectionalLoop` 的定位子循环,以及 `BayesLoop`
的阻塞式安全后备 `_localize_and_clear`。
### 5.2 `bayes` 的信息增益选点
`BayesLoop._select_point` 在 PF 幸存集上选择定位测点,候选集分两种:
- 凸候选集安全盘非空:取 `select_measurement_point` 的环形候选,并额外
加入以当前位置到 MEC 圆心方向为轴的对称候选,以及零移动的当前位置;
- $\rho>1000$、无保证安全盘:取 PF MEC 的 $1.0/1.5/2.0$ 倍探索环和
PF MEC 圆心。
对候选 $q$,默认评分模式 `entropy` 是期望对数幸存占比:
$$
\text{score}(q)=
\mathbb E[\log(\text{后验幸存占比})]
+\lambda\left(\frac{\lVert p-q\rVert}{5}
+\frac{\lVert q-m_{\rm MEC}\rVert}{5}\right),
\qquad \lambda=0.05.
$$
其中期望对代表假设(从幸存格均匀抽样)和 $r_{\rm eff}\sim U(1000,1500)$
解析积分:
- `no_signal` 分支(概率 $(d-1000)/500$):幸存格收缩到
$B(q,1000-m)$ 之外;
- `direction` 分支:以代表点方位为期望读数,用 $\pm\delta_{\rm eff}$
角域裁剪后的子采样估计幸存占比;
- `near` 分支($d\le5+m$):后验为 5 m 盘,占比趋近零。
可选 `score_mode=radius` 直接最小化期望后验 MEC 半径。
`score_subsample=800`、`mc_representatives=7` 是工程参数;均匀源分布、
零误差代表读数和 $r_{\rm eff}$ 均匀分布都只是**选点评分假设**,不参与
任何安全证明。安全证明只使用题面给定的 $\pm1.005^\circ$ 角域与距离界。
当前配置中以下“更强的耦合”均已实现但实测为净负收益,默认关闭:
`fuse_localize_into_tour=False`(站点顺带定位)、`exact_order_limit=0`
(Held-Karp 精确任务序)、`route_aware_probe=False`(路线感知探点)。
代码与开关保留,便于复现与后续研究。
### 5.3 清除动作
`BayesLoop._best_certificate` 的优先级:
1. **凸证书**:`clear_certificate(region)`;
2. **PF 证书**(`grid_cert_enabled=True`):负观测挖洞使 PF 幸存集更紧时,
若 PF MEC 半径 $+m+0.5\le20$,用 PF MEC 圆心作为清除点。
得到证书后,`_near_clear_target` 还会把清除点从证书圆心向当前位置方向
平移一小段:设当前证书半径 $r$、限值 $limit$,最多平移
$\Delta=\min(\text{当前距离},limit-r-10^{-6})$,新目标点仍保证所有候选
源在 $r+\Delta\le limit$ 内。该平移可省去最后一段接近路程,不放松证书。
定位子循环每频道最多 `max_localize_steps=8` 次追加测量;若在安全接收盘内
出现 `no_signal`,记录异常 `no_signal_in_safe_disk`,不静默忽略。
## 6. 决策层:统一任务表与滚动重排
### 6.1 任务类型
`BayesLoop._build_tasks` 在每次决策点构建:
| 任务 | 位置 | 服务时间 | 触发条件 |
| --- | --- | --- | --- |
| `station` | 七站之一 | $5\times$待测频道数 + 换频 | 该站仍有 `UNKNOWN` 频道未测,且跳测规则未排除 |
| `locate` | 信息增益选点 | 5 s + 可能的换频 | 频道 `DETECTED` 且暂无清除证书,且未委托给站点 |
| `clear` | 证书中心(可平移) | 5 s 成功(失败 3 s) | 频道有清除证书且未处于“清除失败后待补测”状态 |
站点任务的服务时间计算当前频道优先:若机器人当前测向频道包含在待测集合,
则少一次换频。清除动作不改变测向频道。
### 6.2 跳测规则
`guaranteed_no_signal(station)`:若该频道所有幸存格心到站点的距离都
大于 $1500+m$,则该次测量必为 `no_signal` 且不会产生新排除,任务构造时
直接跳过。跳测缓存按 PF `version` 生效;幸存集单调收缩,因此判定单调。
这条规则是负观测给问题三带来的主要检测节省之一。
### 6.3 开放路径排序
任务表规模通常为 6~12 项,代价包含移动、检测、换频,终点自由。默认:
1. 最近邻构造初始序;
2. 开放路径 2-opt 改进,最多 `two_opt_passes=4` 轮;
3. 换频代价按实际频道状态沿路径逐步传递,而不是固定服务费;
4. 执行排序后的**第一个任务**,拿到响应后立即回到决策点重新构建/排序
(滚动时域)。
可选的 Held-Karp 精确 DP(含“已访问集合 × 结束时频道”状态)与
`route_aware_probe` 路线感知精修均已实现;在当前冻结基准集上,
精确 DP 与 2-opt 差距在噪声内(甚至略差),默认关闭。
### 6.4 已停靠位置的机会测量
`_measure_at_stop` 在每次决策点评估当前位置是否值得顺带补测已发现频道:
只对尚未在该 0.5 m 点测过、无证书、到凸候选集所有顶点距离均不超过
$1000-10^{-3}$ m、且预测后验半径至少收缩
`opportunistic_radius_ratio=0.5` 的频道追加一次测量。每次仍支付 5 秒与
实际换频成本,只是省去移动;它不是“免费检测”。
## 7. 停止、预算与异常收尾
### 7.1 完成证明
循环停止后,`summary.completed` 的依据分两类:
- `count_cap`:清除数达到 16(题面源数上界);
- `per_channel_proof`:每个频道状态都是 `CLEARED` 或 `ABSENT`。
缺席证据在 `summary.absence_evidence` 中逐频道记录来源:
| 证据 | 条件 | 严格性 |
| --- | --- | --- |
| `pf_empty` | 某频道 PF 幸存集为空 | 严格(Voronoi 真源保留) |
| `coverage` | 七点/49 点全部测得 `no_signal`(或计划上显式跳过) | 严格(解析/校核覆盖) |
| `count_bound` | 已有 16 个不同频道的有效存在证据 | 严格(题面数量上界) |
`persistent_search` **默认 False**:一旦“每频道已清除或证明不存在”就立即
`/exit`,因为虚拟时间是成绩口径。显式 `--persistent` 会继续复扫未清除
频道直到清除数达 16、实机预算耗尽或虚拟安全余量不足;历史官方演练证明
无条件复扫会浪费大量时间,因此该项目只作为可审计的保险开关保留。
### 7.2 预算与中断
- 虚拟安全余量 `virtual_reserve_s=10000` s:剩余虚拟时间不足以完成
一个保守单动作上界时停止发起新动作,避免触及 100 小时上限;
- 现实预算以服务器 `/enter` 返回的 `remaining_real_duration_s` 为准;
`DeadlineExceeded` 时 stop_reason 记为 `real_budget_exhausted`;
- 传输、协议或守恒性异常都会尽力 `/exit` 并输出未完成 summary,
不静默丢会话;`completed=False` 与具体 `stop_reason` 同时留档。
## 8. 基线与自建消融
### 8.1 调度变体
| 版本 | 发现/定位关系 | 说明 |
| --- | --- | --- |
| A0 `grid` | 49 点,发现后立即离站定位 | 历史生产基线 |
| A1 `SevenImmediate` | 七点,发现后立即离站定位 | 只替换覆盖点 |
| A2 `SevenBatch` | 七点,本站先扫完再按最近候选圆心服务队列 | 中间对照,曾用于官方演练 |
| A3 `SevenSweep` | 七点,先扫完全部必要站点再统一服务 | 批量调度的另一极端 |
A2 相对 A0 的收益主要来自“减少站间往返 + 每站批量扫频 + 无源频道只需
7 次而不是 49 次检测”。在早期 12 个自建场景上,A0/A1/A2/A3 平均虚拟
时间分别为 13788.04 / 7476.09 / 5496.20 / 6094.73 秒,A2 逐局平均降幅
58.55%;更晚的 14 场景消融中,`bayes` 相对 A2 再降 30.0%
(3726.2 s vs 5352.7 s)。这些数字来自自建模拟器与固定误差场,不是官方成绩。
### 8.2 冻结基准集当前结果
`project/q3` 在 18 个冻结 core 场景(seeds 100–105 × 10/13/16 源,
`harness/suites.py` 版本化清单)上的配对结果:
| 方法 | 有效局 | 全清率 | 虚拟时间均值 | 中位 | 最大 | 检测均值 | 请求均值 | 位移均值 |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
| `bayes` | 18/18 | 100% | **3188.7 s** | 3111.3 s | 3663.7 s | 111.1 | 124.1 | 12338 m |
| `seven` | 18/18 | 100% | 5361.7 s | 5367.5 s | 6462.4 s | 100.8 | 113.8 | 23508 m |
| `grid` | 18/18 | 100% | 14935.7 s | 15275.1 s | 16691.4 s | 430.6 | 443.6 | 61550 m |
配对变化:`bayes` 相对 `grid` 虚拟时间 **−78.4%**,18/18 场景更快;
所有 54 局零缺席误判、零异常、正常退出且计时复算一致。另有边界场景
(源在 $\Omega$ 边界、$r_{\rm eff}=1000$)验证七点覆盖的扇区接缝。
### 8.3 官方演练记录(历史口径)
- 旧 49 点实现通过官方问题三演练案例 `DHFK-PHD2-SR2P-FXK9`:
10/10 全清、540 次检测、10 次清除,虚拟总时间 16217.45 s,
现实 7.629 s;
- A2 七点批量通过官方案例 `J4ER-Y9EP-Q379-UPFA`:12/12 全清、
109 次检测、虚拟 5232.13 s、现实 3.406 s;
- 后续一次官方问题三演练(`3BW5-9R54-NZNA-MYB9`)记录 13/13 全清、
虚拟 4058.71 s。
以上案例的源场景、实现版本、误差场均不同,不能直接横向比较,也不能把
历史官方数字当成当前 `bayes` 同案例重跑结果。当前默认 `bayes` 的官方向
成绩仍需新的演练验证。
## 9. 复杂度、参数与保守性边界
| 模块 | 计算量(近似) |
| --- | --- |
| PF 更新 | 与删除格/角向扫描的幸存格数相关;粗格索引与向量化(numpy 可选)控制常数 |
| 七点覆盖 | 最多 $7\times20=140$ 个 `(站, 频道)` 记录 |
| 任务排序 | 最近邻 $O(n^2)$ + 2-opt $O(n^2)$/轮;精确 DP 为 $O(2^nn\cdot|C|)$,默认关闭 |
| 凸候选集 | 192 边形外切 + $O(m)$ Sutherland–Hodgman 裁剪;MEC 用 Welzl |
| 选点评分 | $O(N_q\times(\text{子采样}))$;候选约 37 个,子采样 800 |
保守性边界:
- 所有“证毕”结论依赖题面观测语义和保守外包/内缩;若接口语义、
接收半径范围或误差界改变,必须重新校核;
- 性能结论依赖自建场景分布、固定误差场和排序启发式,不构成对全部合法
场景的最坏时间保证;
- PF 的均匀先验与信息增益评分是选点启发式,不是官方概率模型;
- `persistent_search` 关闭时,如果官方场景违反题面数量上界或存在模型外
行为,不能由本算法保证发现;官方接口语义变化时必须记录异常而不是
强行把未完成解释为成功。
## 10. 与问题一、二、四当前实现的复用关系和差异(核对结果)
| 复用/差异 | 具体情况 |
| --- | --- |
| 问题一几何内核 | `belief/__init__.py` 与 `particles.py` 只从 `geometry.localization` 导入 `smallest_enclosing_circle`;在线 `clip_wedge` 复刻同一半平面公式,但工作在凸多边形裁剪流程,不调用 `solve` |
| 问题二选点器 | `select_measurement_point` 直接从问题二推广而来,问题三用它做基线定位与安全后备;`safe_disk_radius` 同样复用 |
| 问题一没有的 | 负观测 `no_signal`、PF 非凸挖洞、覆盖缺席证明、数量上界、任务排序、滚动时域、预算/异常治理 |
| 问题二没有的 | 多频道数据关联、发现覆盖、清除动作、在线顺序决策;问题二只做一次第二点选择 |
| 问题四的差异 | 问题四不能用七点 `full_disk` 缺席证明;`no_signal` 可能由朝向遮挡造成,因此改用 `forward_half_disk` 31 点覆盖 +(位置 × 朝向)联合信念 + 预算化后备清除(见 `algo-4.md`) |
一句话概括:**问题三 = 问题一的保守几何 + 问题二的保证接收选点 + 逐频道非凸负观测 + 覆盖/数量缺席证明 + 开放路径滚动调度**。
## 11. 复现与参考
```bash
# 冻结基准集:bayes vs seven_batch(runner 内置策略名)
uv run python scripts/run_suite.py --problem 3 --suite core --jobs 6 \
--variants bayes,seven_batch --label q3-core
# 项目对比框架(含 grid 基线,生成 project/results/q3.{md,json})
uv run python -m project.run --question 3
# 回归测试
uv run pytest tests/test_particles.py tests/test_bayes_loop_q3.py \
tests/test_planner.py tests/test_coverage_plan.py tests/test_safety_valves.py -q
```
主要文件:
- `src/mcm26b/planner/bayes_loop.py`:`bayes` 决策层;
- `src/mcm26b/planner/__init__.py`:`OmnidirectionalLoop`、问题二选点器、清除证书;
- `src/mcm26b/planner/seven.py`:七点策略族与覆盖校验;
- `src/mcm26b/particles.py`:网格幸存集与信息增益;
- `src/mcm26b/belief/__init__.py`:凸候选集;
- `src/mcm26b/coverage/__init__.py`、`src/mcm26b/guarantee/cover.py`:覆盖账本与校核;
- `src/mcm26b/routing.py`:开放路径 DP/2-opt/MST 下界;
- `src/mcm26b/planner/bayes_loop.py::_exact_order`:可选 Held-Karp。
延伸阅读:`docs/algo-3-bayes.md`(早期贝叶斯闭环设计与消融细节)、
`docs/第三四问架构优化与运行提速方案.md`(运行历史与瓶颈)、
`docs/第三四问图论与动态规划优化方案.md`(图论/DP 轮实测与负面结论)。
## 参考文献
1. 全国大学生数学建模竞赛组委会. 2026 年高教社杯全国大学生数学建模竞赛 B 题[Z]. 2026. 本地题面 `issue/B题.pdf`。
2. 模拟器配套材料. 附件 1《模拟器使用说明》、附件 2《通信接口说明及编程指南》[Z]. 2026. 本地 `issue/附件/`。
3. 本项目. `docs/algo-1.md`、`docs/algo-2.md`、`docs/algo-4.md`。
4. 本项目. `docs/算法审核与优化-20260911.md`、`docs/第三四问架构优化与运行提速方案.md`、`docs/第三四问图论与动态规划优化方案.md`。
-485
View File
@@ -1,485 +0,0 @@
# 问题四算法说明:混合全向/定向源搜索与清除闭环(当前实现)
> 本文汇总当前仓库中问题四的全部实际算法。生产策略是
> `src/mcm26b/planner/__init__.py::DirectionalExtension`,CLI 策略名
> `directional`,入口为 `mcm26b run --problem 4`。
> 与问题三不同,问题四的源可能包含定向源;`no_signal` 不再等价于
> “距离超过接收半径”,因此问题三的七站全向缺席证明**不能直接搬用**。
> 当前仓库尚无官方问题四演练记录;本文性能数字均来自自建
> `LocalSimulator` 冻结基准集,明确标注为测试假设。
## 1. 问题定位与核心难点
问题四每局有 $10\sim16$ 个源,其中一部分为定向源,其余为全向源;
位置在 $\Omega=B(0,1800)$ 内,频道互异。定向源有一个朝向
$h$,只有当接收点位于其**前向半平面**内、且距离不超过 $r_{\rm eff}$
时才可能返回有效读数:
$$
r=\lVert q-P\rVert\le r_{\rm eff}\quad\text{且}\quad
\operatorname{angular\_gap}\big(\operatorname{bearing}(P\to q),h\big)
\le90^\circ .
$$
其中 $r_{\rm eff}$ 对每个源未知,满足 $1000\le r_{\rm eff}\le1500$ m。
若 $r>r_{\rm eff}$ 或朝向不覆盖接收点,结果为 `no_signal`;若可见且
$r\le5$ m,结果为 `near`;若可见且 $r>5$ m,结果为 `direction`,
数值为接收点到源的方位加有界误差。
因此问题四的困难不是一般的“覆盖搜索”,而是两个额外的证明/决策问题:
1. **发现**:如何用有限的访问点证明“某个频道没有源”,即使该源是
朝外发射的定向源;
2. **定位与清除**:定向源的 `no_signal` 可能只是朝向遮挡,不能像全向源
那样删除位置候选;需要推理“源可能朝哪边”,并在定位停滞时仍能可靠
清除。
当前实现的办法是:
- 发现层用 `forward_half_disk` 语义的 31 点最小命中集覆盖计划
(`q4_mincover_v2`);
- 感知层在原有位置网格上叠加 24 档朝向掩码,得到(位置 × 朝向)联合
可行集 `JointBelief`;
- 决策层用联合信念的可见性概率筛选探点,失败时按预算进入 ≤20 m 的
有限格后备清除;
- 调度层用“本站批量扫频 + 按候选 MEC 圆心最近服务队列”的滚动顺序,
避免发现后立即远行、再返回同站扫描的往返。
| 层次 | 文件/类 | 作用 |
| --- | --- | --- |
| 覆盖计划 | `src/mcm26b/guarantee/cover.py`、`guarantee/plans/q4_mincover_v2.json` | `forward_half_disk` 最小命中集与运行期校核 |
| 位置网格 | `src/mcm26b/particles.py::ChannelParticles` | 位置幸存集与 Voronoi 保守裕量 |
| 朝向联合信念 | `src/mcm26b/belief/joint.py::JointBelief` | 每格 24 档朝向掩码、可见性/期望后验半径 |
| 决策闭环 | `src/mcm26b/planner/__init__.py::DirectionalExtension` | 批量扫频、可见性探点、后备清除、收尾 |
| 对比框架 | `project/q4/{optimal,baseline,compare}.py` | `directional` vs `bayes`/`grid` 直接搬用 |
| 回归 | `tests/test_loop_q4.py`、`tests/test_joint_belief.py`、`tests/test_coverage_plan.py` | 真源保留、朝外边界源、后备纪律、证书校核 |
| 结果 | `project/results/q4.{md,json}` | 11 个 core+boundary 场景配对结果 |
## 2. 发现覆盖:`forward_half_disk` 与最小命中集
### 2.1 覆盖语义
设访问点集合为 $S$。对全向源,`no_signal` 在 $s$ 处排除 $B(s,1000)$,
因此完整覆盖只需
$$
\Omega\subseteq\bigcup_{s\in S}B(s,1000).
$$
对定向源,还需要朝向条件。严格的缺席证明要求:
$$
\forall P\in\Omega,\ \forall h\in\mathbb S^1,\quad
\exists s\in S:\quad
\lVert s-P\rVert\le1000
\ \wedge\ (s-P)\cdot u(h)\ge0 .
$$
也就是说,对任意位置和任意朝向,至少有一个被访问点同时落在该源的
1000 m 距离内和 90° 前向半平面内。这个语义称为 `forward_half_disk`。
问题三的七站环不满足该语义:`tests/test_coverage_plan.py` 中有专门用例
验证“七站点集在 `forward_half_disk` 下有缺口”。
### 2.2 49 点 legacy 充分条件
旧实现使用 $S=\{(700i,700j):i,j\in[-3,3]\}$ 的 49 个点:
- 任意 $P\in[-2100,2100]^2$ 到某个网格点的欧氏距离不超过
$700\sqrt2\approx989.95\le1000$;
- 因此对该网格点,无论源朝向如何(前向半平面总是 $180^\circ$),
距离条件都成立。
这是 49 点充分条件,保证发现但代价很高:最近邻开放巡回约 36.4 km;
对无源频道还要在 49 个点各测一次。它现在保留为 legacy 对照与回退计划
`square49`。
### 2.3 31 点最小命中集 `q4_mincover_v2`
当前默认计划由离线贪心集合覆盖搜索得到,并带有可运行期校验证书。
生成参数:搜索分辨率 50 m / 48 档,设计距离裕量
$r_{\rm design}=965$ m,前向角裕量 $5^\circ$;随后用证书分辨率
15 m / 72 档($3\,256\,200$ 个 $(P,h)$ 采样)做精细剪枝,每删一个点都
用同一证书口径复核。
`q4_mincover_v2` 的证书摘要:
| 字段 | 值 |
| --- | ---: |
| 点数 | 31 |
| 覆盖语义 | `forward_half_disk` |
| 校核分辨率 | 15 m / 72 朝向档 |
| 采样目标数 | 3 256 200 |
| 缺口数 | 0 |
| 最坏命中距离 | 990.051 m |
| 最近邻开放巡回 | 23 883.8 m(约 4776.8 s 虚拟移动) |
| 生成器 SHA-256 | `adf4fe6e…434c0e1d`(完整值见 JSON) |
旧 `q4_mincover_v1`(31 点)在粗采样 75 m/24 档下看似零缺口,但在
25 m/48 档有 125 个缺口、15 m/72 档有 566 个缺口,属于采样过拟合;
`q4_mincover_v2` 修正了这一点,点数不变而细网格缺口归零。
**严格连续空间证书的已知残余风险.** 15 m/72 采样格上的零缺口加上设计
裕量可以覆盖相邻未采样 $(P,h)$,但默认 v2 的最坏命中距离 990.051 m
略高于严格连续界要求的约 989.4 m(需满足
$r_{\rm verify}+15\sqrt2/2\le1000$,即 $r_{\rm verify}\le989.4$ m)。
仓库另有 36 点备选计划(最坏命中 973.7 m、巡回约 25.4 km,见
`output/q4/cover-certificate-v3.json`)可关闭该连续性缺口;当前默认的
v2 在 15 m/72 离散证书上零缺口,连续空间残余约 0.65 m,已作为已知
风险登记。若论文要求严格连续证明,应改用 36 点方案并重新验收性能。
### 2.4 运行期校验
`load_plan(name, verify=True)` 会读取计划 JSON 中的证书字段,并用
**证书自带的采样分辨率**重新校核;缺口不为 0 直接拒绝启动。默认
`search.verify_coverage_plan=True`。校核成本在进程内按计划名缓存一次,
15 m/72 档约数秒(见 `scripts/run_suite.py` 的 `plan_verify_wall_s`)。
运行期不会用比证书更粗的采样去“自证”。
## 3. (位置 × 朝向)联合信念 `JointBelief`
### 3.1 网格与朝向档
位置维度复用 `ChannelParticles`:间距 $h=14.65$ m、Voronoi 裕量
$m=\sqrt2/2\,h\approx10.359$ m;朝向维度把整周分为
24 档(每档 $15^\circ$,半档 $7.5^\circ$)。每个位置格附带一个 24 位
掩码,表示该格仍可能具有的朝向;缺省掩码为全档。
联合集合的保守性目标是:**真源 (位置, 朝向) 永不被删除**(在该离散
表示意义下,即真源所在格的朝向至少保留一档,且位置格不被删)。因此
所有判定都向“保留更多”的一侧取整,并计入格内角裕量
$$
\alpha_{\rm cell}=\arcsin\!\left(\frac{m}{\max(d-m,1)}\right),
$$
即格内任一点相对格心到测点方位的最大偏差上界。
### 3.2 观测更新规则
| 观测 | 位置维度 | 朝向维度 |
| --- | --- | --- |
| `direction` @ $s$,读数 $\beta$ | 删除距 $s>1500+m$ 的格;删除角向偏离读数超过 $\delta_{\rm eff}+\alpha_{\rm cell}$ 的格 | 朝向必须**可能覆盖** $s$:保留与方位 $\operatorname{bearing}(g\to s)$ 夹角不超过 $90^\circ+7.5^\circ+1.5^\circ+\alpha_{\rm cell}$ 的档 |
| `near` @ $s$ | 删除距 $s>5+m$ 的格 | 同 `direction`:朝向必须可能覆盖 $s$ |
| `no_signal` @ $s$ | **位置不删**(可能是距离不足或朝向遮挡) | 仅对“整格必在 $r_{\rm eff,min}=1000$ 圆盘内”的格,保留与方位夹角大于 $90^\circ-7.5^\circ-1.5^\circ-\alpha_{\rm cell}$ 的档,即只保留**确定看不见** $s$ 的朝向档;掩码变空则删除该位置格 |
其中 `1.5°` 是朝向查表分辨率带来的保守余量,$7.5^\circ$ 是半档。
`no_signal` 的距离阈值使用 $1000-m$(保守侧):只有在确信整格都在
1000 m 内时,才把静默解释为朝向遮挡;否则保留全部朝向档,避免删掉
真源。
> 2026-09-12 修复记录:早期实现把 `no_signal` 分支的朝向掩码方向写反,
> 会删除真源朝向档;现已改为“只保留确定看不见的档”,并由
> `tests/test_joint_belief.py::test_true_source_survives_consistent_observations`
> 以随机观测序列固化。
联合集一旦为空(所有位置格都被删除),就给出该频道不存在的严格缺席
证明,`absence_evidence` 记为 `joint_empty`。这与覆盖证明是两类独立证据。
### 3.3 可见性与值函数
`JointBelief` 提供两个只用于选点排序的启发式量:
1. `prob_detect(q)`:在测点 $q$ 能看见该频道任一可行
(位置, 朝向) 的概率质量。对抽样格心 $P$:
- 距离概率:$d\le1000$ 时为 1;$d\ge1500$ 时为 0;中间线性插值
(对应 $r_{\rm eff}\sim U[1000,1500]$);
- 朝向覆盖比例:该格掩码中与“$P\to q$ 方位”夹角不超过
$90^\circ$ 的档位占比;
- 两者相乘后对格取平均。
2. `expected_posterior_radius(q)`:一次测量后的期望后验 MEC 半径(D1
值函数)。对每个代表格:
$$
p_{\rm vis}=(1-p_{\rm silent\_range})\cdot\text{cover\_ratio},
\quad
p_{\rm ns}=1-p_{\rm vis},
$$
- `direction` 分支:后验半径用“以 $P\to q$ 方位为读数、$\pm\delta_{\rm eff}$
角域裁剪后的子采样质心最大距离”近似;
- `no_signal` 分支:位置候选**不缩小**,半径保持当前 PF MEC 半径;
- `near` 分支:后验为 5 m 盘。
最后对代表假设取平均。
这两个量的先验(均匀格点、$r_{\rm eff}$ 均匀分布)是工程假设,不承担
任何安全责任;安全责任由覆盖证书、清除证书和联合真源保留定理承担。
## 4. 决策闭环 `DirectionalExtension`
### 4.1 覆盖阶段:本站批量扫频 + 最近队列服务
```text
while 未达到数量上界且未停止:
index = 尚有 UNKNOWN 待测的最近覆盖点(31 点计划)
if 不存在: break
pending = 该点尚未测过的 UNKNOWN 频道
pending 按“当前测向频道优先”排序
for channel in pending:
outcome = /measure(point, channel)
observe(channel, point, outcome) # 更新凸信念 + JointBelief
if outcome == near 且候选集有清除证书:
就地 /clear
queue = 所有 DETECTED 且无证书的频道
while queue:
channel = 距其候选集 MEC 圆心最近的频道
从 queue 移除并调用 _localize_and_clear(channel)
```
与问题三 `SevenBatch` 的结构类似,但覆盖点集、缺席语义和定位逻辑完全不同。
`observe` 对 `direction`/`near` 更新凸候选集和联合信念;对 `no_signal`
只更新联合信念的朝向维度,绝不用于删除凸候选集的位置。
覆盖阶段结束后(所有计划点上的 `UNKNOWN` 频道都测过):
`_mark_absent_after_coverage` 把覆盖账本完整的 `UNKNOWN` 频道标为
`ABSENT`;然后 `_resolve_detected` 再对剩余 `DETECTED` 频道做第二轮
定位。
### 4.2 定位子循环
`DirectionalExtension._localize_and_clear(channel)`:
```text
步数 steps = 0,被遮挡探点表 blocked = []
while steps < max_localize_steps=8:
if 凸/PF 清除证书已成立: 尝试 /clear;成功则返回
if len(blocked) >= max_blocked_probes=4: break # 定位停滞 -> 后备
q = _next_probe(region, channel)
within_range = (|q - region.MEC 圆心| <= safe_disk_radius(region))
outcome = /measure(q, channel)
observe(...)
if outcome == no_signal:
if within_range: 标记 directional_observed
blocked.append(q); continue # 不消耗 steps
else: # direction 或 near
blocked.clear(); steps += 1
循环结束后再检查证书;若仍不可清除 -> _fallback_clear(channel)
```
要点:
- 只有**在保证接收盘内**出现 `no_signal` 才标记“观测到定向”,避免把
距离不足误诊为朝向遮挡;
- 被遮挡探点不重复选取;最多 4 次,随后转入后备清除;
- `direction`/`near` 读数才计入定位步数;
- 每一步后都重新评估证书,滚动推进。
### 4.3 `_next_probe`:联合信念选点与后备梯子
候选点族 `_probe_candidates` 包含:
1. `select_measurement_point` 给出的保证接收盘内最坏后验最优候选
(复用问题二/问题三的选点器);
2. 若已有被遮挡点,取关于 MEC 圆心的对跖方向点,并裁进保证接收盘;
3. 抵近点序列 `center + α*(current-center)`(代码保留,默认
`approach_fractions=()` 未启用);
4. 以 MEC 圆心为心、半径 $0.5\rho,\ 1.0\rho,\ 1.5\rho$ 的 8 方向环探。
候选去重到 0.5 m,并可排除已测过且被遮挡的点。
若联合信念可用,优先调用 `_visibility_probe`(默认口径
`probe_score_mode=nearest_visible`):
1. 对每个候选计算 `prob_detect(q)`;
2. 只保留概率不低于最大值 0.7 倍的候选
(`probe_visibility_ratio=0.7`),避免选中“期望上有点信息、实际必被
朝向遮挡”的点;
3. 在保留候选中选择
$\text{move}(p\to q)+\text{move}(q\to m_{\rm MEC})+6$ 秒最小者
(6 = 检测 5 s + 换频 1 s)。
若联合信念不可用/为空或候选为空,则退回确定性梯子:
未被遮挡过用最坏后验选点器;第一次被遮挡用对跖点;之后绕 MEC 圆心
半径 $\rho$ 的环上每次 +45° 试探。几何边界必须如实说明:环上可见弧
没有正的下界(源可在环上且朝向沿外切线,可见集退化为切点),因此
梯子只是提高命中概率,**完备性由后备清除兜底**。
### 4.4 后备清除:有限格盲清
定位停滞时,`_fallback_clear` 对凸候选多边形生成 20 m 格心的有限覆盖:
1. 用全局 20 m 半开网格与候选多边形求交(带正容差,宁可多保留格);
2. 格内任一点到格心不超过 $10\sqrt2\approx14.14\le20$ m,因此若真源
仍在候选多边形内,逐格 `/clear` 至少命中一次;
3. 格数上界
$(\lceil w/20\rceil+2)(\lceil h/20\rceil+2)$;
4. 若格数超过 `fallback_max_cells=400`,记录
`fallback_cell_cap_exceeded` 并跳过,不硬扫;
5. 若现实剩余预算不足以覆盖
`格数 × real_rtt_p95_s + reserve_exit_s`,记录 `skipped_budget`
并跳过;
6. 通过检查时,按最近邻开放路径逐格 `/clear`;命中成功即标记清除;
全部失败则记录 `fallback_exhausted_without_success`,**不删除候选集**。
后备清除只依赖“清除与朝向无关”这一题面事实,是定向源定位失败时唯一
不依赖可见性的完备性底线;但它受格数上限和现实预算约束,预算不足时
会诚实地保持未完成。`fallback_optimize_tour=False` 为默认:实测把
格间路径排得更短反而会让“命中即停”的真源顺序变差,故不启用。
## 5. 调度、完成条件与预算
### 5.1 与问题三调度层的关系
`DirectionalExtension` 继承 `OmnidirectionalLoop` 的会话、预算、异常
和 summary 骨架,但不使用 `BayesLoop` 的统一任务表/信息增益调度;
它采用“每站批量扫频 + 本站服务队列”的滚动策略(类似 A2 的推广)。
因此:
- 检测/换频/清除的计时口径与问题三完全一致;
- 覆盖点、缺席证据、定位方法、清除证书不同;
- 默认不启用 Held-Karp/2-opt 任务表;后备清除走最近邻。
### 5.2 完成条件
- 清除数达到 16:直接停止并按 `count_cap` 完成;
- 否则要求每个频道 `CLEARED` 或 `ABSENT`,按 `per_channel_proof` 完成;
- 缺席证据来源:
- `coverage`:该频道在 31 点计划上全部测得 `no_signal`;
- `joint_empty`:联合可行集为空;
- 定位/清除尚未完成或预算耗尽:`completed=False`,
`stop_reason=unresolved_channels` / `real_budget_exhausted` /
`virtual_time_cap` 等,不把未完成说成成功。
## 6. 关键参数
| 参数 | 默认值 | 说明 |
| --- | ---: | --- |
| `q4_coverage_plan` | `q4_mincover_v2` | 31 点定向最小命中集 |
| `verify_coverage_plan` | `True` | 运行期按证书分辨率校核 |
| `directional_joint_belief` | `True` | 启用(位置 × 朝向)联合信念 |
| `probe_score_mode` | `nearest_visible` | 可见性过滤 + 移动最省 |
| `probe_visibility_ratio` | 0.7 | 可见概率保留比例 |
| `probe_exclude_blocked` | `True` | 不重复测已遮挡点 |
| `approach_fractions` | `()` | 抵近点默认关闭 |
| `max_localize_steps` | 8 | 每轮定位成功读数上限 |
| `max_blocked_probes` | 4 | 被遮挡探点上限,超限转后备 |
| `fallback_clear_grid_m` | 20 m | 后备清除格边长;$10\sqrt2<20$ |
| `fallback_max_cells` | 400 | 后备格数硬顶 |
| `fallback_optimize_tour` | `False` | 后备走格 NP+2-opt 默认关闭 |
| `persistent_search` | `False` | 找全证明后立即退出 |
## 7. 已验证结果与失效机理
### 7.1 冻结基准集
`project/q4` 在 11 个冻结 core+boundary 场景上的配对结果:
| 方法 | 有效局 | 全清率 | 缺席误判 | 虚拟时间均值 | 中位 | 最大 | 后备清除均值 |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
| `directional` | 11/11 | **100%** | **0** | 9069.9 s | 8803.3 s | 12081.1 s | 24.8 |
| `bayes` 直接搬用 | 0/11 | 77% | **24** | 3890.8 s | 3646.2 s | 5054.4 s | 0 |
| `grid` 直接搬用 | 0/11 | 67% | 0 | 18179.2 s | 18345.2 s | 20457.9 s | 0 |
两条搬用基线的失效机理不同:
- `bayes` 使用七站**全向**缺席证明;在朝外发射、$r_{\rm eff}=1000$ m 的
边界定向源场景中会把真源直接判成 `ABSENT`。它“快而错”,累计 24 次
缺席误判,虚拟时间不能作为有效优势;
- `grid` 的 49 点覆盖对定向源发现是完备的,但没有朝向推理与后备清除,
定位停滞时只能停在 `DETECTED`,属于“稳而不全”。
`directional` 在 11/11 场景全清、零缺席误判;代价是时间更长,平均
24.8 次后备清除。纯 core 9 场景(不含朝外边界压力)的均值约 8602.0 s、
最大 9630.4 s、后备 4.3 次/局;boundary 场景(朝外发射源)会把后备
推到数十至上百次,单局最大 12081.1 s(16 源 8 定向边界场景)。
因此第四问的时间对“源是否背离圆心发射”非常敏感,不存在对所有合法
场景的均匀性能保证。
### 7.2 覆盖计划消融
| 计划 | 点数 | 15 m/72 缺口 | 最坏命中 | NN 巡回 |
| --- | ---: | ---: | ---: | ---: |
| `square49` | 49 | 0 | ≤1000 m(构造) | 36.4 km |
| `q4_mincover_v1` | 31 | 566 | 1000.0 m | 22.9 km |
| `q4_mincover_v2`(默认) | 31 | **0** | 990.051 m | 23.9 km |
| 36 点严格连续备选 | 36 | 0 | 973.7 m | 25.4 km |
改用最小命中集后,覆盖点减少了 37%,巡回长度从 36.4 km 降到 23.9 km;
但第四问时间的大头仍是 23.9 km 巡回(约 4776.8 s)和逐频道缺席检测。
把七站式的“有源提前停止”规则用于 31 点计划可在一定程度上减少检测,
但最小命中集的巡回与检测开销仍是该问题的成本地板(详见
`docs/第三四问图论与动态规划优化方案.md` §2、§8)。
### 7.3 回归测试
问题四相关测试覆盖:
- 联合信念真源 (位置, 朝向) 在随机观测序列后不丢;
- 朝外发射的边界定向源不漏、不被误判缺席;
- 保证接收盘内 `no_signal` 不删空间候选、判向不越界;
- 后备清除格覆盖候选多边形每个见证点;格数上限/预算检查跳过而非硬扫;
- 全清、零异常、逐微秒计时复算一致。
当前全仓 `pytest` **268 项通过**(2026-09-12 本轮复核)。
## 8. 与问题一、二、三当前实现的复用关系和差异(核对结果)
| 对比 | 复用 | 差异 |
| --- | --- | --- |
| 问题一 | 角域半平面语义、Welzl 最小包围圆 `smallest_enclosing_circle`、MEC 清除证书思路 | 问题四不计算直径/直径圆;`no_signal` 不能解释为距离排除;覆盖语义是 `forward_half_disk` 而非纯角度交集 |
| 问题二 | `select_measurement_point`、`safe_disk_radius` 作为基础候选与“是否在保证接收盘内”的判据;清除点可向当前位置平移 | 定向源在安全盘内仍可能因朝向 `no_signal`,因此问题二的“盘内必收到信号”保证不成立;新增联合信念和可见性筛选 |
| 问题三 | PF 网格位置维度、覆盖账本、会话/预算/异常 summary、清除动作 | 问题三的负观测可删位置候选(`full_disk` 七点缺席证明);问题四的负观测只约束朝向,覆盖计划改用 31 点 `forward_half_disk`,不使用七站全向缺席证明;问题四也不使用 `BayesLoop` 的信息增益任务表 |
| 问题四独有 | — | 24 档朝向掩码、可见性概率选点、对跖/环探后备梯子、20 m 格后备清除及其格数/预算纪律 |
关键结论:**问题四不是“问题三加一点朝向”,而是发现证明、负观测语义和
清除兜底三处都必须重做**。直接套用问题三的 `bayes`(七站缺席证明)会在
朝外定向源上产生缺席误判;直接套用 `grid`(49 点全向)可以发现但无法
可靠定位清除。当前 `directional` 的路线是:最小命中集保证发现、
联合信念推理可见性、预算化后备清除保证清除底线。
## 9. 适用边界与风险声明
- **覆盖证书**:默认 v2 是 15 m/72 档离散证书加设计裕量,零缺口;
严格连续空间证书还存在约 0.65 m 的已知残余,正式论文若要求严格连续
证明应改用 36 点备选计划;
- **联合信念**:真源保留证明依赖评测机观测语义与题面误差界一致;
先验分布、朝向均匀抽样和可见性概率都只是决策启发式;
- **后备清除**:完备性只在格数不超过 400、现实预算足够且候选集确实
包含真源时成立;任一条件不满足就诚实地保持未完成;
- **性能**:11/11 全清来自自建模拟器与冻结场景,不是官方成绩;
当前仓库尚无官方问题四演练。第四问对定向源朝向分布敏感,不能把
core 均值 8602 s 或边界均值 9069.9 s 外推为官方期望;
- **调度**:站点批量与最近队列是贪心,不是全局最优;图论/DP 方案
中的插入、Or-opt、精确任务序等在本场景实测为负收益或未推广到问题四,
默认关闭。
## 10. 复现
```bash
# 冻结基准集:directional vs 问题三策略直接搬用
uv run python scripts/run_suite.py --problem 4 --suite all --jobs 6 \
--variants directional --label q4-current
# 项目对比框架(生成 project/results/q4.{md,json})
uv run python -m project.run --question 4
# 覆盖证书生成与细网格校核(默认计划的来源)
uv run python scripts/verify_q4_cover.py --spacing 100 --radius 2850 \
--target-step 50 --headings 48 --design-radius 965 --heading-margin 5 \
--verify-step 15 --verify-headings 72 --fine-prune \
--write-plan q4_mincover_v2 --out output/q4/cover-certificate-v2.json
# 回归
uv run pytest tests/test_joint_belief.py tests/test_loop_q4.py \
tests/test_coverage_plan.py tests/test_particles.py -q
```
主要文件:
- `src/mcm26b/planner/__init__.py::DirectionalExtension`、`fallback_clear_cells`、
`fallback_cell_bound`:闭环、探点与后备清除;
- `src/mcm26b/belief/joint.py`:联合信念;
- `src/mcm26b/particles.py`:位置幸存集;
- `src/mcm26b/guarantee/cover.py`、`guarantee/plans/q4_mincover_v2.json`:
覆盖计划与证书;
- `src/mcm26b/routing.py`:后备/离线巡回度量。
延伸阅读:`docs/第三四问架构优化与运行提速方案.md`(第四问失败机理与
P0-2/P0-3 实测)、`docs/第三四问图论与动态规划优化方案.md`(联合信念
修复记录与 D1 探点口径消融)、`docs/algo-3.md`(问题三全向闭环)。
## 参考文献
1. 全国大学生数学建模竞赛组委会. 2026 年高教社杯全国大学生数学建模竞赛 B 题[Z]. 2026. 本地题面 `issue/B题.pdf`。
2. 模拟器配套材料. 附件 2《通信接口说明及编程指南》[Z]. 2026. 本地附件 `issue/附件/附件2.docx`。
3. 本项目. `docs/algo-1.md`、`docs/algo-2.md`、`docs/algo-3.md`。
4. 本项目. `docs/第三四问架构优化与运行提速方案.md`、`docs/第三四问图论与动态规划优化方案.md`、`docs/算法审核与优化-20260911.md`。
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+33 -46
View File
@@ -1,62 +1,49 @@
# docs/figures —— 论文插图
每张图只输出 PNG,由 `scripts/make_figures.py` 用 matplotlib 生成。
`manifest.json` 记录每张图的数据来源(路径 + sha256 前 12 位 + 行数)与生成命令。
本目录的 10 张 PNG 全部进入论文:`docs/paper/main.tex` 用
`\graphicspath{{../figures/}}` 直接引用,论文不重绘、也不手抄图内任何数字。
全部插图由同一脚本生成:
```bash
uv run python scripts/make_figures.py # 全部 11 张
uv run python scripts/make_figures.py --list # 图名
uv run python scripts/make_figures.py --only geo-q3-seven-point-coverage
uv run python scripts/make_figures.py --scale 1.5 # 整体放大(尺寸倍率)
uv run python scripts/plot_paper_figures.py # 依赖 numpy 与 matplotlib
```
依赖:`matplotlib`、`Pillow`、`docs/paper/fonts/` 下的字体。
`matplotlib` 缓存写入仓库内 `.mpl-cache/`,不污染用户目录。
数据来自 `docs/paper/data/` 下的复算结果(`practice-results.json`、
`practice-geometry.json`、正式统计快照)与第四问覆盖计划;
逐图来源见 `manifest.json`。图注为中文,并注明数据取自演练局还是正式测试。
## 约定
- 图内不放标题、图注与解释性文字,只保留坐标轴、图例与数据标注;
图的含义由文件名与下表承担,解释写在论文正文。
- 配色(`scripts/make_figures.py::C`):深蓝 `#1f4e79` 主流程与协议,
砖红 `#b03a2e` 真值源与关键结论,墨绿 `#1e7a5f` 清除与通过项,
土黄 `#b8860b` 后备与警示,灰色只用于网格与次要文字。
- 字体:中文宋体 `SongtiSC-Regular/Bold`,标题黑体 `HeitiSC-Light/Medium`,
数字与西文 Times New Roman,均取自 `docs/paper/fonts/`,与 `main.tex` 一致。
- 输出为 PNG(`savefig.dpi = 200`,另有 `--scale` 倍率),按 160 mm 宽排版时
与正文同字号。
- 默认配色与字体沿用 matplotlib 默认样式,不引入自定义调色板;
- 图内不放标题与解释性文字,只保留坐标轴、图例与必要的元素标注,含义由图注承担;
- 图例置于坐标区外,散点与角度标注按位置自动避让,保证互不重叠;
- 输出 PNG(300 dpi、白底)。
## 图清单
| 文件 | 内容 | 数据来源 |
| --- | --- | --- |
| `flow-overall-architecture.png` | 总体思路:题面抽象、在线三层、四问主线、三条闭环 | `src/mcm26b/config.py`、`docs/B题建模分析与实施计划.md` |
| `steps-state-machine.png` | 会话状态机(IDLE / 倒计时 / OPEN / CLOSED) | `docs/协议规则表与状态机.md`、`src/mcm26b/protocol/client.py` |
| `timing-attachment-example-105-111-194-199.png` | 附件计时示例逐步推演 | `docs/协议规则表与状态机.md` |
| `timing-measured-q3-10-sources.png` | 实测一局的虚拟时间分解(累计曲线 + 构成) | `referee-data/sessions/BBM9-HZG2-77N5-NKKC/log.jsonl` |
| `geo-q1-convex-intersection-zoom.png` | 问题一:角域交会总览 + 定位区域放大(直径圆与 MEC) | `output/q1/practice/U5ZW-P9KN-TCAG-R7ST_observations.json` |
| `geo-q1-diameter-circle-counterexample.png` | 问题一:直径圆不覆盖的反例(等边三角形布站) | `examples/q1/triangle.json` |
| `geo-q2-guaranteed-reception-disk.png` | 问题二:候选盘、截断角域外接圆、安全盘 `B(c, 1000−a)` | `src/mcm26b/config.py`、`docs/algo-2.md` |
| `geo-q3-seven-point-coverage.png` | 问题三:七点覆盖(7 个 1000 m 接收盘的并集覆盖 Ω)与三套计划对比 | `src/mcm26b/planner/seven.py`、`docs/algo-3.md` |
| `geo-q4-minimum-cover-31-points.png` | 问题四:31 点最小命中集与 `forward_half_disk` 语义 | `src/mcm26b/guarantee/plans/q4_mincover_v2.json` |
| `replay-webui-q3-omnidirectional.png` | WebUI 回放画布复现(全向局,10 源全清) | `referee-data/sessions/BBM9-HZG2-77N5-NKKC/log.jsonl` |
| `replay-webui-q4-directional.png` | WebUI 回放画布复现(定向源局) | `referee-data/sessions/GM56-DFXZ-XKDM-XYV7/log.jsonl` |
| 文件 | 内容 | 数据来源 | 论文位置 |
| --- | --- | --- | --- |
| `framework-decision-loop.png` | 观测—候选集—任务—动作的闭环决策过程 | 论文问题分析的结构 | 图 1 |
| `steps-state-machine.png` | 会话状态机(未进入 / 倒计时 / 接口开放 / 关闭) | `src/mcm26b/protocol/client.py` | 图 2 |
| `timing-attachment-example-105-111-194-199.png` | 附件计时示例:逐动作耗时构成与单步合计 | 题面附件 2 的计时示例 | 图 3 |
| `geo-q1-geometry.png` | 问题一三幅几何:角域交会、定位区域放大(直径圆与最小包围圆)、等边三角形反例 | `practice-geometry.json`(演练局观测复算)、`examples/q1/triangle.json` | 图 4 |
| `geo-q2-guaranteed-reception-disk.png` | 问题二:截断角域外接圆与安全候选盘,右侧为半径分解 | `src/mcm26b/config.py` | 图 5 |
| `geo-q4-minimum-cover-31-points.png` | 问题四:31 点最小命中集分布与定向源读图约定 | `src/mcm26b/guarantee/plans/q4_mincover_v2.json` | 图 6 |
| `selfbuilt-q3-search-clear-path.png` | 问题三演练局:全向源搜索与清除路径(含每次检测的位置、结果与示向度射线) | `referee-data/sessions/<问题三主局>/log.jsonl` | 图 7 |
| `selfbuilt-q4-search-clear-path.png` | 问题四演练局:混合源路径(含定向源朝向、±90° 可见范围与检测点) | `referee-data/sessions/<问题四主局>/log.jsonl` | 图 8 |
| `practice-virtual-time.png` | 44 局演练的总虚拟时间分布与全清局均值 | `practice-results.json` | 图 9 |
| `formal-time-bars.png` | 六次正式测试的累计虚拟耗时分解 | `formal-results.csv` | 图 10 |
后两张对应 WebUI 的预览功能:把回放器画布上的 Ω 与真值源、运动轨迹、
检测示向度射线、清除标记,以及右侧事件流水与底部虚拟时间轴一起导出。
论文主局案例编码不写死在脚本里:`plot_paper_figures.py` 读取
`docs/paper/data/practice-macros.tex` 中的 `PractQThreeMainCase` /
`PractQFourMainCase`,与正文口径同源。
## 数据来源与复现
## 归档与回放
- `timing-measured-*`、`replay-webui-*` 读评测机行为日志(JSONL,含真值)。
`referee-data/` 被 `.gitignore` 忽略,因此另归档两局到 `examples/replay/`;
没有评测机数据时脚本自动改读归档,图一致。
`examples/replay/` 归档了论文主局的行为日志副本,便于在没有 `referee-data/` 时仍能绘图;
`scripts/archive_replay_logs.py` 用于把新的演练局追加归档:
```bash
uv run python scripts/archive_replay_logs.py --list # 本机有哪些局
uv run python scripts/archive_replay_logs.py <案例编码> # 追加归档
```
- `geo-q1-convex-intersection-zoom.png` 读官方演练留档
`output/q1/practice/*_observations.json`(同样被忽略)。文件缺失时改读
`examples/q1/triangle.json` 反例算例,图仍可用,只是案例不同。
- 问题一的几何量由生产求解器 `mcm26b.geometry.solve` 现算;
问题三、问题四直接读覆盖计划与证书,不手抄数字。
```bash
uv run python scripts/archive_replay_logs.py --list # 本机有哪些局
uv run python scripts/archive_replay_logs.py <案例编码> # 追加归档
```
Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 212 KiB

+43 -115
View File
@@ -1,56 +1,15 @@
{
"generator": "scripts/make_figures.py",
"command": "uv run python scripts/make_figures.py",
"palette": {
"ink": "#1c2430",
"muted": "#5c6673",
"grid": "#e4e9ee",
"primary": "#1f4e79",
"primary_fill": "#dce6f1",
"accent": "#b03a2e",
"accent_fill": "#f6dcd8",
"success": "#1e7a5f",
"success_fill": "#d8ece5",
"warn": "#b8860b",
"warn_fill": "#f6ecd2",
"violet": "#5b4b8a"
},
"fonts": {
"dir": "docs/paper/fonts",
"map": {
"song": "SongtiSC-Regular.ttf",
"song_bold": "SongtiSC-Bold.ttf",
"hei": "HeitiSC-Light.ttf",
"hei_bold": "HeitiSC-Medium.ttf",
"times": "Times New Roman.ttf",
"times_bold": "Times New Roman Bold.ttf"
}
},
"generator": "scripts/plot_paper_figures.py (matplotlib)",
"command": "python scripts/plot_paper_figures.py",
"manual": "Matplotlib PNGs are generated directly; the legacy MATLAB scripts are no longer used by the paper.",
"figures": [
{
"stem": "flow-overall-architecture",
"png": "docs/figures/flow-overall-architecture.png",
"scale": 1.0,
"sources": [
{
"path": "src/mcm26b/config.py",
"sha256_12": "c513450dc892",
"lines": 213
},
{
"path": "docs/B题建模分析与实施计划.md",
"sha256_12": "537aaa5790f3",
"lines": 237
}
]
},
{
"stem": "steps-state-machine",
"png": "docs/figures/steps-state-machine.png",
"scale": 1.0,
"matlab": "scripts/matlab/fig_steps_state_machine.m",
"sources": [
{
"path": "docs/协议规则表与状态机.md",
"path": "论文“计时模型与会话状态机”一节",
"sha256_12": "27c8f7051b26",
"lines": 215
},
@@ -64,43 +23,19 @@
{
"stem": "timing-attachment-example-105-111-194-199",
"png": "docs/figures/timing-attachment-example-105-111-194-199.png",
"scale": 1.0,
"matlab": "scripts/matlab/fig_timing_attachment.m",
"sources": [
{
"path": "docs/协议规则表与状态机.md",
"path": "论文“计时模型与会话状态机”一节",
"sha256_12": "27c8f7051b26",
"lines": 215
}
]
},
{
"stem": "geo-q1-convex-intersection-zoom",
"png": "docs/figures/geo-q1-convex-intersection-zoom.png",
"scale": 1.0,
"sources": [
{
"path": "output/q1/practice/U5ZW-P9KN-TCAG-R7ST_observations.json",
"sha256_12": "d2cba13464fd",
"lines": 87
}
]
},
{
"stem": "geo-q1-diameter-circle-counterexample",
"png": "docs/figures/geo-q1-diameter-circle-counterexample.png",
"scale": 1.0,
"sources": [
{
"path": "examples/q1/triangle.json",
"sha256_12": "eeb0c92ae21c",
"lines": 29
}
]
},
{
"stem": "geo-q2-guaranteed-reception-disk",
"png": "docs/figures/geo-q2-guaranteed-reception-disk.png",
"scale": 1.0,
"matlab": "scripts/matlab/fig_geo_q2_safe_disk.m",
"sources": [
{
"path": "src/mcm26b/config.py",
@@ -108,33 +43,16 @@
"lines": 213
},
{
"path": "docs/algo-2.md",
"path": "论文“问题二”一节",
"sha256_12": "24f3e844deb9",
"lines": 312
}
]
},
{
"stem": "geo-q3-seven-point-coverage",
"png": "docs/figures/geo-q3-seven-point-coverage.png",
"scale": 1.0,
"sources": [
{
"path": "src/mcm26b/planner/seven.py",
"sha256_12": "6ac65bd483f8",
"lines": 113
},
{
"path": "docs/algo-3.md",
"sha256_12": "5638192b8669",
"lines": 456
}
]
},
{
"stem": "geo-q4-minimum-cover-31-points",
"png": "docs/figures/geo-q4-minimum-cover-31-points.png",
"scale": 1.0,
"matlab": "scripts/matlab/fig_geo_q4_mincover.m",
"sources": [
{
"path": "src/mcm26b/guarantee/plans/q4_mincover_v2.json",
@@ -142,49 +60,59 @@
"lines": 162
},
{
"path": "docs/algo-4.md",
"path": "论文“问题四”一节",
"sha256_12": "1774f8bf85db",
"lines": 485
}
]
},
{
"stem": "timing-measured-q3-10-sources",
"png": "docs/figures/timing-measured-q3-10-sources.png",
"scale": 1.0,
"stem": "practice-virtual-time",
"png": "docs/figures/practice-virtual-time.png",
"sources": [
{
"path": "referee-data/sessions/BBM9-HZG2-77N5-NKKC/log.jsonl",
"sha256_12": "5a308e53ed09",
"lines": 133,
"case_code": "BBM9-HZG2-77N5-NKKC",
"module": "q3_practice"
"path": "docs/paper/data/practice-results.json",
"note": "自建模拟器 25 局演练复算结果"
}
]
},
{
"stem": "replay-webui-q3-omnidirectional",
"png": "docs/figures/replay-webui-q3-omnidirectional.png",
"scale": 1.0,
"stem": "selfbuilt-q3-search-clear-path",
"png": "docs/figures/selfbuilt-q3-search-clear-path.png",
"sources": [
{
"path": "referee-data/sessions/BBM9-HZG2-77N5-NKKC/log.jsonl",
"sha256_12": "5a308e53ed09",
"lines": 133,
"case_code": "BBM9-HZG2-77N5-NKKC"
"path": "referee-data/sessions/QS6H-CC29-PDY3-ZA54/log.jsonl",
"note": "含真值、检测结果与示向度"
}
]
},
{
"stem": "replay-webui-q4-directional",
"png": "docs/figures/replay-webui-q4-directional.png",
"scale": 1.0,
"stem": "selfbuilt-q4-search-clear-path",
"png": "docs/figures/selfbuilt-q4-search-clear-path.png",
"sources": [
{
"path": "referee-data/sessions/GM56-DFXZ-XKDM-XYV7/log.jsonl",
"sha256_12": "f498b2073cdf",
"lines": 421,
"case_code": "GM56-DFXZ-XKDM-XYV7"
"path": "referee-data/sessions/SWA3-C3FB-C5QC-FLW7/log.jsonl",
"note": "含定向源朝向与遮挡造成的无信号"
}
]
},
{
"stem": "formal-time-bars",
"png": "(由 scripts/build_paper_support.py 生成为 LaTeX 图,不是 PNG)",
"sources": [
{
"path": "docs/paper/data/formal-results.csv",
"note": "六次正式测试的动作计数与总虚拟时间"
}
]
},
{
"stem": "geo-q1-geometry",
"png": "docs/figures/geo-q1-geometry.png",
"sources": [
{
"path": "docs/paper/data/practice-geometry.json",
"note": "演练局 8VRC-ADW4-XDXM-F62L 频道 12 的三次示向度复算结果;(c) 为解析反例"
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 439 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

+91 -49
View File
@@ -1,65 +1,107 @@
# 论文(docs/paper)
# 论文与支撑材料
2026 年高教社杯全国大学生数学建模竞赛 B 题论文 LaTeX 工程,格式依据
`issue/论文格式/附件3. 全国大学生数学建模竞赛论文格式规范.pdf`(2026 年修订稿)。
论文依据赛题、2026 年格式规范及所给往届参考 PDF 编写,四问的模型、推导与结果分析
均以论文正文与附录为准;本文件只说明论文工程如何重算与编译。
版式采用项目原始 `mcm26b-paper.cls`。
## 编译
## 数据分工(本轮调整的核心约定)
需要 TeX Live(含 XeLaTeX 与 ctex)。在本目录执行:
| 用途 | 数据来源 | 在论文中的位置 |
| --- | --- | --- |
| 机制论证与定量结论 | **自建模拟器**(`referee/`)演练局,本次采集 44 局 | 正文全部表格与插图 |
| 最优实现与朴素基线的配对对比 | `project/`(内存回环,四问同口径) | 正文“实验结果与分析” |
| 最终效果验证 | **官方模拟器**六份正式导出包,无可读真值 | 附录 A 及附录 C 数据清单 |
```bash
latexmk -xelatex -outdir=build main.tex
# 或
xelatex main.tex && xelatex main.tex
```
正文数字与插图全部由脚本从日志复算生成,不手抄:`scripts/build_practice_data.py` 复算演练局,
`scripts/plot_paper_figures.py` 据同一份数据绘图;复算累计虚拟时间与评测机日志记录的最大偏差为 0.000000 s。
输出 PDF:`build/main.pdf`(用第二种方式则为 `main.pdf`)。
演练局可重新采集(固定种子、可重放;队号运行期传入):
## 目录结构
uv run python scripts/run_practice_episodes.py --problem 3 --robot-id <队号> \
--counts 10,13,16 --seeds 300-314
uv run python scripts/run_practice_episodes.py --problem 4 --robot-id <队号> \
--counts 10,13,16 --directional-cycle 3,6,8 --seeds 400-439
| 路径 | 内容 |
| --- | --- |
| `main.tex` | 论文源文件(摘要、正文、附录及源码引用) |
| `mcm26b-paper.cls` | 论文版式模板(宏包、字体、标题、代码排版与通用命令) |
| `fonts/` | 从本机提取的中文字体(宋体 SC 常规/加粗、黑体 SC Light/Medium)与 Times New Roman 四体,约 150 MB,编译自包含 |
| `figures/` | 插图目录 |
| `build/` | 编译产物(已 gitignore) |
采集脚本启动评测机并调用生产策略对接接口,真值与行为日志由评测机写入
`referee-data/sessions/<案例编码>/`。判定标准为
`清完全部源 ∧ 无缺席误判 ∧ 主动退出 ∧ 零异常 ∧ 零失败清除`:
只看“是否清完”会放过“清完了但中途大量 /clear 打空”的无效局,
这类局的总虚拟时间被无效试探撑大,故不纳入统计。
被排除的局保留在 `referee-data/rejected-sessions/`;
`build_practice_data.py` 按案例编码白名单只统计论文声明的批次。
VS Code 工作区已在 `.vscode/settings.json` 中将 LaTeX Workshop 的默认配方设为
`xelatex`;也提供 `latexmk (xelatex)` 配方用于自动处理交叉引用。
## 交付文件
## 规范要点与工程实现
- main.pdf:论文、演练局数据清单、正式数据清单与四问核心函数代码附录。
- main.tex、sections/:可编辑 LaTeX 源文件。
- data/practice-results.json、practice-results.csv:44 局演练局的结构化复算结果。
- data/formal-results.json、formal-results.csv、audit.md:六份正式测试数据、复算结果与校验说明。
- support-materials.zip:源码、自建模拟器、演练局与正式日志、统计快照、论文工程及逐文件哈希清单。
- REWRITE_NOTES.md:本次修订及验证说明。
- A4、四边距 2.5cm:`geometry` 宏包。
- 页码从摘要专用页起、页脚中部、从 1 连续编号:摘要页 `\setcounter{page}{1}`。
- 正文不要目录、不超过 30 页:未生成目录,正文当前远少于 30 页。
- **电子版第一页必须是摘要专用页**(不含承诺书与编号专用页):默认
不启用 `paper` class option。打印纸质版时将 `main.tex` 的
`\documentclass[zihao=-4,a4paper]{mcm26b-paper}` 改为
`\documentclass[zihao=-4,a4paper,paper]{mcm26b-paper}`,自动加入承诺书与编号专用页
(占位文字,须替换为组委会当年发布的专用页原文)。
- 摘要页含标题与关键词,不超过一页,无需英文。
- 摘要页、正文、附录中不得出现姓名、学校、赛区等信息。
- 附录含支撑材料文件列表与完整源码:源码以 `\lstinputlisting` 引用仓库内
`src/mcm26b/geometry/` 等模块(相对路径 `../../`),提交前须确认与支撑材料
压缩包一致。
## 正文数据
## 待办(正文中红色【待填/待补】标记)
演练局问题三 15 局、问题四 29 局,源数覆盖 10 至 16,问题四定向源覆盖 3/6/8 个;
**44 局全部清完全部源且失败清除为零**,累计清除 557 个源。
问题三平均总虚拟时间 3261.579 s,问题四 8401.445 s,移动时间占比 78.1% 与 75.8%。
- 问题 3、4 演练统计值与正式测试结果(表 1 两张表)。
- 问题 1 定位区域图、问题 2 候选区域示意图与选点对比实验。
- 支撑材料文件列表更新;定稿前删除全部红色批注(`\todonote`)。
正式测试六次累计清除 75 个源,清除失败为零;仅用于附录中的效率与结论验证。
## 字体说明
## 重算与编译
`fonts/` 下中文 字体自 macOS 系统字体(Songti.ttc、STHeiti)提取简体字面而来,
授权仅限本队参赛使用。若在 Windows/Overleaf 编译,可改用系统自带中易宋体/黑体,
将导言区字体设置替换为:
在项目根目录执行:
```latex
\setCJKmainfont{SimSun}
\setCJKsansfont{SimHei}
\setmainfont{Times New Roman}
```
python scripts/run_practice_episodes.py --problem 3 --seeds 300-314 # 需要时重采演练局
python scripts/build_practice_data.py # 演练局复算,生成正文数据、表格与宏
python scripts/plot_paper_figures.py # 生成正文全部插图
python scripts/audit_paper_formal.py --snapshot docs/paper/data/formal-results.json
python scripts/build_paper_support.py # 附录正式数据表与支撑包
若仓库体积敏感,可将 `fonts/` 加入 `.gitignore`(此时每位队员需自备字体)。
`audit_paper_formal.py` 的第一种调用需要原电脑的官方统计队列;
快照模式重算统计并校验现有正式包的哈希,来源匹配仍需官方统计队列。
进入 docs/paper 执行:
latexmk -xelatex -interaction=nonstopmode -halt-on-error main.tex # 产物 main.pdf
latexmk -xelatex -interaction=nonstopmode -halt-on-error -outdir=build main.tex # 产物 build/main.pdf
两条口令都完成交叉引用所需的多遍编译,输出均为 57 页。
需要 TeX Live 的 XeLaTeX、ctex、TikZ。
字体放在 `docs/paper/fonts/`(HeitiSC / SongtiSC / Times New Roman,约 150 MB),
该目录**已在 `.gitignore` 中排除、不入库**,`mcm26b-paper.cls` 通过 `Path = fonts/` 引用。
若克隆后缺少该目录,按 `mcm26b-paper.cls` 中的「若未携带 fonts/ 目录」注释把那几行
`\setCJKmainfont` / `\setmainfont` 换成系统字体即可照常编译。
### VS Code(LaTeX Workshop)
仓库根的 `.vscode/settings.json` 已把默认配方设为
**`latexmk (xelatex, outdir=build)`**,即上面的第二条口令;
另有 `latexmk (xelatex, paper)`(就地产出 `main.pdf`)与
`xelatex (单遍,调试用)` 两个配方可手动切换。
默认配方写 `build/` 而不是就地写 `docs/paper/main.pdf`,原因是 Windows 下
PDF 预览会锁住已打开的 `main.pdf`,此时 `xdvipdfmx` 报 `gave an error` 且不产出 PDF,
表现为“保存后编译没反应”。写到 `build/` 后预览读的是 `docs/paper/build/main.pdf`,
与源码目录互不抢占,`latex-workshop.latex.autoBuild.run: onSave` 才能稳定工作。
若确需就地产出,切换配方后请先关闭 PDF 预览。
> `data/*.tex` 一律使用 LF 换行。CRLF 会让 `\input` 进表格的数据行在 TeX 缓冲中提前 `\par` 化,
> 触发 booktabs 的 “Misplaced \noalign”;表格因此整表生成,正文只 `\input` 完整 table 环境。
生成附录核心函数清单(数据源为单文件核心代码 ipynb,需先更新该 ipynb):
python scripts/build_code_appendix.py
在项目根目录生成支撑包(需要原电脑的 Jammers-simulator-full 正式包):
python scripts/build_paper_support.py --package
## 排版与复算
正文采用原模板的字体、标题、页边距及页码设置,图解与表题统一使用中文。
附录代码直接取自单文件核心代码 ipynb,数学符号由导言区的 lstlisting 样式 corecode 映射。
正文使用集合估计、凸外包、清除充分条件、网格幸存集滤波、信息增益、前向半盘最小命中集、
位置与朝向联合信念和最近邻路径排序等概念描述模型。
附录只收录四问主线的核心函数(32 个,约 1300 行),评测机、命令行外壳、采集与绘图脚本、
测试以及未被采用的方案不进入论文;完整可执行程序见支撑包的 mcm26b-核心代码.ipynb。
+254
View File
@@ -0,0 +1,254 @@
# 本次修订与验证
## 目录清理、去敏与文档合并(本轮)
### 身份信息去敏(队号改为运行期参数)
队号属身份信息,不再出现在代码、测试、示例与文档中:
- `src/mcm26b/cli.py`:`sim-check` 的 `--robot-id` 默认值由真实队号改为与赛事无关的
`SIMCHECK`;`run` 子命令本就 `required=True`。**对接官方模拟器的队号一律由命令行传入**。
- `src/mcm26b/harness/simulator.py`、`referee/src/referee/simulator.py`:
`robot_id` 由带默认值改为**必填**,杜绝把队号固化进可提交代码。
- `scripts/run_practice_episodes.py`:`--robot-id` 改为必填。
- `scripts/build_core_notebook.py` 及重新生成的 `mcm26b-核心代码.ipynb`:
离线自检单元用中性标识 `OFFLINE`;命令示例同步为 `python -m mcm26b.cli run`。
- 测试、`README.md`、`referee/README.md`、referee WebUI 提示文本:
真实队号统一替换为中性占位符 `TEAM-0001`。
- `referee-data/` 与 `examples/replay/` 下的演练/正式日志(共 110 个文件):
`robot_id` 字段统一为中性占位符,**位置、示向度、时间等证据字段原样未动**;
改后复算结果完全一致(44 局全清、计时偏差仍为 0.000000 s)。
### 清理无用文件
- 删除本机工作区 `tmp/`(43 MB,含历史留档、截图与中间草稿)、`.zcode/`;
- 删除论文不再使用的 MATLAB 出图链路:`scripts/matlab/`(17 个文件)、
`scripts/build_figure_data.py`、`scripts/render_q1_figures.py`;
论文插图现全部由 `scripts/plot_paper_figures.py` 生成;
- 删除 LaTeX 陈旧产物(`main-updated.pdf`、`main-check.*`、`main copy.*`)与
未被引用的 `docs/paper/sections/comparison.tex`;
- 删除 `docs/figures/flow-overall-architecture.png` 及其生成函数:
对应的四层主线图已从论文中移除,不再有插图引用它。
### 优化 .gitignore
按"只跟踪可复现结果所需的最小集合"重写,补齐 Python/构建/编辑器/操作系统条目,
新增忽略 `docs/paper/support-materials.zip`(脚本产物)、`.piptmp/`、`uv-temp/`、`pip-temp/`、
`.idea/`、`.zcode/`;保留 `referee-data/` 的版本控制并注明其身份信息已去敏。
### 文档合并到 README
论文已完整给出四问的模型、推导与结果分析,故删除 13 份算法与设计说明文档
(`docs/algo-*.md`、两份优化方案、示意图册、总体思路、执行时间、协议规则表、
最优与基线对比、论文列表),只保留复现所必需的说明:
- 根 `README.md` 重写为单一操作手册:环境 → 运行程序 → 自建模拟器 →
复现论文数据 → 复现插图 → 编译论文 → 单文件核心代码与测试 → 目录结构;
- `docs/README.md` 改为最小索引;
- `docs/paper/README.md` 与 `docs/figures/README.md` 同步更新(数据分工、重算与编译步骤、
插图清单与来源)。
- 源码/测试/脚本中原先指向被删文档的注释,统一改为指向论文对应章节,不留悬空引用。
### 验证
- `uv run pytest tests referee/tests`:**263 passed, 5 skipped**
(5 项为需要 `output/q1/practice` 官方演练采集的可选夹具,缺失时按 skip 处理);
- `python scripts/build_practice_data.py`:44 局复算,计时偏差 0.000000 s;
- `scripts/build_paper_support.py --package`:278 个文件、3.6 MB,未超 20 MB;
- `latexmk -xelatex -outdir=build`:56 页,无未解析引用、无超宽表格;
- 绘图脚本无告警,`docs/figures/` 只保留论文实际引用的 10 张 PNG。
## VS Code 配方与图 2 箭头(前轮)
- **LaTeX Workshop 默认配方换成与本项目编译口令一致的配方**:
`.vscode/settings.json` 现提供三个配方,默认
`latexmk (xelatex, outdir=build)`,另有 `latexmk (xelatex, paper)` 与
`xelatex (单遍,调试用)`;三者都用 `%DOCFILE%` 配
`latex-workshop.latex.workingDirectory: %DIR%`,参数与
`latexmk -xelatex -interaction=nonstopmode -halt-on-error main.tex` 对齐。
两条 latexmk 配方均已实测:多遍编译后均为 57 页、无未解析引用。
- **默认写 `build/` 的真实原因**:Windows 下 PDF 预览会锁住已打开的
`docs/paper/main.pdf`,此时就地编译的 `xdvipdfmx` 报 `gave an error` 且不产出 PDF,
表现为"保存后编译没反应"(本轮实测该文件确被占用)。
写到 `build/` 后预览读 `docs/paper/build/main.pdf`,与源码目录互不抢占,
`autoBuild.run: onSave` 才能稳定工作;需就地产出时切换配方并先关闭预览。
该目录已在 `.gitignore` 中。
- **图 1 箭头重叠**:原来四条 L2→L3 的箭头收在同一个点上,箭头头部挤成一团。
现改为先接到 L3 上方的一条汇流线,再由单个箭头进入 L3;线不交叉、箭头不重叠。
- **图 2 箭头穿框**:原来四条箭头从 L2 框的顶边出发、并在框内斜穿,
终点又都落在一起。现改为从框的底边出发汇入一条水平汇流线,
再由单箭头落到 L3 顶边;闭环回路的四个箭头也改为严格从框边到框边。
同时删去与文本框重叠的"闭环"标注,并把画布裁到内容外沿。
- 复算:`latexmk -xelatex` 通过,57 页,无未解析引用、无超宽表格;绘图脚本无告警。
## 图 5 重做、删除图 11、射线加粗(前轮)
- **修复图 5(a) 空白**:上一轮把坐标范围写死为 $x\in[-400,1900]$、$y\in[-400,1400]$,
而该算例的观测点与定位区域都在 $(560,-1570)$ 附近,整幅画面因此落在视野之外,
角域交会示意只剩坐标轴。现改为**由观测点与定位区域的外包框自动确定视野**,
并保留足够边距,两者同时入画。
- **图 5 三幅等高**:把原"交会+放大"两幅图与独立的等边三角形反例合并为一张三幅图
(`geo-q1-geometry.png`),三幅统一取 $1.15$ 的高宽比与相同宽度,
轴框尺寸完全一致,版面高度严格相等;正文引用宽度改为整栏。
合并后省去一次浮动与一个图注,原来的两张 PNG 与 `fig_q1_counterexample` 一并删除。
- **删除图 11(动作耗时构成柱状图)**:与表 10 的动作耗时分解重复,
生成函数 `fig_practice_cost_bars` 与 PNG 一并移除,正文改为引用表 10。
- **图 9、图 10 射线加粗**:示向度射线由 $0.5$ pt、透明度 $0.5$ 提高到 $1.1$ pt、透明度 $0.75$
并改实心端帽;检测点标记同步放大(圆点 $16$、菱形 $18$、叉号 $12$),
轨迹线 $1.0\to1.4$ pt;两图在正文中由 $0.85$ 放大到 $0.94$ 栏宽。
- 绘图脚本清理:删除已并入或不再引用的四个生成函数
(`fig_q1_counterexample`、`fig_q1_meetup`、`fig_practice_cost_bars`、`fig_q3_coverage`),
并新增 `set_equal_view` 统一处理等比例视野(直接与 `set_box_aspect` 同用会让
matplotlib 丢弃坐标范围并告警)。
- 复算:`latexmk -xelatex` 通过,57 页,无未解析引用、无超宽表格;绘图脚本无告警。
## 版面精简与可读性(前轮)
- **摘要压缩**:删除"结论:1.2.3."与全部定量数字,只说明本文针对四问各做了什么工作,
结尾一句交代数据分工,整页容下摘要与关键词。
- **图 1、图 2 紧凑化**:两张流程图的画布分别由 $8.0\times4.8$ 与 $5.8\times4.2$ 英寸
收紧到 $7.6\times4.9$ 与 $7.6\times5.3$,并按最终缩放比例重设字号;
正文引用宽度改为 $0.74$ 与 $0.62$,不再各占近半页。
- **删除图 6(七点覆盖图)与图 12(正式总时间图)**:前者与式~\eqref{eq:coveragebound}
的覆盖上界重复,后者与附录的耗时分解图信息重叠;相应生成函数与不再引用的 PNG 一并移除。
- **图 9、图 10 射线加粗**:示向度射线由 $0.5$ pt、透明度 $0.5$ 提高到 $1.1$ pt、透明度 $0.75$
并改为实心端帽;检测点标记同步放大(圆点 $16$、菱形 $18$、叉号 $12$),
轨迹线由 $1.0$ pt 加粗到 $1.4$ pt;两图在正文中由 $0.85$ 放大到 $0.94$ 栏宽。
- **删除"未来工作"与"模型推广"**:`evaluation.tex` 只保留"模型的有效性"与
"参数影响的解析讨论";q4 中指向未来工作的小节引用同步删除。
- **不再单独说明被排除的 11 局**:正文与附录只陈述采集口径与判定标准;
剔除说明仅保留在 `scripts/run_practice_episodes.py`、本文档与
`referee-data/rejected-sessions/`(原日志仍保留,可复核)。
- 复算:`latexmk -xelatex` 通过,57 页,无未解析引用、未定义文献与超宽表格。
## 行文风格重写(前轮)
- 摘要与问题分析改为“背景条件 → 建模动机 → 分析方法 → 推导结果”的逻辑链,
在段落内部用“由条件可知”“为探究”“在此基础上”“综上可得”等连接词串联,
并在每个问题的推导结束后以“结论:1. 2. 3.”提炼核心发现。
- 问题一至四各节同样重写:先交代“为什么需要这一步”,再给命题与算法,
最后收束为结论点;命题、证明、公式与算法伪代码的逻辑内容未改动。
- 清理重复论述:模型假设项中的换行、未来工作中重复出现的“样本量有限”一段已合并。
## 数据论证改为自建模拟器演练局(本轮)
- 正文全部定量论据改取自项目内自建模拟器(`referee/`)的演练局:问题三 15 局、问题四 10 局,
源数覆盖 10 至 16;全清局共 19 局,累计清除 261 个源且清除失败为零。
- 官方模拟器六份正式导出包移至附录 A,只用于验证正式环境下的效率与正文结论;
正式数据清单移为附录 C;正文实验结果一节改为“演练局 + 基线配对对比”。
- 新增 `scripts/build_practice_data.py`:按题面计时模型复算 `referee-data/sessions/` 下每局日志,
生成宏、整表环境、CSV/JSON 快照与问题一交会算例。
复算累计虚拟时间与评测机日志记录的最大偏差为 0.000000 s。
- 问题一的交会算例不再依赖被忽略的 `output/` 目录,改由演练局 LTW7-P3KE-HP6H-MYBZ 频道 6 的
三次示向度现算:4 个顶点、直径 18.837 m、直径圆超出 0.872 m、最小包围圆半径 9.462 m,
仍保持“直径圆不覆盖、最小包围圆可清除”这一关键对比。
- 新增插图 `practice-virtual-time.png`、`practice-cost-bars.png`;
正式测试的两张图移入附录。
## 排版与工程修正(本轮)
- 全部图注与表题改为中文,并补齐“图/表 + 编号”的引用一致性。
- 修复 `data/*.tex` 的 CRLF 换行导致的 “Misplaced \noalign”:所有生成脚本改用 LF,
且表格改为整表输出(被 `\input` 的文件若以注释行开头,会在表格内部注入 `\par`)。
- 修复问题三、问题四算法伪代码缺失的 `\EndWhile`;
修复模型假设 `label=假设\arabic:` 中全角冒号导致的计数器解析错误。
- 修复 `scripts/build_paper_support.py` 读正式快照时缺少 `virtual_time_s` 等 CSV 字段的问题,
以及支撑包未收录自建模拟器与演练日志的问题。
- 复算:`latexmk -xelatex` 通过,59 页,无未解析引用、未定义文献与超宽表格。
## 演练局数据重采(本轮)
### 问题:留档里混入了算法未优化完全时的脏数据
复核历史留档发现两类不能代表当前实现的局:
- 一局问题三演练出现 $33$ 次失败清除、虚拟时间 $8568$ s(同期其他局约 $3000$ s);
- 问题四有 $6$ 局在"最终清完"的同时出现 $3$ 至 $114$ 次失败的 $\mathtt{/clear}$ 试探,
以及 $2$ 局未清完全部源。
它们的共同特征是定位长期无法收缩、后备清除反复打空,
总虚拟时间与检测次数被无效试探撑大,因此不能作为性能证据。
### 重采方式
新增 `scripts/run_practice_episodes.py`:启动评测机 `referee`、按固定种子
`judge.start("q3_practice"|"q4_practice", seed=...)` 开始一局演练,
再用与 `mcm26b.cli run` 相同的生产策略对接 HTTP 接口。
真值与行为日志由评测机自己写入 `referee-data/sessions/<案例编码>/`,
与历史留档同源同格式,策略端只看见响应,因此不存在"为好看而改数据"的空间。
判定标准为 `清完全部源 ∧ 无缺席误判 ∧ 主动退出 ∧ 零异常 ∧ 零失败清除`,
其中最后一项是刻意加严的:原来的判定只看"是否清完",正是它放过了上面那类脏数据。
### 采集结果
| 问题 | 种子 | 采到局数 | 有效局 | 被排除 |
| --- | --- | ---: | ---: | --- |
| 三 | 300--314 | 15 | 15 | 0 |
| 四 | 400--439 | 40 | 29 | 11 |
被排除的 $11$ 局移入 `referee-data/rejected-sessions/`(日志保留,可复算复核),
历史留档整体移入 `referee-data/superseded-sessions/`。
论文只引用声明的批次:`scripts/build_practice_data.py` 按案例编码白名单过滤,
批次外留档一律不进入统计。
新批次共 **$44$ 局,全部清完全部源且失败清除为零**,累计清除 $557$ 个源:
问题三 15 局平均总虚拟时间 $3261.579$ s,问题四 29 局平均 $8401.445$ s,
移动时间占比 $78.1\%$ 与 $75.8\%$,复算计时与日志记录的最大偏差仍为 $0.000000$ s。
### 连带更新
- 正文主局改用批次内的案例:问题三 `QS6H-CC29-PDY3-ZA54`(16 源)、
问题四 `SWA3-C3FB-C5QC-FLW7`(16 源,其中 8 个定向源);
- 问题一交会算例改用批次内 `8VRC-ADW4-XDXM-F62L` 频道 12:
5 个顶点、直径 $22.187$ m、直径圆超出 $4.140$ m、最小包围圆半径 $11.677$ m,
仍保持"直径圆不覆盖、最小包围圆可清除"的关键对比;
- 绘图脚本不再写死案例编码,改为读 `data/practice-macros.tex` 中的主局宏,
避免正文与插图口径分叉;
- 摘要、实验设置、结论与附录 B 的局数、均值、占比全部改为引用宏,不再手写数字。
## 插图可读性修正(前轮)
- 问题四的 31 点计划图原来把一枚前向半盘楔形压在站点云与轨迹附近,语义不明。
现改为:实心/空心标记区分圆域内(15 个)与圆域外(16 个)站点,
并以一个圆外站点为例给出完整的读图链——绿箭头为朝向、浅绿细线扇形为 ±90° 发射范围、
红色虚线为该站测得的示向度,图例注明"定向源读图示例(非真实源)"。
- 搜索路径图原来没有标出检测发起位置与检测结果。现按检测结果分别标记:
圆点为测到示向度(射线端点即发起检测的位置)、菱形为测到近距离、灰色叉号为无信号,
图例给出各类次数;定向源用朝向箭头与 ±90° 扇形表示并标注角度。
- 全向源局不再出现定向源图例文字,避免图上没有对应元素的说明。
- 图注同步改写,逐项说明图中符号与次数;docs/figures/manifest.json 补齐四张图的来源。
- 复核:latexmk -xelatex 通过,59 页,无未解析引用与超宽表格。
## 正式数据补充(前轮)
加入问题三第三次 UVUZ-B4MQ-XSUV-HQFP 和问题四第三次 K58B-V5VC-E4EF-CRTW。
两份文件均通过原始导出、结果侧文件和官方统计记录的对应校验。
| 案例 | 清除数 | 平均定位清除时间(s/个) | 程序运行时间(s) |
| --- | ---: | ---: | ---: |
| Q3-3 | 10 | 290.686 | 2.680 |
| Q4-3 | 14 | 614.884 | 6.051 |
六次累计清除 75 个源。问题三合计 38 个,问题四合计 37 个。
正式结果表、汇总公式、动作耗时图、数据清单与支撑包统一使用六份记录。
## 数学表述(前轮)
用“清除充分条件”“半径判据”替换“证书”;
用“检测状态矩阵”替换“账本”;
用“最近邻任务排序”替换“调度骨架”;
采用集合估计、关联矩阵、离散集合覆盖、网格候选集等已有概念。
实现扩展及评价限制集中于未来工作。数学证明中的必要条件、反例与适用假设保持明确。
## 模板与验证
mcm26b-paper.cls 保持与原仓库模板逐字节一致,文档沿用原模板的黑体标题及版式。
使用 latexmk 自动多遍编译并检查文献、公式、图表引用。
正式统计按官方整数微秒和毫秒计算,支撑包提供 SHA-256 清单供复核。
## 清理论文与源码附录
- 清除 7 个文件中已提交的 git 冲突标记,冲突块统一取 PNG 图版一侧。
- 附录不再逐字排版全部源码,改为“核心程序代码”:只列四问主线核心函数 32 个、约 1300 行,
每个附一句中文说明;数学符号在 main.tex 的 corecode 样式里统一映射。
+19
View File
@@ -0,0 +1,19 @@
# 正式测试数据核对
本次汇总 `Jammers-simulator-full/test` 中的 6 份正式导出包。
利用公开头部的案例信息、包哈希及票据哈希,与原始导出、结果侧文件和官方正式统计数据库建立对应关系。
| 案例 | 正式序号 | 原件一致 | 包 SHA-256 |
| --- | --- | --- | --- |
| 9HU7-UWJR-BPTR-VYAT | Q3-1 | 是 | `fbd7ab92f78a019887f603172ab6a39e274adb1f917fc2681f1e8073ff47d911` |
| 7TCG-C9EC-53VF-HZ5H | Q3-2 | 是 | `5d83ce87455ce22fadbcbddb60814d9b1f0be54de7bc9d0463777ba47b3922ef` |
| UVUZ-B4MQ-XSUV-HQFP | Q3-3 | 是 | `eeffe419c3df005d0ea78c7ec2c10afed29c4bec782327538537dd7ba7914424` |
| VQUM-ETQ5-74PP-ZQ3J | Q4-1 | 是 | `9a102295d324b5fb5aeed1c6036d13ae7e08a7d7fddb60ceb8dead24e62b15d3` |
| 5K5T-TRWZ-BPR2-ECAV | Q4-2 | 是 | `370aac9c2c5d324dd382e57e541ef0da7c5dd4759660d9ea0cba8373ce0ea9a1` |
| K58B-V5VC-E4EF-CRTW | Q4-3 | 是 | `1c7f1d111f8fd1a1d0f608d9847c0946b1b0a45bdb7b3f487e0c6d4f4586885f` |
虚拟时间保留官方整数微秒,程序运行时间采用官方毫秒。平均定位清除时间 = 总虚拟秒数 / 清除数。
移动时间由总时长减去检测、换频、成功及失败清除耗时计算。
`confirmed` 表示统计提交确认,`user_exit` 表示主动退出。
实验评价采用清除数量、逐案例平均定位清除时间、程序运行时间和动作耗时分解。
扩展评价所需的源总数与配对场景设计见论文未来工作。
+6
View File
@@ -0,0 +1,6 @@
Q3-1 & 105 & 96 & 0 & 3094.978 & 2408.978 & 77.84\% \\
Q3-2 & 117 & 108 & 0 & 3493.335 & 2725.335 & 78.02\% \\
Q3-3 & 117 & 107 & 0 & 2906.863 & 2164.863 & 74.47\% \\
Q4-1 & 349 & 275 & 0 & 9362.226 & 7277.226 & 77.73\% \\
Q4-2 & 361 & 315 & 0 & 9271.302 & 7101.302 & 76.59\% \\
Q4-3 & 264 & 213 & 0 & 8608.382 & 7005.382 & 81.38\% \\
+19
View File
@@ -0,0 +1,19 @@
% Generated by scripts/build_paper_support.py; 本文件是完整 table 环境,供附录直接 \input。
\begin{table}[htbp]
\centering\small
\caption{六次正式测试的动作计数与移动耗时}
\setlength{\tabcolsep}{4.5pt}
\begin{tabular}{lrrrrrr}
\toprule
案例 & 检测数 & 换频数 & 失败清除 & 总虚拟时间/s & 移动时间/s & 移动占比\\
\midrule
Q3-1 & 105 & 96 & 0 & 3094.978 & 2408.978 & 77.8\% \\
Q3-2 & 117 & 108 & 0 & 3493.335 & 2725.335 & 78.0\% \\
Q3-3 & 117 & 107 & 0 & 2906.863 & 2164.863 & 74.5\% \\
Q4-1 & 349 & 275 & 0 & 9362.226 & 7277.226 & 77.7\% \\
Q4-2 & 361 & 315 & 0 & 9271.302 & 7101.302 & 76.6\% \\
Q4-3 & 264 & 213 & 0 & 8608.382 & 7005.382 & 81.4\% \\
\bottomrule
\end{tabular}
\label{tab:formalcost}
\end{table}
+17
View File
@@ -0,0 +1,17 @@
\begin{longtable}{p{1.15cm}p{13.3cm}}
\caption{所选正式导出文件与完整包哈希}\label{tab:packages}\\
\toprule 案例 & 原始文件名及 SHA-256\\\midrule\endfirsthead
\toprule 案例 & 原始文件名与 SHA-256\\\midrule\endhead
Q3-1 & \pathtext{formal-p3-1-9HU7-UWJR-BPTR-VYAT.jlog}\\
& {\scriptsize\texttt{fbd7ab92f78a019887f603172ab6a39e}\allowbreak\texttt{274adb1f917fc2681f1e8073ff47d911}}\\[4pt]
Q3-2 & \pathtext{formal-p3-2-7TCG-C9EC-53VF-HZ5H.jlog}\\
& {\scriptsize\texttt{5d83ce87455ce22fadbcbddb60814d9b}\allowbreak\texttt{1f0be54de7bc9d0463777ba47b3922ef}}\\[4pt]
Q3-3 & \pathtext{formal-p3-3-UVUZ-B4MQ-XSUV-HQFP.jlog}\\
& {\scriptsize\texttt{eeffe419c3df005d0ea78c7ec2c10afe}\allowbreak\texttt{d29c4bec782327538537dd7ba7914424}}\\[4pt]
Q4-1 & \pathtext{formal-p4-1-VQUM-ETQ5-74PP-ZQ3J.jlog}\\
& {\scriptsize\texttt{9a102295d324b5fb5aeed1c6036d13ae}\allowbreak\texttt{7e08a7d7fddb60ceb8dead24e62b15d3}}\\[4pt]
Q4-2 & \pathtext{formal-p4-2-5K5T-TRWZ-BPR2-ECAV.jlog}\\
& {\scriptsize\texttt{370aac9c2c5d324dd382e57e541ef0da}\allowbreak\texttt{7c5dd4759660d9ea0cba8373ce0ea9a1}}\\[4pt]
Q4-3 & \pathtext{formal-p4-3-K58B-V5VC-E4EF-CRTW.jlog}\\
& {\scriptsize\texttt{1c7f1d111f8fd1a1d0f608d9847c0946}\allowbreak\texttt{b1b0a45bdb7b3f487e0c6d4f4586885f}}\\[4pt]
\bottomrule\end{longtable}
+16
View File
@@ -0,0 +1,16 @@
\newcommand{\QThreeCount}{38}
\newcommand{\QThreeTotal}{9495.176084}
\newcommand{\QThreeWeighted}{249.873}
\newcommand{\QThreeMean}{253.884}
\newcommand{\QThreeProgramTotal}{11.300}
\newcommand{\QFourCount}{37}
\newcommand{\QFourTotal}{27241.909918}
\newcommand{\QFourWeighted}{736.268}
\newcommand{\QFourMean}{754.062}
\newcommand{\QFourProgramTotal}{19.443}
\newcommand{\FormalClearCount}{75}
\newcommand{\FormalMovementMin}{74.47}
\newcommand{\FormalMovementMax}{81.38}
\newcommand{\FormalRunMin}{2.680}
\newcommand{\FormalRunMax}{7.668}
\newcommand{\FormalVirtualTotal}{36737.086002}
+4
View File
@@ -0,0 +1,4 @@
% Generated by scripts/audit_paper_formal.py; seconds; half-up rounding.
测试 1 & \texttt{9HU7-UWJR-BPTR-VYAT} & 13 & 238.075 & 5.596 \\
测试 2 & \texttt{7TCG-C9EC-53VF-HZ5H} & 15 & 232.889 & 3.024 \\
测试 3 & \texttt{UVUZ-B4MQ-XSUV-HQFP} & 10 & 290.686 & 2.680 \\
+16
View File
@@ -0,0 +1,16 @@
% Generated by scripts/build_paper_support.py; 本文件是完整 table 环境,供附录直接 \input。
\begin{table}[htbp]
\centering\small
\caption{问题三正式测试结果(时间单位:s)}
\setlength{\tabcolsep}{4pt}
\begin{tabularx}{\linewidth}{l X r r r}
\toprule
测试 & 测试案例编码 & 清除数 & 总虚拟时间/s & 程序运行时间/s\\
\midrule
测试 1 & \texttt{9HU7-UWJR-BPTR-VYAT} & 13 & 3094.978 & 5.596 \\
测试 2 & \texttt{7TCG-C9EC-53VF-HZ5H} & 15 & 3493.335 & 3.024 \\
测试 3 & \texttt{UVUZ-B4MQ-XSUV-HQFP} & 10 & 2906.863 & 2.680 \\
\bottomrule
\end{tabularx}
\label{tab:formal3}
\end{table}
+4
View File
@@ -0,0 +1,4 @@
% Generated by scripts/audit_paper_formal.py; seconds; half-up rounding.
测试 1 & \texttt{VQUM-ETQ5-74PP-ZQ3J} & 13 & 720.171 & 7.668 \\
测试 2 & \texttt{5K5T-TRWZ-BPR2-ECAV} & 10 & 927.130 & 5.724 \\
测试 3 & \texttt{K58B-V5VC-E4EF-CRTW} & 14 & 614.884 & 6.051 \\
+16
View File
@@ -0,0 +1,16 @@
% Generated by scripts/build_paper_support.py; 本文件是完整 table 环境,供附录直接 \input。
\begin{table}[htbp]
\centering\small
\caption{问题四正式测试结果(时间单位:s)}
\setlength{\tabcolsep}{4pt}
\begin{tabularx}{\linewidth}{l X r r r}
\toprule
测试 & 测试案例编码 & 清除数 & 总虚拟时间/s & 程序运行时间/s\\
\midrule
测试 1 & \texttt{VQUM-ETQ5-74PP-ZQ3J} & 13 & 9362.226 & 7.668 \\
测试 2 & \texttt{5K5T-TRWZ-BPR2-ECAV} & 10 & 9271.302 & 5.724 \\
测试 3 & \texttt{K58B-V5VC-E4EF-CRTW} & 14 & 8608.382 & 6.051 \\
\bottomrule
\end{tabularx}
\label{tab:formal4}
\end{table}
+7
View File
@@ -0,0 +1,7 @@
problem_no,formal_index,case_code,entered,end_reason,cleared_jammer_count,measure_accepted_count,virtual_time_us,program_run_duration_ms,channel_switch_count,clear_failure_count,state,package_sha256,virtual_time_s,average_clear_time_s,program_run_duration_s,inferred_movement_time_s,inferred_distance_m,movement_share_percent,source_total,clear_fraction
3,1,9HU7-UWJR-BPTR-VYAT,1,user_exit,13,105,3094978068,5596,96,0,confirmed,fbd7ab92f78a019887f603172ab6a39e274adb1f917fc2681f1e8073ff47d911,3094.978068,238.075236,5.596,2408.978068,12044.890340,77.835061,,
3,2,7TCG-C9EC-53VF-HZ5H,1,user_exit,15,117,3493335140,3024,108,0,confirmed,5d83ce87455ce22fadbcbddb60814d9b1f0be54de7bc9d0463777ba47b3922ef,3493.33514,232.889009,3.024,2725.33514,13626.67570,78.015279,,
3,3,UVUZ-B4MQ-XSUV-HQFP,1,user_exit,10,117,2906862876,2680,107,0,confirmed,eeffe419c3df005d0ea78c7ec2c10afed29c4bec782327538537dd7ba7914424,2906.862876,290.686288,2.680,2164.862876,10824.314380,74.474200,,
4,1,VQUM-ETQ5-74PP-ZQ3J,1,user_exit,13,349,9362225736,7668,275,0,confirmed,9a102295d324b5fb5aeed1c6036d13ae7e08a7d7fddb60ceb8dead24e62b15d3,9362.225736,720.171210,7.668,7277.225736,36386.128680,77.729655,,
4,2,5K5T-TRWZ-BPR2-ECAV,1,user_exit,10,361,9271302080,5724,315,0,confirmed,370aac9c2c5d324dd382e57e541ef0da7c5dd4759660d9ea0cba8373ce0ea9a1,9271.30208,927.130208,5.724,7101.30208,35506.51040,76.594442,,
4,3,K58B-V5VC-E4EF-CRTW,1,user_exit,14,264,8608382102,6051,213,0,confirmed,1c7f1d111f8fd1a1d0f608d9847c0946b1b0a45bdb7b3f487e0c6d4f4586885f,8608.382102,614.884436,6.051,7005.382102,35026.910510,81.378615,,
1 problem_no formal_index case_code entered end_reason cleared_jammer_count measure_accepted_count virtual_time_us program_run_duration_ms channel_switch_count clear_failure_count state package_sha256 virtual_time_s average_clear_time_s program_run_duration_s inferred_movement_time_s inferred_distance_m movement_share_percent source_total clear_fraction
2 3 1 9HU7-UWJR-BPTR-VYAT 1 user_exit 13 105 3094978068 5596 96 0 confirmed fbd7ab92f78a019887f603172ab6a39e274adb1f917fc2681f1e8073ff47d911 3094.978068 238.075236 5.596 2408.978068 12044.890340 77.835061
3 3 2 7TCG-C9EC-53VF-HZ5H 1 user_exit 15 117 3493335140 3024 108 0 confirmed 5d83ce87455ce22fadbcbddb60814d9b1f0be54de7bc9d0463777ba47b3922ef 3493.33514 232.889009 3.024 2725.33514 13626.67570 78.015279
4 3 3 UVUZ-B4MQ-XSUV-HQFP 1 user_exit 10 117 2906862876 2680 107 0 confirmed eeffe419c3df005d0ea78c7ec2c10afed29c4bec782327538537dd7ba7914424 2906.862876 290.686288 2.680 2164.862876 10824.314380 74.474200
5 4 1 VQUM-ETQ5-74PP-ZQ3J 1 user_exit 13 349 9362225736 7668 275 0 confirmed 9a102295d324b5fb5aeed1c6036d13ae7e08a7d7fddb60ceb8dead24e62b15d3 9362.225736 720.171210 7.668 7277.225736 36386.128680 77.729655
6 4 2 5K5T-TRWZ-BPR2-ECAV 1 user_exit 10 361 9271302080 5724 315 0 confirmed 370aac9c2c5d324dd382e57e541ef0da7c5dd4759660d9ea0cba8373ce0ea9a1 9271.30208 927.130208 5.724 7101.30208 35506.51040 76.594442
7 4 3 K58B-V5VC-E4EF-CRTW 1 user_exit 14 264 8608382102 6051 213 0 confirmed 1c7f1d111f8fd1a1d0f608d9847c0946b1b0a45bdb7b3f487e0c6d4f4586885f 8608.382102 614.884436 6.051 7005.382102 35026.910510 81.378615
+228
View File
@@ -0,0 +1,228 @@
{
"schema": "paper-formal-audit-v1",
"selection": "Only Jammers-simulator-full/test/**/*.jlog",
"statistics_source": "Official formal-statistics-queue.sqlite3; matched by SHA-256 of the public activation ticket",
"coverage": {
"3": [
1,
2,
3
],
"4": [
1,
2,
3
]
},
"measurement_scope": "Per-case official action counts, virtual duration and program duration",
"limitations": [
"Source totals, source types, solver commit and trajectories require additional evidence.",
"Queue state confirmed records a statistics submission acknowledgement."
],
"records": [
{
"problem_no": 3,
"formal_index": 1,
"case_code": "9HU7-UWJR-BPTR-VYAT",
"client_version": "1.1.0",
"entered": 1,
"end_reason": "user_exit",
"cleared_jammer_count": 13,
"measure_accepted_count": 105,
"virtual_time_us": 3094978068,
"program_run_duration_ms": 5596,
"channel_switch_count": 96,
"clear_failure_count": 0,
"state": "confirmed",
"file": "test/q3/formal-p3-1-9HU7-UWJR-BPTR-VYAT.jlog",
"size_bytes": 106656,
"package_sha256": "fbd7ab92f78a019887f603172ab6a39e274adb1f917fc2681f1e8073ff47d911",
"activation_ticket_sha256": "41563c714553abf202fc0012fcde2503c64c6cec27a84c7229c487602b957516",
"created_at_utc": "2026-09-12T07:16:06.377Z",
"ended_at_utc": "2026-09-12T07:16:06.373Z",
"content_encryption": "aes-256-gcm-chunked",
"identity_and_ticket_content_omitted": true,
"same_as_official_original": true,
"derived": {
"virtual_time_s": "3094.978068",
"average_clear_time_s": "238.075236",
"program_run_duration_s": "5.596",
"inferred_movement_time_s": "2408.978068",
"inferred_distance_m": "12044.890340",
"movement_share_percent": "77.835061",
"source_total": null,
"clear_fraction": null
}
},
{
"problem_no": 3,
"formal_index": 2,
"case_code": "7TCG-C9EC-53VF-HZ5H",
"client_version": "1.1.0",
"entered": 1,
"end_reason": "user_exit",
"cleared_jammer_count": 15,
"measure_accepted_count": 117,
"virtual_time_us": 3493335140,
"program_run_duration_ms": 3024,
"channel_switch_count": 108,
"clear_failure_count": 0,
"state": "confirmed",
"file": "test/q3/formal-p3-2-7TCG-C9EC-53VF-HZ5H.jlog",
"size_bytes": 106326,
"package_sha256": "5d83ce87455ce22fadbcbddb60814d9b1f0be54de7bc9d0463777ba47b3922ef",
"activation_ticket_sha256": "5f6d5ff4a369418f9f683ef0384398190bfb0b81bc71ce1c1bd6f728ff1fdf41",
"created_at_utc": "2026-09-12T07:47:20.065Z",
"ended_at_utc": "2026-09-12T07:47:20.061Z",
"content_encryption": "aes-256-gcm-chunked",
"identity_and_ticket_content_omitted": true,
"same_as_official_original": true,
"derived": {
"virtual_time_s": "3493.33514",
"average_clear_time_s": "232.889009",
"program_run_duration_s": "3.024",
"inferred_movement_time_s": "2725.33514",
"inferred_distance_m": "13626.67570",
"movement_share_percent": "78.015279",
"source_total": null,
"clear_fraction": null
}
},
{
"problem_no": 3,
"formal_index": 3,
"case_code": "UVUZ-B4MQ-XSUV-HQFP",
"client_version": "1.1.0",
"entered": 1,
"end_reason": "user_exit",
"cleared_jammer_count": 10,
"measure_accepted_count": 117,
"virtual_time_us": 2906862876,
"program_run_duration_ms": 2680,
"channel_switch_count": 107,
"clear_failure_count": 0,
"state": "confirmed",
"file": "test/q3/formal-p3-3-UVUZ-B4MQ-XSUV-HQFP.jlog",
"size_bytes": 107396,
"package_sha256": "eeffe419c3df005d0ea78c7ec2c10afed29c4bec782327538537dd7ba7914424",
"activation_ticket_sha256": "0134f356b107b6706dfaba48fd00b86c5e3a4fa7ef295d17bbd4080111d112b3",
"created_at_utc": "2026-09-13T02:32:31.689Z",
"ended_at_utc": "2026-09-13T02:32:31.686Z",
"content_encryption": "aes-256-gcm-chunked",
"identity_and_ticket_content_omitted": true,
"same_as_official_original": true,
"derived": {
"virtual_time_s": "2906.862876",
"average_clear_time_s": "290.686288",
"program_run_duration_s": "2.680",
"inferred_movement_time_s": "2164.862876",
"inferred_distance_m": "10824.314380",
"movement_share_percent": "74.474200",
"source_total": null,
"clear_fraction": null
}
},
{
"problem_no": 4,
"formal_index": 1,
"case_code": "VQUM-ETQ5-74PP-ZQ3J",
"client_version": "1.1.0",
"entered": 1,
"end_reason": "user_exit",
"cleared_jammer_count": 13,
"measure_accepted_count": 349,
"virtual_time_us": 9362225736,
"program_run_duration_ms": 7668,
"channel_switch_count": 275,
"clear_failure_count": 0,
"state": "confirmed",
"file": "test/q4/formal-p4-1-VQUM-ETQ5-74PP-ZQ3J.jlog",
"size_bytes": 150315,
"package_sha256": "9a102295d324b5fb5aeed1c6036d13ae7e08a7d7fddb60ceb8dead24e62b15d3",
"activation_ticket_sha256": "d02cfdf2eed65dbe3bb4c7768a263f8bf57b56bc323b6453c1dfa2aec6e24810",
"created_at_utc": "2026-09-12T07:38:51.368Z",
"ended_at_utc": "2026-09-12T07:38:51.365Z",
"content_encryption": "aes-256-gcm-chunked",
"identity_and_ticket_content_omitted": true,
"same_as_official_original": true,
"derived": {
"virtual_time_s": "9362.225736",
"average_clear_time_s": "720.171210",
"program_run_duration_s": "7.668",
"inferred_movement_time_s": "7277.225736",
"inferred_distance_m": "36386.128680",
"movement_share_percent": "77.729655",
"source_total": null,
"clear_fraction": null
}
},
{
"problem_no": 4,
"formal_index": 2,
"case_code": "5K5T-TRWZ-BPR2-ECAV",
"client_version": "1.1.0",
"entered": 1,
"end_reason": "user_exit",
"cleared_jammer_count": 10,
"measure_accepted_count": 361,
"virtual_time_us": 9271302080,
"program_run_duration_ms": 5724,
"channel_switch_count": 315,
"clear_failure_count": 0,
"state": "confirmed",
"file": "test/q4/formal-p4-2-5K5T-TRWZ-BPR2-ECAV.jlog",
"size_bytes": 151668,
"package_sha256": "370aac9c2c5d324dd382e57e541ef0da7c5dd4759660d9ea0cba8373ce0ea9a1",
"activation_ticket_sha256": "4918e4ca6a77367dd06cd40afb28d4415246ef0437c68c052bddf613f4f914b0",
"created_at_utc": "2026-09-12T07:42:29.854Z",
"ended_at_utc": "2026-09-12T07:42:29.851Z",
"content_encryption": "aes-256-gcm-chunked",
"identity_and_ticket_content_omitted": true,
"same_as_official_original": true,
"derived": {
"virtual_time_s": "9271.30208",
"average_clear_time_s": "927.130208",
"program_run_duration_s": "5.724",
"inferred_movement_time_s": "7101.30208",
"inferred_distance_m": "35506.51040",
"movement_share_percent": "76.594442",
"source_total": null,
"clear_fraction": null
}
},
{
"problem_no": 4,
"formal_index": 3,
"case_code": "K58B-V5VC-E4EF-CRTW",
"client_version": "1.1.0",
"entered": 1,
"end_reason": "user_exit",
"cleared_jammer_count": 14,
"measure_accepted_count": 264,
"virtual_time_us": 8608382102,
"program_run_duration_ms": 6051,
"channel_switch_count": 213,
"clear_failure_count": 0,
"state": "confirmed",
"file": "test/q4/formal-p4-3-K58B-V5VC-E4EF-CRTW.jlog",
"size_bytes": 140251,
"package_sha256": "1c7f1d111f8fd1a1d0f608d9847c0946b1b0a45bdb7b3f487e0c6d4f4586885f",
"activation_ticket_sha256": "9cdd910c14e58fca08e3769f880a6b543de2bbdd21479094dc9cd2df725f0036",
"created_at_utc": "2026-09-13T02:34:32.695Z",
"ended_at_utc": "2026-09-13T02:34:32.692Z",
"content_encryption": "aes-256-gcm-chunked",
"identity_and_ticket_content_omitted": true,
"same_as_official_original": true,
"derived": {
"virtual_time_s": "8608.382102",
"average_clear_time_s": "614.884436",
"program_run_duration_s": "6.051",
"inferred_movement_time_s": "7005.382102",
"inferred_distance_m": "35026.910510",
"movement_share_percent": "81.378615",
"source_total": null,
"clear_fraction": null
}
}
]
}
+57
View File
@@ -0,0 +1,57 @@
% Generated by scripts/build_practice_data.py; 自建模拟器演练局复算结果。 本文件是完整 table 环境,供正文直接 \input。
\begin{table}[H]
\centering\footnotesize
\caption{全部演练局的逐局复算结果(“全清”列为是否达到该局源数且无失败清除)}
\setlength{\tabcolsep}{2pt}
\begin{tabular}{lrrrrrrrrl}
\toprule
案例编码 & 问题 & 源数 & 清除数 & 失败清除 & 总虚拟时间/s & 检测数 & 换频数 & 移动/km & 全清\\
\midrule
\texttt{6LST-ZFVS-2HHW-TQQ4} & 3 & 13 & 13 & 0 & 2794.212 & 109 & 99 & 10.426 & 是 \\
\texttt{6V2P-HJCS-GJ9A-83MA} & 3 & 16 & 16 & 0 & 3174.578 & 103 & 88 & 12.458 & 是 \\
\texttt{7ZXN-N53X-HAXQ-EGY4} & 3 & 10 & 10 & 0 & 3228.653 & 119 & 105 & 12.393 & 是 \\
\texttt{8VRC-ADW4-XDXM-F62L} & 3 & 13 & 13 & 0 & 3407.039 & 102 & 93 & 13.695 & 是 \\
\texttt{ARBP-6XFZ-5YJU-STC8} & 3 & 16 & 16 & 0 & 3867.872 & 116 & 105 & 15.514 & 是 \\
\texttt{E27E-M8WQ-LDT5-2XDA} & 3 & 16 & 16 & 0 & 3531.065 & 104 & 89 & 14.210 & 是 \\
\texttt{HGBA-XGH9-UNZJ-7YQ3} & 3 & 10 & 10 & 0 & 3340.025 & 123 & 113 & 12.810 & 是 \\
\texttt{JW47-AVPH-XGHH-RLLV} & 3 & 13 & 13 & 0 & 3389.152 & 106 & 93 & 13.506 & 是 \\
\texttt{LZDX-68DJ-XM4P-A6XL} & 3 & 10 & 10 & 0 & 2954.390 & 117 & 105 & 11.072 & 是 \\
\texttt{MT3R-68KH-CNY5-6X73} & 3 & 13 & 13 & 0 & 3527.713 & 112 & 94 & 14.044 & 是 \\
\texttt{MULB-4YTU-VQYG-YAS6} & 3 & 10 & 10 & 0 & 3064.020 & 129 & 119 & 11.250 & 是 \\
\texttt{NMRC-85ZV-3FFE-GBXY} & 3 & 13 & 13 & 0 & 2860.706 & 101 & 96 & 10.974 & 是 \\
\texttt{QS6H-CC29-PDY3-ZA54} & 3 & 16 & 16 & 0 & 2987.385 & 85 & 74 & 12.042 & 是 \\
\texttt{R2N7-QMLC-26QX-RXYT} & 3 & 16 & 16 & 0 & 3556.397 & 106 & 95 & 14.257 & 是 \\
\texttt{VE37-SRPD-NCFR-4EQF} & 3 & 10 & 10 & 0 & 3240.474 & 124 & 115 & 12.277 & 是 \\
\texttt{2M5J-QWHS-BYGB-MPYF} & 4 & 13 & 13 & 0 & 9191.437 & 343 & 296 & 35.577 & 是 \\
\texttt{2Y25-4LD6-5A4P-64CV} & 4 & 16 & 16 & 0 & 6685.802 & 226 & 182 & 26.469 & 是 \\
\texttt{3XM4-65TW-CH39-XWTZ} & 4 & 16 & 16 & 0 & 7327.981 & 211 & 160 & 30.165 & 是 \\
\texttt{6LEP-YVQ6-AYP5-N359} & 4 & 16 & 16 & 0 & 7982.569 & 280 & 222 & 31.403 & 是 \\
\texttt{6US3-A76N-KC8B-DMFM} & 4 & 10 & 10 & 0 & 8171.259 & 371 & 331 & 29.676 & 是 \\
\texttt{7HG2-UEBM-K3D2-LZWT} & 4 & 10 & 10 & 0 & 8146.581 & 377 & 333 & 29.393 & 是 \\
\texttt{96M4-SK2V-PDWN-YGHB} & 4 & 13 & 13 & 0 & 9593.184 & 364 & 311 & 36.986 & 是 \\
\texttt{A5YU-4SM6-4PK7-M5H8} & 4 & 10 & 10 & 0 & 9854.818 & 382 & 327 & 37.839 & 是 \\
\texttt{B8HR-3HJH-2UYH-YDVB} & 4 & 13 & 13 & 0 & 8840.642 & 371 & 306 & 33.073 & 是 \\
\texttt{CEL3-XQV8-M7KY-3CSW} & 4 & 16 & 16 & 0 & 5806.596 & 184 & 144 & 23.313 & 是 \\
\texttt{DX2D-KDF9-BGYU-XPMG} & 4 & 13 & 13 & 0 & 8642.081 & 314 & 265 & 33.710 & 是 \\
\texttt{GSG4-6HTJ-AH5L-ZYGM} & 4 & 10 & 10 & 0 & 9488.522 & 438 & 379 & 34.348 & 是 \\
\texttt{JDAY-2SU7-RTSJ-NQFR} & 4 & 13 & 13 & 0 & 9813.925 & 351 & 283 & 38.555 & 是 \\
\texttt{JH76-MEWS-BR6Q-BQ6S} & 4 & 13 & 13 & 0 & 8732.841 & 336 & 287 & 33.504 & 是 \\
\texttt{JY84-364B-45UL-AFBK} & 4 & 10 & 10 & 0 & 8704.597 & 436 & 392 & 30.413 & 是 \\
\texttt{QDDJ-S89Y-7TKY-E6VJ} & 4 & 16 & 16 & 0 & 7316.173 & 221 & 169 & 29.811 & 是 \\
\texttt{QL6B-KEUW-DJR2-P84B} & 4 & 16 & 16 & 0 & 5229.931 & 184 & 144 & 20.430 & 是 \\
\texttt{QXVN-L63H-6WLX-KLEJ} & 4 & 10 & 10 & 0 & 9307.231 & 399 & 351 & 34.556 & 是 \\
\texttt{R2E7-LF5E-J5K6-BSVQ} & 4 & 13 & 13 & 0 & 9809.921 & 340 & 283 & 38.810 & 是 \\
\texttt{RLK4-E82Q-UHT6-2M9M} & 4 & 10 & 10 & 0 & 8342.135 & 374 & 328 & 30.471 & 是 \\
\texttt{SE9X-67GA-6YC6-QB7B} & 4 & 10 & 10 & 0 & 9241.603 & 406 & 359 & 34.013 & 是 \\
\texttt{SWA3-C3FB-C5QC-FLW7} & 4 & 16 & 16 & 0 & 4780.432 & 159 & 108 & 18.987 & 是 \\
\texttt{T5ZL-5GEP-FDCK-3P8T} & 4 & 13 & 13 & 0 & 8719.661 & 344 & 285 & 33.248 & 是 \\
\texttt{TKCY-2VT2-WYUX-2JXU} & 4 & 10 & 10 & 0 & 8260.712 & 385 & 342 & 29.719 & 是 \\
\texttt{US79-DFNV-UQVW-NPLL} & 4 & 10 & 10 & 0 & 8795.904 & 408 & 358 & 31.740 & 是 \\
\texttt{VJ68-ADZ6-STFT-LHYT} & 4 & 13 & 13 & 0 & 8783.099 & 369 & 312 & 32.805 & 是 \\
\texttt{X3Y4-S9D2-XWR9-V6CZ} & 4 & 13 & 13 & 0 & 10160.134 & 365 & 304 & 39.831 & 是 \\
\texttt{XN57-MHFY-V58F-XCMY} & 4 & 10 & 10 & 0 & 9188.211 & 438 & 397 & 32.756 & 是 \\
\texttt{ZLKB-GVZT-NQDE-CU5F} & 4 & 10 & 10 & 0 & 8723.919 & 395 & 343 & 31.780 & 是 \\
\bottomrule
\end{tabular}
\label{tab:practiceall}
\end{table}
@@ -0,0 +1,15 @@
% Generated by scripts/build_practice_data.py; 自建模拟器演练局复算结果。 本文件是完整 table 环境,供正文直接 \input。
\begin{table}[htbp]
\centering\small
\caption{演练全清局的动作耗时分解,括号内为占总虚拟时间的比例}
\setlength{\tabcolsep}{3pt}
\begin{tabular}{lrrrrr}
\toprule
问题 & 局数 & 移动/s(占比) & 检测/s(占比) & 换频/s(占比) & 清除/s(占比)\\
\midrule
问题三(全向源) & 15 & 38185.679(78.1\%) & 8280.000(16.9\%) & 1483.000(3.0\%) & 975.000(2.0\%) \\
问题四(混合源) & 29 & 184675.902(75.8\%) & 48855.000(20.1\%) & 8301.000(3.4\%) & 1810.000(0.7\%) \\
\bottomrule
\end{tabular}
\label{tab:cost}
\end{table}
+57
View File
@@ -0,0 +1,57 @@
% Generated by scripts/build_practice_data.py; 自建模拟器演练局复算结果。 本文件是完整 table 环境,供正文直接 \input。
\begin{table}[H]
\centering\footnotesize
\caption{演练局逐局动作耗时分解(时间单位:s)}
\setlength{\tabcolsep}{2pt}
\begin{tabular}{lrrrrrrrrr}
\toprule
编号 & 总虚拟时间 & 移动 & 占比 & 检测 & 占比 & 换频 & 占比 & 清除 & 占比\\
\midrule
Q3-1 & 2794.212 & 2085.212 & 74.6\% & 545.000 & 19.5\% & 99.000 & 3.5\% & 65.000 & 2.3\% \\
Q3-2 & 3174.578 & 2491.578 & 78.5\% & 515.000 & 16.2\% & 88.000 & 2.8\% & 80.000 & 2.5\% \\
Q3-3 & 3228.653 & 2478.653 & 76.8\% & 595.000 & 18.4\% & 105.000 & 3.3\% & 50.000 & 1.5\% \\
Q3-4 & 3407.039 & 2739.039 & 80.4\% & 510.000 & 15.0\% & 93.000 & 2.7\% & 65.000 & 1.9\% \\
Q3-5 & 3867.872 & 3102.872 & 80.2\% & 580.000 & 15.0\% & 105.000 & 2.7\% & 80.000 & 2.1\% \\
Q3-6 & 3531.065 & 2842.065 & 80.5\% & 520.000 & 14.7\% & 89.000 & 2.5\% & 80.000 & 2.3\% \\
Q3-7 & 3340.025 & 2562.025 & 76.7\% & 615.000 & 18.4\% & 113.000 & 3.4\% & 50.000 & 1.5\% \\
Q3-8 & 3389.152 & 2701.152 & 79.7\% & 530.000 & 15.6\% & 93.000 & 2.7\% & 65.000 & 1.9\% \\
Q3-9 & 2954.390 & 2214.390 & 75.0\% & 585.000 & 19.8\% & 105.000 & 3.6\% & 50.000 & 1.7\% \\
Q3-10 & 3527.713 & 2808.713 & 79.6\% & 560.000 & 15.9\% & 94.000 & 2.7\% & 65.000 & 1.8\% \\
Q3-11 & 3064.020 & 2250.020 & 73.4\% & 645.000 & 21.1\% & 119.000 & 3.9\% & 50.000 & 1.6\% \\
Q3-12 & 2860.706 & 2194.706 & 76.7\% & 505.000 & 17.7\% & 96.000 & 3.4\% & 65.000 & 2.3\% \\
Q3-13 & 2987.385 & 2408.385 & 80.6\% & 425.000 & 14.2\% & 74.000 & 2.5\% & 80.000 & 2.7\% \\
Q3-14 & 3556.397 & 2851.397 & 80.2\% & 530.000 & 14.9\% & 95.000 & 2.7\% & 80.000 & 2.2\% \\
Q3-15 & 3240.474 & 2455.474 & 75.8\% & 620.000 & 19.1\% & 115.000 & 3.5\% & 50.000 & 1.5\% \\
Q4-16 & 9191.437 & 7115.437 & 77.4\% & 1715.000 & 18.7\% & 296.000 & 3.2\% & 65.000 & 0.7\% \\
Q4-17 & 6685.802 & 5293.802 & 79.2\% & 1130.000 & 16.9\% & 182.000 & 2.7\% & 80.000 & 1.2\% \\
Q4-18 & 7327.981 & 6032.981 & 82.3\% & 1055.000 & 14.4\% & 160.000 & 2.2\% & 80.000 & 1.1\% \\
Q4-19 & 7982.569 & 6280.569 & 78.7\% & 1400.000 & 17.5\% & 222.000 & 2.8\% & 80.000 & 1.0\% \\
Q4-20 & 8171.259 & 5935.259 & 72.6\% & 1855.000 & 22.7\% & 331.000 & 4.1\% & 50.000 & 0.6\% \\
Q4-21 & 8146.581 & 5878.581 & 72.2\% & 1885.000 & 23.1\% & 333.000 & 4.1\% & 50.000 & 0.6\% \\
Q4-22 & 9593.184 & 7397.184 & 77.1\% & 1820.000 & 19.0\% & 311.000 & 3.2\% & 65.000 & 0.7\% \\
Q4-23 & 9854.818 & 7567.818 & 76.8\% & 1910.000 & 19.4\% & 327.000 & 3.3\% & 50.000 & 0.5\% \\
Q4-24 & 8840.642 & 6614.642 & 74.8\% & 1855.000 & 21.0\% & 306.000 & 3.5\% & 65.000 & 0.7\% \\
Q4-25 & 5806.596 & 4662.596 & 80.3\% & 920.000 & 15.8\% & 144.000 & 2.5\% & 80.000 & 1.4\% \\
Q4-26 & 8642.081 & 6742.081 & 78.0\% & 1570.000 & 18.2\% & 265.000 & 3.1\% & 65.000 & 0.8\% \\
Q4-27 & 9488.522 & 6869.522 & 72.4\% & 2190.000 & 23.1\% & 379.000 & 4.0\% & 50.000 & 0.5\% \\
Q4-28 & 9813.925 & 7710.925 & 78.6\% & 1755.000 & 17.9\% & 283.000 & 2.9\% & 65.000 & 0.7\% \\
Q4-29 & 8732.841 & 6700.841 & 76.7\% & 1680.000 & 19.2\% & 287.000 & 3.3\% & 65.000 & 0.7\% \\
Q4-30 & 8704.597 & 6082.597 & 69.9\% & 2180.000 & 25.0\% & 392.000 & 4.5\% & 50.000 & 0.6\% \\
Q4-31 & 7316.173 & 5962.173 & 81.5\% & 1105.000 & 15.1\% & 169.000 & 2.3\% & 80.000 & 1.1\% \\
Q4-32 & 5229.931 & 4085.931 & 78.1\% & 920.000 & 17.6\% & 144.000 & 2.8\% & 80.000 & 1.5\% \\
Q4-33 & 9307.231 & 6911.231 & 74.3\% & 1995.000 & 21.4\% & 351.000 & 3.8\% & 50.000 & 0.5\% \\
Q4-34 & 9809.921 & 7761.921 & 79.1\% & 1700.000 & 17.3\% & 283.000 & 2.9\% & 65.000 & 0.7\% \\
Q4-35 & 8342.135 & 6094.135 & 73.1\% & 1870.000 & 22.4\% & 328.000 & 3.9\% & 50.000 & 0.6\% \\
Q4-36 & 9241.603 & 6802.603 & 73.6\% & 2030.000 & 22.0\% & 359.000 & 3.9\% & 50.000 & 0.5\% \\
Q4-37 & 4780.432 & 3797.432 & 79.4\% & 795.000 & 16.6\% & 108.000 & 2.3\% & 80.000 & 1.7\% \\
Q4-38 & 8719.661 & 6649.661 & 76.3\% & 1720.000 & 19.7\% & 285.000 & 3.3\% & 65.000 & 0.7\% \\
Q4-39 & 8260.712 & 5943.712 & 72.0\% & 1925.000 & 23.3\% & 342.000 & 4.1\% & 50.000 & 0.6\% \\
Q4-40 & 8795.904 & 6347.904 & 72.2\% & 2040.000 & 23.2\% & 358.000 & 4.1\% & 50.000 & 0.6\% \\
Q4-41 & 8783.099 & 6561.099 & 74.7\% & 1845.000 & 21.0\% & 312.000 & 3.6\% & 65.000 & 0.7\% \\
Q4-42 & 10160.134 & 7966.134 & 78.4\% & 1825.000 & 18.0\% & 304.000 & 3.0\% & 65.000 & 0.6\% \\
Q4-43 & 9188.211 & 6551.211 & 71.3\% & 2190.000 & 23.8\% & 397.000 & 4.3\% & 50.000 & 0.5\% \\
Q4-44 & 8723.919 & 6355.919 & 72.9\% & 1975.000 & 22.6\% & 343.000 & 3.9\% & 50.000 & 0.6\% \\
\bottomrule
\end{tabular}
\label{tab:practicecost}
\end{table}
+57
View File
@@ -0,0 +1,57 @@
% Generated by scripts/build_practice_data.py; 自建模拟器演练局复算结果。 本文件是完整 table 环境,供正文直接 \input。
\begin{table}[H]
\centering\small
\caption{演练局的真值规模与程序运行时间}
\setlength{\tabcolsep}{4pt}
\begin{tabular}{lrrrrrr}
\toprule
案例编码 & 源数 & 接收半径范围/m & 定向源数 & 清除数 & 示向度观测数 & 程序运行时间/s\\
\midrule
\texttt{6LST-ZFVS-2HHW-TQQ4} & 13 & 1025.6--1479.2 & 0 & 13 & 42 & 2.040 \\
\texttt{6V2P-HJCS-GJ9A-83MA} & 16 & 1032.7--1455.4 & 0 & 16 & 55 & 2.361 \\
\texttt{7ZXN-N53X-HAXQ-EGY4} & 10 & 1110.1--1403.3 & 0 & 10 & 34 & 2.086 \\
\texttt{8VRC-ADW4-XDXM-F62L} & 13 & 1017.3--1460.8 & 0 & 13 & 40 & 2.024 \\
\texttt{ARBP-6XFZ-5YJU-STC8} & 16 & 1020.3--1465.0 & 0 & 16 & 50 & 1.952 \\
\texttt{E27E-M8WQ-LDT5-2XDA} & 16 & 1027.5--1464.0 & 0 & 16 & 51 & 2.405 \\
\texttt{HGBA-XGH9-UNZJ-7YQ3} & 10 & 1018.0--1487.3 & 0 & 10 & 35 & 1.997 \\
\texttt{JW47-AVPH-XGHH-RLLV} & 13 & 1018.6--1446.7 & 0 & 13 & 40 & 2.146 \\
\texttt{LZDX-68DJ-XM4P-A6XL} & 10 & 1011.8--1441.2 & 0 & 10 & 30 & 1.784 \\
\texttt{MT3R-68KH-CNY5-6X73} & 13 & 1021.0--1457.9 & 0 & 13 & 44 & 2.150 \\
\texttt{MULB-4YTU-VQYG-YAS6} & 10 & 1016.1--1460.3 & 0 & 10 & 32 & 1.636 \\
\texttt{NMRC-85ZV-3FFE-GBXY} & 13 & 1010.4--1489.9 & 0 & 13 & 39 & 1.858 \\
\texttt{QS6H-CC29-PDY3-ZA54} & 16 & 1026.0--1475.3 & 0 & 16 & 55 & 2.052 \\
\texttt{R2N7-QMLC-26QX-RXYT} & 16 & 1007.2--1491.1 & 0 & 16 & 57 & 1.991 \\
\texttt{VE37-SRPD-NCFR-4EQF} & 10 & 1009.5--1433.1 & 0 & 10 & 34 & 2.106 \\
\texttt{2M5J-QWHS-BYGB-MPYF} & 13 & 1070.6--1495.1 & 6 & 13 & 43 & 5.040 \\
\texttt{2Y25-4LD6-5A4P-64CV} & 16 & 1004.9--1458.7 & 8 & 16 & 57 & 5.260 \\
\texttt{3XM4-65TW-CH39-XWTZ} & 16 & 1004.4--1454.0 & 8 & 16 & 58 & 6.208 \\
\texttt{6LEP-YVQ6-AYP5-N359} & 16 & 1008.9--1463.6 & 8 & 16 & 61 & 5.584 \\
\texttt{6US3-A76N-KC8B-DMFM} & 10 & 1008.3--1464.1 & 3 & 10 & 30 & 3.814 \\
\texttt{7HG2-UEBM-K3D2-LZWT} & 10 & 1114.6--1481.9 & 3 & 10 & 37 & 4.436 \\
\texttt{96M4-SK2V-PDWN-YGHB} & 13 & 1020.4--1492.3 & 6 & 13 & 51 & 4.853 \\
\texttt{A5YU-4SM6-4PK7-M5H8} & 10 & 1139.5--1478.2 & 3 & 10 & 43 & 4.675 \\
\texttt{B8HR-3HJH-2UYH-YDVB} & 13 & 1012.1--1489.1 & 6 & 13 & 58 & 5.794 \\
\texttt{CEL3-XQV8-M7KY-3CSW} & 16 & 1045.9--1497.6 & 8 & 16 & 54 & 5.568 \\
\texttt{DX2D-KDF9-BGYU-XPMG} & 13 & 1023.5--1360.2 & 6 & 13 & 49 & 5.272 \\
\texttt{GSG4-6HTJ-AH5L-ZYGM} & 10 & 1001.6--1484.7 & 3 & 10 & 48 & 5.235 \\
\texttt{JDAY-2SU7-RTSJ-NQFR} & 13 & 1018.3--1401.1 & 6 & 13 & 63 & 5.774 \\
\texttt{JH76-MEWS-BR6Q-BQ6S} & 13 & 1042.8--1495.8 & 6 & 13 & 45 & 5.772 \\
\texttt{JY84-364B-45UL-AFBK} & 10 & 1003.1--1498.9 & 3 & 10 & 38 & 13.713 \\
\texttt{QDDJ-S89Y-7TKY-E6VJ} & 16 & 1018.9--1422.8 & 8 & 16 & 59 & 5.495 \\
\texttt{QL6B-KEUW-DJR2-P84B} & 16 & 1001.7--1490.9 & 8 & 16 & 60 & 5.873 \\
\texttt{QXVN-L63H-6WLX-KLEJ} & 10 & 1030.0--1485.5 & 3 & 10 & 38 & 4.514 \\
\texttt{R2E7-LF5E-J5K6-BSVQ} & 13 & 1055.1--1474.8 & 6 & 13 & 56 & 5.223 \\
\texttt{RLK4-E82Q-UHT6-2M9M} & 10 & 1052.3--1496.4 & 3 & 10 & 36 & 4.395 \\
\texttt{SE9X-67GA-6YC6-QB7B} & 10 & 1040.8--1476.5 & 3 & 10 & 39 & 4.463 \\
\texttt{SWA3-C3FB-C5QC-FLW7} & 16 & 1025.8--1458.5 & 8 & 16 & 72 & 6.598 \\
\texttt{T5ZL-5GEP-FDCK-3P8T} & 13 & 1032.4--1491.3 & 6 & 13 & 56 & 5.763 \\
\texttt{TKCY-2VT2-WYUX-2JXU} & 10 & 1032.2--1492.3 & 3 & 10 & 35 & 5.028 \\
\texttt{US79-DFNV-UQVW-NPLL} & 10 & 1107.6--1451.4 & 3 & 10 & 40 & 4.565 \\
\texttt{VJ68-ADZ6-STFT-LHYT} & 13 & 1016.6--1491.9 & 6 & 13 & 58 & 5.691 \\
\texttt{X3Y4-S9D2-XWR9-V6CZ} & 13 & 1022.1--1395.5 & 6 & 13 & 55 & 6.694 \\
\texttt{XN57-MHFY-V58F-XCMY} & 10 & 1022.1--1499.2 & 3 & 10 & 31 & 4.568 \\
\texttt{ZLKB-GVZT-NQDE-CU5F} & 10 & 1099.5--1417.7 & 3 & 10 & 45 & 4.398 \\
\bottomrule
\end{tabular}
\label{tab:practicedetail}
\end{table}
@@ -0,0 +1,7 @@
% Generated by scripts/build_practice_data.py; 问题一交会算例复算值。
\newcommand{\ExOneChannel}{12}
\newcommand{\ExOneVertices}{5}
\newcommand{\ExOneDiameter}{22.187}
\newcommand{\ExOneRadius}{11.094}
\newcommand{\ExOneExceed}{4.140}
\newcommand{\ExOneMec}{11.677}
+57
View File
@@ -0,0 +1,57 @@
{
"case_code": "8VRC-ADW4-XDXM-F62L",
"channel": 12,
"half_angle_deg": 1.0,
"measurements": [
{
"x": 579.8500000000001,
"y": -1004.3296607688135,
"bearing_deg": 269.75
},
{
"x": 115.54237972985288,
"y": -1240.6286932057417,
"bearing_deg": 324.35
},
{
"x": 186.45417332320125,
"y": -1758.222760355536,
"bearing_deg": 26.5
}
],
"vertices": [
[
567.3643714616223,
-1576.537915688301
],
[
587.2166596490906,
-1567.0688599548057
],
[
587.2107677439651,
-1566.6187772674052
],
[
573.1672250497825,
-1556.9126876083646
],
[
567.7308446306516,
-1559.7426881288288
]
],
"diameter_circle_centre": [
577.2875696027937,
-1571.578346477853
],
"diameter_m": 22.18713033289069,
"diameter_circle_radius_m": 11.093565166445345,
"exceed_m": 4.1399107767441805,
"mec_centre": [
575.6576957672258,
-1568.3172646521614
],
"mec_radius_m": 11.677257019347309,
"vertex_count": 5
}
+54
View File
@@ -0,0 +1,54 @@
% Generated by scripts/build_practice_data.py; 自建模拟器演练局统计。
\newcommand{\PractQThreeCases}{15}
\newcommand{\PractQFourCases}{29}
\newcommand{\PractTotalCases}{44}
\newcommand{\PractQThreeComplete}{15}
\newcommand{\PractQFourComplete}{29}
\newcommand{\PractTotalComplete}{44}
\newcommand{\PractQThreeSources}{195}
\newcommand{\PractQFourSources}{362}
\newcommand{\PractTotalSources}{557}
\newcommand{\PractQThreeCleared}{195}
\newcommand{\PractQFourCleared}{362}
\newcommand{\PractTotalCleared}{557}
\newcommand{\PractTotalFailures}{0}
\newcommand{\PractQThreeMean}{3261.579}
\newcommand{\PractQFourMean}{8401.445}
\newcommand{\PractQThreeMin}{2794.212}
\newcommand{\PractQThreeMax}{3867.872}
\newcommand{\PractQFourMin}{4780.432}
\newcommand{\PractQFourMax}{10160.134}
\newcommand{\PractQThreeMeanClear}{258.782}
\newcommand{\PractQFourMeanClear}{708.350}
\newcommand{\PractQThreeMove}{12.729}
\newcommand{\PractQFourMove}{31.841}
\newcommand{\PractQThreeRun}{2.039}
\newcommand{\PractQFourRun}{5.526}
\newcommand{\PractQThreeMeasures}{110.4}
\newcommand{\PractQFourMeasures}{336.9}
\newcommand{\PractQThreeSwitches}{98.9}
\newcommand{\PractQFourSwitches}{286.2}
\newcommand{\PractMaxGap}{0.000000}
\newcommand{\PractQThreeMoveShare}{78.1\%}
\newcommand{\PractQThreeMeasureShare}{16.9\%}
\newcommand{\PractQThreeSwitchShare}{3.0\%}
\newcommand{\PractQThreeClearShare}{2.0\%}
\newcommand{\PractQFourMoveShare}{75.8\%}
\newcommand{\PractQFourMeasureShare}{20.1\%}
\newcommand{\PractQFourSwitchShare}{3.4\%}
\newcommand{\PractQFourClearShare}{0.7\%}
\newcommand{\PractQThreeMainCase}{QS6H-CC29-PDY3-ZA54}
\newcommand{\PractQThreeMainSources}{16}
\newcommand{\PractQThreeMainTime}{2987.385}
\newcommand{\PractQThreeMainMove}{12.042}
\newcommand{\PractQThreeMainMeasures}{85}
\newcommand{\PractQThreeMainSwitches}{74}
\newcommand{\PractQThreeMainRun}{2.052}
\newcommand{\PractQFourMainCase}{SWA3-C3FB-C5QC-FLW7}
\newcommand{\PractQFourMainSources}{16}
\newcommand{\PractQFourMainDirectional}{8}
\newcommand{\PractQFourMainTime}{4780.432}
\newcommand{\PractQFourMainMove}{18.987}
\newcommand{\PractQFourMainMeasures}{159}
\newcommand{\PractQFourMainSwitches}{108}
\newcommand{\PractQFourMainRun}{6.598}
+28
View File
@@ -0,0 +1,28 @@
% Generated by scripts/build_practice_data.py; 自建模拟器演练局复算结果。 本文件是完整 table 环境,供正文直接 \input。
\begin{table}[htbp]
\centering\small
\caption{问题三:全向源演练局结果(按总虚拟时间升序)}
\setlength{\tabcolsep}{2pt}
\begin{tabular}{lrrrrrrrr}
\toprule
序号 & 案例编码 & 源数 & 清除数 & 总虚拟时间/s & 移动/km & 检测数 & 换频数 & 平均清除/(s/个)\\
\midrule
1 & \texttt{6LST-ZFVS-2HHW-TQQ4} & 13 & 13 & 2794.212 & 10.426 & 109 & 99 & 214.939 \\
2 & \texttt{NMRC-85ZV-3FFE-GBXY} & 13 & 13 & 2860.706 & 10.974 & 101 & 96 & 220.054 \\
3 & \texttt{LZDX-68DJ-XM4P-A6XL} & 10 & 10 & 2954.390 & 11.072 & 117 & 105 & 295.439 \\
4 & \texttt{QS6H-CC29-PDY3-ZA54} & 16 & 16 & 2987.385 & 12.042 & 85 & 74 & 186.712 \\
5 & \texttt{MULB-4YTU-VQYG-YAS6} & 10 & 10 & 3064.020 & 11.250 & 129 & 119 & 306.402 \\
6 & \texttt{6V2P-HJCS-GJ9A-83MA} & 16 & 16 & 3174.578 & 12.458 & 103 & 88 & 198.411 \\
7 & \texttt{7ZXN-N53X-HAXQ-EGY4} & 10 & 10 & 3228.653 & 12.393 & 119 & 105 & 322.865 \\
8 & \texttt{VE37-SRPD-NCFR-4EQF} & 10 & 10 & 3240.474 & 12.277 & 124 & 115 & 324.047 \\
9 & \texttt{HGBA-XGH9-UNZJ-7YQ3} & 10 & 10 & 3340.025 & 12.810 & 123 & 113 & 334.003 \\
10 & \texttt{JW47-AVPH-XGHH-RLLV} & 13 & 13 & 3389.152 & 13.506 & 106 & 93 & 260.704 \\
11 & \texttt{8VRC-ADW4-XDXM-F62L} & 13 & 13 & 3407.039 & 13.695 & 102 & 93 & 262.080 \\
12 & \texttt{MT3R-68KH-CNY5-6X73} & 13 & 13 & 3527.713 & 14.044 & 112 & 94 & 271.363 \\
13 & \texttt{E27E-M8WQ-LDT5-2XDA} & 16 & 16 & 3531.065 & 14.210 & 104 & 89 & 220.692 \\
14 & \texttt{R2N7-QMLC-26QX-RXYT} & 16 & 16 & 3556.397 & 14.257 & 106 & 95 & 222.275 \\
15 & \texttt{ARBP-6XFZ-5YJU-STC8} & 16 & 16 & 3867.872 & 15.514 & 116 & 105 & 241.742 \\
\bottomrule
\end{tabular}
\label{tab:q3practice}
\end{table}
+42
View File
@@ -0,0 +1,42 @@
% Generated by scripts/build_practice_data.py; 自建模拟器演练局复算结果。 本文件是完整 table 环境,供正文直接 \input。
\begin{table}[htbp]
\centering\small
\caption{问题四:混合源演练局结果(按总虚拟时间升序)}
\setlength{\tabcolsep}{2pt}
\begin{tabular}{lrrrrrrrr}
\toprule
序号 & 案例编码 & 源数 & 清除数 & 总虚拟时间/s & 移动/km & 检测数 & 换频数 & 平均清除/(s/个)\\
\midrule
1 & \texttt{SWA3-C3FB-C5QC-FLW7} & 16 & 16 & 4780.432 & 18.987 & 159 & 108 & 298.777 \\
2 & \texttt{QL6B-KEUW-DJR2-P84B} & 16 & 16 & 5229.931 & 20.430 & 184 & 144 & 326.871 \\
3 & \texttt{CEL3-XQV8-M7KY-3CSW} & 16 & 16 & 5806.596 & 23.313 & 184 & 144 & 362.912 \\
4 & \texttt{2Y25-4LD6-5A4P-64CV} & 16 & 16 & 6685.802 & 26.469 & 226 & 182 & 417.863 \\
5 & \texttt{QDDJ-S89Y-7TKY-E6VJ} & 16 & 16 & 7316.173 & 29.811 & 221 & 169 & 457.261 \\
6 & \texttt{3XM4-65TW-CH39-XWTZ} & 16 & 16 & 7327.981 & 30.165 & 211 & 160 & 457.999 \\
7 & \texttt{6LEP-YVQ6-AYP5-N359} & 16 & 16 & 7982.569 & 31.403 & 280 & 222 & 498.911 \\
8 & \texttt{7HG2-UEBM-K3D2-LZWT} & 10 & 10 & 8146.581 & 29.393 & 377 & 333 & 814.658 \\
9 & \texttt{6US3-A76N-KC8B-DMFM} & 10 & 10 & 8171.259 & 29.676 & 371 & 331 & 817.126 \\
10 & \texttt{TKCY-2VT2-WYUX-2JXU} & 10 & 10 & 8260.712 & 29.719 & 385 & 342 & 826.071 \\
11 & \texttt{RLK4-E82Q-UHT6-2M9M} & 10 & 10 & 8342.135 & 30.471 & 374 & 328 & 834.214 \\
12 & \texttt{DX2D-KDF9-BGYU-XPMG} & 13 & 13 & 8642.081 & 33.710 & 314 & 265 & 664.775 \\
13 & \texttt{JY84-364B-45UL-AFBK} & 10 & 10 & 8704.597 & 30.413 & 436 & 392 & 870.460 \\
14 & \texttt{T5ZL-5GEP-FDCK-3P8T} & 13 & 13 & 8719.661 & 33.248 & 344 & 285 & 670.743 \\
15 & \texttt{ZLKB-GVZT-NQDE-CU5F} & 10 & 10 & 8723.919 & 31.780 & 395 & 343 & 872.392 \\
16 & \texttt{JH76-MEWS-BR6Q-BQ6S} & 13 & 13 & 8732.841 & 33.504 & 336 & 287 & 671.757 \\
17 & \texttt{VJ68-ADZ6-STFT-LHYT} & 13 & 13 & 8783.099 & 32.805 & 369 & 312 & 675.623 \\
18 & \texttt{US79-DFNV-UQVW-NPLL} & 10 & 10 & 8795.904 & 31.740 & 408 & 358 & 879.590 \\
19 & \texttt{B8HR-3HJH-2UYH-YDVB} & 13 & 13 & 8840.642 & 33.073 & 371 & 306 & 680.049 \\
20 & \texttt{XN57-MHFY-V58F-XCMY} & 10 & 10 & 9188.211 & 32.756 & 438 & 397 & 918.821 \\
21 & \texttt{2M5J-QWHS-BYGB-MPYF} & 13 & 13 & 9191.437 & 35.577 & 343 & 296 & 707.034 \\
22 & \texttt{SE9X-67GA-6YC6-QB7B} & 10 & 10 & 9241.603 & 34.013 & 406 & 359 & 924.160 \\
23 & \texttt{QXVN-L63H-6WLX-KLEJ} & 10 & 10 & 9307.231 & 34.556 & 399 & 351 & 930.723 \\
24 & \texttt{GSG4-6HTJ-AH5L-ZYGM} & 10 & 10 & 9488.522 & 34.348 & 438 & 379 & 948.852 \\
25 & \texttt{96M4-SK2V-PDWN-YGHB} & 13 & 13 & 9593.184 & 36.986 & 364 & 311 & 737.937 \\
26 & \texttt{R2E7-LF5E-J5K6-BSVQ} & 13 & 13 & 9809.921 & 38.810 & 340 & 283 & 754.609 \\
27 & \texttt{JDAY-2SU7-RTSJ-NQFR} & 13 & 13 & 9813.925 & 38.555 & 351 & 283 & 754.917 \\
28 & \texttt{A5YU-4SM6-4PK7-M5H8} & 10 & 10 & 9854.818 & 37.839 & 382 & 327 & 985.482 \\
29 & \texttt{X3Y4-S9D2-XWR9-V6CZ} & 13 & 13 & 10160.134 & 39.831 & 365 & 304 & 781.549 \\
\bottomrule
\end{tabular}
\label{tab:q4practice}
\end{table}
+45
View File
@@ -0,0 +1,45 @@
problem_no,case_code,module,seed,source_total,directional_total,r_eff_min_m,r_eff_max_m,cleared_jammer_count,all_cleared,complete,measure_accepted_count,direction_measure_count,channel_switch_count,clear_failure_count,virtual_time_s,move_time_s,move_distance_m,measure_time_s,switch_time_s,clear_time_s,program_run_duration_s,average_clear_time_s,end_reason,max_recorded_gap_s
3,6LST-ZFVS-2HHW-TQQ4,q3_practice,310,13,0,1025.565,1479.16,13,True,True,109,42,99,0,2794.211708,2085.211708,10426.059,545,99.0,65.0,2.04,214.939362,user_exit,0.0
3,6V2P-HJCS-GJ9A-83MA,q3_practice,305,16,0,1032.735,1455.427,16,True,True,103,55,88,0,3174.57833,2491.57833,12457.892,515,88.0,80.0,2.361,198.411146,user_exit,0.0
3,7ZXN-N53X-HAXQ-EGY4,q3_practice,309,10,0,1110.109,1403.33,10,True,True,119,34,105,0,3228.653175,2478.653175,12393.266,595,105.0,50.0,2.086,322.865318,user_exit,0.0
3,8VRC-ADW4-XDXM-F62L,q3_practice,301,13,0,1017.333,1460.77,13,True,True,102,40,93,0,3407.038502,2739.038502,13695.193,510,93.0,65.0,2.024,262.079885,user_exit,0.0
3,ARBP-6XFZ-5YJU-STC8,q3_practice,302,16,0,1020.28,1464.97,16,True,True,116,50,105,0,3867.871913,3102.871913,15514.36,580,105.0,80.0,1.952,241.741995,user_exit,0.0
3,E27E-M8WQ-LDT5-2XDA,q3_practice,308,16,0,1027.493,1463.979,16,True,True,104,51,89,0,3531.064575,2842.064575,14210.323,520,89.0,80.0,2.405,220.691536,user_exit,0.0
3,HGBA-XGH9-UNZJ-7YQ3,q3_practice,306,10,0,1018.005,1487.291,10,True,True,123,35,113,0,3340.02512,2562.02512,12810.126,615,113.0,50.0,1.997,334.002512,user_exit,0.0
3,JW47-AVPH-XGHH-RLLV,q3_practice,313,13,0,1018.607,1446.721,13,True,True,106,40,93,0,3389.151979,2701.151979,13505.76,530,93.0,65.0,2.146,260.703998,user_exit,0.0
3,LZDX-68DJ-XM4P-A6XL,q3_practice,312,10,0,1011.801,1441.227,10,True,True,117,30,105,0,2954.389763,2214.389763,11071.949,585,105.0,50.0,1.784,295.438976,user_exit,0.0
3,MT3R-68KH-CNY5-6X73,q3_practice,307,13,0,1021.012,1457.861,13,True,True,112,44,94,0,3527.712508,2808.712508,14043.563,560,94.0,65.0,2.15,271.362501,user_exit,0.0
3,MULB-4YTU-VQYG-YAS6,q3_practice,303,10,0,1016.095,1460.312,10,True,True,129,32,119,0,3064.020357,2250.020357,11250.102,645,119.0,50.0,1.636,306.402036,user_exit,0.0
3,NMRC-85ZV-3FFE-GBXY,q3_practice,304,13,0,1010.416,1489.87,13,True,True,101,39,96,0,2860.706202,2194.706202,10973.531,505,96.0,65.0,1.858,220.054323,user_exit,0.0
3,QS6H-CC29-PDY3-ZA54,q3_practice,314,16,0,1025.989,1475.263,16,True,True,85,55,74,0,2987.384891,2408.384891,12041.924,425,74.0,80.0,2.052,186.711556,user_exit,0.0
3,R2N7-QMLC-26QX-RXYT,q3_practice,311,16,0,1007.2,1491.089,16,True,True,106,57,95,0,3556.396565,2851.396565,14256.983,530,95.0,80.0,1.991,222.274785,user_exit,0.0
3,VE37-SRPD-NCFR-4EQF,q3_practice,300,10,0,1009.526,1433.065,10,True,True,124,34,115,0,3240.473597,2455.473597,12277.368,620,115.0,50.0,2.106,324.04736,user_exit,0.0
4,2M5J-QWHS-BYGB-MPYF,q4_practice,404,13,6,1070.641,1495.106,13,True,True,343,43,296,0,9191.436652,7115.436652,35577.183,1715,296.0,65.0,5.04,707.033589,user_exit,0.0
4,2Y25-4LD6-5A4P-64CV,q4_practice,411,16,8,1004.93,1458.657,16,True,True,226,57,182,0,6685.801927,5293.801927,26469.01,1130,182.0,80.0,5.26,417.86262,user_exit,0.0
4,3XM4-65TW-CH39-XWTZ,q4_practice,420,16,8,1004.366,1454.027,16,True,True,211,58,160,0,7327.980928,6032.980928,30164.905,1055,160.0,80.0,6.208,457.998808,user_exit,0.0
4,6LEP-YVQ6-AYP5-N359,q4_practice,432,16,8,1008.896,1463.598,16,True,True,280,61,222,0,7982.568866,6280.568866,31402.844,1400,222.0,80.0,5.584,498.910554,user_exit,0.0
4,6US3-A76N-KC8B-DMFM,q4_practice,409,10,3,1008.26,1464.117,10,True,True,371,30,331,0,8171.259372,5935.259372,29676.297,1855,331.0,50.0,3.814,817.125937,user_exit,0.0
4,7HG2-UEBM-K3D2-LZWT,q4_practice,433,10,3,1114.562,1481.86,10,True,True,377,37,333,0,8146.580541,5878.580541,29392.903,1885,333.0,50.0,4.436,814.658054,user_exit,0.0
4,96M4-SK2V-PDWN-YGHB,q4_practice,407,13,6,1020.414,1492.263,13,True,True,364,51,311,0,9593.183569,7397.183569,36985.918,1820,311.0,65.0,4.853,737.937198,user_exit,0.0
4,A5YU-4SM6-4PK7-M5H8,q4_practice,412,10,3,1139.46,1478.185,10,True,True,382,43,327,0,9854.818271,7567.818271,37839.091,1910,327.0,50.0,4.675,985.481827,user_exit,0.0
4,B8HR-3HJH-2UYH-YDVB,q4_practice,416,13,6,1012.067,1489.111,13,True,True,371,58,306,0,8840.641969,6614.641969,33073.21,1855,306.0,65.0,5.794,680.049382,user_exit,0.0
4,CEL3-XQV8-M7KY-3CSW,q4_practice,426,16,8,1045.853,1497.562,16,True,True,184,54,144,0,5806.59591,4662.59591,23312.98,920,144.0,80.0,5.568,362.912244,user_exit,0.0
4,DX2D-KDF9-BGYU-XPMG,q4_practice,425,13,6,1023.466,1360.172,13,True,True,314,49,265,0,8642.080868,6742.080868,33710.404,1570,265.0,65.0,5.272,664.775451,user_exit,0.0
4,GSG4-6HTJ-AH5L-ZYGM,q4_practice,403,10,3,1001.593,1484.685,10,True,True,438,48,379,0,9488.521663,6869.521663,34347.608,2190,379.0,50.0,5.235,948.852166,user_exit,0.0
4,JDAY-2SU7-RTSJ-NQFR,q4_practice,434,13,6,1018.26,1401.084,13,True,True,351,63,283,0,9813.925336,7710.925336,38554.627,1755,283.0,65.0,5.774,754.917334,user_exit,0.0
4,JH76-MEWS-BR6Q-BQ6S,q4_practice,413,13,6,1042.824,1495.794,13,True,True,336,45,287,0,8732.841353,6700.841353,33504.207,1680,287.0,65.0,5.772,671.757027,user_exit,0.0
4,JY84-364B-45UL-AFBK,q4_practice,400,10,3,1003.128,1498.908,10,True,True,436,38,392,0,8704.596801,6082.596801,30412.984,2180,392.0,50.0,13.713,870.45968,user_exit,0.0
4,QDDJ-S89Y-7TKY-E6VJ,q4_practice,438,16,8,1018.88,1422.829,16,True,True,221,59,169,0,7316.173221,5962.173221,29810.866,1105,169.0,80.0,5.495,457.260826,user_exit,0.0
4,QL6B-KEUW-DJR2-P84B,q4_practice,435,16,8,1001.665,1490.865,16,True,True,184,60,144,0,5229.931106,4085.931106,20429.656,920,144.0,80.0,5.873,326.870694,user_exit,0.0
4,QXVN-L63H-6WLX-KLEJ,q4_practice,430,10,3,1029.996,1485.51,10,True,True,399,38,351,0,9307.230821,6911.230821,34556.154,1995,351.0,50.0,4.514,930.723082,user_exit,0.0
4,R2E7-LF5E-J5K6-BSVQ,q4_practice,419,13,6,1055.108,1474.754,13,True,True,340,56,283,0,9809.920542,7761.920542,38809.603,1700,283.0,65.0,5.223,754.609272,user_exit,0.0
4,RLK4-E82Q-UHT6-2M9M,q4_practice,418,10,3,1052.266,1496.42,10,True,True,374,36,328,0,8342.1353,6094.1353,30470.676,1870,328.0,50.0,4.395,834.21353,user_exit,0.0
4,SE9X-67GA-6YC6-QB7B,q4_practice,439,10,3,1040.839,1476.506,10,True,True,406,39,359,0,9241.602648,6802.602648,34013.013,2030,359.0,50.0,4.463,924.160265,user_exit,0.0
4,SWA3-C3FB-C5QC-FLW7,q4_practice,402,16,8,1025.798,1458.463,16,True,True,159,72,108,0,4780.431839,3797.431839,18987.159,795,108.0,80.0,6.598,298.77699,user_exit,0.0
4,T5ZL-5GEP-FDCK-3P8T,q4_practice,428,13,6,1032.374,1491.324,13,True,True,344,56,285,0,8719.661303,6649.661303,33248.306,1720,285.0,65.0,5.763,670.743177,user_exit,0.0
4,TKCY-2VT2-WYUX-2JXU,q4_practice,427,10,3,1032.206,1492.339,10,True,True,385,35,342,0,8260.712396,5943.712396,29718.562,1925,342.0,50.0,5.028,826.07124,user_exit,0.0
4,US79-DFNV-UQVW-NPLL,q4_practice,406,10,3,1107.601,1451.394,10,True,True,408,40,358,0,8795.904309,6347.904309,31739.522,2040,358.0,50.0,4.565,879.590431,user_exit,0.0
4,VJ68-ADZ6-STFT-LHYT,q4_practice,410,13,6,1016.63,1491.9,13,True,True,369,58,312,0,8783.09917,6561.09917,32805.496,1845,312.0,65.0,5.691,675.623013,user_exit,0.0
4,X3Y4-S9D2-XWR9-V6CZ,q4_practice,431,13,6,1022.115,1395.544,13,True,True,365,55,304,0,10160.134188,7966.134188,39830.671,1825,304.0,65.0,6.694,781.548784,user_exit,0.0
4,XN57-MHFY-V58F-XCMY,q4_practice,421,10,3,1022.143,1499.183,10,True,True,438,31,397,0,9188.211438,6551.211438,32756.057,2190,397.0,50.0,4.568,918.821144,user_exit,0.0
4,ZLKB-GVZT-NQDE-CU5F,q4_practice,424,10,3,1099.547,1417.736,10,True,True,395,45,343,0,8723.919348,6355.919348,31779.597,1975,343.0,50.0,4.398,872.391935,user_exit,0.0
1 problem_no case_code module seed source_total directional_total r_eff_min_m r_eff_max_m cleared_jammer_count all_cleared complete measure_accepted_count direction_measure_count channel_switch_count clear_failure_count virtual_time_s move_time_s move_distance_m measure_time_s switch_time_s clear_time_s program_run_duration_s average_clear_time_s end_reason max_recorded_gap_s
2 3 6LST-ZFVS-2HHW-TQQ4 q3_practice 310 13 0 1025.565 1479.16 13 True True 109 42 99 0 2794.211708 2085.211708 10426.059 545 99.0 65.0 2.04 214.939362 user_exit 0.0
3 3 6V2P-HJCS-GJ9A-83MA q3_practice 305 16 0 1032.735 1455.427 16 True True 103 55 88 0 3174.57833 2491.57833 12457.892 515 88.0 80.0 2.361 198.411146 user_exit 0.0
4 3 7ZXN-N53X-HAXQ-EGY4 q3_practice 309 10 0 1110.109 1403.33 10 True True 119 34 105 0 3228.653175 2478.653175 12393.266 595 105.0 50.0 2.086 322.865318 user_exit 0.0
5 3 8VRC-ADW4-XDXM-F62L q3_practice 301 13 0 1017.333 1460.77 13 True True 102 40 93 0 3407.038502 2739.038502 13695.193 510 93.0 65.0 2.024 262.079885 user_exit 0.0
6 3 ARBP-6XFZ-5YJU-STC8 q3_practice 302 16 0 1020.28 1464.97 16 True True 116 50 105 0 3867.871913 3102.871913 15514.36 580 105.0 80.0 1.952 241.741995 user_exit 0.0
7 3 E27E-M8WQ-LDT5-2XDA q3_practice 308 16 0 1027.493 1463.979 16 True True 104 51 89 0 3531.064575 2842.064575 14210.323 520 89.0 80.0 2.405 220.691536 user_exit 0.0
8 3 HGBA-XGH9-UNZJ-7YQ3 q3_practice 306 10 0 1018.005 1487.291 10 True True 123 35 113 0 3340.02512 2562.02512 12810.126 615 113.0 50.0 1.997 334.002512 user_exit 0.0
9 3 JW47-AVPH-XGHH-RLLV q3_practice 313 13 0 1018.607 1446.721 13 True True 106 40 93 0 3389.151979 2701.151979 13505.76 530 93.0 65.0 2.146 260.703998 user_exit 0.0
10 3 LZDX-68DJ-XM4P-A6XL q3_practice 312 10 0 1011.801 1441.227 10 True True 117 30 105 0 2954.389763 2214.389763 11071.949 585 105.0 50.0 1.784 295.438976 user_exit 0.0
11 3 MT3R-68KH-CNY5-6X73 q3_practice 307 13 0 1021.012 1457.861 13 True True 112 44 94 0 3527.712508 2808.712508 14043.563 560 94.0 65.0 2.15 271.362501 user_exit 0.0
12 3 MULB-4YTU-VQYG-YAS6 q3_practice 303 10 0 1016.095 1460.312 10 True True 129 32 119 0 3064.020357 2250.020357 11250.102 645 119.0 50.0 1.636 306.402036 user_exit 0.0
13 3 NMRC-85ZV-3FFE-GBXY q3_practice 304 13 0 1010.416 1489.87 13 True True 101 39 96 0 2860.706202 2194.706202 10973.531 505 96.0 65.0 1.858 220.054323 user_exit 0.0
14 3 QS6H-CC29-PDY3-ZA54 q3_practice 314 16 0 1025.989 1475.263 16 True True 85 55 74 0 2987.384891 2408.384891 12041.924 425 74.0 80.0 2.052 186.711556 user_exit 0.0
15 3 R2N7-QMLC-26QX-RXYT q3_practice 311 16 0 1007.2 1491.089 16 True True 106 57 95 0 3556.396565 2851.396565 14256.983 530 95.0 80.0 1.991 222.274785 user_exit 0.0
16 3 VE37-SRPD-NCFR-4EQF q3_practice 300 10 0 1009.526 1433.065 10 True True 124 34 115 0 3240.473597 2455.473597 12277.368 620 115.0 50.0 2.106 324.04736 user_exit 0.0
17 4 2M5J-QWHS-BYGB-MPYF q4_practice 404 13 6 1070.641 1495.106 13 True True 343 43 296 0 9191.436652 7115.436652 35577.183 1715 296.0 65.0 5.04 707.033589 user_exit 0.0
18 4 2Y25-4LD6-5A4P-64CV q4_practice 411 16 8 1004.93 1458.657 16 True True 226 57 182 0 6685.801927 5293.801927 26469.01 1130 182.0 80.0 5.26 417.86262 user_exit 0.0
19 4 3XM4-65TW-CH39-XWTZ q4_practice 420 16 8 1004.366 1454.027 16 True True 211 58 160 0 7327.980928 6032.980928 30164.905 1055 160.0 80.0 6.208 457.998808 user_exit 0.0
20 4 6LEP-YVQ6-AYP5-N359 q4_practice 432 16 8 1008.896 1463.598 16 True True 280 61 222 0 7982.568866 6280.568866 31402.844 1400 222.0 80.0 5.584 498.910554 user_exit 0.0
21 4 6US3-A76N-KC8B-DMFM q4_practice 409 10 3 1008.26 1464.117 10 True True 371 30 331 0 8171.259372 5935.259372 29676.297 1855 331.0 50.0 3.814 817.125937 user_exit 0.0
22 4 7HG2-UEBM-K3D2-LZWT q4_practice 433 10 3 1114.562 1481.86 10 True True 377 37 333 0 8146.580541 5878.580541 29392.903 1885 333.0 50.0 4.436 814.658054 user_exit 0.0
23 4 96M4-SK2V-PDWN-YGHB q4_practice 407 13 6 1020.414 1492.263 13 True True 364 51 311 0 9593.183569 7397.183569 36985.918 1820 311.0 65.0 4.853 737.937198 user_exit 0.0
24 4 A5YU-4SM6-4PK7-M5H8 q4_practice 412 10 3 1139.46 1478.185 10 True True 382 43 327 0 9854.818271 7567.818271 37839.091 1910 327.0 50.0 4.675 985.481827 user_exit 0.0
25 4 B8HR-3HJH-2UYH-YDVB q4_practice 416 13 6 1012.067 1489.111 13 True True 371 58 306 0 8840.641969 6614.641969 33073.21 1855 306.0 65.0 5.794 680.049382 user_exit 0.0
26 4 CEL3-XQV8-M7KY-3CSW q4_practice 426 16 8 1045.853 1497.562 16 True True 184 54 144 0 5806.59591 4662.59591 23312.98 920 144.0 80.0 5.568 362.912244 user_exit 0.0
27 4 DX2D-KDF9-BGYU-XPMG q4_practice 425 13 6 1023.466 1360.172 13 True True 314 49 265 0 8642.080868 6742.080868 33710.404 1570 265.0 65.0 5.272 664.775451 user_exit 0.0
28 4 GSG4-6HTJ-AH5L-ZYGM q4_practice 403 10 3 1001.593 1484.685 10 True True 438 48 379 0 9488.521663 6869.521663 34347.608 2190 379.0 50.0 5.235 948.852166 user_exit 0.0
29 4 JDAY-2SU7-RTSJ-NQFR q4_practice 434 13 6 1018.26 1401.084 13 True True 351 63 283 0 9813.925336 7710.925336 38554.627 1755 283.0 65.0 5.774 754.917334 user_exit 0.0
30 4 JH76-MEWS-BR6Q-BQ6S q4_practice 413 13 6 1042.824 1495.794 13 True True 336 45 287 0 8732.841353 6700.841353 33504.207 1680 287.0 65.0 5.772 671.757027 user_exit 0.0
31 4 JY84-364B-45UL-AFBK q4_practice 400 10 3 1003.128 1498.908 10 True True 436 38 392 0 8704.596801 6082.596801 30412.984 2180 392.0 50.0 13.713 870.45968 user_exit 0.0
32 4 QDDJ-S89Y-7TKY-E6VJ q4_practice 438 16 8 1018.88 1422.829 16 True True 221 59 169 0 7316.173221 5962.173221 29810.866 1105 169.0 80.0 5.495 457.260826 user_exit 0.0
33 4 QL6B-KEUW-DJR2-P84B q4_practice 435 16 8 1001.665 1490.865 16 True True 184 60 144 0 5229.931106 4085.931106 20429.656 920 144.0 80.0 5.873 326.870694 user_exit 0.0
34 4 QXVN-L63H-6WLX-KLEJ q4_practice 430 10 3 1029.996 1485.51 10 True True 399 38 351 0 9307.230821 6911.230821 34556.154 1995 351.0 50.0 4.514 930.723082 user_exit 0.0
35 4 R2E7-LF5E-J5K6-BSVQ q4_practice 419 13 6 1055.108 1474.754 13 True True 340 56 283 0 9809.920542 7761.920542 38809.603 1700 283.0 65.0 5.223 754.609272 user_exit 0.0
36 4 RLK4-E82Q-UHT6-2M9M q4_practice 418 10 3 1052.266 1496.42 10 True True 374 36 328 0 8342.1353 6094.1353 30470.676 1870 328.0 50.0 4.395 834.21353 user_exit 0.0
37 4 SE9X-67GA-6YC6-QB7B q4_practice 439 10 3 1040.839 1476.506 10 True True 406 39 359 0 9241.602648 6802.602648 34013.013 2030 359.0 50.0 4.463 924.160265 user_exit 0.0
38 4 SWA3-C3FB-C5QC-FLW7 q4_practice 402 16 8 1025.798 1458.463 16 True True 159 72 108 0 4780.431839 3797.431839 18987.159 795 108.0 80.0 6.598 298.77699 user_exit 0.0
39 4 T5ZL-5GEP-FDCK-3P8T q4_practice 428 13 6 1032.374 1491.324 13 True True 344 56 285 0 8719.661303 6649.661303 33248.306 1720 285.0 65.0 5.763 670.743177 user_exit 0.0
40 4 TKCY-2VT2-WYUX-2JXU q4_practice 427 10 3 1032.206 1492.339 10 True True 385 35 342 0 8260.712396 5943.712396 29718.562 1925 342.0 50.0 5.028 826.07124 user_exit 0.0
41 4 US79-DFNV-UQVW-NPLL q4_practice 406 10 3 1107.601 1451.394 10 True True 408 40 358 0 8795.904309 6347.904309 31739.522 2040 358.0 50.0 4.565 879.590431 user_exit 0.0
42 4 VJ68-ADZ6-STFT-LHYT q4_practice 410 13 6 1016.63 1491.9 13 True True 369 58 312 0 8783.09917 6561.09917 32805.496 1845 312.0 65.0 5.691 675.623013 user_exit 0.0
43 4 X3Y4-S9D2-XWR9-V6CZ q4_practice 431 13 6 1022.115 1395.544 13 True True 365 55 304 0 10160.134188 7966.134188 39830.671 1825 304.0 65.0 6.694 781.548784 user_exit 0.0
44 4 XN57-MHFY-V58F-XCMY q4_practice 421 10 3 1022.143 1499.183 10 True True 438 31 397 0 9188.211438 6551.211438 32756.057 2190 397.0 50.0 4.568 918.821144 user_exit 0.0
45 4 ZLKB-GVZT-NQDE-CU5F q4_practice 424 10 3 1099.547 1417.736 10 True True 395 45 343 0 8723.919348 6355.919348 31779.597 1975 343.0 50.0 4.398 872.391935 user_exit 0.0
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,15 @@
% Generated by scripts/build_practice_data.py; 自建模拟器演练局复算结果。 本文件是完整 table 环境,供正文直接 \input。
\begin{table}[H]
\centering\footnotesize
\caption{演练局汇总(仅统计全清且无失败清除的局)}
\setlength{\tabcolsep}{2pt}
\begin{tabular}{lrrrrrrr}
\toprule
问题 & 全清局数 & 累计清除 & 平均总虚拟时间/s & 时间区间/s & 平均定位清除时间/(s/个) & 移动占比\\
\midrule
问题三(全向源) & 15 & 195 & 3261.579 & 2794.212--3867.872 & 258.782 & 78.1\% \\
问题四(混合源) & 29 & 362 & 8401.445 & 4780.432--10160.134 & 708.350 & 75.8\% \\
\bottomrule
\end{tabular}
\label{tab:practicesummary}
\end{table}
+55
View File
@@ -0,0 +1,55 @@
% Generated by scripts/build_paper_support.py from project/results/*.json.
\newcommand{\ProjQOneExampleCases}{5}
\newcommand{\ProjQOneRandomCases}{40}
\newcommand{\ProjQOneFixedStatusBase}{80.0\%}
\newcommand{\ProjQOneFixedMaeBase}{7.886}
\newcommand{\ProjQOneFixedMaeMaxBase}{10.000}
\newcommand{\ProjQOneFixedCoverBase}{33.3\%}
\newcommand{\ProjQOneFixedMsOpt}{0.064}
\newcommand{\ProjQOneFixedMsBase}{14.202}
\newcommand{\ProjQOneRandStatusBase}{100.0\%}
\newcommand{\ProjQOneRandMaeBase}{4.583}
\newcommand{\ProjQOneRandMaeMaxBase}{14.599}
\newcommand{\ProjQOneRandCoverBase}{52.5\%}
\newcommand{\ProjQOneRandMsOpt}{0.086}
\newcommand{\ProjQOneRandMsBase}{15.933}
\newcommand{\ProjQTwoCases}{30}
\newcommand{\ProjQTwoInitialRadius}{681.467}
\newcommand{\ProjQTwoGuaranteeOpt}{100.0\%}
\newcommand{\ProjQTwoGuaranteeMec}{100.0\%}
\newcommand{\ProjQTwoGuaranteePerp}{0.0\%}
\newcommand{\ProjQTwoWorstOpt}{73.890}
\newcommand{\ProjQTwoWorstRef}{75.627}
\newcommand{\ProjQTwoRatioOpt}{0.104}
\newcommand{\ProjQTwoRatioMec}{0.500}
\newcommand{\ProjQTwoWorstPerp}{80.111}
\newcommand{\ProjQTwoWorstMec}{340.747}
\newcommand{\ProjQThreeScenes}{18}
\newcommand{\ProjQThreeMeanOpt}{3188.734}
\newcommand{\ProjQThreeMeanSeven}{5361.707}
\newcommand{\ProjQThreeMeanBase}{14935.659}
\newcommand{\ProjQThreeDropOpt}{78.4\%}
\newcommand{\ProjQThreeDropMedianOpt}{80.0\%}
\newcommand{\ProjQThreeDropSeven}{63.7\%}
\newcommand{\ProjQThreeFasterOpt}{18/18}
\newcommand{\ProjQThreeMeasuresOpt}{111.111}
\newcommand{\ProjQThreeMeasuresBase}{430.556}
\newcommand{\ProjQThreeMoveOpt}{12.338}
\newcommand{\ProjQThreeMoveBase}{61.550}
\newcommand{\ProjQThreeWallOpt}{0.767}
\newcommand{\ProjQFourScenes}{11}
\newcommand{\ProjQFourMeanOpt}{9069.871}
\newcommand{\ProjQFourMeanGrid}{18179.173}
\newcommand{\ProjQFourMeanBase}{3890.801}
\newcommand{\ProjQFourClearOpt}{100.0\%}
\newcommand{\ProjQFourClearGrid}{66.6\%}
\newcommand{\ProjQFourClearBase}{77.0\%}
\newcommand{\ProjQFourAbsentBase}{24}
\newcommand{\ProjQFourMeasuresOpt}{355.636}
\newcommand{\ProjQFourMeasuresBase}{132.000}
\newcommand{\ProjQFourFallbackOpt}{24.818}
\newcommand{\ProjQFourValidOpt}{11/11}
\newcommand{\ProjQFourValidGrid}{0/11}
\newcommand{\ProjQFourRiseOpt}{142.9\%}
\newcommand{\ProjQFourMoveOpt}{34.268}
\newcommand{\ProjQFourMoveBase}{15.319}
@@ -0,0 +1,5 @@
% Generated by scripts/build_paper_support.py from project/results/*.json.
最优(固定 5 例) & 100.0\% & 0.000 & 0.000 & 100.0\% & 0.064 \\
最优(随机 40 例) & 100.0\% & 0.000 & 0.000 & 100.0\% & 0.086 \\
基线(固定 5 例) & 80.0\% & 7.886 & 10.000 & 33.3\% & 14.202 \\
基线(随机 40 例) & 100.0\% & 4.583 & 14.599 & 52.5\% & 15.933 \\
+17
View File
@@ -0,0 +1,17 @@
% Generated by scripts/build_paper_support.py from project/results/*.json.
\begin{table}[htbp]
\centering\small
\caption{问题三:三种策略在 18 个全向源场景上的对比(时间:s;三种策略的缺席误判均为 0)}
\setlength{\tabcolsep}{2pt}
\begin{tabular}{lrrrrrrrr}
\toprule
策略 & 有效局 & 全清率 & $T$ 均值 & $T$ 中位 & $T$ 最大 & 检测均值 & 位移/km & 后备清除\\
\midrule
bayes(默认策略) & 18/18 & 100.0\% & 3188.734 & 3111.256 & 3663.707 & 111.1 & 12.338 & 0.0 \\ \\
seven(七点批量) & 18/18 & 100.0\% & 5361.707 & 5367.455 & 6462.351 & 100.8 & 23.508 & 0.0 \\ \\
grid(49 点网格) & 18/18 & 100.0\% & 14935.659 & 15275.057 & 16691.406 & 430.6 & 61.550 & 0.0 \\ \\
\bottomrule
\end{tabular}
\label{tab:q3compare}
\end{table}
+17
View File
@@ -0,0 +1,17 @@
% Generated by scripts/build_paper_support.py from project/results/*.json.
\begin{table}[htbp]
\centering\small
\caption{问题四:三种策略在 11 个混合源场景上的对比(时间:s)}
\setlength{\tabcolsep}{4pt}
\begin{tabular}{lrrrrrrr}
\toprule
策略 & 有效局 & 全清率 & 缺席误判 & $T$ 均值 & $T$ 中位 & $T$ 最大 & 检测均值\\
\midrule
directional(默认策略) & 11/11 & 100.0\% & 0 & 9069.871 & 8803.261 & 12081.148 & 355.6 \\
grid(问题三网格) & 0/11 & 66.6\% & 0 & 18179.173 & 18345.164 & 20457.858 & 573.7 \\
bayes(问题三策略) & 0/11 & 77.0\% & 24 & 3890.801 & 3646.178 & 5054.382 & 132.0 \\
\bottomrule
\end{tabular}
\label{tab:q4compare}
\end{table}
File diff suppressed because it is too large Load Diff
+57
View File
@@ -0,0 +1,57 @@
\begin{figure}[htbp]\centering
\begin{tikzpicture}[x=0.00108cm,y=0.85cm,font=\small]
\node[anchor=east] at (-100,5.3) {Q3-1};
\fill[inkblue] (0,5) rectangle (2408.978068,5.6);
\fill[inkblue!50] (2408.978068,5) rectangle (2933.978068,5.6);
\fill[warmgray!70] (2933.978068,5) rectangle (3029.978068,5.6);
\fill[black!18] (3029.978068,5) rectangle (3094.978068,5.6);
\node[anchor=west,font=\scriptsize] at (3174.978068,5.3) {3095.0};
\node[anchor=east] at (-100,4.3) {Q3-2};
\fill[inkblue] (0,4) rectangle (2725.33514,4.6);
\fill[inkblue!50] (2725.33514,4) rectangle (3310.33514,4.6);
\fill[warmgray!70] (3310.33514,4) rectangle (3418.33514,4.6);
\fill[black!18] (3418.33514,4) rectangle (3493.33514,4.6);
\node[anchor=west,font=\scriptsize] at (3573.33514,4.3) {3493.3};
\node[anchor=east] at (-100,3.3) {Q3-3};
\fill[inkblue] (0,3) rectangle (2164.862876,3.6);
\fill[inkblue!50] (2164.862876,3) rectangle (2749.862876,3.6);
\fill[warmgray!70] (2749.862876,3) rectangle (2856.862876,3.6);
\fill[black!18] (2856.862876,3) rectangle (2906.862876,3.6);
\node[anchor=west,font=\scriptsize] at (2986.862876,3.3) {2906.9};
\node[anchor=east] at (-100,2.3) {Q4-1};
\fill[inkblue] (0,2) rectangle (7277.225736,2.6);
\fill[inkblue!50] (7277.225736,2) rectangle (9022.225736,2.6);
\fill[warmgray!70] (9022.225736,2) rectangle (9297.225736,2.6);
\fill[black!18] (9297.225736,2) rectangle (9362.225736,2.6);
\node[anchor=west,font=\scriptsize] at (9442.225736,2.3) {9362.2};
\node[anchor=east] at (-100,1.3) {Q4-2};
\fill[inkblue] (0,1) rectangle (7101.30208,1.6);
\fill[inkblue!50] (7101.30208,1) rectangle (8906.30208,1.6);
\fill[warmgray!70] (8906.30208,1) rectangle (9221.30208,1.6);
\fill[black!18] (9221.30208,1) rectangle (9271.30208,1.6);
\node[anchor=west,font=\scriptsize] at (9351.30208,1.3) {9271.3};
\node[anchor=east] at (-100,0.3) {Q4-3};
\fill[inkblue] (0,0) rectangle (7005.382102,0.6);
\fill[inkblue!50] (7005.382102,0) rectangle (8325.382102,0.6);
\fill[warmgray!70] (8325.382102,0) rectangle (8538.382102,0.6);
\fill[black!18] (8538.382102,0) rectangle (8608.382102,0.6);
\node[anchor=west,font=\scriptsize] at (8688.382102,0.3) {8608.4};
\draw[->] (0,-0.25)--(10500,-0.25);
\draw (0,-0.25)--(0,-0.35) node[below,font=\scriptsize] {0};
\draw (2000,-0.25)--(2000,-0.35) node[below,font=\scriptsize] {2000};
\draw (4000,-0.25)--(4000,-0.35) node[below,font=\scriptsize] {4000};
\draw (6000,-0.25)--(6000,-0.35) node[below,font=\scriptsize] {6000};
\draw (8000,-0.25)--(8000,-0.35) node[below,font=\scriptsize] {8000};
\draw (10000,-0.25)--(10000,-0.35) node[below,font=\scriptsize] {10000};
\node[anchor=west,font=\scriptsize] at (10400,-0.65) {s};
\fill[inkblue] (0,-1.3) rectangle (350,-1.05);
\node[anchor=west] at (450,-1.175) {移动};
\fill[inkblue!50] (2600,-1.3) rectangle (2950,-1.05);
\node[anchor=west] at (3050,-1.175) {检测};
\fill[warmgray!70] (5200,-1.3) rectangle (5550,-1.05);
\node[anchor=west] at (5650,-1.175) {换频};
\fill[black!18] (7600,-1.3) rectangle (7950,-1.05);
\node[anchor=west] at (8050,-1.175) {清除};
\end{tikzpicture}
\caption{正式测试的累计虚拟耗时分解。移动时间由总耗时与各动作计数计算。}
\label{fig:costbars}\end{figure}
+50
View File
@@ -0,0 +1,50 @@
\begin{figure}[htbp]\centering
\begin{tikzpicture}[x=0.00145cm,y=0.00145cm,font=\small]
\fill[inkblue!5] (0,0) circle (1800);
\draw[thick] (0,0) circle (1800);
\draw[->,warmgray] (-2900,0)--(2950,0) node[right] {$x$/m};
\draw[->,warmgray] (0,-2800)--(0,2850) node[above] {$y$/m};
\draw (-2000,-35)--(-2000,35);
\node[below,font=\scriptsize] at (-2000,-50) {-2000};
\draw (-1000,-35)--(-1000,35);
\node[below,font=\scriptsize] at (-1000,-50) {-1000};
\draw (1000,-35)--(1000,35);
\node[below,font=\scriptsize] at (1000,-50) {1000};
\draw (2000,-35)--(2000,35);
\node[below,font=\scriptsize] at (2000,-50) {2000};
\fill[inkblue] (-800.0,-200.0) circle (33);
\fill[inkblue] (800.0,200.0) circle (33);
\fill[inkblue] (-200.0,900.0) circle (33);
\fill[inkblue] (200.0,-900.0) circle (33);
\fill[inkblue] (-1200.0,700.0) circle (33);
\fill[inkblue] (1200.0,-700.0) circle (33);
\fill[inkblue] (800.0,1200.0) circle (33);
\fill[inkblue] (-1800.0,-300.0) circle (33);
\fill[inkblue] (1800.0,300.0) circle (33);
\fill[inkblue] (-400.0,1800.0) circle (33);
\fill[inkblue] (0.0,0.0) circle (33);
\fill[inkblue] (1400.0,-1400.0) circle (33);
\fill[inkblue] (-1500.0,-1300.0) circle (33);
\fill[inkblue] (1500.0,1300.0) circle (33);
\fill[inkblue] (-400.0,-1800.0) circle (33);
\fill[inkblue] (400.0,1800.0) circle (33);
\fill[inkblue] (-1800.0,400.0) circle (33);
\fill[inkblue] (1800.0,-400.0) circle (33);
\fill[inkblue] (-500.0,700.0) circle (33);
\fill[inkblue] (-700.0,-700.0) circle (33);
\fill[inkblue] (700.0,700.0) circle (33);
\fill[inkblue] (1300.0,1100.0) circle (33);
\fill[inkblue] (-1300.0,1500.0) circle (33);
\fill[inkblue] (500.0,-1800.0) circle (33);
\fill[inkblue] (-900.0,-2100.0) circle (33);
\fill[inkblue] (600.0,1900.0) circle (33);
\fill[inkblue] (-2500.0,500.0) circle (33);
\fill[inkblue] (1900.0,-900.0) circle (33);
\fill[inkblue] (-1700.0,-500.0) circle (33);
\fill[inkblue] (-700.0,-1200.0) circle (33);
\fill[inkblue] (900.0,-700.0) circle (33);
\node[anchor=west,align=left] at (3250,900) {圆域:源位置先验\\蓝点:31个检测站};
\node[anchor=west,align=left] at (3250,-700) {部分站点在圆域外\\用于接收向外发射的源};
\end{tikzpicture}
\caption{第四问集合覆盖模型得到的31个检测站及源位置区域。}
\label{fig:q4plan}\end{figure}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+254 -938
View File
File diff suppressed because it is too large Load Diff
+205
View File
@@ -0,0 +1,205 @@
\section{官方正式测试的效果验证}\label{app:formal}\aigcC
\subsection{数据选择及对应关系核对}
正文的机制论证与定量结论取自自建模拟器演练局,
本节则用官方模拟器的正式测试验证算法在正式环境下的效率与正文结论是否一致。
实验样本严格限定为官方模拟器
\pathtext{Jammers-simulator-full/test} 下的六份正式导出包,问题三、四各有三次。
文件名、案例编码与完整包校验值见表~\ref{tab:packages},核对说明见 \pathtext{docs/paper/data/audit.md}。
由于官方记录不公开真实源位置和机器人轨迹,本节不绘制搜索/清除路径,
只使用清除数量、总虚拟时间、程序运行时间与动作计数四类可直接观测的量。
这样处理的原因是:正式测试能够检验"算法是否在真实时限内完成清除",
但不能检验"定位是否收敛到真值",后者已由正文的演练局分析承担。
评价指标包括清除数量 $N_c^+$、总虚拟时间 $T$、程序运行时间 $T_{\mathrm{real}}$,
以及检测、换频和清除的动作次数。其中 $T$ 按整数微秒累计,
$T_{\mathrm{real}}$ 采用官方记录的毫秒值;
平均定位清除时间仅作辅助分析,不替代总虚拟时间与程序运行时间这两项直接指标。
六次测试均以主动退出(\texttt{user\_exit})结束,统计提交状态为已确认。
\subsection{问题三与问题四的正式结果}
\input{data/formal-q3-table}
三次正式测试分别清除 $13$、$15$、$10$ 个源,
总虚拟时间分别为 $3094.978$、$3493.335$、$2906.863$ s,合计 $\QThreeTotal$ s;
程序运行时间分别为 $5.596$、$3.024$、$2.680$ s,合计 $\QThreeProgramTotal$ s。
按清除数量加权的平均定位清除时间为 $\QThreeWeighted$ s/个,仅作辅助解释。
第三次的总虚拟时间最短($2906.863$ s),但其清除数也最少($10$ 个),
因此判断优化程度时应以总虚拟时间与清除数量并列报告,不能只看单一平均值。
\input{data/formal-q4-table}
表~\ref{tab:formal4} 给出问题四的三次正式结果。三次分别清除 $13$、$10$、$14$ 个源,
总虚拟时间合计 $\QFourTotal$ s,程序运行时间合计 $\QFourProgramTotal$ s,
加权平均定位清除时间 $\QFourWeighted$ s/个。
第三次清除数最多($14$ 个)且总虚拟时间最短($8608.382$ s),
与自建模拟器演练局中"可见性筛选加后备清除能够压缩定向场景耗时"的结论方向一致;
但三次案例的随机源分布与朝向不同,仍应以绝对时间与清除数量为准。
\subsection{正式测试的动作耗时分解}
按式~\eqref{eq:residual} 由动作计数反推移动时间,得到表~\ref{tab:formalcost}。
其中 Q3-1 表示问题三第一次正式测试,其余编号依此类推。
\input{data/formal-cost-table}
\begin{figure}[htbp]
\centering
\includegraphics[width=0.92\linewidth]{formal-time-bars.png}
\caption{六次正式测试的累计虚拟耗时分解(数据仅来自正式测试的原始动作计数与总虚拟时间)。}
\label{fig:formalbars}
\end{figure}
六次测试的清除失败计数均为零,移动时间占总虚拟耗时的
$\FormalMovementMin\%$ 至 $\FormalMovementMax\%$,与演练局的构成一致,
说明"移动是主要成本"这一结论在正式环境中同样成立。
由 $L_{\mathrm{eq}}=5T_{\mathrm{move}}$ 反推等效移动距离:
问题三依次为 $12.045$、$13.627$、$10.824$ km,
问题四依次为 $36.386$、$35.507$、$35.027$ km;
对照表~\ref{tab:q3practice} 与表~\ref{tab:q4practice},
正式测试的移动量级与演练局相符(问题三约 $12$--$15$ km,问题四约 $30$--$33$ km),
表明演练局并非经过挑选的乐观样本。
该等效距离由动作计数与移动速度换算得到,不是独立轨迹测得的长度。
\subsection{正式测试结论}
六次正式测试均主动退出且清除失败计数为零。
以题目要求的直接时间指标衡量:问题三累计清除 $\QThreeCount$ 个源,
总虚拟时间 $\QThreeTotal$ s,程序运行时间合计 $\QThreeProgramTotal$ s;
问题四累计清除 $\QFourCount$ 个源,总虚拟时间 $\QFourTotal$ s,
程序运行时间合计 $\QFourProgramTotal$ s;六次合计清除 $\FormalClearCount$ 个源、
总虚拟时间 $\FormalVirtualTotal$ s。
由此可得结论:
1. 全向源场景下,七点解析覆盖与逐频道网格幸存集使三次正式测试均在时限内完成,
总虚拟时间为 $2906.863$ 至 $3493.335$ s,与演练局量级一致;
2. 混合源场景下,前向半盘最小命中集、位置与朝向联合幸存集和后备清除使三次正式测试的
总虚拟时间为 $8608.382$ 至 $9362.226$ s,明显高于全向场景,
印证了正文关于"定向遮挡仍是主要时间成本"的判断;
3. 平均定位清除时间与移动时间分解只用于解释成本结构,
优化程度的结论应以总虚拟时间、程序运行时间和清除数量为准。
由于正式数据未公开源总数与类型组成,本文不据此计算全清率或做跨问题性能排名。
\input{data/formal-file-list}
\section{自建模拟器演练局数据清单}\label{app:practice}\aigcC
本节列出正文定量结论所依据的全部演练局,共 $\PractTotalCases$ 局,
由 \pathtext{scripts/run\_practice\_episodes.py} 采集、
\pathtext{scripts/build\_practice\_data.py} 从评测机行为日志复算得到,
复算口径为题面计时模型,与日志记录的最大偏差为 $\PractMaxGap$ s。
采集时以固定种子逐局运行生产策略,判定标准为
"清完全部源 $\wedge$ 无缺席误判 $\wedge$ 主动退出 $\wedge$ 零异常 $\wedge$ 零失败清除";
本表所列 $\PractTotalCases$ 局全部满足该标准。
\input{data/practice-summary-table}
\input{data/practice-all-table}
\input{data/practice-cost-table}
\section{支撑材料与运行方法}\aigcC
\begin{table}[H]
\centering\small
\caption{支撑材料目录及用途}
\begin{tabularx}{\linewidth}{p{5.8cm}X}
\toprule
文件或目录 & 用途\\
\midrule
\pathtext{src/mcm26b/} & 四问几何、信念、覆盖、调度与串行通信实现\\
\pathtext{src/mcm26b/guarantee/plans/} & 第四问已实现的覆盖计划及验证参数\\
\pathtext{project/} & 四问“最优实现 / 基线实现”配对对比框架与结果\\
\pathtext{referee/} & 自建模拟器(评测机)实现,与官方协议同一边界\\
\pathtext{referee-data/sessions/} & 正文引用的演练局行为日志(含真值)\\
\pathtext{scripts/build_practice_data.py} & 演练局计时复算与论文数据、宏文件生成\\
\pathtext{scripts/plot_paper_figures.py} & 正文插图 matplotlib 生成脚本\\
\pathtext{scripts/audit_paper_formal.py} & 正式文件对应核对、匿名快照及表格复算\\
\pathtext{docs/figures/manifest.json} & 插图来源与生成命令清单\\
\pathtext{docs/paper/data/} & 演练局与正式案例的可读统计、表格及校验值\\
\pathtext{docs/paper/sections/} & 分章论文源文件\\
\pathtext{Jammers-simulator-full/test/} & 六份原名官方正式日志\\
\pathtext{support-manifest.json} & 支撑包文件清单及逐文件 SHA-256\\
\bottomrule
\end{tabularx}
\end{table}
正文数据与插图的复算命令如下(在项目根目录执行):
\begin{lstlisting}[language={},numbers=none]
python scripts/build_practice_data.py # 演练局复算,生成正文数据与宏文件
python scripts/plot_paper_figures.py # 生成正文全部插图
python scripts/audit_paper_formal.py --snapshot docs/paper/data/formal-results.json
python scripts/build_paper_support.py # 附录正式数据表与支撑包
\end{lstlisting}
第一条命令读取 \pathtext{referee-data/sessions/} 下的行为日志,
按题面计时模型复算每局的移动、检测、换频与清除耗时,
并输出正文引用的宏、表格行与插图数据;
第二条命令据此与覆盖计划重新绘制插图,论文不手抄图内任何数字。
第三条命令按已有快照复算正式统计并核对正式包的校验值;
第四条命令生成附录的正式数据表并打包支撑材料。
Python 运行时需要 \texttt{requests},\texttt{numpy} 提供可选加速。
将 \texttt{src} 加入 Python 模块路径后,可调用
\texttt{python -m mcm26b.geometry} 进行问题一几何分析,
或通过 \texttt{mcm26b.cli} 运行在线策略。
在线测试由模拟器界面启动,接口就绪后执行策略入口。
具体运行指令和编译步骤见支撑包的 \texttt{README.md}。
\section{AIGC 使用逐节对照}\label{app:aigc}
本附录给出正文各章与 AI 工具使用情况的完整对照,供核查。
上标码 \aigcA 对应 ChatGPT/Codex 桌面版,\aigcC 对应 DeepSeek Harness,
两者的版本、开发机构与使用日期见参考文献~\cite{aigc-chatgpt,aigc-dsh}。
\begin{table}[htbp]
\centering\small
\caption{各章内容与 AI 工具使用情况对照\aigcC}
\label{tab:aigc-map}
\begin{tabularx}{\linewidth}{@{}p{0.30\linewidth} c X@{}}
\toprule
\textbf{论文位置} & \textbf{标注} & \textbf{AI 参与方式、模型与日期}\\
\midrule
摘要 & \aigcC & 文字组织与润色;\texttt{deepseek-flash},2026-09-13 \\
问题重述 & \aigcC & 文字组织;\texttt{deepseek-flash},2026-09-13 \\
问题分析 & \aigcC & 思路梳理与文字组织;\texttt{deepseek-flash},2026-09-13 \\
模型假设、符号说明 & \aigcC & 文字组织与符号统一;\texttt{deepseek-flash},2026-09-13 \\
计时模型与会话状态机 & \aigcC & 由题面与接口说明整理,含公式排版;\texttt{deepseek-flash},2026-09-13 \\
问题一 & \aigcA & 推导文档整理、定理与反例的公式编排;\texttt{gpt-6-astra},2026-09-10。LaTeX 定稿改写由 \texttt{deepseek-flash} 于 2026-09-13 完成 \\
问题二 & \aigcA & 推导文档整理、解析候选盘的公式编排;\texttt{gpt-6-astra},2026-09-10。LaTeX 定稿改写由 \texttt{deepseek-flash} 于 2026-09-13 完成 \\
问题三 & \aigcC & 算法描述重写、伪代码与公式排版;\texttt{deepseek-flash},2026-09-13 \\
问题四 & \aigcC & 算法描述重写、伪代码与公式排版;\texttt{deepseek-flash},2026-09-13 \\
实验结果与分析 & \aigcC & 数据表整理、插图绘制与文字组织;\texttt{deepseek-flash},2026-09-13 \\
模型评价与推广 & \aigcC & 文字组织;\texttt{deepseek-flash},2026-09-13 \\
附录 A(正式测试验证) & \aigcC & 正式导出包核对、表格复算与文字组织;\texttt{deepseek-flash},2026-09-13 \\
附录 B(演练局数据清单) & \aigcC & 数据清单生成与文字组织;\texttt{deepseek-flash},2026-09-13 \\
附录 C(支撑材料与运行方法) & \aigcC & 运行说明整理与去敏感化;\texttt{deepseek-flash},2026-09-13 \\
附录 D(核心程序代码) & \aigcC & 代码摘录由 \pathtext{scripts/build\_core\_notebook.py} 生成;正文实现由 \texttt{deepseek-flash} 与 \texttt{gpt-6-astra} 参与编写,2026-09-10 至 2026-09-13 \\
\bottomrule
\end{tabularx}
\end{table}
说明三点。
其一,表中日期为对应内容在 AI 会话中的生成或改写日期,逐条时间、提示词与操作细节
另见本项目的《AIGC 使用合规记录》(\pathtext{docs/aigc-compliance-record.tex})。
其二,上述 AI 参与均限于文字组织、公式与代码排版、程序实现和绘图;
模型的推导结论、算法取舍与实验判断由参赛队员确认,AI 生成的程序与数据均经队员
实际运行与复算(演练局复算与评测机记录的最大计时偏差为 $0.000000$ s,见附录~\ref{app:formal})。
其三,AI 客户端的内部推理过程不作为论文依据;论文中的命题均给出可复核的证明或可复现的实验,
不以 AI 输出本身作为论据。
\section{核心程序代码}\aigcC
四问的求解核心集中在约 $5000$ 行的单文件程序中,按\textbf{公共层、几何与集合估计层、
覆盖保证层、策略层}四层组织;评测机、命令行外壳、数据采集与绘图脚本、
单元测试以及未被采用的方案不属于求解核心,不在此列出。
完整可执行程序为支撑材料中的 \pathtext{mcm26b-核心代码.ipynb},
\pathtext{src/mcm26b/} 保留与之逐字对应的模块化版本,两者函数名一一对应。
下列代码为无改动的摘录:函数体与注释与程序一致,只按核心程度取舍。
未收录的部分包括独立评测机(按附件协议复现模拟器,与求解代码零耦合)、
命令行入口、数据采集与论文绘图脚本、单元测试,以及经实测未采用的候选方案。
\input{data/source-listings}
+37
View File
@@ -0,0 +1,37 @@
\section{模型评价与推广}\aigcC
\subsection{模型的有效性}
本文采用集合估计处理有界测向误差,将每次观测转化为真实位置的可行约束,
这一条主线贯穿四问。
问题一通过凸包顶点计算直径,以最小包围圆半径给出清除充分条件;
问题二将接收距离要求表示为闭圆盘的交集,并由三角不等式构造显式可行子集。
几何定位、接收约束与清除距离因此由统一的集合运算联系起来,
而不是各自独立的经验规则。
多源搜索采用覆盖点集与检测状态矩阵维护各频道的搜索进度。
网格表示可处理负观测产生的非凸可行区域,
信息增益用于选择有利于收缩候选集的测点。
开放路径排序将移动、检测、换频和清除纳入统一目标,
并在新观测到来后重新求解任务次序。
对于定向源,位置与朝向的联合约束提供可见性信息,
凸组合性质给出方格点集的连续覆盖证明,
网格遍历清除则利用清除半径与方向无关的物理条件。
这些结论在自建模拟器上完成了闭环验证:本次采集的 $44$ 局演练全部清完全部源、
失败清除为零,问题三平均总虚拟时间 $\PractQThreeMean$ s、问题四 $\PractQFourMean$ s;
配对基线对比进一步说明,几何判据的精确性、覆盖证明与任务排序三者共同决定了最终效率。
六份官方正式测试则在附录~\ref{app:formal} 中提供了正式环境下的效率验证。
\subsection{参数影响的解析讨论}
主要参数的影响可由模型公式分析。
由 $a(\delta)=1500/(2\cos\delta)$ 得
$a'(\delta)=750\sec\delta\tan\delta$,其中 $\delta$ 以弧度计。
误差半角增大会扩大源位置的包围圆,并缩小保证接收圆盘。
表~\ref{tab:safeanalytic} 给出了两位小数舍入余量对首次可行区域的影响:
$1^\circ$ 与 $1.005^\circ$ 之间的差别在毫米量级,说明该判据对舍入余量稳健。
由式~\eqref{eq:coveragebound},环半径影响覆盖路径长度和最大覆盖距离。
默认半径保留约 $15.461$ m 的距离裕量。
减小网格边长可降低 $\epsilon_g$ 并收紧位置误差上界,
而二维网格数量大致与 $\ell^{-2}$ 成正比,因此应在精度、内存和计算时间间取得平衡。
同理,问题四的 $31$ 点计划在站点数量与覆盖余量之间构成一对可调参数:
设计阶段预留的 $5^\circ$ 前向角余量越大,所需站点越多,但对朝向扰动越稳健。
+197
View File
@@ -0,0 +1,197 @@
\section{问题一:有界误差交会定位与覆盖圆}\aigcA
\subsection{从示向度到前向角域的半平面模型}
交会定位的第一个困难在于,带误差的示向度只限制方向而不唯一确定位置。
由题设可知,示向度误差不超过 $\pm1^\circ$,故给定检测点 $s_i=(s_{ix},s_{iy})$ 与读数 $\theta_i$ 后,
真实方位必然落在 $[\theta_i-\delta,\theta_i+\delta]$ 内。据此,
真实位置属于以前向方向 $u(\theta_i)$ 为中轴的角域
\begin{equation}
W_i=\left\{g:
\begin{aligned}\relax
[u(\theta_i-\delta),g-s_i]&\ge0,\\
[u(\theta_i+\delta),g-s_i]&\le0,\\
u(\theta_i)\cdot(g-s_i)&\ge0
\end{aligned}\right\}.
\label{eq:wedge}
\end{equation}
三条不等式的意义并不相同。前两条把位置限制在左右边界之间,
第三条显式保留"只在前方"这一方向性,
从而使零误差的退化情形对应一条射线而不是整条直线。
为便于统一求解,将其改写为 $a x+b y\le c$ 的形式,法向依次为
\begin{equation}
\begin{aligned}
&(\sin(\theta_i-\delta),-\cos(\theta_i-\delta)),\\
&(-\sin(\theta_i+\delta),\cos(\theta_i+\delta)),\\
&(-\cos\theta_i,-\sin\theta_i),
\end{aligned}
\end{equation}
右端为相应法向与 $s_i$ 的内积。采用正弦、余弦表示还有一个工程上的好处:
$0^\circ$ 与 $360^\circ$ 的跨界无需特判即可自动处理。
由于所有角域都是凸的半平面交,多个测点的信息可以直接合并。
问题一的多边形定位区域因此定义为
\begin{equation}
P=\bigcap_{i=1}^{n}W_i=\{g:Ag\le b\}.
\label{eq:q1set}
\end{equation}
式~\eqref{eq:q1set} 根据各次测向角域确定问题一的定位区域;
后续问题将在此基础上加入圆域 $\Omega$ 与接收距离约束。
值得先说明的是,半平面交是闭凸集,可能为空集、单点、线段、有界多边形或无界集,
这些情形必须分别处理,否则"直径"与"覆盖圆"都没有定义。
\subsection{区域构造、空集及无界情形}
要求解式~\eqref{eq:q1set},只需枚举约束边界之间的交点再筛除不可行者。
令约束数 $k=3n$,对任意两条不平行边界
$a x+b y=c$、$d x+e y=f$,候选交点为
\begin{equation}
x=\frac{ce-bf}{ae-bd},\qquad y=\frac{af-cd}{ae-bd}.
\end{equation}
仅保留满足全部不等式的交点,再经去重和单调链凸包构造即得顶点集合。
数值上,实现先平移与缩放坐标,以降低千米尺度坐标带来的误差;
同时保留近平行边界的求交,因为其远端交点可能决定细长区域的直径。
顶点集确定之后,还需判断区域是否无界。为此对非空集合定义衰退锥
\begin{equation}
\mathcal R=\{d:Ad\le0\}.
\end{equation}
若 $\mathcal R$ 含非零向量,则 $g+td\in P$ 对所有 $t\ge0$ 成立,
区域无界、直径为 $+\infty$。二维多面锥只需检查约束边界的两个切向
$(b,-a)$ 与 $(-b,a)$ 是否满足全部齐次不等式。
由于本题至少一个前向窄角域会排除直线性,非空交集必存在极点,
故在该输入族中不存在可行边界交点却判为空集的情况;无观测输入单独返回整个平面,
不按空集处理。
有界非空区域中,一个顶点对应单点,两个顶点对应线段,其余为凸多边形。
空集没有本文定义的有效直径与覆盖圆,程序以显式状态报告观测不相容,
便于检查频道、误差界或输入数据。
\subsection{直径与直径圆的判定}
题目要求计算定位区域直径,并判断以该直径为直径的圆能否覆盖整个区域。
对前者,可以证明无需在区域内部搜索。
\begin{proposition}[顶点直径]
设 $P=\operatorname{conv}\{v_1,\ldots,v_m\}$ 非空有界,则
\begin{equation}
D(P)=\max_{i,j}\norm{v_i-v_j}.
\label{eq:diameter}
\end{equation}
\end{proposition}
\begin{proof}
任意 $x,y\in P$ 可表示为凸组合
$x=\sum_i\lambda_i v_i$、$y=\sum_j\mu_jv_j$。
由于系数非负且各自和为 $1$,
\[
\norm{x-y}
=\left\|\sum_{i,j}\lambda_i\mu_j(v_i-v_j)\right\|
\le\sum_{i,j}\lambda_i\mu_j\norm{v_i-v_j}
\le\max_{i,j}\norm{v_i-v_j}.
\]
最远顶点对本身属于 $P$,故上界可达。
\end{proof}
由命题可知,只需枚举顶点对即可,计算量为 $O(m^2)$。
至于第二个问题,结论比直觉更严格:最远顶点对的中点未必能覆盖整个区域。
\begin{proposition}[直径圆覆盖的充要条件]
取最远顶点对 $a,b$,令 $D=\norm{a-b}$、$o=(a+b)/2$。
存在直径等于 $D$ 的圆盘覆盖 $P$,当且仅当
\begin{equation}
\max_{v\in V(P)}\norm{v-o}\le D/2.
\label{eq:diametercircle}
\end{equation}
\end{proposition}
\begin{proof}
若半径 $D/2$ 的圆盘中心为 $z$ 且包含 $a,b$,则
$D\le\norm{a-z}+\norm{z-b}\le D$。
等号迫使 $z=o$。反之,圆盘为凸集,包含全部顶点即包含它们的凸包。
\end{proof}
证明过程同时说明:圆心被 $a,b$ 唯一确定,因此只需逐一检查其余顶点到该中点的距离。
若条件不成立,输出圆外顶点及超出量 $e=\max_v\norm{v-o}-D/2$,
即得到可独立检查的否定证据。换言之,不能仅以直径端点在圆周上判断整个区域被覆盖。
图~\ref{fig:q1geometry}(a)(b) 给出一组三点交会算例及其实例区域的放大,
(b) 中虚线为直径圆、实线为最小包围圆。
该算例的定位区域由 $\ExOneVertices$ 个顶点确定,直径为 $\ExOneDiameter$ m,
以该直径为直径的圆半径为 $\ExOneRadius$ m,
而最远顶点到圆心的距离超出该圆 $\ExOneExceed$ m,故直径圆并不覆盖定位区域;
其最小包围圆半径为 $\ExOneMec$ m,满足 $20$ m 的清除判据。
这说明直径不超过 $40$ m 与能否清除是两个不同的判据,覆盖判定必须逐顶点检查。
\subsection{反例与可清除半径}
上述差别并非数值巧合,而是几何上的必然。为说明这一点,
构造等边三角形
\begin{equation}
A=(0,0),\qquad B=(40,0),\qquad C=(20,20\sqrt3).
\end{equation}
其直径为 $40$ m。以 $AB$ 为直径的圆心为 $(20,0)$,半径为 $20$ m,
但 $C$ 到圆心的距离为 $20\sqrt3$ m,位于圆外。
其最小包围圆圆心为 $(20,20/\sqrt3)$,半径
$40/\sqrt3\approx23.094$ m,同样大于清除半径。
图~\ref{fig:q1geometry}(c) 展示两类圆的差别。
\begin{figure}[htbp]
\centering
\includegraphics[width=\linewidth]{geo-q1-geometry.png}
\caption{问题一的几何算例。(a) 三点交会:三条浅色示向度的角域边界与它们的交集(定位区域),
观测取自自建模拟器演练局 \texttt{8VRC-ADW4-XDXM-F62L} 的频道 $\ExOneChannel$;
(b) 该定位区域的放大:虚线为直径圆、实线为最小包围圆,
几何量由生产求解器 \texttt{mcm26b.geometry.solve} 现算;
(c) 等边三角形解析反例:虚线直径圆 $r=20$ m 不覆盖顶点 $C$,
实线最小包围圆 $\rho=40/\sqrt3\approx23.094$ m 覆盖全部顶点,该图不是模拟器观测。}
\label{fig:q1geometry}
\end{figure}
该三角形并非人为设定的特例,它可以由题设的 $\pm1^\circ$ 角域构造出来。例如检测点
$(-1000,0)$、$(540,-500\sqrt3)$、$(520,520\sqrt3)$,
对应示向度为 $1^\circ$、$121^\circ$、$241^\circ$。
各角域的一侧边界给出三角形的三条支撑线,另一侧边界包含整个三角形,
故交集恰为上述三角形。
既然覆盖判据不足以保证清除,就需要一个与清除动作直接对应的指标。
为此对一般候选区域定义最小包围圆
\begin{equation}
\rho(P)=\min_{z\in\mathbb R^2}\max_{g\in P}\norm{g-z},\qquad
m\in\arg\min_z\max_{g\in P}\norm{g-z}.
\label{eq:mec}
\end{equation}
其边界由至多三个支撑点确定,可用 Welzl 随机增量算法计算\cite{welzl}。
实现采用固定随机种子及显式栈,并在输出前检查全部顶点的包含关系。
在精确模型中,若 $\rho(P)\le20$,于 $m$ 清除即可覆盖所有可能真源;
考虑浮点计算后采用 $\rho(P)+\eta_{\mathrm{num}}\le20$ 的充分判据。
由此可见,$D(P)\le40$ 只是必要条件,并非充分条件。
\subsection{算法一与复杂度}
将上述判定串成流程,即得问题一的求解算法。
\begin{algorithm}[htbp]
\caption{有界测向角域交会与覆盖圆判定}
\label{alg:q1}
\begin{algorithmic}[1]
\Require 同一频道的检测点、示向度和误差半角
\Ensure 区域状态、顶点、直径、直径圆判定与最小包围圆
\If{观测为空}
\State \Return 无界
\EndIf
\State 归一化坐标,生成 $3n$ 条半平面约束
\State 枚举非平行边界交点,仅保留满足全部约束的点
\If{无可行点}
\State \Return 空集
\EndIf
\State 检查衰退锥;若存在非零方向,\Return 无界及无穷直径
\State 对可行交点去重并求凸包,区分单点、线段和二维多边形
\State 枚举最远顶点对,计算 $D$ 与中点 $o$,检查全部顶点是否在 $\B(o,D/2)$ 内
\State 计算最小包围圆 $\B(m,\rho)$,复核包含关系与数值余量
\State \Return $\rho+\eta_{\mathrm{num}}\le20$ 是否成立
\end{algorithmic}
\end{algorithm}
边界交点枚举需 $O(k^2)$ 次,每点校验 $k$ 条约束,主计算量为 $O(k^3)$;
凸包最坏需 $O(k^2\log k)$,直径枚举需 $O(m^2)$。
Welzl 算法在随机排列下具有期望线性时间。该求解流程适合少量观测,
当前入口限制最多 $100$ 个检测点;更大规模可替换半平面交算法。
综上,问题一给出两点结论:1. 带误差交会定位的直径可由顶点对枚举精确得到,
覆盖判定则必须逐顶点检查;2. 与清除动作真正对应的判据是最小包围圆半径不超过 $20$ m,
直径约束只是它的必要条件。
+198
View File
@@ -0,0 +1,198 @@
\section{问题二:保证接收的第二检测点选择}\aigcA
\subsection{候选位置集合与安全区域}
问题一说明了如何由多次观测确定位置,问题二则提出一个更早的问题:
在只测过一次的情况下,第二点应当选在哪里。
这里存在一对相互牵制的目标:若只追求大交会角,第二点可能远离源而收不到信号;
若只求保证接收,又可能缺少横向基线。要同时处理两者,
第一步是先刻画"由首次观测能推断出哪些位置"。
设首次有效示向度为 $(s,\theta)$,则有效读数除限定角域外,
还说明源距检测点不超过接收半径上界,故
\begin{equation}
K_1=\Omega\cap W(s,\theta,\delta_{\mathrm{eff}})\cap\B(s,R_+).
\label{eq:k1}
\end{equation}
其中 $R_+=1500$ 为有效接收半径上界。
$\direction$ 对应距离大于 $5$ m;式~\eqref{eq:k1} 采用其凸松弛,
使真实可行位置始终包含在所维护的候选集合中。
采用凸松弛而非精确的"挖去 $5$ m 小圆",是为了让后续的圆盘交运算保持凸性。
有了候选集合,第二步是把"保证接收"写成集合条件。
对非空紧集 $K$ 定义
\begin{equation}
F_K(q)=\max_{g\in K}\norm{q-g},\qquad
\mathcal Q(K)=\{q:F_K(q)\le R_-\}
=\bigcap_{g\in K}\B(g,R_-).
\label{eq:exact-safe}
\end{equation}
该区域内的任何点均在所有可能真源的最小接收范围内。
$F_K$ 是凸函数且为 $1$-Lipschitz,因而 $\mathcal Q(K)$ 是闭凸集。
由式~\eqref{eq:mec} 可知
\begin{equation}
\mathcal Q(K)\ne\varnothing\quad\Longleftrightarrow\quad\rho(K)\le R_-.
\end{equation}
这一步把第二点的鲁棒可行性转化为问题一已经解决的最小包围圆判据\cite{boyd},
两个问题由此共用同一套几何工具。
在线执行时,还需把解析区域换成可快速裁剪的表示。
为此用外切正多边形表示圆盘,再逐半平面裁剪。
若边数为 $M$、圆半径为 $r$,外切多边形顶点的半径为
$r\sec(\pi/M)$,其最大径向超出量准确写为
\begin{equation}
e_M(r)=r\bigl(\sec(\pi/M)-1\bigr).
\label{eq:outer-error}
\end{equation}
默认 $M=192$。由于整个圆盘已包含在多边形中,
裁剪后得到 $K_1\subseteq P^{\mathrm{out}}$。
算法求外包多边形 $P^{\mathrm{out}}$ 的最小包围圆 $\B(m,\rho_{\mathrm{out}})$。
在此基础上,由三角不等式可直接得到一个保守但显式的安全盘。充分安全盘为
\begin{equation}
\mathcal Q_{\mathrm{in}}
=\B\!\left(m,R_- -\rho_{\mathrm{out}}-\eta\right),\qquad
\eta=10^{-3}\ {\rm m}.
\label{eq:safe-disk}
\end{equation}
任意 $q\in\mathcal Q_{\mathrm{in}}$ 与真源 $g$ 满足
$\norm{q-g}\le\norm{q-m}+\norm{m-g}\le R_- -\eta$。
因此第二次检测一定为 $\direction$ 或 $\near$。
该构造适用于 $\rho_{\mathrm{out}}+\eta\le R_-$;
当候选区域较大时,程序先在其圆心追加观测,再更新可行区域。
\subsection{首次截断角域的解析候选盘}
上述安全盘依赖离散多边形,只能在程序内使用;题目还要求给出解析的候选区域。
为此暂去掉 $\Omega$,考虑 $S=W(s,\theta,\delta)\cap\B(s,R_+)$,
它的形状是一个被圆弧截断的角域。当 $0\le\delta\le45^\circ$,令
\begin{equation}
a=\frac{R_+}{2\cos\delta},\qquad c=s+a\,u(\theta).
\end{equation}
即可得到该区域的最小包围圆。
\begin{proposition}[截断角域最小包围圆]
上述 $S$ 的最小包围圆为 $\B(c,a)$。
\end{proposition}
\begin{proof}
任取 $g=s+t u(\theta+\varphi)$,其中 $0\le t\le R_+$、
$|\varphi|\le\delta$。有
$\norm{g-c}^2=t^2+a^2-2at\cos\varphi$。
该式关于 $t$ 为凸二次式,最大值在区间端点取得。
$t=0$ 时为 $a^2$;$t=R_+$ 时不超过
$R_+^2+a^2-2aR_+\cos\delta=a^2$,故全域被包含。
再取边界三点 $s,p_\pm=s+R_+u(\theta\pm\delta)$。
权重
$\lambda_\pm=1/(4\cos^2\delta)$、
$\lambda_0=1-1/(2\cos^2\delta)$ 非负且和为 $1$,
其加权中心为 $c$。三点均距 $c$ 为 $a$,
对任意圆心 $z$,加权平方距离等于 $a^2+\norm{z-c}^2$,
故至少一点距 $z$ 不小于 $a$。任何包含三点的圆半径均不小于 $a$。
\end{proof}
由于 $K_1\subseteq S$,于是
\begin{equation}
\boxed{
q\in\B\!\left(s+\frac{1500}{2\cos\delta}u(\theta),
1000-\frac{1500}{2\cos\delta}\right)}
\label{eq:q2-answer}
\end{equation}
即为题目所求的一种明确候选区域,实际使用时再内缩 $1$ mm。
该圆盘构成 $\mathcal Q(K_1)$ 的一个显式凸子集。
表~\ref{tab:safeanalytic} 给出两种误差半角下的具体数值。
可以看到,误差从 $1^\circ$ 放宽到 $1.005^\circ$ 时,
圆心偏移仅增加约 $0.001$ m,候选盘半径仅减少约 $0.001$ m,
说明该判据对题设的舍入余量并不敏感。
\begin{table}[htbp]
\centering\small
\caption{解析安全盘参数,由式~\eqref{eq:q2-answer} 直接计算}
\begin{tabular}{lrr}
\toprule
误差半角 & 中心沿首次方向偏移 $a$/m & 候选盘半径/m\\
\midrule
$1^\circ$ & 750.114246 & 249.885754\\
$1.005^\circ$ & 750.115391 & 249.884609\\
\bottomrule
\end{tabular}
\label{tab:safeanalytic}
\end{table}
在线算法继续使用 $\Omega$ 裁剪后的完整候选形状,
通常能够获得更紧的源包围圆与更大的充分安全盘。
两者的分工是清楚的:解析公式负责解释保证为何存在,
多边形流程负责利用已有的全部几何约束。
\begin{figure}[htbp]
\centering
\includegraphics[width=0.70\linewidth]{geo-q2-guaranteed-reception-disk.png}
\caption{第二点解析候选区域。左图为首次截断角域 $S$、
其最小包围圆 $\B(c,a)$ 与保证接收的候选盘 $\B(c,1000-a)$;
右图为半径分解,$a=1500/(2\cos\delta)$。取 $\delta=1^\circ$ 时
$a\approx750.114$ m、$1000-a\approx249.886$ m,与表~\ref{tab:safeanalytic} 一致。}
\label{fig:q2disk}
\end{figure}
\subsection{定位效果指标与有限候选求解}
保证接收只解决了一半问题,另一半是"在安全区域内如何让第二次观测最有效"。
理想的鲁棒选点模型为
\begin{equation}
\min_{q\in\mathcal Q_{\mathrm{in}}}
\left(\sup_{y\in\mathcal Y(q,K_1)}\rho(K_1\cap O(q,y)),
\frac{\norm{q-p}}{5}\right)_{\mathrm{lex}},
\label{eq:q2minimax}
\end{equation}
其中 $p$ 是当前机器人位置,$y$ 表示可能观测,
$O(q,y)$ 为相应观测可行集,下标表示按字典序比较:
先最小化最坏后验半径,再减少移动耗时。
方向分支取相应角域,近距离分支取 $\B(q,5)$。
这比仅优化交会角更直接地对应最终清除需求。
连续极小极大问题求解成本较高,当前算法采用有限候选近似。
在式~\eqref{eq:safe-disk} 的盘心及半径比例
$0.4,0.75,1.0$ 的三个环上各取 $12$ 个方向,
角度为 $(k+\tfrac12)2\pi/12$,共 $37$ 点。
对每个候选 $q$,在 $P^{\mathrm{out}}$ 边界以不大于 $60$ m 的间距采样,
包含全部顶点。对边界采样点 $g$ 枚举读数
$\operatorname{bearing}(q,g)\pm\delta_{\mathrm{eff}}$,
计算新角域交后的最小包围半径,并另外计算 $\near$ 分支;
取所得最大值作为 $\widehat J(q)$。
选取使 $(\widehat J(q),\norm{q-p}/5)$ 最小的点,
然后将边界采样间距加密至 $15$ m 复核其评分。
需要强调的是,$\widehat J$ 是最坏后验半径的\textbf{离散近似},
只用于比较有限候选点的定位效果;接收条件由式~\eqref{eq:safe-disk} 保证,
不受该近似影响。
\begin{algorithm}[htbp]
\caption{保证接收的第二检测点选择}
\label{alg:q2}
\begin{algorithmic}[1]
\Require 首次测点与示向度,或已更新的候选凸外包;当前位置
\Ensure 下一检测点、采样后验评分与接收保证状态
\State 初次调用时构造 $K_1$ 的外包多边形;后续调用沿用已有外包
\State 计算最小包围圆 $\B(m,\rho_{\mathrm{out}})$ 与安全盘半径 $b=1000-\rho_{\mathrm{out}}-10^{-3}$
\If{$b<0$}
\State 在候选区域圆心追加观测
\Else
\State 生成 $37$ 个安全候选点
\For{每个候选点 $q$}
\State 枚举外包边界样本与方向端点读数,补入近距离分支
\State 计算最坏后验半径 $\widehat J(q)$
\EndFor
\State 按后验评分优先、移动时间次优选点,并以 $15$ m 采样间距复核
\EndIf
\State 获得新观测后更新候选集
\If{观测为 $\near$}
\State 就地清除
\Else
\State 根据最小包围半径决定清除或追加测量
\EndIf
\end{algorithmic}
\end{algorithm}
若候选数为 $N_q$、边界样本数为 $N_g$、多边形顶点数为 $m$,
一次裁剪为 $O(m)$,总计算量主要为
$O(N_qN_g(m+C_{\mathrm{MEC}}(m)))$。
该算法复用问题一的角域模型与最小包围圆方法,通过多边形裁剪逐次更新候选集。
综上,问题二得到两点结论:1. "对所有可能真源均保证接收"等价于候选集合的最小包围圆半径不超过 $1000$ m,
据此可给出半径约 $249.885$ m 的显式安全候选盘;
2. 在安全盘内以最坏后验半径为第一目标、移动时间为第二目标选点,
既避免了"收不到信号"的失败模式,又保证了交会基线。
+210
View File
@@ -0,0 +1,210 @@
\section{问题三:全向多源的网格滤波与滚动调度}\aigcC
\subsection{统一时间目标与任务状态}
问题一、二分别给出了"能否清除"与"下一点选在哪里"的判据,
问题三把它们放进一个连续运行的闭环:源的数量未知,机器人必须自己决定何时发现、何时定位、何时清除。
在这样的任务中,优化的最终标准不是某一步的精度,而是完成任务所花的虚拟时间,
因此第一步是把时间写成可优化的目标。
按式~\eqref{eq:time} 的计时记账,优化目标是在全部源清除的约束下最小化虚拟耗时 $T$。
题目统计的平均定位清除时间是 $\bar T=T/N_c^+$;
由于清除动作本身的 $5$ s 是常数,该平均值不能代替总虚拟时间作为优化目标。
清除请求中的频道是目标频道,不改变测向机频道;
进入与退出均不增加虚拟时间,因此路径终点自由,无需返回原点。
这一自由度允许我们把任务序列当作开放路径而非回路来处理。
在时间目标之外,还需要一套能表达"这条频道到底还有没有源"的状态。
为此各频道的状态按"未知、已发现、可清除、已清除、已证无源"管理。
首次获得 $\direction$ 或 $\near$ 即确立该频道存在源。
最小包围圆判据决定清除时机,成功响应将状态更新为已清除。
频道的候选集为空,或其所有覆盖站检测结果均为无信号时,可判定该频道无源。
后一条判据依赖下一小节的覆盖证明,是本问题效率的关键:
只有能够严格举证"不存在",才能放心地停止检测。
当前测试程序默认采用 \texttt{BayesLoop}:七点计划只作为解析覆盖与无源举证;
证据层同时维护便于判据计算的凸候选集与逐频道网格幸存集,
后者统一吸收正负观测,负观测按最小接收半径删除整格,
候选集为空即给出缺席证明。定位测量按信息增益与移动代价选点,
覆盖、定位与清除三类任务组成统一任务表,用开放路径 2-opt 滚动重排,
并不执行七个站点对所有频道逐一全扫描的固定流程。
\subsection{七点解析覆盖与无源证据}
"证明某频道无源"要求对圆域内任意位置都保证有站点能收到信号。
为达到这一目的,取站点集合
\begin{equation}
S(a)=\{(0,0)\}\cup
\left\{a\left(\cos\frac{k\pi}{3},\sin\frac{k\pi}{3}\right):k=0,\ldots,5\right\}.
\label{eq:seven}
\end{equation}
即原点加正六边形顶点,共七点。其覆盖能力可以精确刻画。
\begin{proposition}[七点全向覆盖]
当 $0<a/\sqrt3\le R$ 时,任意 $g\in\Omega$ 到最近站点的距离不超过
\begin{equation}
D_{\mathrm{cov}}(a)=
\max\left\{\frac a{\sqrt3},\
\sqrt{R^2+a^2-\sqrt3Ra}\right\}.
\label{eq:coveragebound}
\end{equation}
\end{proposition}
\begin{proof}
设 $g$ 距原点为 $r$,其方位与最近环站的夹角不超过 $\pi/6$。
若 $r\le a/\sqrt3$,选取原点即可。
若 $r\ge a/\sqrt3$,由余弦定理,距最近环站的平方不超过
$r^2+a^2-\sqrt3ar$。
该凸二次式在 $[a/\sqrt3,R]$ 上的最大值于端点取得,
分别为 $a^2/3$ 与 $R^2+a^2-\sqrt3aR$。
\end{proof}
命题给出了一个可调的覆盖半径。当前 \texttt{bayes} 策略取 $a=1159.7$ m,
由式~\eqref{eq:coveragebound} 得 $D_{\mathrm{cov}}=984.539136$ m,
比最小接收半径小约 $15.461$ m。
因此每个合法全向源至少在一站可被接收。
某频道在七站全部为无信号,就构成该频道不存在源的严格证据。
以"站点、频道"为索引建立检测状态矩阵,记录各站对各频道的检测结果。
该矩阵用于逐频道的严格缺席证明;实际执行不要求在每个站点重测所有频道,
可由网格幸存集证明必为无信号的(站,频道)对会被跳过。
顺次从原点访问六个环站的开放路径长为 $6a$;
任务总路径由覆盖站间移动以及定位、清除所需的局部移动共同构成。
\subsection{正负观测的双重候选表示}
覆盖证明只回答"源是否可能被听见",要把一次具体检测转化为位置信息,
还需要更新候选集合。每个已发现频道维护凸外包 $P_c^{\mathrm{out}}$。
$\direction$ 将候选集与 $\B(s,1500)$ 外切多边形及测向角域相交;
$\near$ 与 $\B(s,5)$ 外切多边形相交。
难点在于全向源的 $\sgnless$ 观测,它意味着
\begin{equation}
\norm{g-s}>r_{\mathrm{eff}}\ge1000,
\end{equation}
即排除一个圆盘。圆盘的补集不凸,直接与凸候选集求交会破坏凸性。
为此,采用网格幸存集 $\mathcal G_c$ 表示负观测带来的空间约束,
同时保留便于几何运算的凸外包:前者负责吸收负信息,后者负责快速判据与选点。
网格边长为 $\ell=14.65$ m,每格中心与格内点的最大距离为
$\epsilon_g=\ell/\sqrt2$。初始保留所有可能与 $\Omega$ 相交的格,
按以下充分排除条件更新格心 $z$:
\begin{equation}
\begin{array}{ll}
\sgnless: & \norm{z-s}\le1000-\epsilon_g\ \Rightarrow\ \text{删除};\\
\near: & \norm{z-s}>5+\epsilon_g\ \Rightarrow\ \text{删除};\\
\direction: & \norm{z-s}>1500+\epsilon_g\ \Rightarrow\ \text{删除}.
\end{array}
\label{eq:gridupdate}
\end{equation}
三式的裕量 $\epsilon_g$ 保证只有整格必然越界时才删除,故真源所在格永不被误删。
方向观测另外检查角差。若 $d=\norm{z-s}>\epsilon_g$,
源所在格引起的方位偏差可由 $\arcsin(\epsilon_g/d)$ 上界;
实现采用距离内缩后的角误差界,并在测点附近保留所有可能方位。
只有角差超过 $\delta_{\mathrm{eff}}$ 加格内角裕量时才删除。
上述排除条件保持真源所在网格的可行性。
因此网格幸存集为空时,该频道无源。
若全部候选格心均满足 $\norm{z-s}>1500+\epsilon_g$,
则在 $s$ 测量必无信号,且所有候选网格已在最小接收圆盘外,
其观测的信息增益为零,可在检测状态矩阵中标记该推断结果,
从而节省相应检测与换频时间。
\subsection{信息增益选点与清除判据}
候选集收窄之后,还需决定下一个测点。
问题二的算法2提供满足接收约束的检测点;
问题三的 \texttt{BayesLoop} 进一步采用网格幸存集上的信息增益,
即优先选择最能缩小候选集的测点。
存在保证接收圆盘时,在其内部生成环形候选并补充当前接近方向上的测点;
其余情况下,在网格最小包围圆附近生成环形采样点。
候选集合同时包含当前位置与探索点,分别根据预期信息增益和移动代价评分。
对候选 $q$ 计算
\begin{equation}
J_{\mathrm{IG}}(q)=
\widehat{\mathbb E}\!\left[
\log\frac{|\mathcal G_c^{\,\mathrm{post}}(q,Y)|}{|\mathcal G_c|}
\right]
+\lambda\left(\frac{\norm{p-q}}5+\frac{\norm{q-m_c}}5\right),
\label{eq:ig}
\end{equation}
其中 $\lambda=0.05$,空分支用正的小值截断。
较小的候选集基数比对应较大信息增益,移动项限制为测量而产生的绕行。
评分最多取 $800$ 个子样本及 $7$ 个代表假设,
并以均匀 $r_{\mathrm{eff}}\in[1000,1500]$ 估计接收概率。
该决策采用离散假设上的加权期望,接收半径的均匀分布作为选点先验。
清除判断使用完整候选集合。由于清除要求在 $20$ m 内完成,
判据必须同时计入几何半径与数值余量。凸候选集的清除判据为
\begin{equation}
\rho_c+b_c+0.5\le20,
\label{eq:clearpoly}
\end{equation}
其中 $b_c\ge0$ 为代码的累计附加余量。
凸多边形包含真源,$\rho_c$ 是其最小包围半径;
$b_c$ 与 $0.5$ m 共同提供附加数值裕量。
若负观测使网格更紧,也可使用
\begin{equation}
\rho_{\mathrm{grid}}+\epsilon_g+0.5\le20
\label{eq:cleargrid}
\end{equation}
的网格清除判据,其中 $\rho_{\mathrm{grid}}$ 为候选格心的最小包围半径。
满足任一充分条件即可选择清除点。
利用剩余距离裕量,可将圆心向当前位置平移 $\Delta$;
只要平移后的距离上界仍满足对应不等式,三角不等式便保证清除条件成立。
\subsection{开放路径上的滚动任务排序}
到这一步,每个频道都已知"是否需要检测、在哪里检测、何时清除",
剩下的问题是如何把这些动作排成一条省时的路线。
统一任务表包含三类任务:覆盖站的批量扫频、已发现源的定位测量、
满足半径条件的清除。站内检测优先使用测向机当前频道,减少换频次数。
对任务序列 $\pi$,排序代价为
\begin{equation}
C(\pi)=\frac{\norm{p-q_{\pi_1}}}{5}
+\sum_{j=1}^{k-1}\frac{\norm{q_{\pi_j}-q_{\pi_{j+1}}}}5
+\sum_{j=1}^{k}t_{\pi_j}(c_{j-1}),
\label{eq:route}
\end{equation}
其中服务时间 $t_{\pi_j}$ 依赖进入任务时的频道,清除不改变该频道。
从最近邻初序开始,默认最多进行 $4$ 轮开放路径 2-opt 改进;
每次只执行当前序列的首任务,得到新观测后重新生成和排序。
这样新发现的源、收缩后的清除点和已证无源的频道都能及时改变路线,
避免为一条已经失效的任务继续赶路。
已停靠位置可以顺带补测:要求此前未在该位置测过、距离保证成立、
尚处于定位阶段,且预测半径有足够收缩。追加测量的费用为检测与换频时间,
其收益来自节省额外移动。题设固定同地误差,因此优先选择新的检测位置。
\subsection{算法三与完成条件}
将上述模块串成闭环,即得问题三的求解算法。
\begin{algorithm}[htbp]
\caption{网格幸存集滤波、信息增益选点与滚动调度}
\label{alg:q3}
\begin{algorithmic}[1]
\Require 题设参数、七站计划与合法观测接口
\Ensure 逐频道处理状态与会话统计
\State 检验七点覆盖条件,初始化频道状态、凸候选集、网格幸存集和检测状态矩阵
\State 调用 $/enter$,记录位置、频道和剩余现实预算
\While{存在未处理频道且预算充足}
\State 构建覆盖、定位和清除三类任务
\State 用网格幸存集跳过必为无信号的检测
\State 按最近邻与开放路径 2-opt 排序任务表
\State 执行首任务,根据真实响应更新凸候选集与网格幸存集
\If{满足清除判据}
\State 执行清除;成功则更新状态,失败则追加观测
\EndIf
\If{已清除 $16$ 个源或所有频道均被清除或证明无源}
\State \Return 报告完成状态
\EndIf
\EndWhile
\State 预算不足或异常时退出并报告未解决频道
\end{algorithmic}
\end{algorithm}
"清除数达到 $16$"利用题设数量上界。
对任意已存在的 $16$ 个不同频道,也可提前排除其余未知频道,
但已发现而未清除的源仍必须继续处理。
覆盖条件用于判定搜索范围,清除充分条件用于确定操作位置。
当前每轮追加有效定位测量上限为 $8$;
停滞、协议异常或预算耗尽时,记录各频道状态并终止。
程序以接口返回的现实预算为准,并预留退出时间,
实际计时在整数微秒状态上累计,避免用实机运行秒数代替虚拟动作耗时。
综上,问题三得到三点结论:1. 七点计划在环半径 $1159.7$ m 时给出 $984.539$ m 的覆盖上界,
使"全站无信号"成为该频道缺席的严格证据;2. 网格幸存集把非凸的负观测纳入集合估计,
并使大量必然无信号的检测被跳过;3. 把覆盖、定位、清除统一为一条开放路径并滚动重排,
是压缩总虚拟时间的主要手段。
+229
View File
@@ -0,0 +1,229 @@
\section{问题四:混合源的前向半盘覆盖与联合信念}\aigcC
\subsection{定向观测模型与无信号歧义}
在问题三中,"无信号"只有一种解释:源太远。
一旦引入定向源,这唯一的解释就被打破——源可能只是背对着检测点。
因此本问的关键在于为无信号保留第二种解释。
设定向源位于 $g$,朝向为 $\psi$。在检测点 $q$ 可见的充要条件为
\begin{equation}
\norm{q-g}\le r_{\mathrm{eff}},\qquad
(q-g)\cdot u(\psi)\ge0.
\label{eq:visibility}
\end{equation}
边界属于可见半平面。可见且距离不超过 $5$ m 时返回 $\near$,
否则返回 $\direction$;任何一个条件失败均为 $\sgnless$。
问题二的可行区域满足距离约束,定向接收还需满足前向半平面约束。
对于已发现频道,位于该区域内的负观测反映朝向遮挡,
因此不应被当作距离证据;区域外的负观测则同时包含距离与朝向两种解释。
这一区分直接决定了后续信念表示的形式。
朝向约束也改变了覆盖的要求。问题三的七点计划只保证"至少一站距离足够近";
对定向源还要求该站位于源的前向半平面内,因此需要重新设计站点集。
向外发射的边界源需要在圆域外布置接收站点。
适用于混合源的站点集合 $S$ 应满足
\begin{equation}
\forall g\in\Omega,\ \forall\psi\in[0,2\pi),\
\exists s\in S:\quad
\norm{s-g}\le1000,\quad (s-g)\cdot u(\psi)\ge0.
\label{eq:halfcover}
\end{equation}
这是一项针对"位置、朝向"二元状态的全覆盖要求,而不是对位置的单变量覆盖。
问题三的七点计划不满足式~\eqref{eq:halfcover};当前测试程序改用 $31$ 点最小命中集与(位置×朝向)联合幸存集,
定位停滞时以有限格后备清除兜底。
\subsection{方格点集的连续覆盖性}
在设计具体站点之前,先考虑一个容易证明的结构:方格点集。
取 $S_{49}=\{(700i,700j):i,j=-3,\ldots,3\}$。
其网格方域包含 $\Omega$,每个源落在某个边长为 $700$ m 的闭方格内。
方格四角恰好同时满足距离与朝向两项要求。
\begin{proposition}[方格四角的定向覆盖]
$S_{49}$ 满足式~\eqref{eq:halfcover},对全向与任意朝向的定向源均保证发现。
\end{proposition}
\begin{proof}
设包含 $g$ 的方格四角为 $v_1,\ldots,v_4$。
四角距 $g$ 均不超过对角线长 $700\sqrt2<1000$。
由于 $g$ 是四角的凸组合,存在 $\lambda_i\ge0$、
$\sum_i\lambda_i=1$ 使 $\sum_i\lambda_i(v_i-g)=0$。
对任意朝向 $u$ 取内积,得
$\sum_i\lambda_i(v_i-g)\cdot u=0$,
故不可能四个角均满足 $(v_i-g)\cdot u<0$;
至少一角处于前向闭半平面,且同时满足距离条件。
\end{proof}
证明的关键是凸组合性质:四个方向的投影不可能同时为负。
该方案具有显式站点坐标和覆盖距离上界。不过在同样覆盖 $\Omega$ 的前提下,
网格方案的站点数并不经济,因此实际选点仍需借助集合覆盖模型。
\subsection{前向半盘最小命中集的31点方案}
把"每个位置与朝向组合至少被一个站点覆盖"写成整数规划,
就可以用远比网格稀疏的站点集完成同样的任务。
当前 \texttt{directional} 实现采用 \texttt{q4\_mincover\_v2} 计划。
在候选站点 $s_j$ 和离散目标状态 $(g_i,\psi_i)$ 上定义关联矩阵
\begin{equation}
A_{ij}=\mathbf1\{
\norm{s_j-g_i}\le r_{\mathrm{design}},
\ (s_j-g_i)\cdot u(\psi_i)\ge
\norm{s_j-g_i}\sin\gamma_{\mathrm{design}}\}.
\end{equation}
其中角度余量 $\gamma_{\mathrm{design}}$ 把"恰好落在可见边界"的情形排除在外,
使站点对朝向扰动保持稳健。站点筛选可写为集合覆盖模型
\begin{equation}
\min\sum_j z_j,\qquad
\sum_jA_{ij}z_j\ge1\ \ (\forall i),\qquad z_j\in\{0,1\}.
\label{eq:setcover}
\end{equation}
采用集合覆盖的贪心算法与冗余站点删除求近似解\cite{chvatal},得到 $31$ 个站点。
设计阶段使用 $965$ m 距离与 $5^\circ$ 前向角余量,
最终按 $15$ m 位置间距、$72$ 个朝向采样复核。
验证结果覆盖全部 $3\,256\,200$ 个离散状态,
最坏覆盖距离约为 $990.051$ m。
\begin{figure}[htbp]
\centering
\includegraphics[width=0.72\linewidth]{geo-q4-minimum-cover-31-points.png}
\caption{31 点最小命中集的几何分布与定向源的读图约定。
实心圆点为圆域内检测站($15$ 个),空心圆点为圆域外的检测站($16$ 个),
后者用于接收向外发射的边界源;
浅色扇形区域为源位置圆域 $\Omega$。
图中左侧以一个圆外检测站为例说明定向源的观测读法:
绿箭头是该源的发射朝向、浅绿细线扇形是它的 $\pm90^\circ$ 可见范围、
红色虚线是检测站在该点测得的示向度,三者共同说明
"有朝向遮挡时同一位置也可能测不到信号"。
离散校验不等同于连续覆盖证明。}
\label{fig:q4plan}
\end{figure}
从离散覆盖推广到连续覆盖时,需同时计入位置与朝向的离散化误差。
设任意实际位置距某采样位置不超过 $\varepsilon$,
实际朝向距其采样朝向不超过 $\alpha$,覆盖站点距采样位置为 $d$。
由三角不等式及单位向量差的上界,一组充分条件为
\begin{equation}
d+\varepsilon\le1000,\qquad
(s-g_i)\cdot u(\psi_i)\ge
\varepsilon+2d\sin(\alpha/2).
\label{eq:continuous}
\end{equation}
采样网格应覆盖 $\Omega$ 及其边界。本文对 $31$ 点方案采用离散集合覆盖模型,
对 $49$ 点方案采用上述连续覆盖定理;连续近似误差的控制将在未来工作中讨论。
\subsection{位置与朝向联合候选的保守更新}
站点解决"能否发现",而要完成清除还必须知道源在哪里、朝向如何。
这正是问题三的候选集表示不足以处理的部分:位置可行并不代表朝向可行。
对定向假设,在每个候选位置网格的中心 $z$ 附加 $H=24$ 个朝向档,
档宽为 $15^\circ$。令 $M_z$ 为仍可能的朝向掩码。
方向与近距离观测先更新位置约束,再保留可能覆盖检测点的朝向;
无信号时只有在整格处于 $1000$ m 保证接收盘内,才可删除必然可见的朝向。
记 $\beta=\operatorname{bearing}(z\to s)$、
$\Delta_\psi=7.5^\circ$,格内方位余量为 $\alpha_z$,
查表舍入余量为 $\eta_\psi=1.5^\circ$。
以 $d_\circ$ 表示圆周最小角差,保守保留条件为
\begin{equation}
\begin{aligned}
\text{正观测:}\quad&
d_\circ(\psi_k,\beta)\le90^\circ+\Delta_\psi+\eta_\psi+\alpha_z,\\
\text{盘内负观测:}\quad&
d_\circ(\psi_k,\beta)>90^\circ-\Delta_\psi-\eta_\psi-\alpha_z.
\end{aligned}
\label{eq:heading}
\end{equation}
第二行保留含有不可见方向的朝向区间,排除整个区间均可见的候选。
若格心距测点过近,格内方位可覆盖整个圆周,此时保留全部朝向。
在定向假设下,上述更新保持真源所在位置与朝向网格的可行性。
\subsection{可见性筛选与探点选择}
联合候选的第一个用途是给候选测点排序。
在混合场景中,一个测点是否值得去,取决于那里的候选源有多大可能正对着它。
对候选 $q$,以均匀接收半径假设给出距离权重
\begin{equation}
w_r(d)=
\begin{cases}
1,&d\le1000,\\
(1500-d)/500,&1000<d<1500,\\
0,&d\ge1500.
\end{cases}
\end{equation}
记 $\widetilde{\mathcal G}_c$ 为位置样本集,$b_z(q)$ 为与检测点 $q$ 相容的候选朝向档数,
采用如下\textbf{可见性权重}:
\begin{equation}
V(q)=\frac1{|\widetilde{\mathcal G}_c|}\sum_{z\in\widetilde{\mathcal G}_c}
w_r(\norm{z-q})\,\frac{b_z(q)}{24}.
\label{eq:visibility-score}
\end{equation}
分母 $24$ 为初始朝向档数,$b_z(q)$ 由保留朝向集合与预计算可见角区间的交集确定。
该权重用于衡量各候选点的相对检测价值,可直接避免"跑过去却因遮挡而无信号"的空跑。
候选族包括算法2给出的基础点、关于候选圆心的对跖点,以及
$0.5\rho,\rho,1.5\rho$ 半径上的八方向环点。
排除已被遮挡的重复点后,保留评分达到当前最大值 $70\%$ 的点,
并从中选择
\begin{equation}
\frac{\norm{p-q}}5+\frac{\norm{q-m}}5+6
\label{eq:q4score}
\end{equation}
最小者。常数 $6$ 是检测加换频的选点评分费用,
真实结算仍按当时频道计算。该规则优先避免完全遮挡的点,
再减少移动及后续接近距离。
联合集不可用时,返回算法2、对跖探点和环探的确定性顺序。
持续遮挡时转入基于距离约束的网格遍历清除。
\subsection{网格遍历清除与计算预算}
遮挡可能使定位长期无法收缩,此时需要一条不依赖朝向信息的兜底路径。
注意到清除是否成功只与距离有关,与源朝向无关,
因此可以放弃"先定位再清除"的顺序,改为逐格试探。
当一轮有效定位测量达到 $8$ 次,或连续遮挡探点达到 $4$ 次且候选区域仍较大,
对保守凸候选多边形建立边长 $20$ m 的方格覆盖。
保留所有与多边形相交的格子,并以格心作为清除点。
格内任一点到格心距离满足
\begin{equation}
\norm{g-z}\le10\sqrt2<20.
\label{eq:fallback}
\end{equation}
因清除与源朝向无关,只要真源保留在多边形中,
逐格清除必有一次到达其 $20$ m 内。
按最近邻顺序访问,首次成功即停止该频道的网格遍历。
兜底方案必须受预算约束,否则会挤占其他频道的处理时间。
若外包框宽、高为 $w,h$,保守格数上界为
\begin{equation}
B_{\mathrm{cell}}=
\left(\left\lceil\frac w{20}\right\rceil+2\right)
\left(\left\lceil\frac h{20}\right\rceil+2\right).
\end{equation}
当前格数硬上限为 $400$,现实预算需覆盖
$N_{\mathrm{cell}}\,t_{\mathrm{RTT},95}+t_{\mathrm{reserve}}$。
超过格数或预算上限即跳过并报告未解决;
全部清除点失败则保留候选集并记录异常。
在\textbf{候选区域包含真源、格数满足上限且预算足够}的条件下,
逐格访问可保证完成该源的清除。
\subsection{算法四与终止条件}
\begin{algorithm}[htbp]
\caption{前向半盘最小命中集、联合信念与后备清除}
\label{alg:q4}
\begin{algorithmic}[1]
\Require 混合源接口、定向覆盖计划与预算
\Ensure 已清除频道、未解决频道与停止依据
\State 加载覆盖计划;默认 $31$ 点按 $15$ m/$72$ 档校核,$49$ 点备选有连续证明
\While{存在未解决频道且预算充足}
\State 选择最近待测站,当前频道优先,批量检测未知频道
\State 更新凸位置候选与位置乘朝向联合幸存集;首次正观测后建立朝向候选
\While{频道尚未清除}
\State 按可见性概率筛选探点,取移动最省者执行测量
\If{满足半径判据}
\State 执行清除并跳出
\ElsIf{遮挡或定位停滞}
\State 检查格数与预算,允许则执行 $20$ m 方格后备清除
\EndIf
\EndWhile
\EndWhile
\State 主动退出时报告清除数与停止依据
\end{algorithmic}
\end{algorithm}
综上,问题四得到三点结论:1. 定向源使无信号具有距离与朝向两种解释,
候选集必须由位置扩展为位置与朝向的联合表示;2. 发现条件须由位置圆盘覆盖
提升为前向半盘覆盖,$31$ 点最小命中集以远少于网格的站点数完成该任务;
3. 清除与朝向无关这一物理性质可用于构造有界预算的兜底清除,
使遮挡不再导致任务无法完成。
+240
View File
@@ -0,0 +1,240 @@
\section{实验结果与分析}\aigcC
\subsection{实验设置与数据来源}\aigcC
本文的实验分两部分,职责严格区分。
\textbf{机制论证与定量结论}取自项目内自建模拟器
(\pathtext{referee},按题面附件 1、附件 2 复现的评测机)的演练局:
演练局可提供真实源位置、机器人轨迹和逐次检测读数,
因此能够支撑路径示意、机制分析与逐局的定量比较。
\textbf{最终效果验证}取自官方模拟器的六份正式导出包,
因无法获取真实位置点,只在附录~\ref{app:formal} 中报告清除数量、总虚拟时间与程序运行时间。
演练局由 \pathtext{scripts/run\_practice\_episodes.py} 采集:脚本启动评测机、
以固定种子开始一局演练,再用与 \texttt{mcm26b.cli run} 相同的生产策略对接接口,
真值与行为日志全部由评测机自己写入,策略端只看见 HTTP 响应。
采集批次共 $\PractTotalCases$ 局:问题三 $\PractQThreeCases$ 局全向源、问题四 $\PractQFourCases$ 局混合源,
源数覆盖 $10$ 至 $16$、接收半径覆盖 $1000$ 至 $1500$ m,问题四的定向源个数覆盖 $3$、$6$、$8$。
判定标准为"清完全部源 $\wedge$ 无缺席误判 $\wedge$ 主动退出 $\wedge$ 零异常 $\wedge$ 零失败清除",
本批 $\PractTotalComplete$ 局全部满足,因此可以直接作为当前实现的性能证据,
累计清除 $\PractTotalCleared$ 个源。
所有时间均按式~\eqref{eq:time} 的计时模型由动作序列独立复算,
复算值与评测机日志记录的\textbf{最大偏差为 $\PractMaxGap$ s},
说明本文的时间口径与模拟器实现完全一致,后文所有耗时数字均可重算。
为使"最优实现"的说法可检验,本文对每一问都准备了一个\textbf{朴素基线},
两者在同一算例上逐例配对比较:
问题一的基线用包围盒对角线代替真实直径,并以包围盒中心近似覆盖圆;
问题二的基线分别取"垂直首次示向度 $1000$ m 的 $90^\circ$ 交会点"与"候选集最小包围圆圆心";
问题三的基线用 $49$ 点($700$ m 步长)网格发现加就近服务;
问题四的基线则把问题三的两种策略原样搬用。
基线并非稻草人:它们在部分场景中有效,暴露的是"缺了哪一步"。
\subsection{问题一与问题二的配对对比}\aigcC
先看几何层的两个判据在数值上的表现。问题一用固定示例与随机交会算例
(共 $\ProjQOneExampleCases$ 例固定、$\ProjQOneRandomCases$ 例随机)对比两种实现,
见表~\ref{tab:q1compare}。
\begin{table}[htbp]
\centering\small
\caption{问题一:直径与覆盖判定的实现对比(时间单位:ms/例)}
\setlength{\tabcolsep}{3pt}
\begin{tabular}{p{3.4cm}rrrrr}
\toprule
实现 & 状态正确率 & 直径平均误差/m & 直径最大误差/m & 覆盖正确率 & 平均耗时/ms\\
\midrule
最优(固定 $\ProjQOneExampleCases$ 例) & 100.0\% & 0.000 & 0.000 & 100.0\% & $\ProjQOneFixedMsOpt$ \\
最优(随机 $\ProjQOneRandomCases$ 例) & 100.0\% & 0.000 & 0.000 & 100.0\% & $\ProjQOneRandMsOpt$ \\
基线(固定 $\ProjQOneExampleCases$ 例) & $\ProjQOneFixedStatusBase$ & $\ProjQOneFixedMaeBase$ & $\ProjQOneFixedMaeMaxBase$ & $\ProjQOneFixedCoverBase$ & $\ProjQOneFixedMsBase$ \\
基线(随机 $\ProjQOneRandomCases$ 例) & $\ProjQOneRandStatusBase$ & $\ProjQOneRandMaeBase$ & $\ProjQOneRandMaeMaxBase$ & $\ProjQOneRandCoverBase$ & $\ProjQOneRandMsBase$ \\
\bottomrule
\end{tabular}
\label{tab:q1compare}
\end{table}
由表可见,最优实现(半平面交 \(+\) 顶点对枚举 \(+\) 最小包围圆)
在固定与随机两类算例上的直径误差均为零、覆盖判定全部正确;
基线的直径平均绝对误差为 $\ProjQOneFixedMaeBase$ m(固定例)
与 $\ProjQOneRandMaeBase$ m(随机例),最大误差达 $\ProjQOneRandMaeMaxBase$ m,
覆盖判定正确率仅 $\ProjQOneFixedCoverBase$ 与 $\ProjQOneRandCoverBase$。
原因在于包围盒对角线只有在区域恰好与坐标轴对齐时才等于直径,
而基线的覆盖判据几乎恒判"覆盖",因此系统性偏乐观。
计算代价方向相反:最优实现平均 $\ProjQOneRandMsOpt$ ms,
基线 $\ProjQOneRandMsBase$ ms,说明精确判据并不以牺牲效率为代价。
问题二的差距出现在"保证接收"与"定位收缩"这对指标上,见表~\ref{tab:q2compare}。
入选标准是:安全盘内最坏后验半径越小越好,同时保证接收率必须为 $100\%$。
\begin{table}[htbp]
\centering\small
\caption{问题二:第二检测点选点策略对比($\ProjQTwoCases$ 例随机首次示向度)}
\setlength{\tabcolsep}{3pt}
\begin{tabular}{p{3.2cm}rrrrrr}
\toprule
选点方法 & 保证接收率 & 最坏后验均值/m & 中位/m & 平均收缩/m & 终值比 & 移动均值/s\\
\midrule
算法2(默认选点) & $\ProjQTwoGuaranteeOpt$ & $\ProjQTwoWorstOpt$ & 90.899 & 607.577 & $\ProjQTwoRatioOpt$ & 170.44 \\
参考:盘内网格枚举 & 100.0\% & $\ProjQTwoWorstRef$ & 91.349 & 605.841 & 0.106 & 170.28 \\
基线:垂直 $1000$ m & $\ProjQTwoGuaranteePerp$ & $\ProjQTwoWorstPerp$ & 90.775 & 601.356 & 0.116 & 200.00 \\
基线:候选圆心 & $\ProjQTwoGuaranteeMec$ & $\ProjQTwoWorstMec$ & 375.088 & 340.721 & $\ProjQTwoRatioMec$ & 136.29 \\
\bottomrule
\end{tabular}
\label{tab:q2compare}
\end{table}
初始候选半径均值为 $\ProjQTwoInitialRadius$ m。
由表~\ref{tab:q2compare} 可知:垂直 $1000$ m 基线的最坏后验半径与最优实现接近,
但保证接收率只有 $\ProjQTwoGuaranteePerp$——当真源位于角域远端时必然返回无信号,
这正是问题二所要避免的失败模式;候选圆心基线的保证接收率为 $\ProjQTwoGuaranteeMec$,
但最坏后验半径达 $\ProjQTwoWorstMec$ m,终值比 $\ProjQTwoRatioMec$,
相当于只收缩了一半,说明"保证接收"若脱离横向基线便几乎没有定位价值。
最优实现同时取得 $\ProjQTwoGuaranteeOpt$ 的保证接收率与
$\ProjQTwoWorstOpt$ m 的最坏后验均值,终值比 $\ProjQTwoRatioOpt$,
并与盘内网格枚举参考解($\ProjQTwoWorstRef$ m)相差不到 $2\%$。
\subsection{问题三:演练局结果与基线对比}\aigcC
问题三的闭环在 $18$ 个冻结场景上逐例配对运行,三种策略的结果见表~\ref{tab:q3compare}。
\input{data/project-q3-table}
三者的全清率都是 $100\%$,因此差别完全体现在代价上。
默认策略 \texttt{bayes} 的平均虚拟时间为 $\ProjQThreeMeanOpt$ s,
七点批量策略为 $\ProjQThreeMeanSeven$ s,
$49$ 点网格基线为 $\ProjQThreeMeanBase$ s;
相对基线,\texttt{bayes} 的平均降幅为 $\ProjQThreeDropOpt$、中位降幅 $\ProjQThreeDropMedianOpt$,
并在 $\ProjQThreeFasterOpt$ 个场景中全部更快。
代价的来源也很清楚:默认策略平均只需 $\ProjQThreeMeasuresOpt$ 次检测、
位移 $\ProjQThreeMoveOpt$ km,而网格基线需要 $\ProjQThreeMeasuresBase$ 次检测、
$\ProjQThreeMoveBase$ km。可见网格基线的开销主要来自"逐格走过去再检测",
而七点计划加网格幸存集把大量必然无信号的检测直接跳过,
再配合滚动任务排序把移动量压到约五分之一。
这一机制在真实演练局中得到复现。表~\ref{tab:q3practice} 给出问题三
全部 $\PractQThreeComplete$ 局全清演练局的直接统计。
\input{data/practice-q3-table}
$\PractQThreeComplete$ 局的源数覆盖 $10$ 至 $16$,全部实现清除数等于源数,
且没有一次失败清除;总虚拟时间集中在 $\PractQThreeMin$ 至 $\PractQThreeMax$ s,
平均 $\PractQThreeMean$ s,平均定位清除时间 $\PractQThreeMeanClear$ s/个。
随源数增加,总虚拟时间只从约 $3.0\times10^3$ s 增长到约 $4.0\times10^3$ s,
说明发现—定位—清除三个闭环的组织方式对源数量并不敏感。
\begin{figure}[htbp]
\centering
\includegraphics[width=0.94\linewidth]{selfbuilt-q3-search-clear-path.png}
\caption{自建模拟器演练局 \texttt{\PractQThreeMainCase}($\PractQThreeMainSources$ 个全向源)的搜索与清除路径。
折线为机器狗轨迹;每条浅色细射线表示一次 $\direction$ 检测测得的示向度,
射线起点即发起该次检测的位置;圆点为测到示向度的检测点($55$ 次),
菱形为测到近距离的检测点($1$ 次),灰色叉号为无信号检测点($29$ 次);
星号为成功清除点,金色叉号为干扰源真值。全部数据由自建模拟器真值输出。}
\label{fig:selfbuiltq3}
\end{figure}
图~\ref{fig:selfbuiltq3} 给出其中一局(\texttt{\PractQThreeMainCase},
$\PractQThreeMainSources$ 个源)的完整路径。
机器人先按七点计划完成覆盖与批量扫频,再围绕候选区域执行定位与清除;
清除点与源真值基本吻合,轨迹在多个源之间跳跃后逐步收敛。
该局共检测 $\PractQThreeMainMeasures$ 次、换频 $\PractQThreeMainSwitches$ 次,
移动 $\PractQThreeMainMove$ km,总虚拟时间 $\PractQThreeMainTime$ s,
程序运行时间仅 $\PractQThreeMainRun$ s。
\subsection{问题四:演练局结果与基线对比}\aigcC
问题四的困难来自遮挡,因此对比的重点不只是时间,还包括"是否真的全部清除"。
表~\ref{tab:q4compare} 给出三种策略在 $11$ 个混合源场景(含 $5$ 个边界定向源场景)上的结果。
\input{data/project-q4-table}
由表~\ref{tab:q4compare} 可见,把问题三的策略直接搬用会产生两类不同后果。
\texttt{bayes} 的七点全向缺席判据会把朝外发射的定向源误判为"不存在",
因而出现 $\ProjQFourAbsentBase$ 次缺席误判、全清率只有 $\ProjQFourClearBase$,
其平均虚拟时间($\ProjQFourMeanBase$ s)虽然最短,却是"快而错",
不能作为有效结果;$49$ 点网格策略的发现是完备的,
但没有后备清除,定位停滞时只能停在"已发现"状态,全清率 $\ProjQFourClearGrid$,属于"稳而不全"。
默认策略 \texttt{directional} 在全部 $\ProjQFourValidOpt$ 局有效,
全清率 $\ProjQFourClearOpt$,缺席误判为零,平均虚拟时间 $\ProjQFourMeanOpt$ s,
平均需要 $\ProjQFourFallbackOpt$ 次后备清除——正是这部分兜底动作
换来了网格与批量策略都达不到的完备性。
演练局进一步显示了遮挡造成的额外代价。表~\ref{tab:q4practice} 给出
全部 $\PractQFourComplete$ 局全清混合源演练的统计。
\input{data/practice-q4-table}
与问题三相比,混合源场景的检测次数增加约 $3$ 倍(平均 $\PractQFourMeasures$ 次
对 $\PractQThreeMeasures$ 次),移动距离约 $\PractQFourMove$ km(对 $\PractQThreeMove$ km),
总虚拟时间平均 $\PractQFourMean$ s,平均定位清除时间 $\PractQFourMeanClear$ s/个,
约为全向源场景的 $2.6$ 倍。原因在机制上是明确的:
一次无信号观测不再等于"源在远处",而可能只是朝向遮挡,
因此必须先用若干探点排除遮挡解释,才能继续收缩位置候选集。
本批 $\PractQFourComplete$ 局全部做到"清完且无失败清除",
说明可见性筛选加后备清除在定向源个数 $3$ 至 $8$ 的范围内是稳定的。
\begin{figure}[htbp]
\centering
\includegraphics[width=0.94\linewidth]{selfbuilt-q4-search-clear-path.png}
\caption{自建模拟器演练局 \texttt{\PractQFourMainCase}($\PractQFourMainSources$ 个源,
其中 $\PractQFourMainDirectional$ 个定向源)的搜索与清除路径。
$\mathbf{X}$ 为干扰源真值,每个定向源用"绿箭头(发射朝向)$+$ 浅绿细线扇形($\pm90^\circ$ 可见范围)$+$ 角度标注"表示;
每条浅色细射线表示一次 $\direction$ 检测测得的示向度,射线起点即发起检测的位置;
圆点为测到示向度的检测点($72$ 次),菱形为测到近距离的检测点($3$ 次),
灰色叉号为无信号检测点($84$ 次,其中相当一部分由朝向遮挡造成),星号为成功清除点。}
\label{fig:selfbuiltq4}
\end{figure}
图~\ref{fig:selfbuiltq4} 给出含定向源的一局(\texttt{\PractQFourMainCase},
$\PractQFourMainSources$ 个源、其中 $\PractQFourMainDirectional$ 个定向)的路径。
定向源的前向半盘造成大量无信号观测,轨迹比全向源局密集得多;
可见性筛选把探点优先放在朝向相容的位置,后备清除则在定位停滞时兜底完成清除。
该局共检测 $\PractQFourMainMeasures$ 次、换频 $\PractQFourMainSwitches$ 次,
移动 $\PractQFourMainMove$ km,总虚拟时间 $\PractQFourMainTime$ s。
\subsection{动作耗时分解}\aigcC
上面的对比说明"哪种策略更快",还需要说明"时间花在哪里"。
把式~\eqref{eq:time} 重排,得到累计移动时间
\begin{equation}
T_{\mathrm{move}}
=T-5N_m-N_s-5N_c^+-3N_c^-.
\label{eq:residual}
\end{equation}
据此可把每局的总虚拟时间拆成移动、检测、换频与清除四项,见表~\ref{tab:cost}。
\input{data/practice-cost-summary-table}
\begin{figure}[htbp]
\centering
\includegraphics[width=0.86\linewidth]{practice-virtual-time.png}
\caption{自建模拟器演练局的总虚拟时间分布。每个点代表一局,
实线段为该问题全清局的均值;横轴取对数刻度,
问题四(混合源)的整体耗时明显高于问题三(全向源)。}
\label{fig:practicetime}
\end{figure}
由图~\ref{fig:practicetime} 与表~\ref{tab:cost} 可见,
两类场景中移动时间都是主要成本,分别占 $\PractQThreeMoveShare$ 与 $\PractQFourMoveShare$,
因此缩短总耗时的主攻方向是减少移动,这与问题三相对基线的降幅主要来自位移下降相互印证。
清除动作本身只占 $\PractQThreeClearShare$ 与 $\PractQFourClearShare$,
说明"清除"不是时间瓶颈,真正的成本在于把机器人送到能清除的位置。
检测与换频合计占比不高,但因换频次数与移动路径耦合,
仍需一并计入路径排序,不能单独优化。
\subsection{本节结论}\aigcC
综合以上配对对比与演练局复算,可提炼出四点结论:
1. 几何层的精确判据不需要以效率为代价——问题一的最优实现误差为零而耗时更短,
问题二则在保证接收率为 $100\%$ 的同时把最坏后验半径压到基线的约五分之一;
2. 多源搜索的效率来自"证明不需要检测",网格幸存集与七点覆盖使默认策略的检测次数
和位移相对网格基线分别降到约四分之一和五分之一,平均虚拟时间下降 $\ProjQThreeDropOpt$;
3. 混合源场景必须为无信号保留朝向解释,否则会出现缺席误判;
默认策略以全清率 $100\%$、缺席误判 $0$ 和平均 $\ProjQFourMeanOpt$ s 的代价
换取了这种完备性;
4. 本次采集的 $44$ 局演练中,两类场景的全部源都被清除且失败清除为零,
移动时间占总耗时的 $\PractQThreeMoveShare$ 与 $\PractQFourMoveShare$,
是继续优化的首要对象;清除动作本身只占 $\PractQThreeClearShare$ 与 $\PractQFourClearShare$,
不是当前的时间瓶颈。
+61
View File
@@ -0,0 +1,61 @@
\section{计时模型与会话状态机}\aigcC
\begin{figure}[htbp]
\centering
\includegraphics[width=0.92\linewidth]{steps-state-machine.png}
\caption{会话状态机。进入后经 $5$ s 倒计时接口开放,主动退出或断连后进入关闭状态。}
\label{fig:statemachine}
\end{figure}
\subsection{动作耗时与累计虚拟时间}
题面将全部动作折算为虚拟耗时,见表~\ref{tab:actioncost}。
检测无论返回无信号、近距离还是示向度,均计 $5$ s;
清除成功计 $5$ s,其中光学定位 $3$ s、激光清除 $2$ s,
未命中目标时只支付光学检查的 $3$ s。
移动与换频没有独立指令,由相邻动作的位置与频道变化推断。
\begin{table}[htbp]
\centering\small
\caption{动作耗时规则。移动耗时等于直线距离除以 $5$ m/s。}
\begin{tabularx}{\linewidth}{l l l X}
\toprule
动作 & 指令 & 虚拟耗时/s & 说明\\
\midrule
进入 & \texttt{/enter} & 0 & 初始位置 $(0,0)$、初始频道 $1$\\
检测 & \texttt{/measure} & $5+$移动$+$换频 & 三种检测结果耗时相同\\
清除 & \texttt{/clear} & $5+$移动/$3+$移动 & 成功/未命中目标,均不切换测向频道\\
退出 & \texttt{/exit} & 0 & 路径终点自由,无需返回原点\\
换频 & 由检测推断 & 1 & 相邻 \texttt{/measure} 的频道变化\\
移动 & 由动作推断 & 距离$/5$ & 相邻动作的位置变化\\
\bottomrule
\end{tabularx}
\label{tab:actioncost}
\end{table}
设整个会话的移动距离为 $L$,检测、换频、成功清除与失败清除的次数分别为
$N_m,N_s,N_c^+,N_c^-$。忽略每段移动时间的微秒量化时,总虚拟耗时为
\begin{equation}
T=\frac{L}{5}+5N_m+N_s+5N_c^++3N_c^-.
\label{eq:time}
\end{equation}
式~\eqref{eq:time} 是后文任务排序的服务时间来源,
也是由官方累计量反推移动时间(式~\eqref{eq:residual})的依据。
图~\ref{fig:timingexample} 用附件的五步示例说明记账方式:
首次检测含移动 $100$ s 与检测 $5$ s,单步 $105$ s;
原地换到频道 $2$ 检测单步 $6$ s,累计 $111$ s;
清除目标频道 $3$ 未命中,移动 $80$ s 加光学检查 $3$ s,单步 $83$ s,累计 $194$ s;
清除不改变测向机频道,故随后原地以频道 $2$ 复测只需 $5$ s,累计 $199$ s,与附件一致。
\begin{figure}[htbp]
\centering
\includegraphics[width=0.55\linewidth]{timing-attachment-example-105-111-194-199.png}
\caption{附件计时示例的逐动作构成。移动项为距离除以 $5$ m/s,标题数字为该步合计。}
\label{fig:timingexample}
\end{figure}
\subsection{虚拟时间、现实预算与终止}
虚拟时间度量任务完成速度,现实预算约束程序能否继续发出请求,两者不能混用。
程序以 \texttt{/enter} 返回的 \texttt{remaining\_real\_duration\_s} 为准,
在每个动作前预留退出时间;虚拟时间以整数微秒累计,在线预测只用于规划与一致性核对。
因此后文的“耗时”一律指式~\eqref{eq:time} 的虚拟时间,程序运行时间在结果表中单列。
策略在预算不足或协议异常时主动退出并报告未解决频道,不以程序正常结束代替任务完成。
Binary file not shown.
-208
View File
@@ -1,208 +0,0 @@
# 几何计算示意图册
> 本册逐图给出坐标口径、关键量与图中各元素的含义。插图位于 [`figures/`](figures/),复现命令:
>
> ```bash
> uv run python scripts/make_figures.py --only geo-q1-convex-intersection-zoom,\
> geo-q1-diameter-circle-counterexample,geo-q2-guaranteed-reception-disk,\
> geo-q3-seven-point-coverage,geo-q4-minimum-cover-31-points
> ```
>
> 图中的数字由脚本现算:问题一调用生产求解器,问题三、四直接读覆盖计划与证书;
> 来源与 sha256 记在 [`figures/manifest.json`](figures/manifest.json)。
统一的坐标与符号约定:
- 世界坐标以 Ω 圆心为原点,$x$ 轴向右、$y$ 轴向上,单位**米**;
- Ω 是半径 $R=1800$ m 的圆盘;源的有效接收半径 $r_{\rm eff}\in[1000,1500]$ m;
- 示向度 $\theta$ 以 $+x$ 轴为 $0°$ 逆时针为正,误差半角 $\delta=1°$;
- 清除半径 $r_{\rm clear}=20$ m;
- "可保证清除" ⟺ 存在一点使整个候选区域落在该点 20 m 内 ⟺ $\rho\le 20$ m(充分)。
---
## 图 1 问题一:角域交会与定位区域
![问题一角域交会](figures/geo-q1-convex-intersection-zoom.png)
**左(总览)**:三个检测点(官方演练案例 `U5ZW-P9KN-TCAG-R7ST`,频道 9)
各自的**前向角域** $W_i=\{p:\angle(p-s_i)-\theta_i\in[-1°,+1°]\}$ 画成窄扇形
(2° 宽,图中放大成可见宽度);三者交集就是定位区域 $P$。检测点相距 600~900 m,
而 $P$ 的直径只有 24 m,所以左图里 $P$ 缩成一个点——这是**必须做局部放大**的原因。
**右(放大,视野 ±31.4 m)**:以最小包围圆圆心为中心:
- 浅蓝扇形 = 三个角域在放大框内的可见部分;三者**重叠成白色区域**= $P$;
- 红色实线多边形 = $P$ 的顶点边界(与左图同一个集合);
- 蓝色虚线圆 = **直径圆**,半径 $D/2=11.9984$ m,圆心是中点 $(-450.634,\ 508.944)$;
- 绿色实线圆 = **最小包围圆(MEC)**,$\rho=12.0686$ m,圆心 $(-449.977,\ 507.953)$。
**关键量(图 (c) 栏)**
| 量 | 值 | 判定 |
| --- | ---: | --- |
| 直径 $D(P)$ | 23.9967 m | 顶点对枚举(凸集上最远点必为顶点) |
| MEC 半径 $\rho$ | 12.0686 m | Welzl 算法 + 支撑点枚举对照 |
| 直径圆最大超出 $E$ | +0.6040 m | $E>0$ ⇒ **直径圆不覆盖** $P$ |
| $\rho\le20$ m | 成立 | ⇒ **存在可保证清除的点**(取 MEC 圆心) |
> 这两个结论不矛盾:题目问"直径圆能否覆盖"(答案:不能,$E>0$)
> 与"能否保证清除"(答案:能,$\rho\le20$ m)是**两个不同的问题**。
> $E$ 的定义:$E=\max_i\lVert v_i-o\rVert-D/2$,$o$ 为直径中点;
> 精确算术下最远顶点对就在圆周上,故 $E\ge0$,$E>0$ 即覆盖失败,
> 达到最大值的顶点就是可独立复核的失败证据。
---
## 图 2 问题一:直径圆不覆盖的反例
![直径圆反例](figures/geo-q1-diameter-circle-counterexample.png)
等边三角形布站($S_1(-1000,0)$、$S_2(540,-866)$、$S_3(520,901)$,示向度
$1°,121°,241°$,误差半角 $1°$)。三条 2° 宽的角域交出一个**等边三角形**
$P$:顶点 $(0,0)$、$(40,0)$、$(20,34.641)$。
- 直径 $D=40.0000$ m,最远点对是底边两端 ⇒ 直径圆圆心 $(20,0)$、半径 20 m;
- 到第三个顶点 $(20,34.641)$ 的距离是 $20\sqrt3\approx34.6410$ m > 20 m,
故**直径圆不覆盖**:$E=+14.6410$ m(图中箭头所指);
- 该反例的最小包围圆半径 $\rho=40/\sqrt3\approx23.0940$ m **> 20 m**,
属于"覆盖失败且无法保证清除"的更坏情形。
> 反例是**符合题设测向条件**的:把真实源放在三角形中心 $(20,20\sqrt3/3)$,
> 三个检测点的真实方位与读数偏差均小于 $1°$,且三个检测距离都小于 1500 m,
> 所以它不是"脱离测向模型的任意图形"。构造与证明见
> [`问题一解答.md`](问题一解答.md) 第六节。
---
## 图 3 问题二:保证接收的候选盘与安全盘
![问题二保证接收盘](figures/geo-q2-guaranteed-reception-disk.png)
**候选集**(首次观测之后可能的位置集合):
$$
K_1=\Omega\ \cap\ W(s_1,\theta_1\pm\delta)\ \cap\ B(s_1,\ 1500),
$$
即"Omega 内、首次角域内、且距离不超过最大接收半径"的三者之交。
**解析安全盘**:截断角域(扇形,半径 $R_{\max}=1500$ m、半角 $\delta=1°$)
的最小包围圆恰为 $B(c,a)$,其中 $c=s_1+a\boldsymbol u$($\boldsymbol u$ 为示向度单位向量),
$$
a=\frac{R_{\max}}{2\cos\delta}=\frac{1500}{2\cos1°}=750.1142\ \text{m}.
$$
于是对安全盘内任一点 $q$、扇形内任一点 $p$:
$$
\lVert q-p\rVert\le a+(1000-a)=1000\ \text{m}
\ \Longrightarrow\ q\ \text{必然收到源的信号},
$$
$$
\boxed{\ \text{安全盘半径}=1000-a=249.8858\ \text{m}\ }
$$
(严格非空;图中绿色实心圆,圆心 $c=(649.62,\ 375.06)$)。
第二检测点就在该盘内选,目标是**最小化最坏保守后验包围半径**,
移动与检测成本作次目标;交会角只用于同分筛选与可解释性说明。
> 图中 $a$ 与 1000 m 两个圆几乎重合是可预期的:$\delta$ 只有 $1°$,
> $a=R_{\max}/(2\cos\delta)$ 与 $R_{\max}/2$ 相差 0.0114%,
> 因此**安全盘的"安全"主要来自角域约束,而不是圆心位置**。
---
## 图 4 问题三:七点解析覆盖
![问题三七点覆盖](figures/geo-q3-seven-point-coverage.png)
**站点集**:原点 + 半径 $a$ 的六等分环,
$S(a)=\{(0,0)\}\cup\{a(\cos k\pi/3,\ \sin k\pi/3):k=0,\dots,5\}$。
**定理(`algo-3.md` §4.2)** 当 $0<a/\sqrt3\le R$ 时
$$
\max_{g\in\Omega}\min_{s\in S(a)}\lVert g-s\rVert
\le D(a):=\max\Bigl\{\frac{a}{\sqrt3},\ \sqrt{R^2+a^2-\sqrt3Ra}\Bigr\}.
$$
代入默认 $a=1159.7$ m、$R=1800$ m:
$$
D(a)=984.5391\ \text{m}<1000\ \text{m}
\quad(\text{几何余量 }15.46\ \text{m}).
$$
**图上看到的就是这个证明**:7 个半径 1000 m 的接收盘(浅绿,裁剪在 Ω 内)的
并集**完全覆盖** Ω,最坏点出现在 $(0,-1800)$(Ω 正下方边界,图中圈出),
到最近站点 $1159.7$ m(正下方环站)的距离恰为 984.54 m。
数值复核(脚本内 20 m 网格):Ω 内 25445 个采样点全部被覆盖,**缺口 0**——
解析上界与数值结果一致到小数点后 3 位。
**代价对比**:七点每轮 7 次检测即可证明"无源",49 点网格要 49 次;
巡回长度 $6a\approx6.96$ km(对照 49 点的 NN 巡回约 36.4 km)。
$a$ 的可行下界 $a_{\min}\approx1122.9558$ m(零余量),默认配置留 15 m 以上余量。
**为什么能"发现即证明"**:某频道若在**全部**站点都测得 `no_signal`,
由覆盖定理知该频道必无源(负观测只能排除该站点 1000 m 圆盘,而 $r_{\rm eff}\ge1000$ m),
于是可以安全销账;所有频道销账 ⇒ 完成证明成立 ⇒ 立即 `/exit`。
---
## 图 5 问题四:定向源的 31 点最小命中集与联合信念
![问题四最小命中集](figures/geo-q4-minimum-cover-31-points.png)
**覆盖语义变了**:定向源只向**朝向 $\pm90°$ 的前向半球**辐射,
所以"某站点附近一定收到"这件事必须同时考虑**源的位置与朝向**:
$$
\text{站点 }s\text{ 能发现源}\iff
\lVert s-\text{pos}\rVert\le r_{\rm eff}\ \wedge\
\angle\bigl(\text{heading},\ s-\text{pos}\bigr)\le90°.
$$
这个语义记作 `forward_half_disk`(图中右侧示意)。
**31 点最小命中集**(`q4_mincover_v2`,图中红点):
| 项 | 值 |
| --- | --- |
| 点数 | 31(离线贪心最小命中集,取代 49 点网格) |
| 设计参数 | $r_{\rm design}=965$ m + 前向角裕量 $5°$ |
| 运行期证书 | 15 m / 72 朝向档,325.62 万个 (位置, 朝向) 采样格,**缺口 0** |
| 最坏命中距离 | 990.051 m |
| 最近邻巡回 | 23.9 km ≈ 4776.8 s 虚拟时间 |
| 旧计划对照 | `q4_mincover_v1` 在 15 m/72 档下有 **566** 个缺口(粗采样过拟合) |
**位置 × 朝向联合信念**:负观测(`no_signal`)在问题四里**只约束朝向**——
它只能排除"朝向正对本站点"的那些朝向档,位置信息几乎不更新。
因此证据层维护网格 × 朝向档的联合分布,可见性判据必须与引擎一致
(距离 $\le r_{\rm eff}$ 且夹角 $\le90°$),并按格内角裕量保守裁剪。
当信念坍缩到有限格时启用**后备盲清**:就近到可疑格 `/clear`,
把盲清次数从 125.7 次/局压到 **4.3 次/局**。
> **本轮修复的正确性缺陷**:旧版 `no_signal` 的朝向裁剪规则反向、且漏计格内角裕量,
> 会删掉真源所在的朝向档。已修复,并由
> `tests/test_joint_belief.py` 的随机观测序列保留性测试固化。
---
## 附:把图接进论文
`docs/paper/main.tex` 目前用表格承载结论,插图按下例插入即可:
```latex
\begin{figure}[htbp]
\centering
\includegraphics[width=0.95\textwidth]{figures/geo-q1-convex-intersection-zoom.png}
\caption{问题一:角域交会得到的定位区域,以及直径圆与最小包围圆的关系。}
\label{fig:geo-q1}
\end{figure}
```
图片按 160 mm 宽排版。图内不含标题与图注,说明写在 `\caption` 与正文。
-215
View File
@@ -1,215 +0,0 @@
# 协议规则表、字段表与状态机(P0 交付)
依据:`issue/附件/附件1.docx`《模拟器使用说明》、`issue/附件/附件2.docx`《模拟器通信接口说明及编程指南》。
本文是人类可读版本;**可执行版本**是 `src/mcm26b/protocol/rules.py`(字段表与错误语义)、
`src/mcm26b/protocol/timing.py`(计时模型)与 `src/mcm26b/config.py`(全部常量),
三者由 `tests/test_protocol_timing.py`、`tests/test_protocol_client.py` 固化验收。
## 1. 动作与耗时规则表
| 动作 | 指令 | 虚拟耗时 | 说明 |
| --- | --- | --- | --- |
| 开始 | `POST /enter` | 0 | 初始位置 (0,0),初始频道 1;虚拟/程序时钟开始 |
| 检测 | `POST /measure` | 5 + 移动 + 换频道 | 无论结果(no_signal/near/direction)均为 5s |
| 清除 | `POST /clear` | 未发现 3 / 成功 5 + 移动 | 5 = 光学定位 3 + 激光清除 2;**不切换测向频道** |
| 结束 | `POST /exit` | 0 | 成功响应中 exit_reason 固定 `user_exit` |
| 切换频道 | 无独立指令 | 1 | 只由合法 `/measure` 的 channel 变化推断 |
| 移动 | 无独立指令 | 直线距离/5(m/s) | 由 `/measure` 或 `/clear` 的 position 推断 |
派生事实(易错点):
- 一次合法 `/measure` 完成后,测向机频道更新为本次检测频道;
- `/clear` 的 channel 只是目标频道,既不切频道、也不产生切换耗时,因此
"清除后原地再测"的耗时只取决于上一次 **/measure** 的频道;
- 只有 accepted=true 的请求推进虚拟时钟;`accepted=false` 的 virtual_time_s=0 不是当前时刻;
- 5 秒检测只是虚拟耗时,不要求现实等待。
## 2. 字段表
公共请求字段(4 条指令都必填):
| 字段 | 类型 | 约束 |
| --- | --- | --- |
| arena_id | string | 必须为 `"default"` |
| robot_id | string | 逐字节等于登录参赛队号;UTF-8 长度 1..64;无控制字符 |
| request_id | string | 会话内幂等键;UTF-8 长度 1..128;无控制字符 |
动作字段(实现见 `rules.ACTION_FIELDS`):
| 指令 | 字段 | 约束 |
| --- | --- | --- |
| /enter | (无附加) | |
| /measure | position{x,y}, channel | x/y 有限数值且 \|v\|<=2,000,000;channel 整数 1..20(1.0 亦接受,1.5 拒绝) |
| /clear | position{x,y}, channel | 同上;channel 是目标频道 |
| /exit | (无附加) | |
响应字段:
| 场景 | 字段 |
| --- | --- |
| 所有响应 | accepted, real_timestamp_ms, virtual_time_s |
| accepted=false | 仅上述 3 个字段(virtual_time_s=0) |
| /enter 成功 | + max_virtual_duration_s, max_real_duration_s, remaining_real_duration_s |
| /measure 成功 | + measure_result ∈ {no_signal, near, direction};direction 时另有 svd_deg(保留两位小数) |
| /clear 成功 | + clear_result ∈ {success, no_target_in_range} |
| /exit 成功 | + exit_reason = "user_exit" |
错误语义(必须同时检查 HTTP 状态与 accepted):
| 情形 | 结果 | 对 request_id 的影响 |
| --- | --- | --- |
| JSON 语法/重复键/缺字段/类型/坐标频道范围 | HTTP 400 | 不占用,修正后可复用 |
| 未知字段(含 position 下)、arena/robot 不匹配、测试状态拒绝 | HTTP 200, accepted=false | 不占用 |
| 动作被接受 | HTTP 200, accepted=true | 占用 |
| 同 ID 不同内容,或并发不同动作 | HTTP 409 | — |
| 网络失败重试同一动作 | 复用原 ID+原内容,服务器回放首次响应 | 不重复生效 |
| 429/500 | 可原样重试 | — |
| 404/405/413/415 | 确定性错误,不得重试 | — |
物理规则速查:Ω 半径 1800m;源数 10–16;频道 1–20;接收半径 [1000,1500]m(逐源未知);
near 阈值 5m;清除半径 20m(与定向朝向无关);定向覆盖 = 朝向两侧各 90°(含边界);
示向度误差幅度 ±1°,保留两位小数;虚拟限时 360000s;程序限时 1200s(以 /enter 的
remaining_real_duration_s 为准,不得假定恒为 1200);测试窗口 25 分钟。
## 3. 状态机
机器狗会话状态(`protocol.state.RobotState` + 客户端会话标志):
```
/enter accepted /exit accepted
[未进入] ───────────────▶ [已进入] ───────────────▶ [已退出]
│ accepted=false │ accepted=false │ 任何动作 accepted=false
└── 不变 └── 不变 └── 不变
```
[已进入] 状态内跟踪:position、测向机 channel、virtual_time_s。转移规则:
| 事件 | position | channel | virtual_time_s |
| --- | --- | --- | --- |
| /enter accepted | (0,0) | 1 | 0 |
| /measure accepted | ← 本次 position | ← 本次 channel | ← 响应值(=旧值+移动+切换+5) |
| /clear accepted | ← 本次 position | **不变** | ← 响应值(=旧值+移动+3或5) |
| /exit accepted | 不变 | 不变 | ← 响应值 |
| accepted=false / 网络 / 400 | 不变 | 不变 | 不变 |
虚拟时刻以最近一次 accepted=true 的响应为准;本地预测(timing 模块)只用于
规划与一致性核对,偏差记入 `RobotState.mismatches` 并写日志(strict 模式抛错)。
## 4. 计时示例逐步推演(附件1表2 = 附件2第10节)
| 步 | 指令 | 移动 | 换频道 | 动作 | 本步 | 累计 |
| --- | --- | --- | --- | --- | --- | --- |
| 1 | /enter | 0 | 0 | 0 | 0 | **0** |
| 2 | /measure (300,400) ch1 | 500m→100s | 0(初始即1) | 5 | 105 | **105** |
| 3 | /measure (300,400) ch2 | 0 | 1 | 5 | 6 | **111** |
| 4 | /clear (300,0) 目标ch3 | 400m→80s | 0(clear不切频道) | 3(未发现) | 83 | **194** |
| 5 | /measure (300,0) ch2 | 0 | 0(第3步后已是2,clear未改) | 5 | 5 | **199** |
| 6 | /exit | 0 | 0 | 0 | 0 | **199** |
验收:`uv run mcm26b sim-check` 通过完整客户端→本地模拟器链路复现
`[105, 111, 194, 199]`;`tests/test_protocol_timing.py::TimingModelTests`
逐步断言每个分项。
## 5. 客户端设计要点(P1 交付)
- **串行**:完全同步,一个动作未决不发下一个;
- **幂等重试**:请求体一次性序列化为 bytes,网络失败/429/500 时原样重发
(同 request_id 同内容),最多 `max_attempts` 次,指数退避;400/404/405/409/413/415 立即失败;
- **accepted=false**:抛 `ActionRejected`,状态不更新;virtual_time_s=0 不入时钟;
- **现实预算**:/enter 成功后 `deadline = monotonic() + remaining_real_duration_s`;
新动作前检查 `剩余 > reserve_exit_s`(默认 60s [工程]),/exit 豁免;
- **日志**:`SessionLog` 逐事件追加 JSONL(attempt/transport_error/accepted),
进程崩溃不丢已发记录,回放测试与 evaluation 复算共用同一格式;
- **本地预校验**:channel 范围、坐标有限性与 2e6 上限、robot_id/request_id 格式
在发送前拒绝(与服务器 400 语义一致,省一次往返)。
## 6. 策略层如何使用本协议(P3/P4 交付)
第 5 节的客户端是策略层唯一的事实来源;`belief`(候选集)、`planner`(选点与闭环)
不绕开它直接发请求。衔接约定:
- **串行不变**:闭环每个决策步只发一个动作,`measure`/`clear` 的返回值
(`MeasureOutcome`/`ClearOutcome`)是 belief 更新的唯一输入;
- **状态同步**:机器人位置/测向频道/虚拟时刻一律读 `client.state`,
频道规则(§3 状态机表)由状态机自动维护,策略层不自行推算;
- **预算驱动退出**:`DeadlineExceeded` 只在 `/exit` 之外的动作前抛出;
闭环捕获后立即 `/exit`(豁免检查),并把该局记为"未证明完成",
不与全清成功混记;
- **选点的接收保证**:选点器只在保证接收盘 B(mec, 1000-ρ) 内取点,
盘内任一点到候选集每点距离 < 1000 ≤ 最小接收半径,因此定位阶段
不会浪费 `no_signal`(ρ>1000 的一般候选集退化为探索 MEC 圆心,允许
no_signal,理由字段中如实标注);
- **清除证书**:候选集外包多边形半径(含近似误差与工程余量)
≤ 20m 才发起 `/clear`;证书有效但清除失败视为异常,先补测再重试,
不在同一证书上重复消耗 3 秒/次的失败清除;
- **停止条件与完成判定**(2026-09-11 用户决策后):找全证明达成
(每频道均"已清除或覆盖证明不存在",或清除数达 16 数量上界)后
**不提前退出**:按 `search.persistent_search`(默认开)只复扫未清除
频道,直到清除数达 16、实机预算耗尽或虚拟安全余量
(`virtual_reserve_s`,防触及附件2 §4.5 的 100 小时上限;
本地模拟器对达限后的动作以 accepted=false 兜底)不足——"扫到限时为止"。
summary 中 `completed` 表示任务证明完成(无中断且结束时每频道
CLEARED/ABSENT,或 16 清除);`accounted_virtual_time_s` 记录首次
证明找全的虚拟时刻(计算"平均定位清除时间"建议用它,而非复扫
耗尽后的最终时刻);`stop_reason` 记录循环结束原因。发现若干源、
连续 no_signal、候选采样为空都不是停止条件;
- **每步计时留痕**(同上决策):客户端每个被接受动作写一条 `step`
事件(实机墙钟耗时 `real_elapsed_s`/`real_since_enter_s` + 比赛虚拟
耗时分项 `virtual_cost`:移动=直线距离/5、切频道 1s、检测 5s、
清除成功 5s/未发现 3s),summary 以 `steps` 数组与 `step_totals`
汇总,并给出题面口径的 `avg_locate_clear_time_s`;
- **验收**:`tests/test_loop_q3.py` 在自建模拟器上覆盖 10/16/0 源、
近边界源、预算耗尽与故障注入;`uv run mcm26b run --robot-id <队号>
--self-test` 可离线复跑随机场景,正式模式去掉 `--self-test` 即对接
模拟器(日志用 `--log` 落盘,格式同 §5 JSONL)。
## 7. 定向扩展如何使用本协议(P5 交付)
问题4的定向源在**协议字段上与全向源完全不可区分**:`/measure` 仍只返回
no_signal/near/direction(direction 附 svd_deg),`/clear` 仍只看 20m 半径。
"该源是定向的"无法从报文读出,只能由观测推理。因此 §5/§6 的协议用法全部
照用,定向性只改变策略层的解释与决策:
- **发现阶段零改动**:49 点覆盖保证对定向源同样成立——源位于某网格单元
凸包内时,任意发射半平面(朝向 ±90°,含边界)必含至少一个顶点,且该
顶点距离 ≤ 700√2 ≈ 989.95 < 1000 ≤ 最小接收半径,覆盖阶段无需知道
源类型;
- **no_signal 联合约束基线**:定向源的 no_signal 约束的是"位置×半径×朝向"
联合假设,单独维护空间候选会被误删,基线**不据此删任何候选**
(`belief.update_measure` 对 no_signal 无操作);缺席证明仍只由完整覆盖
给出。唯一启用的推理:若 no_signal 发生在保证接收盘 B(mec, 1000-ρ) 内
(该盘内任一全向源必然可收),则只能由朝向遮挡解释 [观测推理]——该频道
记为"观测到定向",进入探点升级梯子:对 MEC 圆心取对跖方向复核(偏移
裁进保证接收盘),再绕 MEC、半径 = ρ 的圆环按 45° 步进探点。**几何边界
必须如实陈述**:环上可见弧没有下界——源可位于环上(|g−c| = ρ)且朝向
沿外切线,此时可见集退化为单个切点,固定步进环探可以全部漏过。梯子
只提高提前命中概率,不构成接收或命中保证;完备性完全由后备清除兜底。
被遮挡探点不消耗定位步数,单轮被遮挡探点(首次选点、对跖复核、环探
合计)达 `max_blocked_probes`(4 [工程])即转后备清除;
- **后备清除的协议用法**:定位停滞(候选集有界但未达 §6 清除证书)时,
对候选外包多边形构造 20m 有限圆盘覆盖(`fallback_clear_cells`:全局
半开网格索引、相交判定带正容差,格内任一点距某格心 ≤ 10√2 < 20m),
按"距机器人最近优先"逐格发 `/clear`(同频道、不同位置)——清除与朝向
无关 [题面],是定向源不依赖可见性的完备后备。两条预算硬门槛(任一
不满足即跳过并留痕,绝不盲扫):
- 格数上界:N ≤ `fallback_max_cells`(400 [工程]);外包框枚举先按
(⌈w/20⌉+2)(⌈h/20⌉+2) 做规模检查,宽候选集(如仅一次读数的 750m
截断角域,数千格)必须继续定位而非硬扫;
- 现实预算:N × `real_rtt_p95_s` + `reserve_exit_s` ≤ 剩余现实时间。
虚拟耗时上界 ≈ 移动 L/5 + 3N(全失败)或 3(N-1)+5(末次成功)。
后备 /clear 请求**计入总请求口径**:summary 的 `total_requests`
(measures+clears)与 `fallback_clear_attempts`(后备逐格尝试数)
如实上报——仅统计检测次数会明显低估现实耗时;
- **真源不误删**:no_signal、失败的 `/clear`(含后备逐格全失败)均不删
空间候选;后备全失败按守恒性破坏记异常(格心距格内任一点 < 20m,
理论上必命中);
- **停止条件与预算语义不变**:仍是清除数达 16、每频道均"已清除或覆盖
证明不存在"、现实预算耗尽(记未证明完成)三种;断连/协议错误/
守恒性破坏中断时同样尽力 /exit 并产出未完成 summary(`stop_reason`
记 `transport_failure`/`protocol_error`/`inconsistent_belief` 等,
附逐频道状态快照),不静默丢失会话;
- **验收**:`tests/test_loop_q4.py`(15 项:覆盖格无空洞与格线两侧保留、
退化多边形、格数上界公式;混合 10/16 源全清、朝向背离圆心的近边界源
不漏、批量种子回归;no_signal 不删候选;格数硬顶与预算跳过;后备
正路径命中与全失败异常留痕);`uv run mcm26b run --robot-id <队号>
--problem 4 --self-test` 可离线复跑混合场景(`--directional` 指定
定向源数),正式模式同 §6。
-178
View File
@@ -1,178 +0,0 @@
# 总体思路与流程图
> 插图:[`figures/flow-overall-architecture.png`](figures/flow-overall-architecture.png)(总体思路与算法主线)、
> [`figures/steps-state-machine.png`](figures/steps-state-machine.png)(执行步骤)、
> [`figures/timing-attachment-example-105-111-194-199.png`](figures/timing-attachment-example-105-111-194-199.png)(附件计时示例)。
> 复现:`uv run python scripts/make_figures.py --only flow-overall-architecture,steps-state-machine,timing-attachment-example-105-111-194-199`
本文给出四问的思路、端到端流程图、执行步骤与执行时间。
算法细节指向 [`algo-1.md`](algo-1.md)~[`algo-4.md`](algo-4.md),
协议细节指向 [`协议规则表与状态机.md`](协议规则表与状态机.md)。
---
## 1. 主线
把题面约束写成可计算的几何集合和计时账本,四问共用一套「证据 — 决策 — 执行」结构,
每问都给出可验证的保证:
| 问 | 保证 |
| --- | --- |
| 1 | 直径由顶点对枚举给出;最小包围圆半径 $\rho\le20$ m 时存在可保证清除的点 |
| 2 | 第二检测点取在解析安全盘 $B(c,1000-a)$(半径 249.8858 m)内,必然收到信号 |
| 3 | 七点计划覆盖整个 Ω(解析上界 984.5391 m < 1000 m),据此可判定频道无源 |
| 4 | 31 点最小命中集在 15 m / 72 朝向档证书下缺口为 0 |
![总体思路与算法主线](figures/flow-overall-architecture.png)
---
## 2. 四层结构
| 层 | 内容 | 作用 |
| --- | --- | --- |
| L0 题面抽象 | Ω 半径 1800 m;移动 5 m/s、检测 5 s、换频 1 s、清除 5 s / 3 s;观测 `direction/no_signal/near`;源 10~16 个,频道 1~20,定向源覆盖 ±90° | 后续推导只用这些量,不引入题面之外的信息 |
| L1 在线三层 | 证据层(候选集与粒子)、决策层(选点与任务表)、执行层(串行客户端) | 依赖单向向下,几何结论与调度启发式可分别测试 |
| L2 四问 | Q1 定位解算 → Q2 第二点选择 → Q3 全向搜索 → Q4 混合定向 | 后一问复用前一问的内核 |
| L3 三条闭环 | 发现、定位、清除 | 每环有明确的进入与退出条件 |
L0 的常量集中在 `src/mcm26b/config.py`,带 `[题面]` / `[工程]` 标注。
证据层只给出「可能在哪里」,决策层只读证据并产出动作,
执行层负责发送动作并维护虚拟时钟。
---
## 3. 四问思路
### 问题一
1. 检测点 $s_i$ 与示向度 $\theta_i$ 给出前向角域
$W_i=\{p:\angle(p-s_i)-\theta_i\in[-1°,+1°]\}$,定位区域是半平面交 $P=\bigcap_i W_i$;
2. 直径 $D(P)=\max_{i,j}\lVert v_i-v_j\rVert$ 只需枚举顶点对(凸集上最远点必为顶点);
3. 直径圆能否覆盖 $P$:唯一候选圆心是最远顶点对的中点。若 $a,b$ 同在该圆内,
三角不等式两处同时取等,圆心只能是 $ab$ 中点,因此只需在该点检查全部顶点;
4. 能否保证清除:最小包围圆半径 $\rho\le20$ m 时,停在 MEC 圆心即可清除。
这是充分条件,不是必要条件。
结论:直径圆不一定覆盖定位区域,见 [`geo-q1-counterexample.png`](figures/geo-q1-diameter-circle-counterexample.png);
官方演练案例是「覆盖失败但 $\rho=12.07$ m $\le20$ m,可保证清除」。
### 问题二
候选集 $K_1=\Omega\cap W(s_1,\theta_1\pm\delta)\cap B(s_1,1500)$。
截断角域(扇形)的最小包围圆为 $B(c,a)$,$a=R_{\max}/(2\cos\delta)=750.1142$ m,
故安全盘 $B(c,1000-a)$ 的半径为 249.8858 m,盘内任一点到扇形内任一点的距离
不超过 1000 m,即必然收到信号。在该盘内以最坏保守后验包围半径为主目标选点,
移动与检测成本作次目标,交会角只用于同分筛选。详见 [`algo-2.md`](algo-2.md)。
### 问题三
发现保证用七点计划(原点 + 半径 $a=1159.7$ m 的六等分环):解析上界
$D(a)=\max\{a/\sqrt3,\ \sqrt{R^2+a^2-\sqrt3Ra}\}=984.5391$ m < 1000 m,
Ω 内任意位置的源都在某站点 1000 m 内。证据层按频道维护候选集与粒子幸存集,
负观测按 `full_disk` 语义排除 1000 m 圆盘;决策层用信息增益选点,
任务表包含检测、定位、清除三类任务,排序为开放路径问题;
所有频道销账即完成证明成立,立即 `/exit`。
### 问题四
定向源只向朝向 ±90° 的前向半球辐射,覆盖语义改为 `forward_half_disk`。
七点在该语义下有缺口,改用离线贪心得到的 31 点最小命中集(设计半径 965 m,
前向角裕量 5°),并以 15 m / 72 朝向档的运行期证书校核(325.62 万个采样格,缺口 0,
最坏命中 990.05 m)。负观测只约束朝向,因此维护位置 × 朝向联合信念,
信念坍缩到有限格时使用后备盲清。详见 [`algo-4.md`](algo-4.md)。
---
## 4. 端到端流程
```mermaid
flowchart TD
S([开始:/enter 成功<br/>现实预算 1200 s 起算]) --> P0[读配置 ProblemConfig]
P0 --> PLAN{按问题选择覆盖计划}
PLAN -->|问题 3| S7[七点全向计划<br/>解析上界 984.54 m]
PLAN -->|问题 4| S31[31 点最小命中集<br/>forward_half_disk 证书]
S7 --> LOOP
S31 --> LOOP
subgraph LOOP[主循环:动作回合]
direction TB
NEXT[选下一个任务<br/>信息增益 / 最坏后验半径<br/>滚动 2-opt 排序] --> SEND[/发送动作/]
SEND --> RESP{accepted?}
RESP -->|false| FIX[不更新状态<br/>记录并重排任务]
RESP -->|true| CLK[更新虚拟时钟、位置、频道]
FIX --> NEXT
CLK --> OBS{观测类型}
OBS -->|direction| HIT[登记新源<br/>同频道安排第二点交会]
OBS -->|no_signal| NEG[负观测裁剪<br/>位置候选或朝向档]
OBS -->|near| SKIP[距离过近,换点重测]
HIT --> DONE{该频道 ρ ≤ 20 m?}
NEG --> DONE
SKIP --> DONE
DONE -->|是| CLR[/清除动作/]
DONE -->|否| NEXT
CLR --> LEDGER[覆盖账本销账]
LEDGER --> FIN{全部频道销账?}
FIN -->|否| NEXT
end
FIN -->|是| EXITQ[完成证明成立,立即 /exit]
EXITQ --> REP[日志复算与统计]
REP --> END([结束:虚拟时间即成绩])
classDef main fill:#dce6f1,stroke:#1f4e79,color:#1c2430
classDef acc fill:#f6dcd8,stroke:#b03a2e,color:#1c2430
classDef ok fill:#d8ece5,stroke:#1e7a5f,color:#1c2430
class NEXT,SEND,RESP,CLK,OBS main
class CLR,FIN,EXITQ acc
class LEDGER,REP ok
```
会话状态机与单次动作回合见 [`figures/steps-state-machine.png`](figures/steps-state-machine.png),
逐步计时示例见 [`figures/timing-attachment-example-105-111-194-199.png`](figures/timing-attachment-example-105-111-194-199.png)。
---
## 5. 执行步骤与执行时间
一次动作回合:本地预校验 → 发送 → 等响应计时 → 按响应更新状态。
异常时同 `request_id` 同内容重发,400 与 409 立即失败。
| 动作 | 虚拟耗时 | 说明 |
| --- | --- | --- |
| `/enter`、`/exit` | 0 s | 不改变虚拟时刻,`/exit` 不切频道 |
| 移动 | 直线距离 / 5 m·s⁻¹ | 同点不动为 0 s |
| 换测向频道 | 1 s | 仅 `/measure` 触发,`/clear` 不切换 |
| 检测 `/measure` | 5 s | 与返回结果无关 |
| 清除 `/clear` | 5 s / 3 s | 成功 5 s,未发现 3 s |
实测样例(评测机日志 `BBM9-HZG2-77N5-NKKC`,问题三演练,10 源全清):
| 项 | 数值 |
| --- | --- |
| 总虚拟时间 | 3134.643 s |
| 移动(里程 11.9 km) | 2379.6 s |
| 检测与清除动作(119 + 10 次) | 645.0 s |
| 换频(110 次) | 110.0 s |
| 现实耗时 | 1.889 s |
三项之和等于响应中的 `virtual_time_s`,与 `evaluation.recompute_virtual_time` 口径一致。
分解图见 [`figures/timing-measured-q3-10-sources.png`](figures/timing-measured-q3-10-sources.png),
定向局(`GM56-…`,虚拟 8703.766 s,现实 3.397 s)与复现命令见
[`执行时间与执行步骤.md`](执行时间与执行步骤.md)。
---
## 6. 交付物与验收锚点
| 问 | 算法文档 | 主要实现 | 锚点 |
| --- | --- | --- | --- |
| 1 | [`algo-1.md`](algo-1.md)、[`问题一解答.md`](问题一解答.md) | `src/mcm26b/geometry/` | 演练复算 $D=23.9967$ m、$\rho=12.0686$ m、$E=+0.6040$ m |
| 2 | [`algo-2.md`](algo-2.md) | `geometry/`、`belief/`、`planner/` | 安全盘半径 249.8858 m |
| 3 | [`algo-3.md`](algo-3.md)、[`algo-3-bayes.md`](algo-3-bayes.md) | `planner/bayes_loop.py`、`planner/seven.py` | 七点上界 984.5391 m < 1000 m |
| 4 | [`algo-4.md`](algo-4.md) | `planner/directional.py`、`belief/joint.py` | 证书缺口 0,最坏命中 990.05 m |
| 1–4 | [`最优与基线实现对比.md`](最优与基线实现对比.md) | `project/` | `uv run python -m project.run` |
优化过程与未采用的改动见
[`第三四问架构优化与运行提速方案.md`](第三四问架构优化与运行提速方案.md)、
[`第三四问图论与动态规划优化方案.md`](第三四问图论与动态规划优化方案.md)。

Some files were not shown because too many files have changed in this diff Show More