Files
mcm-26-b/README.md
T
2026-09-12 16:58:25 +08:00

192 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# mcm26b — CUMCM 2026 B题:无线电干扰源的快速自动定位与清除
统一框架:有界误差几何定位、主动选点、带覆盖证明的搜索、按真实动作耗时调度。
分析依据 `issue/B题.pdf`、附件1《模拟器使用说明》、附件2《通信接口说明及编程指南》。
- [四问建模分析与 P0–P7 实施计划](docs/B题建模分析与实施计划.md)
- [协议规则表、字段表与状态机(P0 交付)](docs/协议规则表与状态机.md)
- [问题一完整解答](docs/问题一解答.md)
- [问题三搜索与总耗时改进方案(含七点覆盖证明和自建消融)](docs/algo-3.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)
## 项目结构
```
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)
output/ examples/ # 演练证据、算例与生成产物
```
## 独立评测机与 WebUI(referee/)
评测机已抽成独立包:`referee/`(uv workspace 成员,`uv sync` 自动挂载为 dev 依赖)。
参赛队运行时代码**零导入** referee,双方仅通过附件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 # 一键:起评测机→开演练局→闭环→汇总
```
- **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
截止/加密上传属官方服务器侧策略,本地不实现;示向度误差场与场景分布是测试假设。
## 快速开始
Python ≥ 3.10,运行时依赖仅 `requests`;测试/自检另需 `pytest` 与独立评测机
包(`uv sync` 一并安装)。
```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
```
## 问题一(P2,已完工)
给定同频道多个检测点及 ±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 基准与舍入敏感性
```
离线交互页:`output/q1/question1.html`。可选 PNG 重绘需要 Pillow 与 Windows
雅黑字体:`python scripts/render_q1_figures.py`;事件校核需要 Node.js:
`node scripts/verify_visualization.cjs`。二者仅为图形校核,非求解依赖。
## 协议基线(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`
回放官方演练日志。
本地模拟器默认执行至多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()
```
## 阶段状态(对照 P0–P6 计划)
| 阶段 | 状态 |
| --- | --- |
| 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定向扩展(联合约束、后备清除、预算) | ✅ 自建完成(官方演练待执行) |
| P6 加速与消融 | ✅ 七点批量(`--strategy seven`,官方演练 12/12)+ 贝叶斯闭环(`--strategy bayes` 默认,自建消融 −30.0%,[算法说明](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` 朝向规则反向缺陷 |
### 图论/DP 轮(2026-09-12,S1–S5)要点
- **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 个
响应时刻全部吻合。生产计时复算函数保持原样。
```bash
uv run python scripts/verify_q3_practice.py output/q3/practice/20260911-port2026
```
本项目只使用官方**演练**采集观测,从未使用正式测试。`scripts/capture_practice.py`
不会启动测试:必须先在界面确认“问题3演练”、接口已就绪,再提供
`--practice-confirmed` 与本局案例编码。正式测试由团队按计划另行安排;
加密日志上传上限 2MB,程序避免异常高频循环。