# mcm26b — CUMCM 2026 B题:无线电干扰源的快速自动定位与清除 统一框架:有界误差几何定位、主动选点、带覆盖证明的搜索、按真实动作耗时调度。 分析依据 `issue/B题.pdf`、附件1《模拟器使用说明》、附件2《通信接口说明及编程指南》。 - [四问建模分析与 P0–P7 实施计划](docs/B题建模分析与实施计划.md) - [协议规则表、字段表与状态机(P0 交付)](docs/协议规则表与状态机.md) - [问题一完整解答](docs/问题一解答.md) - [论文](docs/paper/main.tex) ## 项目结构 ``` src/mcm26b/ ├── config.py # 参数中心:题面常量[题面] + 工程参数[工程],唯一字面量来源 ├── protocol/ # P0/P1 字段表、计时模型、状态机、串行幂等客户端(已完工) ├── geometry/ # P2 角域交会、直径、MEC、问题二安全候选盘证书(已完工) ├── sim/ # 自建模拟器、故障注入、演练日志回放(测试专用,已完工) ├── belief/ # P3 逐频道候选集合 K_c(骨架) ├── coverage/ # P4 49点覆盖账本(骨架 + 网格生成) ├── planner/ # P3 选点 / P4 全向闭环 / P5 定向扩展(骨架) └── evaluation/ # 日志复算与统计(复算已完工) tests/ # pytest(兼容 unittest 风格),53 项 scripts/ # 采集、基准、可视化与校核脚本 output/ examples/ # 演练证据、算例与生成产物 ``` ## 快速开始 Python ≥ 3.10,依赖仅 `requests`(测试另需 `pytest`)。 ```bash uv sync # 安装(可编辑挂载本包) uv run pytest # 全部测试 uv run mcm26b sim-check # P0 自检:复现附件计时示例 105/111/194/199 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 会话日志; - `sim.LocalSimulator`:按附件语义复现模拟器(观测门限、定向覆盖角、幂等回放、 400/accepted=false 语义),真值只对测试端开放;`ScriptedFaultTransport` 注入断连/超时/500, `PlaybackTransport` 回放官方演练日志。 ```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、采样评估) | 🦴 骨架(证书已完工) | | P4 问题3全向闭环(49点覆盖、定位队列、清除、停止) | 🦴 骨架 | | P5 问题4定向扩展(联合约束、后备清除、预算) | 🦴 骨架 | | P6 加速与消融 | 🦴 未开始 | ## 采集与正式测试约束 本项目只使用官方**演练**采集观测,从未使用正式测试。`scripts/capture_practice.py` 不会启动测试:必须先在界面确认“问题3演练”、接口已就绪,再提供 `--practice-confirmed` 与本局案例编码。正式测试由团队按计划另行安排; 加密日志上传上限 2MB,程序避免异常高频循环。