4000s上限优化

This commit is contained in:
2026-09-11 11:16:23 +08:00
parent 9cf94281a9
commit 7dedcd0629
202 changed files with 8609 additions and 38 deletions
+17 -8
View File
@@ -14,8 +14,11 @@
1. **感知层**:每频道一个贝叶斯后验(网格幸存集),融合全部正/负观测; 1. **感知层**:每频道一个贝叶斯后验(网格幸存集),融合全部正/负观测;
2. **决策层**:站点扫频、定位测量、清除三类任务统一建表,开放路径 2. **决策层**:站点扫频、定位测量、清除三类任务统一建表,开放路径
最近邻 + 2-opt 排序,每个动作后滚动重排(动态 TSP); 最近邻 + 2-opt 排序,每个动作后滚动重排(动态 TSP);
3. **选点层**:定位测量点按期望后验半径 + λ·移动时间评分(信息增益贪心 3. **选点层**:默认按期望log幸存占比和“到检测点、再接近源”的移动代价评分。
的半径代理形式),直指 20m 清除证书阈值。 已停靠位置可逐频道补交会观测,真实清除始终由完整角域证书批准。
2026-09-11 当前修订的审核与配对验收见 [三四问算法审核与优化](算法审核与优化-20260911.md)。
本文件第5节是早期版本的历史结果,不应当作当前默认参数的复算结果。
## 2. 网格幸存集滤波与真源保留定理 ## 2. 网格幸存集滤波与真源保留定理
@@ -56,11 +59,15 @@
评分(`BayesConfig.score_mode`): 评分(`BayesConfig.score_mode`):
- `radius`(默认):期望后验半径 —— 对 K 个代表假设(幸存格均匀抽样) - `radius`(可选):期望后验半径 —— 对 K 个代表假设(幸存格均匀抽样)
各自模拟一次测量的幸存分支,分支半径用幸存子采样的质心最大距离近似, 各自模拟一次测量的幸存分支,分支半径用幸存子采样的质心最大距离近似,
r_eff~U(1000,1500) 的不确定性解析积分(p_no_signal = (d−1000)/500); r_eff~U(1000,1500) 的不确定性解析积分(p_no_signal = (d−1000)/500);
总分 = E[半径] + λ·移动秒数(λ=0.1); 总分 = E[半径] + λ·移动秒数(λ=0.1);
- `entropy`:期望 log 幸存占比(香农信息增益在均匀先验下的形式)。 - `entropy`(当前默认,λ=0.0105):期望log幸存占比,加上λ乘以
当前点→候选检测点→候选源中心的移动秒数。来向对称候选补充固定全局方向网格。
这里的均匀先验、零误差代表读数和均匀接收半径是选点评分的工程假设,
不属于题面给定的概率模型;只有完整±1.005°角域与距离界参与安全证明。
λ 与半径同量纲,量级必须小:λ 过大时终局阶段"走 300m"的代价压过 λ 与半径同量纲,量级必须小:λ 过大时终局阶段"走 300m"的代价压过
"半径 35m→25m"的收益,选点器原地重测、收敛停滞(消融实测 λ≥0.5 时 "半径 35m→25m"的收益,选点器原地重测、收敛停滞(消融实测 λ≥0.5 时
@@ -70,13 +77,15 @@
每个决策点构建任务表并排序执行首个任务,随后滚动重排: 每个决策点构建任务表并排序执行首个任务,随后滚动重排:
- **站点任务**:七站(原点 + 1200m 环六点,覆盖半径解析上界 968.9m - **站点任务**:七站(原点 + 当前1159.7m环六点)上的UNKNOWN频道;
< 1000m)上仍待测的 UNKNOWN 频道;跳测规则与覆盖账本过滤; 构造时验证全向覆盖解析界小于1000m,跳测规则与覆盖账本过滤;
- **定位任务**:DETECTED 且无证书的频道,位置由信息增益选点产生; - **定位任务**:DETECTED 且无证书的频道,位置由信息增益选点产生;
- **清除任务**:有证书(凸或网格)的频道,目标为证书圆心。 - **清除任务**:有证书(凸或网格)的频道,可沿当前位置方向移动证书圆心,
但平移量与原半径之和不得超过清除证书阈值,节省最后一段接近路程。
排序 = 开放路径最近邻打底 + 2-opt 改进(`two_opt_passes` 轮,成本含 排序 = 开放路径最近邻打底 + 2-opt 改进(`two_opt_passes` 轮,成本含
移动 + 换频 + 动作耗时;终点自由不回起点)。这是 A2"站内最近邻服务 移动 + 换频 + 动作耗时;换频按路径顺序逐步传递当前频道,clear保持频道;
终点自由不回起点)。这是 A2"站内最近邻服务
队列"的推广:消融显示距离缩短约 24% 是主要收益来源。 队列"的推广:消融显示距离缩短约 24% 是主要收益来源。
停止条件与基线一致:清满 16(数量上界)或全部频道 CLEARED/ABSENT; 停止条件与基线一致:清满 16(数量上界)或全部频道 CLEARED/ABSENT;
Binary file not shown.
+102
View File
@@ -0,0 +1,102 @@
# 第三、四问算法审核与优化
依据:原始 `issue/B题.pdf` 第1—3页,重点为附录2(3)(4),并结合(1)(2)(5)(6)(8)与第三、四问要求。
审核起点为 `9cf9428` 的程序;最后一次官方第三问演练为 `3BW5-9R54-NZNA-MYB9`,
13/13源成功清除、虚拟总时间4058.709750秒。本轮改进验证使用本地模拟器,没有启动或消耗官方测试。
## 1. 题设约束及审查结论
附录2(3)中的交会是有宽度的角域交集。不能把两条示向线的交点当作精确真值,
也不能利用同地重测求平均缩小±1°误差。程序已保留完整角域及0.005°舍入裕量,
本轮继续使用该证据颁发清除证书。统计评分仅用于选点,不能替代保守几何证书。
附录2(4)要求逐频道检测,换频1秒;结合(5),每次停靠检测5秒且不能在移动中检测。
已有HTTP客户端是串行的,没有把20频道视为一次免费测量。缺陷在于规划成本和站点利用:
| 审核发现 | 影响 | 当前改进 |
| --- | --- | --- |
| 已停靠点只测UNKNOWN频道,已发现频道容易错失交会机会 | 之后为第二条方位线另走一段路 | 对DETECTED频道预测收缩;当前位置到整个候选集均小于1000m、未在此处测过且预测半径减少35%时,逐频道补测;每次仍支付5秒和实际换频成本 |
| 定位选点只计到测点的移动 | 测完后到清除区域的路程没有进入选点目标 | 加入候选检测点→候选源中心的接近代价,保留后续根据真实响应重新规划 |
| 候选方向固定在全局角度网格 | 与当前交会几何不对齐,可能产生多余绕行 | 增加以当前位置到候选中心为轴的对称候选;均仍位于距离保证盘内 |
| 路线代价中的service_s按初始频道一次估计 | 2-opt比较不同顺序时没有正确传递频道状态 | 路径成本逐任务传递频道,站内当前频道优先,clear保持频道;两个任务也比较完整开放路径成本 |
| 清除默认走到候选集包围圆心 | 未利用20米光学定位/清除范围 | 在证书允许范围内向当前位置平移目标;平移距离+原包围半径不超过阈值,保留三角不等式证明 |
| 七站环半径可调但没有执行覆盖校验 | 不合法调参可能把“都没测到”误作不存在 | 构造时检查解析覆盖界;不满足条件直接拒绝运行 |
| 第四问盘外探点无信号也可能记为定向遮挡 | 把接收距离不足误诊为已确认定向 | 仅当实际探点位于距离保证盘内才据无信号确认定向;盘外无信号保留不确定性 |
| 第四问发现一个源就离站定位,后续频道再返回原站 | 同站频道间产生长距离往返 | 保留49站定向覆盖,先逐频道扫完本站,再按当前位置就近处理已发现源 |
| 后备清除按初始位置距离静态排序 | 狭长候选集可能反复折返,且循环内无虚拟预算检查 | 每一步从当前位置选最近未处理格,并逐次检查虚拟预算 |
第三问所有源均为全向,才能用no_signal排除1000米圆盘。第四问源类型与朝向未知,
no_signal还可能是半平面遮挡,不能用上述排除规则,也不能直接沿用七站缺席证明。
本轮没有把BayesLoop套到第四问;第四问继续采用49站覆盖和独立的定向定位/后备清除。
回归用例包含(1800,0)向外发射的源:七站全无信号,49站中有站可检出。
七站覆盖界为 `max(r/√3, sqrt(R²+r²−√3Rr))`,前提是`0<r≤√3R`。
当前R=1800m、r=1159.7m,通过小于1000m的校验。网格滤波额外带Voronoi裕量,
故无源时仍可能留下边界格;此时完整七站覆盖可以证明缺席,不要求PF一定为空。
## 2. 验收口径
4000秒目标按整场虚拟总时间(包含移动、换频、全部检测、清除和缺席确认)比较,
没有在4000秒强行停止,也没有以只清除部分源或最后一次成功清除的时刻代替总时间。
题面表格的平均定位清除时间仍等于总时间除以实际清除源数。
第三问优化开发集固定为种子0—5、10/16源,加两个最小接收半径的圆周边界场景(14场)。
选择实现后停止调整,再运行种子100—105、10/13/16源的独立验证集(18场)。
同场景前后使用相同位置、频道、有效半径和逐点固定误差种子。
真值只传给本地模拟器和执行后的校验,不提供给算法;全部请求和响应保存。
有效运行要求:全部真实源清除、没有误判真实频道缺席、正常exit、无算法异常、逐步耗时复算一致。
| 第三问指标 | 旧版 | 改进后 |
| --- | ---: | ---: |
| 开发集全清且有效 | 14/14 | 14/14 |
| 开发集平均总时间 | 3812.97s | 3390.88s |
| 开发集最大总时间 | 5535.13s | 4624.97s |
| 开发集中小于4000s | 10/14 | 12/14 |
| 独立验证集全清且有效 | 18/18 | 18/18 |
| 独立验证集平均总时间 | 3799.72s | **3315.89s(减少12.73%)** |
| 独立验证集最大总时间 | 4569.47s | **3981.74s** |
| 独立验证集中小于4000s | 12/18 | **18/18** |
两个人工圆周边界场景改进后仍为4145.19s、4624.97s左右。因此本轮实现达成的是
独立验证组每场小于4000秒,**不是对全部合法题目场景的最坏时间保证**。
旧官方案例已经结束,无法对新路线查询其未知响应;本地结果不冒充官方同案例重跑。
更新后的官方成绩仍需新演练验证,不能由前后不同案例的数字直接得出提升比例。
## 3. 第四问结果
固定四场:10源/3定向,种子0、1;16源/8定向,种子2、3。覆盖朝向未知场景,
每场源分布与误差种子前后相同。旧版、改进版均4/4全清、正常退出、零异常和零计时偏差。
| 场景 | 旧版总时间 | 改进后总时间 |
| --- | ---: | ---: |
| 10源,种子0 | 18599.317s | 13652.140s |
| 10源,种子1 | 16709.225s | 14918.134s |
| 16源,种子2 | 16388.604s | 11635.398s |
| 16源,种子3 | 16983.270s | 12453.274s |
| 平均 | 17170.104s | **13164.737s(减少23.33%)** |
第四问尚未降到4000秒。保留域外49站是为未知朝向源提供发现证据;本轮优化减少重复移动,
没有用第三问假设缩小第四问覆盖范围。其后备清除仍是有预算上限的算法,不能据四场结果声称所有混合场景必定在预算内完成。
## 4. 数据及复现
- 第三问数据根目录:`output/q3/optimization-20260911/`,含冻结旧版代码、配置、逐场景真值、动作日志、summary及汇总。
- 最终开发集:`development/improved/results.json`;独立验证:`validation/verified/results.json`;对应旧版在各自`baseline/results.json`。
- 第四问:`output/q4/optimization-20260911/{baseline,improved}-{10,16}.json`。
- 中间开发试验也保留:同点补测、移动前瞻、路线终点、来向候选、路径计费及自适应发现。最终未采用均值变差的路线终点估计和未知频道自适应补扫。
- 回归测试:`pytest -q`,**166项全部通过**。新增用例验证串行6秒补测、不重复同地读数、频道状态成本、清除圆平移证书、无信号诊断及七站/49站的适用边界。
在项目根目录运行(label使用未存在的名称以保护已有证据):
```powershell
.venv/Scripts/python.exe scripts/benchmark_q3_revision.py --label rerun-development
.venv/Scripts/python.exe scripts/benchmark_q3_revision.py --label rerun-validation --suite validation
.venv/Scripts/python.exe scripts/benchmark_q3_revision.py --label rerun-baseline --suite validation --baseline
.venv/Scripts/python.exe scripts/benchmark_q4.py --seeds 0,1 --sources 10 --directional 3 --out output/q4/rerun-10.json
.venv/Scripts/python.exe scripts/benchmark_q4.py --seeds 2,3 --sources 16 --directional 8 --out output/q4/rerun-16.json
```
概率限制:网格幸存集是保守可行集,不是已知官方概率模型的精确贝叶斯后验。
均匀源分布、接收半径分布、代表读数和哈希误差均属测试或启发式假设。
完备覆盖与清除证书依赖题面给出的确定性边界,性能数字则依赖具体测试分布。
@@ -0,0 +1,429 @@
"""P4b 贝叶斯网格滤波闭环(问题3新策略 ``bayes``)。
在 :class:`OmnidirectionalLoop` 骨架(run/异常收尾/summary/预算/异常留痕)
上的三层重构,对应 docs/algo-3-bayes.md 的架构:
1. 感知层:每频道一个网格幸存集(particles.ChannelParticles),全部读数
(含 no_signal 负观测)即时更新;幸存集为空即缺席证明,无需等覆盖账本;
2. 决策层:统一任务循环——站点扫频、定位测量、清除三类任务合成任务表,
开放路径最近邻 + 2-opt 排序,每执行一个任务滚动重排(动态 TSP);
3. 选点层:定位测量点在保证接收盘(凸证书)或 PF MEC 探索环(宽候选集)
内按"期望 log 幸存占比 + λ·移动时间"评分(信息增益贪心)。
与基线 SevenBatch 的差异:负观测跳站/跳测(必 no_signal 的 (站,频道) 对
不消耗检测与换频)、PF 缺席证明提前证毕、全局任务排序替代"站内最近邻"。
清除证书仍以凸证书为主(PF 网格证书仅在负观测挖洞使幸存集更紧时提前
触发),两者均满足 Voronoi/保守裕量,不牺牲全清率。
"""
from __future__ import annotations
import math
from dataclasses import dataclass
from ..belief import ChannelStatus
from ..config import ProblemConfig, Vec2
from ..coverage import CoverageLedger
from ..particles import ChannelParticles
from ..protocol.client import SimulatorClient
from ..protocol.rules import DIRECTION, NEAR, NO_SIGNAL
from ..protocol.timing import move_time
from . import (ClearCertificate, OmnidirectionalLoop, clear_certificate,
candidate_points, safe_disk_radius, select_measurement_point)
from .seven import seven_points
@dataclass(frozen=True)
class Task:
"""统一任务表的一项。service_s 为不含移动的固有耗时(检测+换频/清除)。"""
kind: str # "station" | "locate" | "clear"
position: Vec2
service_s: float
channel: int | None = None
station_index: int | None = None
def _point_key(point: Vec2) -> tuple[int, int]:
"""候选点去重键:0.5m 网格取整(同一物理点不重复测量)。"""
return (int(round(point[0] * 2)), int(round(point[1] * 2)))
class BayesLoop(OmnidirectionalLoop):
"""问题3贝叶斯闭环:负观测感知 + 信息增益选点 + 滚动任务排序。"""
def __init__(self, client: SimulatorClient,
config: ProblemConfig = ProblemConfig()):
super().__init__(client, config)
self.ledger = CoverageLedger(
config, points=seven_points(config.bayes.station_ring_radius_m))
self.particles = {channel: ChannelParticles(config)
for channel in self.belief.channels}
self._measured_points: dict[int, set[tuple[int, int]]] = {}
self._clear_failed: set[int] = set() # 证书清除失败后须先补测再重试
self._stall: dict[int, int] = {} # 连续无收缩计数(异常留痕用)
self._skip_cache: dict[tuple[int, int], tuple[int, bool]] = {}
self.skipped_measures = 0 # 跳测规则省下的检测次数
self.no_shrink_measures = 0 # 未收缩幸存集的定位检测(诊断用)
self.pf_absent_channels: list[int] = [] # 由幸存集为空证明缺席的频道
# ------------------------------------------------------------ 主循环
def _coverage_phase(self) -> None:
"""统一任务循环:发现 + 定位 + 清除滚动调度,直到任务表为空。"""
while self.stop_reason is None:
if self._count_limit_reached() or self._virtual_cap_reached():
return
if not self._step_once():
return
def _step_once(self) -> bool:
"""构建任务表、排序并执行首任务;无可执行任务返回 False。"""
tasks = self._build_tasks()
if not tasks:
return False
order = self._order_tasks(tasks)
self._execute_task(order[0])
return True
# ------------------------------------------------------------ 任务构建
def _station_pending(self, index: int) -> list[int]:
"""站点待测频道:UNKNOWN、未测过、非"必 no_signal"且未证缺席。"""
point = self.ledger.points[index]
pending = []
for channel, belief in self.belief.channels.items():
if belief.status is not ChannelStatus.UNKNOWN:
continue
if self.ledger.measured_at(channel, index):
continue
if self._skip_station_channel(channel, index, point):
continue
pending.append(channel)
return pending
def _skip_station_channel(self, channel: int, index: int, point: Vec2) -> bool:
"""跳测规则(按 pf.version 缓存;幸存集单调收缩,判定单调)。"""
pf = self.particles[channel]
if not len(pf):
return True
cached = self._skip_cache.get((channel, index))
if cached is not None and cached[0] == pf.version:
return cached[1]
value = pf.guaranteed_no_signal(point)
self._skip_cache[(channel, index)] = (pf.version, value)
return value
def _build_tasks(self) -> list[Task]:
tasks: list[Task] = []
for index, point in enumerate(self.ledger.points):
pending = self._station_pending(index)
if not pending:
continue
switches = len(pending) - (1 if self.client.state.channel in pending else 0)
tasks.append(Task("station", tuple(point),
self.config.cost.measure_s * len(pending)
+ self.config.cost.switch_s * max(switches, 0),
station_index=index))
for channel in self.belief.channels_by_status(ChannelStatus.DETECTED):
cert = self._best_certificate(channel)
if cert is not None and cert.certified \
and channel not in self._clear_failed:
tasks.append(Task("clear", cert.center,
self.config.cost.clear_success_s,
channel=channel))
continue
point = self._select_point(channel)
if point is None:
continue
tasks.append(Task("locate", point,
self.config.cost.measure_s + self.config.cost.switch_s,
channel=channel))
return tasks
# ------------------------------------------------------------ 任务排序
def _order_tasks(self, tasks: list[Task]) -> list[Task]:
"""开放路径排序:最近邻打底,2-opt 改进(终点自由,不回起点)。"""
if len(tasks) <= 2:
return sorted(tasks, key=lambda t: (
move_time(self.client.state.position, t.position, self.config.cost),
t.kind, t.channel or 0))
order = self._nearest_order(tasks)
if not self.config.bayes.two_opt_enabled:
return order
return self._two_opt(order)
def _nearest_order(self, tasks: list[Task]) -> list[Task]:
remaining = list(tasks)
order = []
position = self.client.state.position
while remaining:
best = min(remaining, key=lambda t: (
move_time(position, t.position, self.config.cost),
t.kind, t.channel or 0))
remaining.remove(best)
order.append(best)
position = best.position
return order
def _path_cost(self, order: list[Task]) -> float:
total = 0.0
position = self.client.state.position
for task in order:
total += move_time(position, task.position, self.config.cost)
total += task.service_s
position = task.position
return total
def _two_opt(self, order: list[Task]) -> list[Task]:
best = list(order)
best_cost = self._path_cost(best)
for _ in range(self.config.bayes.two_opt_passes):
improved = False
for i in range(len(best) - 1):
for j in range(i + 1, len(best)):
candidate = best[:i] + best[i:j + 1][::-1] + best[j + 1:]
cost = self._path_cost(candidate)
if cost < best_cost - 1e-6:
best, best_cost, improved = candidate, cost, True
if not improved:
break
return best
# ------------------------------------------------------------ 任务执行
def _execute_task(self, task: Task) -> None:
if task.kind == "station":
self._execute_station(task.station_index)
elif task.kind == "clear":
cert = self._best_certificate(task.channel)
if cert is not None and cert.certified:
if not self._attempt_clear(task.channel, cert.center, cert):
self._clear_failed.add(task.channel)
self._may_clear.discard(task.channel)
else:
self._clear_failed.discard(task.channel)
elif task.kind == "locate":
self._execute_locate(task.channel, task.position)
def _execute_station(self, index: int) -> None:
"""单站批量扫频:只测待测频道(跳测规则已过滤),扫完即返回重排。"""
point = self.ledger.points[index]
pending = self._station_pending(index)
unknown = [c for c, b in self.belief.channels.items()
if b.status is ChannelStatus.UNKNOWN]
self.skipped_measures += len(unknown) - len(pending)
# 当前频道优先,减少换频;同站 near 直接清除不打断扫频
pending.sort(key=lambda c: (c != self.client.state.channel, c))
for channel in pending:
if self.stop_reason is not None or self._count_limit_reached() \
or self._virtual_cap_reached():
return
outcome = self.client.measure(point, channel)
self.ledger.mark_measured(channel, index)
self._record_measure(channel, point, outcome)
if outcome.result in (DIRECTION, NEAR):
self._may_clear.add(channel)
if outcome.result == NEAR:
region = self.belief.candidate_set(channel)
cert = clear_certificate(region, channel, self.config)
if cert.certified:
if self._attempt_clear(channel, point, cert):
self._clear_failed.discard(channel)
else:
self._clear_failed.add(channel)
self._may_clear.discard(channel)
else:
self._anomaly("near_without_certificate", channel, position=point)
def _execute_locate(self, channel: int, point: Vec2) -> None:
"""单步定位测量:执行后立即重排(滚动时域),收敛则顺路清除。"""
pf = self.particles[channel]
before = len(pf)
outcome = self.client.measure(point, channel)
self._record_measure(channel, point, outcome)
self._may_clear.add(channel)
if outcome.result == NO_SIGNAL:
region = self.belief.candidate_set(channel)
if region is not None and safe_disk_radius(region, self.config) >= 0 \
and math.dist(point, region.mec()[0]) \
<= safe_disk_radius(region, self.config):
self._anomaly("no_signal_in_safe_disk", channel, position=point)
after = len(pf)
cert = self._best_certificate(channel)
if cert is not None and cert.certified:
if self._attempt_clear(channel, cert.center, cert):
self._clear_failed.discard(channel)
self._stall.pop(channel, None)
return
self._clear_failed.add(channel)
self._may_clear.discard(channel)
if after == before:
self._stall[channel] = self._stall.get(channel, 0) + 1
self.no_shrink_measures += 1 # 只是浪费不破坏守恒性,不进异常表
else:
self._stall[channel] = 0
# ------------------------------------------------------------ 感知与证书
def _record_measure(self, channel: int, position: Vec2, outcome) -> None:
"""belief(凸证书)与 PF(幸存集)同步更新;PF 空即证缺席。"""
self.belief.update_measure(channel, position, outcome.result,
outcome.svd_deg)
self._measured_points.setdefault(channel, set()).add(_point_key(position))
self._clear_failed.discard(channel) # 新证据落地:允许再次尝试清除
belief = self.belief.channels[channel]
if belief.status in (ChannelStatus.CLEARED, ChannelStatus.ABSENT):
return # 已证毕:清除/缺席后的 no_signal 与距离无关,不进 PF
pf = self.particles[channel]
pf.apply_measure(position, outcome.result, outcome.svd_deg)
if not len(pf):
if belief.status is ChannelStatus.UNKNOWN:
self.belief.mark_absent(channel)
if channel not in self.pf_absent_channels:
self.pf_absent_channels.append(channel)
else:
self._anomaly("pf_empty_while_detected", channel, position=position)
def _best_certificate(self, channel: int) -> ClearCertificate | None:
"""凸证书优先;负观测挖洞使 PF 幸存集更紧时用网格证书补位。"""
region = self.belief.candidate_set(channel)
cert = clear_certificate(region, channel, self.config) \
if region is not None else None
if cert is not None and cert.certified:
return cert
if self.config.bayes.grid_cert_enabled:
pf = self.particles[channel]
if len(pf):
center, radius = pf.mec()
limit = (self.config.field.clear_radius_m - pf.margin_m
- self.config.search.clear_margin_m)
if radius <= limit:
return ClearCertificate(channel, center, radius, limit, True)
return cert
# ------------------------------------------------------------ 信息增益选点
def _select_point(self, channel: int) -> Vec2 | None:
"""定位测量点:期望 log 幸存占比 + λ·移动时间 最小的候选。"""
bayes, search = self.config.bayes, self.config.search
pf = self.particles[channel]
if not len(pf):
return None
region = self.belief.candidate_set(channel)
center, radius = pf.mec()
measured = self._measured_points.get(channel, set())
candidates: list[Vec2] = []
safe = safe_disk_radius(region, self.config) if region is not None else -1.0
if region is not None and safe >= 0:
# 保证接收盘(凸证书口径):任意候选必产生 direction/near
candidates = candidate_points(tuple(region.mec()[0]), safe,
search.candidate_rings,
search.candidate_angles)
else:
# 宽候选集:PF MEC 探索环(负观测挖洞后幸存集的包围圆)
for fraction in bayes.wide_rings:
ring = max(radius * fraction, 2.0 * pf.margin_m)
candidates.extend(candidate_points(center, ring, (1.0,),
search.candidate_angles))
candidates.append(tuple(center))
candidates = [c for c in candidates if _point_key(c) not in measured]
if not candidates:
return None
subsample = pf.subsample(bayes.score_subsample)
stride = max(len(subsample) // bayes.mc_representatives, 1)
representatives = [subsample[k]
for k in range(0, len(subsample), stride)]
position = self.client.state.position
def score(q: Vec2) -> float:
move = bayes.lambda_move_s * move_time(position, q, self.config.cost)
if bayes.score_mode == "entropy":
return (pf.expected_survival(q, subsample, representatives)
+ move)
return (pf.expected_posterior_radius(q, subsample, representatives)
+ move)
return min(candidates, key=lambda q: (score(q), _point_key(q)))
# ------------------------------------------------------------ 安全网与复扫
def _localize_and_clear(self, channel: int) -> bool:
"""阻塞式定位子循环(resolve 阶段安全网):PF 选点,失败退凸选点。"""
search = self.config.search
self._may_clear.add(channel)
for _ in range(search.max_localize_steps):
if self._virtual_cap_reached():
return False
cert = self._best_certificate(channel)
if cert is not None and cert.certified and channel in self._may_clear:
if self._attempt_clear(channel, cert.center, cert):
self._clear_failed.discard(channel)
return True
self._clear_failed.add(channel)
self._may_clear.discard(channel)
continue
point = self._select_point(channel)
if point is None:
region = self.belief.candidate_set(channel)
if region is None:
return False
point = select_measurement_point(
region, self.client.state.position, self.config).position
outcome = self.client.measure(point, channel)
self._record_measure(channel, point, outcome)
self._may_clear.add(channel)
if outcome.result == NO_SIGNAL:
region = self.belief.candidate_set(channel)
if region is not None and safe_disk_radius(region, self.config) >= 0 \
and math.dist(point, region.mec()[0]) \
<= safe_disk_radius(region, self.config):
self._anomaly("no_signal_in_safe_disk", channel, position=point)
cert = self._best_certificate(channel)
if cert is not None and cert.certified:
if self._attempt_clear(channel, cert.center, cert):
self._clear_failed.discard(channel)
return True
self._clear_failed.add(channel)
self._may_clear.discard(channel)
return self.belief.channels[channel].status is ChannelStatus.CLEARED
def _persistent_round(self) -> None:
"""一轮复扫:与基线一致的全站复测,但读数同步进 PF(防假设偏差)。"""
measured: set[tuple[int, int]] = set()
while self.stop_reason is None:
index = self._next_resweep_point(measured)
if index is None:
return
point = self.ledger.points[index]
for channel in self._resweep_channels_at(index, measured):
if self._virtual_cap_reached():
return
measured.add((channel, index))
was_absent = (self.belief.channels[channel].status
is ChannelStatus.ABSENT)
outcome = self.client.measure(point, channel)
self._record_measure(channel, point, outcome)
if was_absent and outcome.result in (DIRECTION, NEAR):
# 复测推翻了缺席证明:守恒性留痕,按新证据定位清除。
self._anomaly("absent_detected_on_resweep", channel,
position=point, result=outcome.result)
if outcome.result == DIRECTION:
self._localize_and_clear(channel)
elif outcome.result == NEAR:
cert = self._best_certificate(channel)
if cert is not None and cert.certified:
if not self._attempt_clear(channel, cert.center, cert):
self._clear_failed.add(channel)
else:
self._anomaly("near_without_certificate", channel,
position=point)
if self.stop_reason is not None:
return
# ------------------------------------------------------------ 收尾
def _summary(self, info) -> dict:
report = super()._summary(info)
report["strategy"] = "bayes"
report["skipped_measures"] = self.skipped_measures
report["no_shrink_measures"] = self.no_shrink_measures
report["pf_absent_channels"] = sorted(self.pf_absent_channels)
report["pf_alive_final"] = {
str(channel): len(self.particles[channel])
for channel in sorted(self.particles)
if self.belief.channels[channel].status is ChannelStatus.DETECTED}
return report
@@ -0,0 +1,79 @@
{
"field": {
"omega_radius_m": 1800.0,
"channel_min": 1,
"channel_max": 20,
"source_count_min": 10,
"source_count_max": 16,
"r_eff_min_m": 1000.0,
"r_eff_max_m": 1500.0,
"near_radius_m": 5.0,
"clear_radius_m": 20.0,
"bearing_error_half_deg": 1.0,
"bearing_decimals": 2,
"coord_abs_limit_m": 2000000.0,
"directional_half_angle_deg": 90.0,
"max_virtual_duration_s": 360000.0,
"max_real_duration_s": 1200.0,
"test_window_s": 1500.0
},
"cost": {
"speed_mps": 5.0,
"measure_s": 5.0,
"switch_s": 1.0,
"clear_success_s": 5.0,
"clear_fail_s": 3.0
},
"session": {
"arena_id": "default",
"base_url": "http://127.0.0.1:2026",
"robot_id_max_bytes": 64,
"request_id_max_bytes": 128,
"request_body_max_bytes": 65536,
"connect_timeout_s": 5.0,
"read_timeout_s": 15.0,
"max_attempts": 3,
"retry_backoff_s": 0.25,
"reserve_exit_s": 60.0,
"real_rtt_p95_s": 1.0,
"self_test_real_budget_s": 1800.0
},
"search": {
"grid_step_m": 700.0,
"grid_half_cells": 3,
"fallback_clear_grid_m": 20.0,
"bearing_rounding_margin_deg": 0.005,
"polygon_sides": 192,
"witness_spacing_m": 60.0,
"candidate_rings": [
0.0,
0.4,
0.75,
1.0
],
"candidate_angles": 12,
"clear_margin_m": 0.5,
"max_localize_steps": 8,
"max_anomalies_per_channel": 3,
"max_blocked_probes": 4,
"fallback_max_cells": 400,
"persistent_search": false,
"virtual_reserve_s": 10000.0
},
"bayes": {
"particle_spacing_m": 25.0,
"score_mode": "entropy",
"score_subsample": 800,
"mc_representatives": 7,
"lambda_move_s": 0.0105,
"wide_rings": [
1.0,
1.5,
2.0
],
"station_ring_radius_m": 1159.7,
"two_opt_enabled": true,
"two_opt_passes": 3,
"grid_cert_enabled": true
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,260 @@
{
"config": {
"field": {
"omega_radius_m": 1800.0,
"channel_min": 1,
"channel_max": 20,
"source_count_min": 10,
"source_count_max": 16,
"r_eff_min_m": 1000.0,
"r_eff_max_m": 1500.0,
"near_radius_m": 5.0,
"clear_radius_m": 20.0,
"bearing_error_half_deg": 1.0,
"bearing_decimals": 2,
"coord_abs_limit_m": 2000000.0,
"directional_half_angle_deg": 90.0,
"max_virtual_duration_s": 360000.0,
"max_real_duration_s": 1200.0,
"test_window_s": 1500.0
},
"cost": {
"speed_mps": 5.0,
"measure_s": 5.0,
"switch_s": 1.0,
"clear_success_s": 5.0,
"clear_fail_s": 3.0
},
"session": {
"arena_id": "default",
"base_url": "http://127.0.0.1:2026",
"robot_id_max_bytes": 64,
"request_id_max_bytes": 128,
"request_body_max_bytes": 65536,
"connect_timeout_s": 5.0,
"read_timeout_s": 15.0,
"max_attempts": 3,
"retry_backoff_s": 0.25,
"reserve_exit_s": 60.0,
"real_rtt_p95_s": 1.0,
"self_test_real_budget_s": 1800.0
},
"search": {
"grid_step_m": 700.0,
"grid_half_cells": 3,
"fallback_clear_grid_m": 20.0,
"bearing_rounding_margin_deg": 0.005,
"polygon_sides": 192,
"witness_spacing_m": 60.0,
"candidate_rings": [
0.0,
0.4,
0.75,
1.0
],
"candidate_angles": 12,
"clear_margin_m": 0.5,
"max_localize_steps": 8,
"max_anomalies_per_channel": 3,
"max_blocked_probes": 4,
"fallback_max_cells": 400,
"persistent_search": false,
"virtual_reserve_s": 10000.0
},
"bayes": {
"particle_spacing_m": 25.0,
"score_mode": "entropy",
"score_subsample": 800,
"mc_representatives": 7,
"lambda_move_s": 0.0105,
"wide_rings": [
1.0,
1.5,
2.0
],
"station_ring_radius_m": 1159.7,
"two_opt_enabled": true,
"two_opt_passes": 3,
"grid_cert_enabled": true,
"opportunistic_measure": true,
"opportunistic_radius_ratio": 0.65,
"opportunistic_discovery_fraction": 0.15
}
},
"source": "local_simulator_only",
"rows": [
{
"case": "random-10-0",
"valid": true,
"virtual_s": 3083.398221,
"measures": 164,
"clears": 10,
"failed_clears": 0,
"distance_m": 10277.0,
"wall_s": 0.8067699000093853
},
{
"case": "random-10-1",
"valid": true,
"virtual_s": 3642.523231,
"measures": 171,
"clears": 10,
"failed_clears": 0,
"distance_m": 12877.6,
"wall_s": 1.4086409000010462
},
{
"case": "random-10-2",
"valid": true,
"virtual_s": 3266.706336,
"measures": 160,
"clears": 10,
"failed_clears": 0,
"distance_m": 11313.5,
"wall_s": 1.6418229000119027
},
{
"case": "random-10-3",
"valid": true,
"virtual_s": 3762.508482,
"measures": 211,
"clears": 10,
"failed_clears": 0,
"distance_m": 12277.5,
"wall_s": 1.7074006000038935
},
{
"case": "random-10-4",
"valid": true,
"virtual_s": 3371.418159,
"measures": 143,
"clears": 10,
"failed_clears": 0,
"distance_m": 12357.1,
"wall_s": 2.1484533000038937
},
{
"case": "random-10-5",
"valid": true,
"virtual_s": 3198.715433,
"measures": 150,
"clears": 10,
"failed_clears": 0,
"distance_m": 11293.6,
"wall_s": 1.6730121000000509
},
{
"case": "boundary-10",
"valid": true,
"virtual_s": 4342.190154,
"measures": 175,
"clears": 10,
"failed_clears": 0,
"distance_m": 16291.0,
"wall_s": 0.7709059999906458
},
{
"case": "random-16-0",
"valid": true,
"virtual_s": 3113.346538,
"measures": 112,
"clears": 16,
"failed_clears": 0,
"distance_m": 11826.7,
"wall_s": 2.458396800007904
},
{
"case": "random-16-1",
"valid": true,
"virtual_s": 3509.22519,
"measures": 113,
"clears": 16,
"failed_clears": 0,
"distance_m": 13771.1,
"wall_s": 2.428945100007695
},
{
"case": "random-16-2",
"valid": true,
"virtual_s": 3280.118211,
"measures": 145,
"clears": 16,
"failed_clears": 0,
"distance_m": 11680.6,
"wall_s": 1.5479743000032613
},
{
"case": "random-16-3",
"valid": true,
"virtual_s": 3384.734199,
"measures": 127,
"clears": 16,
"failed_clears": 0,
"distance_m": 12763.7,
"wall_s": 3.6217957000044407
},
{
"case": "random-16-4",
"valid": true,
"virtual_s": 3358.282938,
"measures": 133,
"clears": 16,
"failed_clears": 0,
"distance_m": 12451.4,
"wall_s": 2.0503644999989774
},
{
"case": "random-16-5",
"valid": true,
"virtual_s": 3953.832941,
"measures": 142,
"clears": 16,
"failed_clears": 0,
"distance_m": 15159.2,
"wall_s": 2.249085699993884
},
{
"case": "boundary-16",
"valid": true,
"virtual_s": 4358.90599,
"measures": 171,
"clears": 16,
"failed_clears": 0,
"distance_m": 16304.5,
"wall_s": 0.8942588000063552
}
],
"mean_s": 3544.7075730714287,
"median_s": 3378.0761789999997,
"max_s": 4358.90599,
"valid": 14,
"under_4000": 12,
"source_sha256": {
"src\\mcm26b\\__init__.py": "a1ea628e2b44a8b288c59fcda19a8f02b53f2d6fec675ef1e8c481ffdcbd7f35",
"src\\mcm26b\\belief\\__init__.py": "8613467122928e70dd2b07f14e1009a1edddb1d495d44f063f222fb118f78ba5",
"src\\mcm26b\\cli.py": "2fac81a16cecdf23ce1f91031009cd2817fd3f2b66cb5f66d0a31bdd16088a04",
"src\\mcm26b\\config.py": "f2c7bf6b6b2cdb4b3a6b1b5e4eec65ecfde9ae6865227c36fe202f8e03c0cc75",
"src\\mcm26b\\coverage\\__init__.py": "ef24a48e91a099ca58a1fd9b5efa01b0bd76c21f63bd5febd444026281ec18c7",
"src\\mcm26b\\evaluation\\__init__.py": "3d7d9103675e4731f65ceacaac76c97096e244d0902e37d62376ea60b0a42217",
"src\\mcm26b\\geometry\\__init__.py": "c8f8d3e6320acb44fe9c14261116f8a668fdd59304e1d5b0318d8d50ea89b25c",
"src\\mcm26b\\geometry\\__main__.py": "41967f321b05abe515d2f0c10839b94c1e5c55a4c760b17345e0815f62acd676",
"src\\mcm26b\\geometry\\localization.py": "019a04a4205ca5cfb5832c7e2337e6ae3274ef9bdae1981c3764b8df8c2afd97",
"src\\mcm26b\\geometry\\planning.py": "5d6a11b2c4633c4f27bb4a61f77f4fbd20cfdce653d839845a735f9f1d3be2d1",
"src\\mcm26b\\particles.py": "c2cfabb07154883d4293f5c739b8ab06bd4b467c773365e1d4c153a0bd0fc30b",
"src\\mcm26b\\planner\\__init__.py": "36620fb5d73b2b257bee1f7bc56f807b7180fc488950aa4c33d5354737f3568b",
"src\\mcm26b\\planner\\bayes_loop.py": "b575206853e25e628ea64d2fe7b5ea165e88c696cf30bccc73f84e30a4bd6ac8",
"src\\mcm26b\\planner\\seven.py": "cc143ce0703f231d8b5444ac6a2b2f4925cabf1556e58b0ea5166a510e6933f0",
"src\\mcm26b\\protocol\\__init__.py": "67423a0fe7f3ee3c7b1c0439da9554dab4bc30a09c5f3720d69e11076a36de0c",
"src\\mcm26b\\protocol\\client.py": "a486694b570bc00286ad30d4be04b01687ef3801d95154e75caa6209314dac36",
"src\\mcm26b\\protocol\\log.py": "0eb51302a0bdfa3c680b7726d0be59cebe6fdc6197fd9643a4d5cc0646e34ac3",
"src\\mcm26b\\protocol\\rules.py": "7941a4cddafd875dedf0c57aa90e640cb5e22201800d3eb300dac313db19e6a3",
"src\\mcm26b\\protocol\\state.py": "dc4c50f38cc1014af848f21d3f972b2f51fba28b0feb3320ce85bf51389d3d34",
"src\\mcm26b\\protocol\\timing.py": "49fb1ca99db9db273364ddb27281b95e6e76099c16ce7fccddccbfe105d604ac",
"src\\mcm26b\\protocol\\transport.py": "668a8ab280e5e42a7994d7cedc0f487af19b140622d76b04da0dbbea3ad4940f",
"src\\mcm26b\\sim\\__init__.py": "7adcbaab5b94d4006ff926306a43c1042182be14789026e71885ed69389a6d55",
"src\\mcm26b\\sim\\playback.py": "073b74c149334604cd678c218e112f69d64fe907ef7c3b6f42b69470e48fbb7a",
"src\\mcm26b\\sim\\scenes.py": "0647bd19409acb5160625dd39e71157aeb20f9e979e82a7fe86aaec75a1cbf32",
"src\\mcm26b\\sim\\simulator.py": "553bf9fbb9fd4875a6ec68792e90a08287e5b87c749ffda9a7556b582a5ecba3",
"src\\mcm26b\\sim\\transport.py": "889c06965fdb905f5d9fa8e947940ea68be216f60a487340c2f326b6e8a9a36d"
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,257 @@
{
"config": {
"field": {
"omega_radius_m": 1800.0,
"channel_min": 1,
"channel_max": 20,
"source_count_min": 10,
"source_count_max": 16,
"r_eff_min_m": 1000.0,
"r_eff_max_m": 1500.0,
"near_radius_m": 5.0,
"clear_radius_m": 20.0,
"bearing_error_half_deg": 1.0,
"bearing_decimals": 2,
"coord_abs_limit_m": 2000000.0,
"directional_half_angle_deg": 90.0,
"max_virtual_duration_s": 360000.0,
"max_real_duration_s": 1200.0,
"test_window_s": 1500.0
},
"cost": {
"speed_mps": 5.0,
"measure_s": 5.0,
"switch_s": 1.0,
"clear_success_s": 5.0,
"clear_fail_s": 3.0
},
"session": {
"arena_id": "default",
"base_url": "http://127.0.0.1:2026",
"robot_id_max_bytes": 64,
"request_id_max_bytes": 128,
"request_body_max_bytes": 65536,
"connect_timeout_s": 5.0,
"read_timeout_s": 15.0,
"max_attempts": 3,
"retry_backoff_s": 0.25,
"reserve_exit_s": 60.0,
"real_rtt_p95_s": 1.0,
"self_test_real_budget_s": 1800.0
},
"search": {
"grid_step_m": 700.0,
"grid_half_cells": 3,
"fallback_clear_grid_m": 20.0,
"bearing_rounding_margin_deg": 0.005,
"polygon_sides": 192,
"witness_spacing_m": 60.0,
"candidate_rings": [
0.0,
0.4,
0.75,
1.0
],
"candidate_angles": 12,
"clear_margin_m": 0.5,
"max_localize_steps": 8,
"max_anomalies_per_channel": 3,
"max_blocked_probes": 4,
"fallback_max_cells": 400,
"persistent_search": false,
"virtual_reserve_s": 10000.0
},
"bayes": {
"particle_spacing_m": 25.0,
"score_mode": "entropy",
"score_subsample": 800,
"mc_representatives": 7,
"lambda_move_s": 0.0105,
"wide_rings": [
1.0,
1.5,
2.0
],
"station_ring_radius_m": 1159.7,
"two_opt_enabled": true,
"two_opt_passes": 3,
"grid_cert_enabled": true
}
},
"source": "local_simulator_only",
"rows": [
{
"case": "random-10-0",
"valid": true,
"virtual_s": 3534.694777,
"measures": 123,
"clears": 10,
"failed_clears": 0,
"distance_m": 13823.5,
"wall_s": 1.0671480999881169
},
{
"case": "random-10-1",
"valid": true,
"virtual_s": 3491.535921,
"measures": 126,
"clears": 10,
"failed_clears": 0,
"distance_m": 13527.7,
"wall_s": 1.187542100000428
},
{
"case": "random-10-2",
"valid": true,
"virtual_s": 3206.547215,
"measures": 118,
"clears": 10,
"failed_clears": 0,
"distance_m": 12317.7,
"wall_s": 1.4321670999925118
},
{
"case": "random-10-3",
"valid": true,
"virtual_s": 3522.648147,
"measures": 127,
"clears": 10,
"failed_clears": 0,
"distance_m": 13633.2,
"wall_s": 0.9682273000071291
},
{
"case": "random-10-4",
"valid": true,
"virtual_s": 3384.25258,
"measures": 114,
"clears": 10,
"failed_clears": 0,
"distance_m": 13326.3,
"wall_s": 1.7609715999860782
},
{
"case": "random-10-5",
"valid": true,
"virtual_s": 2958.257944,
"measures": 107,
"clears": 10,
"failed_clears": 0,
"distance_m": 11376.3,
"wall_s": 1.4250285000016447
},
{
"case": "boundary-10",
"valid": true,
"virtual_s": 4472.993699,
"measures": 143,
"clears": 10,
"failed_clears": 0,
"distance_m": 17920.0,
"wall_s": 0.5052678000065498
},
{
"case": "random-16-0",
"valid": true,
"virtual_s": 4119.15033,
"measures": 92,
"clears": 16,
"failed_clears": 0,
"distance_m": 17505.8,
"wall_s": 2.044811599989771
},
{
"case": "random-16-1",
"valid": true,
"virtual_s": 3739.922403,
"measures": 93,
"clears": 16,
"failed_clears": 0,
"distance_m": 15589.6,
"wall_s": 2.6635076999955345
},
{
"case": "random-16-2",
"valid": true,
"virtual_s": 3597.390398,
"measures": 109,
"clears": 16,
"failed_clears": 0,
"distance_m": 14377.0,
"wall_s": 1.3540113999915775
},
{
"case": "random-16-3",
"valid": true,
"virtual_s": 3688.169478,
"measures": 109,
"clears": 16,
"failed_clears": 0,
"distance_m": 14885.8,
"wall_s": 2.9790097000077367
},
{
"case": "random-16-4",
"valid": true,
"virtual_s": 4406.22739,
"measures": 129,
"clears": 16,
"failed_clears": 0,
"distance_m": 17896.1,
"wall_s": 2.47406759999285
},
{
"case": "random-16-5",
"valid": true,
"virtual_s": 3724.696901,
"measures": 112,
"clears": 16,
"failed_clears": 0,
"distance_m": 14963.5,
"wall_s": 2.3959249000035925
},
{
"case": "boundary-16",
"valid": true,
"virtual_s": 5535.128195,
"measures": 129,
"clears": 16,
"failed_clears": 0,
"distance_m": 23465.6,
"wall_s": 0.6980149000009988
}
],
"mean_s": 3812.972527,
"median_s": 3642.7799379999997,
"max_s": 5535.128195,
"valid": 14,
"under_4000": 10,
"source_sha256": {
"src\\mcm26b\\__init__.py": "a1ea628e2b44a8b288c59fcda19a8f02b53f2d6fec675ef1e8c481ffdcbd7f35",
"src\\mcm26b\\belief\\__init__.py": "8613467122928e70dd2b07f14e1009a1edddb1d495d44f063f222fb118f78ba5",
"src\\mcm26b\\cli.py": "2fac81a16cecdf23ce1f91031009cd2817fd3f2b66cb5f66d0a31bdd16088a04",
"src\\mcm26b\\config.py": "781a096f20f5e17446b6faeb5efaea23997cbf3fc1e7a435118d610f0b1443dd",
"src\\mcm26b\\coverage\\__init__.py": "ef24a48e91a099ca58a1fd9b5efa01b0bd76c21f63bd5febd444026281ec18c7",
"src\\mcm26b\\evaluation\\__init__.py": "3d7d9103675e4731f65ceacaac76c97096e244d0902e37d62376ea60b0a42217",
"src\\mcm26b\\geometry\\__init__.py": "c8f8d3e6320acb44fe9c14261116f8a668fdd59304e1d5b0318d8d50ea89b25c",
"src\\mcm26b\\geometry\\__main__.py": "41967f321b05abe515d2f0c10839b94c1e5c55a4c760b17345e0815f62acd676",
"src\\mcm26b\\geometry\\localization.py": "019a04a4205ca5cfb5832c7e2337e6ae3274ef9bdae1981c3764b8df8c2afd97",
"src\\mcm26b\\geometry\\planning.py": "5d6a11b2c4633c4f27bb4a61f77f4fbd20cfdce653d839845a735f9f1d3be2d1",
"src\\mcm26b\\particles.py": "c2cfabb07154883d4293f5c739b8ab06bd4b467c773365e1d4c153a0bd0fc30b",
"src\\mcm26b\\planner\\__init__.py": "bdd36737b2a8562612634d45290bf7165ee81c80fa8e7bcb9fcc9f4001390cda",
"src\\mcm26b\\planner\\bayes_loop.py": "068cde2bbcbea0333193b5d3d6ec850d8e310fb1368f682fcaa4f5f0fd90379b",
"src\\mcm26b\\planner\\seven.py": "cc143ce0703f231d8b5444ac6a2b2f4925cabf1556e58b0ea5166a510e6933f0",
"src\\mcm26b\\protocol\\__init__.py": "67423a0fe7f3ee3c7b1c0439da9554dab4bc30a09c5f3720d69e11076a36de0c",
"src\\mcm26b\\protocol\\client.py": "a486694b570bc00286ad30d4be04b01687ef3801d95154e75caa6209314dac36",
"src\\mcm26b\\protocol\\log.py": "0eb51302a0bdfa3c680b7726d0be59cebe6fdc6197fd9643a4d5cc0646e34ac3",
"src\\mcm26b\\protocol\\rules.py": "7941a4cddafd875dedf0c57aa90e640cb5e22201800d3eb300dac313db19e6a3",
"src\\mcm26b\\protocol\\state.py": "dc4c50f38cc1014af848f21d3f972b2f51fba28b0feb3320ce85bf51389d3d34",
"src\\mcm26b\\protocol\\timing.py": "49fb1ca99db9db273364ddb27281b95e6e76099c16ce7fccddccbfe105d604ac",
"src\\mcm26b\\protocol\\transport.py": "668a8ab280e5e42a7994d7cedc0f487af19b140622d76b04da0dbbea3ad4940f",
"src\\mcm26b\\sim\\__init__.py": "7adcbaab5b94d4006ff926306a43c1042182be14789026e71885ed69389a6d55",
"src\\mcm26b\\sim\\playback.py": "073b74c149334604cd678c218e112f69d64fe907ef7c3b6f42b69470e48fbb7a",
"src\\mcm26b\\sim\\scenes.py": "0647bd19409acb5160625dd39e71157aeb20f9e979e82a7fe86aaec75a1cbf32",
"src\\mcm26b\\sim\\simulator.py": "553bf9fbb9fd4875a6ec68792e90a08287e5b87c749ffda9a7556b582a5ecba3",
"src\\mcm26b\\sim\\transport.py": "889c06965fdb905f5d9fa8e947940ea68be216f60a487340c2f326b6e8a9a36d"
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,259 @@
{
"config": {
"field": {
"omega_radius_m": 1800.0,
"channel_min": 1,
"channel_max": 20,
"source_count_min": 10,
"source_count_max": 16,
"r_eff_min_m": 1000.0,
"r_eff_max_m": 1500.0,
"near_radius_m": 5.0,
"clear_radius_m": 20.0,
"bearing_error_half_deg": 1.0,
"bearing_decimals": 2,
"coord_abs_limit_m": 2000000.0,
"directional_half_angle_deg": 90.0,
"max_virtual_duration_s": 360000.0,
"max_real_duration_s": 1200.0,
"test_window_s": 1500.0
},
"cost": {
"speed_mps": 5.0,
"measure_s": 5.0,
"switch_s": 1.0,
"clear_success_s": 5.0,
"clear_fail_s": 3.0
},
"session": {
"arena_id": "default",
"base_url": "http://127.0.0.1:2026",
"robot_id_max_bytes": 64,
"request_id_max_bytes": 128,
"request_body_max_bytes": 65536,
"connect_timeout_s": 5.0,
"read_timeout_s": 15.0,
"max_attempts": 3,
"retry_backoff_s": 0.25,
"reserve_exit_s": 60.0,
"real_rtt_p95_s": 1.0,
"self_test_real_budget_s": 1800.0
},
"search": {
"grid_step_m": 700.0,
"grid_half_cells": 3,
"fallback_clear_grid_m": 20.0,
"bearing_rounding_margin_deg": 0.005,
"polygon_sides": 192,
"witness_spacing_m": 60.0,
"candidate_rings": [
0.0,
0.4,
0.75,
1.0
],
"candidate_angles": 12,
"clear_margin_m": 0.5,
"max_localize_steps": 8,
"max_anomalies_per_channel": 3,
"max_blocked_probes": 4,
"fallback_max_cells": 400,
"persistent_search": false,
"virtual_reserve_s": 10000.0
},
"bayes": {
"particle_spacing_m": 25.0,
"score_mode": "entropy",
"score_subsample": 800,
"mc_representatives": 7,
"lambda_move_s": 0.0105,
"wide_rings": [
1.0,
1.5,
2.0
],
"station_ring_radius_m": 1159.7,
"two_opt_enabled": true,
"two_opt_passes": 3,
"grid_cert_enabled": true,
"opportunistic_measure": true,
"opportunistic_radius_ratio": 0.65
}
},
"source": "local_simulator_only",
"rows": [
{
"case": "random-10-0",
"valid": true,
"virtual_s": 2796.517992,
"measures": 116,
"clears": 10,
"failed_clears": 0,
"distance_m": 10302.6,
"wall_s": 0.6851706000015838
},
{
"case": "random-10-1",
"valid": true,
"virtual_s": 3383.633624,
"measures": 118,
"clears": 10,
"failed_clears": 0,
"distance_m": 13183.2,
"wall_s": 1.3136940999975195
},
{
"case": "random-10-2",
"valid": true,
"virtual_s": 2903.420125,
"measures": 111,
"clears": 10,
"failed_clears": 0,
"distance_m": 10972.1,
"wall_s": 1.4448951999947894
},
{
"case": "random-10-3",
"valid": true,
"virtual_s": 3183.873778,
"measures": 120,
"clears": 10,
"failed_clears": 0,
"distance_m": 12129.4,
"wall_s": 1.54364629999327
},
{
"case": "random-10-4",
"valid": true,
"virtual_s": 3248.440388,
"measures": 112,
"clears": 10,
"failed_clears": 0,
"distance_m": 12677.2,
"wall_s": 1.9964945999963675
},
{
"case": "random-10-5",
"valid": true,
"virtual_s": 2962.211049,
"measures": 109,
"clears": 10,
"failed_clears": 0,
"distance_m": 11331.1,
"wall_s": 1.4274002000020118
},
{
"case": "boundary-10",
"valid": true,
"virtual_s": 4169.474072,
"measures": 142,
"clears": 10,
"failed_clears": 0,
"distance_m": 16412.4,
"wall_s": 0.5755983000126434
},
{
"case": "random-16-0",
"valid": true,
"virtual_s": 3691.667793,
"measures": 104,
"clears": 16,
"failed_clears": 0,
"distance_m": 14978.3,
"wall_s": 2.8522586999897612
},
{
"case": "random-16-1",
"valid": true,
"virtual_s": 3893.998179,
"measures": 97,
"clears": 16,
"failed_clears": 0,
"distance_m": 16190.0,
"wall_s": 2.773552300001029
},
{
"case": "random-16-2",
"valid": true,
"virtual_s": 3257.127865,
"measures": 110,
"clears": 16,
"failed_clears": 0,
"distance_m": 12620.6,
"wall_s": 1.731503300004988
},
{
"case": "random-16-3",
"valid": true,
"virtual_s": 3244.820414,
"measures": 94,
"clears": 16,
"failed_clears": 0,
"distance_m": 13039.1,
"wall_s": 2.862451599998167
},
{
"case": "random-16-4",
"valid": true,
"virtual_s": 3258.651071,
"measures": 100,
"clears": 16,
"failed_clears": 0,
"distance_m": 12938.3,
"wall_s": 1.7853647000010824
},
{
"case": "random-16-5",
"valid": true,
"virtual_s": 3627.497192,
"measures": 101,
"clears": 16,
"failed_clears": 0,
"distance_m": 14767.5,
"wall_s": 1.812008799999603
},
{
"case": "boundary-16",
"valid": true,
"virtual_s": 4637.818558,
"measures": 139,
"clears": 16,
"failed_clears": 0,
"distance_m": 18649.1,
"wall_s": 0.648526299992227
}
],
"mean_s": 3447.082292857143,
"median_s": 3257.889468,
"max_s": 4637.818558,
"valid": 14,
"under_4000": 12,
"source_sha256": {
"src\\mcm26b\\__init__.py": "a1ea628e2b44a8b288c59fcda19a8f02b53f2d6fec675ef1e8c481ffdcbd7f35",
"src\\mcm26b\\belief\\__init__.py": "8613467122928e70dd2b07f14e1009a1edddb1d495d44f063f222fb118f78ba5",
"src\\mcm26b\\cli.py": "2fac81a16cecdf23ce1f91031009cd2817fd3f2b66cb5f66d0a31bdd16088a04",
"src\\mcm26b\\config.py": "deeb25419a7c7b7fba81b943fa25c32255d6607e6666f172c56893fe58addea0",
"src\\mcm26b\\coverage\\__init__.py": "ef24a48e91a099ca58a1fd9b5efa01b0bd76c21f63bd5febd444026281ec18c7",
"src\\mcm26b\\evaluation\\__init__.py": "3d7d9103675e4731f65ceacaac76c97096e244d0902e37d62376ea60b0a42217",
"src\\mcm26b\\geometry\\__init__.py": "c8f8d3e6320acb44fe9c14261116f8a668fdd59304e1d5b0318d8d50ea89b25c",
"src\\mcm26b\\geometry\\__main__.py": "41967f321b05abe515d2f0c10839b94c1e5c55a4c760b17345e0815f62acd676",
"src\\mcm26b\\geometry\\localization.py": "019a04a4205ca5cfb5832c7e2337e6ae3274ef9bdae1981c3764b8df8c2afd97",
"src\\mcm26b\\geometry\\planning.py": "5d6a11b2c4633c4f27bb4a61f77f4fbd20cfdce653d839845a735f9f1d3be2d1",
"src\\mcm26b\\particles.py": "c2cfabb07154883d4293f5c739b8ab06bd4b467c773365e1d4c153a0bd0fc30b",
"src\\mcm26b\\planner\\__init__.py": "36620fb5d73b2b257bee1f7bc56f807b7180fc488950aa4c33d5354737f3568b",
"src\\mcm26b\\planner\\bayes_loop.py": "ea86e20b6edb31ab51534c1bfafd0189b058cf822d83139ee5de6e63655cb01a",
"src\\mcm26b\\planner\\seven.py": "cc143ce0703f231d8b5444ac6a2b2f4925cabf1556e58b0ea5166a510e6933f0",
"src\\mcm26b\\protocol\\__init__.py": "67423a0fe7f3ee3c7b1c0439da9554dab4bc30a09c5f3720d69e11076a36de0c",
"src\\mcm26b\\protocol\\client.py": "a486694b570bc00286ad30d4be04b01687ef3801d95154e75caa6209314dac36",
"src\\mcm26b\\protocol\\log.py": "0eb51302a0bdfa3c680b7726d0be59cebe6fdc6197fd9643a4d5cc0646e34ac3",
"src\\mcm26b\\protocol\\rules.py": "7941a4cddafd875dedf0c57aa90e640cb5e22201800d3eb300dac313db19e6a3",
"src\\mcm26b\\protocol\\state.py": "dc4c50f38cc1014af848f21d3f972b2f51fba28b0feb3320ce85bf51389d3d34",
"src\\mcm26b\\protocol\\timing.py": "49fb1ca99db9db273364ddb27281b95e6e76099c16ce7fccddccbfe105d604ac",
"src\\mcm26b\\protocol\\transport.py": "668a8ab280e5e42a7994d7cedc0f487af19b140622d76b04da0dbbea3ad4940f",
"src\\mcm26b\\sim\\__init__.py": "7adcbaab5b94d4006ff926306a43c1042182be14789026e71885ed69389a6d55",
"src\\mcm26b\\sim\\playback.py": "073b74c149334604cd678c218e112f69d64fe907ef7c3b6f42b69470e48fbb7a",
"src\\mcm26b\\sim\\scenes.py": "0647bd19409acb5160625dd39e71157aeb20f9e979e82a7fe86aaec75a1cbf32",
"src\\mcm26b\\sim\\simulator.py": "553bf9fbb9fd4875a6ec68792e90a08287e5b87c749ffda9a7556b582a5ecba3",
"src\\mcm26b\\sim\\transport.py": "889c06965fdb905f5d9fa8e947940ea68be216f60a487340c2f326b6e8a9a36d"
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,259 @@
{
"config": {
"field": {
"omega_radius_m": 1800.0,
"channel_min": 1,
"channel_max": 20,
"source_count_min": 10,
"source_count_max": 16,
"r_eff_min_m": 1000.0,
"r_eff_max_m": 1500.0,
"near_radius_m": 5.0,
"clear_radius_m": 20.0,
"bearing_error_half_deg": 1.0,
"bearing_decimals": 2,
"coord_abs_limit_m": 2000000.0,
"directional_half_angle_deg": 90.0,
"max_virtual_duration_s": 360000.0,
"max_real_duration_s": 1200.0,
"test_window_s": 1500.0
},
"cost": {
"speed_mps": 5.0,
"measure_s": 5.0,
"switch_s": 1.0,
"clear_success_s": 5.0,
"clear_fail_s": 3.0
},
"session": {
"arena_id": "default",
"base_url": "http://127.0.0.1:2026",
"robot_id_max_bytes": 64,
"request_id_max_bytes": 128,
"request_body_max_bytes": 65536,
"connect_timeout_s": 5.0,
"read_timeout_s": 15.0,
"max_attempts": 3,
"retry_backoff_s": 0.25,
"reserve_exit_s": 60.0,
"real_rtt_p95_s": 1.0,
"self_test_real_budget_s": 1800.0
},
"search": {
"grid_step_m": 700.0,
"grid_half_cells": 3,
"fallback_clear_grid_m": 20.0,
"bearing_rounding_margin_deg": 0.005,
"polygon_sides": 192,
"witness_spacing_m": 60.0,
"candidate_rings": [
0.0,
0.4,
0.75,
1.0
],
"candidate_angles": 12,
"clear_margin_m": 0.5,
"max_localize_steps": 8,
"max_anomalies_per_channel": 3,
"max_blocked_probes": 4,
"fallback_max_cells": 400,
"persistent_search": false,
"virtual_reserve_s": 10000.0
},
"bayes": {
"particle_spacing_m": 25.0,
"score_mode": "entropy",
"score_subsample": 800,
"mc_representatives": 7,
"lambda_move_s": 0.0105,
"wide_rings": [
1.0,
1.5,
2.0
],
"station_ring_radius_m": 1159.7,
"two_opt_enabled": true,
"two_opt_passes": 3,
"grid_cert_enabled": true,
"opportunistic_measure": true,
"opportunistic_radius_ratio": 0.65
}
},
"source": "local_simulator_only",
"rows": [
{
"case": "random-10-0",
"valid": true,
"virtual_s": 2781.468909,
"measures": 115,
"clears": 10,
"failed_clears": 0,
"distance_m": 10252.3,
"wall_s": 0.6727236000006087
},
{
"case": "random-10-1",
"valid": true,
"virtual_s": 3373.375027,
"measures": 118,
"clears": 10,
"failed_clears": 0,
"distance_m": 13121.9,
"wall_s": 1.3332279000023846
},
{
"case": "random-10-2",
"valid": true,
"virtual_s": 2971.246636,
"measures": 112,
"clears": 10,
"failed_clears": 0,
"distance_m": 11266.2,
"wall_s": 1.5427381999907084
},
{
"case": "random-10-3",
"valid": true,
"virtual_s": 3183.51691,
"measures": 120,
"clears": 10,
"failed_clears": 0,
"distance_m": 12127.6,
"wall_s": 1.4840739999926882
},
{
"case": "random-10-4",
"valid": true,
"virtual_s": 3219.028475,
"measures": 112,
"clears": 10,
"failed_clears": 0,
"distance_m": 12530.1,
"wall_s": 1.9207030000106897
},
{
"case": "random-10-5",
"valid": true,
"virtual_s": 2992.69413,
"measures": 109,
"clears": 10,
"failed_clears": 0,
"distance_m": 11488.5,
"wall_s": 1.4631770999985747
},
{
"case": "boundary-10",
"valid": true,
"virtual_s": 4145.190154,
"measures": 142,
"clears": 10,
"failed_clears": 0,
"distance_m": 16291.0,
"wall_s": 0.5581967000034638
},
{
"case": "random-16-0",
"valid": true,
"virtual_s": 2859.541671,
"measures": 85,
"clears": 16,
"failed_clears": 0,
"distance_m": 11372.7,
"wall_s": 2.1188361999957124
},
{
"case": "random-16-1",
"valid": true,
"virtual_s": 3877.191308,
"measures": 97,
"clears": 16,
"failed_clears": 0,
"distance_m": 16106.0,
"wall_s": 2.2593173000059323
},
{
"case": "random-16-2",
"valid": true,
"virtual_s": 3191.726738,
"measures": 110,
"clears": 16,
"failed_clears": 0,
"distance_m": 12283.6,
"wall_s": 1.4188941000029445
},
{
"case": "random-16-3",
"valid": true,
"virtual_s": 3271.530271,
"measures": 95,
"clears": 16,
"failed_clears": 0,
"distance_m": 13142.7,
"wall_s": 2.956349500003853
},
{
"case": "random-16-4",
"valid": true,
"virtual_s": 3260.063212,
"measures": 99,
"clears": 16,
"failed_clears": 0,
"distance_m": 12980.3,
"wall_s": 1.8893916000088211
},
{
"case": "random-16-5",
"valid": true,
"virtual_s": 3720.822867,
"measures": 117,
"clears": 16,
"failed_clears": 0,
"distance_m": 14729.1,
"wall_s": 1.7041139000066323
},
{
"case": "boundary-16",
"valid": true,
"virtual_s": 4624.968743,
"measures": 141,
"clears": 16,
"failed_clears": 0,
"distance_m": 18534.8,
"wall_s": 0.6890837999962969
}
],
"mean_s": 3390.8832179285714,
"median_s": 3239.5458435,
"max_s": 4624.968743,
"valid": 14,
"under_4000": 12,
"source_sha256": {
"src\\mcm26b\\__init__.py": "a1ea628e2b44a8b288c59fcda19a8f02b53f2d6fec675ef1e8c481ffdcbd7f35",
"src\\mcm26b\\belief\\__init__.py": "8613467122928e70dd2b07f14e1009a1edddb1d495d44f063f222fb118f78ba5",
"src\\mcm26b\\cli.py": "2fac81a16cecdf23ce1f91031009cd2817fd3f2b66cb5f66d0a31bdd16088a04",
"src\\mcm26b\\config.py": "c684a887e103da3d163d671579c63a64f694015c04690d73a4777dc94084b915",
"src\\mcm26b\\coverage\\__init__.py": "ef24a48e91a099ca58a1fd9b5efa01b0bd76c21f63bd5febd444026281ec18c7",
"src\\mcm26b\\evaluation\\__init__.py": "3d7d9103675e4731f65ceacaac76c97096e244d0902e37d62376ea60b0a42217",
"src\\mcm26b\\geometry\\__init__.py": "c8f8d3e6320acb44fe9c14261116f8a668fdd59304e1d5b0318d8d50ea89b25c",
"src\\mcm26b\\geometry\\__main__.py": "41967f321b05abe515d2f0c10839b94c1e5c55a4c760b17345e0815f62acd676",
"src\\mcm26b\\geometry\\localization.py": "019a04a4205ca5cfb5832c7e2337e6ae3274ef9bdae1981c3764b8df8c2afd97",
"src\\mcm26b\\geometry\\planning.py": "5d6a11b2c4633c4f27bb4a61f77f4fbd20cfdce653d839845a735f9f1d3be2d1",
"src\\mcm26b\\particles.py": "c2cfabb07154883d4293f5c739b8ab06bd4b467c773365e1d4c153a0bd0fc30b",
"src\\mcm26b\\planner\\__init__.py": "36620fb5d73b2b257bee1f7bc56f807b7180fc488950aa4c33d5354737f3568b",
"src\\mcm26b\\planner\\bayes_loop.py": "a2852d3c923b96ce78ba4613ff4c53a962643625076208c4ae79c3e72298c18a",
"src\\mcm26b\\planner\\seven.py": "4787372aea85561874eae35d4cb38e1e556c4a863a5e803ac5d88742775d3656",
"src\\mcm26b\\protocol\\__init__.py": "67423a0fe7f3ee3c7b1c0439da9554dab4bc30a09c5f3720d69e11076a36de0c",
"src\\mcm26b\\protocol\\client.py": "a486694b570bc00286ad30d4be04b01687ef3801d95154e75caa6209314dac36",
"src\\mcm26b\\protocol\\log.py": "0eb51302a0bdfa3c680b7726d0be59cebe6fdc6197fd9643a4d5cc0646e34ac3",
"src\\mcm26b\\protocol\\rules.py": "7941a4cddafd875dedf0c57aa90e640cb5e22201800d3eb300dac313db19e6a3",
"src\\mcm26b\\protocol\\state.py": "dc4c50f38cc1014af848f21d3f972b2f51fba28b0feb3320ce85bf51389d3d34",
"src\\mcm26b\\protocol\\timing.py": "49fb1ca99db9db273364ddb27281b95e6e76099c16ce7fccddccbfe105d604ac",
"src\\mcm26b\\protocol\\transport.py": "668a8ab280e5e42a7994d7cedc0f487af19b140622d76b04da0dbbea3ad4940f",
"src\\mcm26b\\sim\\__init__.py": "7adcbaab5b94d4006ff926306a43c1042182be14789026e71885ed69389a6d55",
"src\\mcm26b\\sim\\playback.py": "073b74c149334604cd678c218e112f69d64fe907ef7c3b6f42b69470e48fbb7a",
"src\\mcm26b\\sim\\scenes.py": "0647bd19409acb5160625dd39e71157aeb20f9e979e82a7fe86aaec75a1cbf32",
"src\\mcm26b\\sim\\simulator.py": "553bf9fbb9fd4875a6ec68792e90a08287e5b87c749ffda9a7556b582a5ecba3",
"src\\mcm26b\\sim\\transport.py": "889c06965fdb905f5d9fa8e947940ea68be216f60a487340c2f326b6e8a9a36d"
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,259 @@
{
"config": {
"field": {
"omega_radius_m": 1800.0,
"channel_min": 1,
"channel_max": 20,
"source_count_min": 10,
"source_count_max": 16,
"r_eff_min_m": 1000.0,
"r_eff_max_m": 1500.0,
"near_radius_m": 5.0,
"clear_radius_m": 20.0,
"bearing_error_half_deg": 1.0,
"bearing_decimals": 2,
"coord_abs_limit_m": 2000000.0,
"directional_half_angle_deg": 90.0,
"max_virtual_duration_s": 360000.0,
"max_real_duration_s": 1200.0,
"test_window_s": 1500.0
},
"cost": {
"speed_mps": 5.0,
"measure_s": 5.0,
"switch_s": 1.0,
"clear_success_s": 5.0,
"clear_fail_s": 3.0
},
"session": {
"arena_id": "default",
"base_url": "http://127.0.0.1:2026",
"robot_id_max_bytes": 64,
"request_id_max_bytes": 128,
"request_body_max_bytes": 65536,
"connect_timeout_s": 5.0,
"read_timeout_s": 15.0,
"max_attempts": 3,
"retry_backoff_s": 0.25,
"reserve_exit_s": 60.0,
"real_rtt_p95_s": 1.0,
"self_test_real_budget_s": 1800.0
},
"search": {
"grid_step_m": 700.0,
"grid_half_cells": 3,
"fallback_clear_grid_m": 20.0,
"bearing_rounding_margin_deg": 0.005,
"polygon_sides": 192,
"witness_spacing_m": 60.0,
"candidate_rings": [
0.0,
0.4,
0.75,
1.0
],
"candidate_angles": 12,
"clear_margin_m": 0.5,
"max_localize_steps": 8,
"max_anomalies_per_channel": 3,
"max_blocked_probes": 4,
"fallback_max_cells": 400,
"persistent_search": false,
"virtual_reserve_s": 10000.0
},
"bayes": {
"particle_spacing_m": 25.0,
"score_mode": "entropy",
"score_subsample": 800,
"mc_representatives": 7,
"lambda_move_s": 0.0105,
"wide_rings": [
1.0,
1.5,
2.0
],
"station_ring_radius_m": 1159.7,
"two_opt_enabled": true,
"two_opt_passes": 3,
"grid_cert_enabled": true,
"opportunistic_measure": true,
"opportunistic_radius_ratio": 0.65
}
},
"source": "local_simulator_only",
"rows": [
{
"case": "random-10-0",
"valid": true,
"virtual_s": 2781.468909,
"measures": 115,
"clears": 10,
"failed_clears": 0,
"distance_m": 10252.3,
"wall_s": 0.6616155999945477
},
{
"case": "random-10-1",
"valid": true,
"virtual_s": 3373.375027,
"measures": 118,
"clears": 10,
"failed_clears": 0,
"distance_m": 13121.9,
"wall_s": 1.2827579000004334
},
{
"case": "random-10-2",
"valid": true,
"virtual_s": 2971.246636,
"measures": 112,
"clears": 10,
"failed_clears": 0,
"distance_m": 11266.2,
"wall_s": 1.474124700005632
},
{
"case": "random-10-3",
"valid": true,
"virtual_s": 3183.51691,
"measures": 120,
"clears": 10,
"failed_clears": 0,
"distance_m": 12127.6,
"wall_s": 1.4255466000031447
},
{
"case": "random-10-4",
"valid": true,
"virtual_s": 3219.028475,
"measures": 112,
"clears": 10,
"failed_clears": 0,
"distance_m": 12530.1,
"wall_s": 1.8383665000001201
},
{
"case": "random-10-5",
"valid": true,
"virtual_s": 2992.69413,
"measures": 109,
"clears": 10,
"failed_clears": 0,
"distance_m": 11488.5,
"wall_s": 1.3896775000030175
},
{
"case": "boundary-10",
"valid": true,
"virtual_s": 4145.190154,
"measures": 142,
"clears": 10,
"failed_clears": 0,
"distance_m": 16291.0,
"wall_s": 0.5317590000049677
},
{
"case": "random-16-0",
"valid": true,
"virtual_s": 2859.541671,
"measures": 85,
"clears": 16,
"failed_clears": 0,
"distance_m": 11372.7,
"wall_s": 2.028615700008231
},
{
"case": "random-16-1",
"valid": true,
"virtual_s": 3877.191308,
"measures": 97,
"clears": 16,
"failed_clears": 0,
"distance_m": 16106.0,
"wall_s": 2.1717706000054022
},
{
"case": "random-16-2",
"valid": true,
"virtual_s": 3191.726738,
"measures": 110,
"clears": 16,
"failed_clears": 0,
"distance_m": 12283.6,
"wall_s": 1.3410574000008637
},
{
"case": "random-16-3",
"valid": true,
"virtual_s": 3271.530271,
"measures": 95,
"clears": 16,
"failed_clears": 0,
"distance_m": 13142.7,
"wall_s": 2.7753489000024274
},
{
"case": "random-16-4",
"valid": true,
"virtual_s": 3260.063212,
"measures": 99,
"clears": 16,
"failed_clears": 0,
"distance_m": 12980.3,
"wall_s": 1.8296510000072885
},
{
"case": "random-16-5",
"valid": true,
"virtual_s": 3720.822867,
"measures": 117,
"clears": 16,
"failed_clears": 0,
"distance_m": 14729.1,
"wall_s": 1.6178049000009196
},
{
"case": "boundary-16",
"valid": true,
"virtual_s": 4624.968743,
"measures": 141,
"clears": 16,
"failed_clears": 0,
"distance_m": 18534.8,
"wall_s": 0.6610209999926155
}
],
"mean_s": 3390.8832179285714,
"median_s": 3239.5458435,
"max_s": 4624.968743,
"valid": 14,
"under_4000": 12,
"source_sha256": {
"src\\mcm26b\\__init__.py": "a1ea628e2b44a8b288c59fcda19a8f02b53f2d6fec675ef1e8c481ffdcbd7f35",
"src\\mcm26b\\belief\\__init__.py": "8613467122928e70dd2b07f14e1009a1edddb1d495d44f063f222fb118f78ba5",
"src\\mcm26b\\cli.py": "2fac81a16cecdf23ce1f91031009cd2817fd3f2b66cb5f66d0a31bdd16088a04",
"src\\mcm26b\\config.py": "deeb25419a7c7b7fba81b943fa25c32255d6607e6666f172c56893fe58addea0",
"src\\mcm26b\\coverage\\__init__.py": "ef24a48e91a099ca58a1fd9b5efa01b0bd76c21f63bd5febd444026281ec18c7",
"src\\mcm26b\\evaluation\\__init__.py": "3d7d9103675e4731f65ceacaac76c97096e244d0902e37d62376ea60b0a42217",
"src\\mcm26b\\geometry\\__init__.py": "c8f8d3e6320acb44fe9c14261116f8a668fdd59304e1d5b0318d8d50ea89b25c",
"src\\mcm26b\\geometry\\__main__.py": "41967f321b05abe515d2f0c10839b94c1e5c55a4c760b17345e0815f62acd676",
"src\\mcm26b\\geometry\\localization.py": "019a04a4205ca5cfb5832c7e2337e6ae3274ef9bdae1981c3764b8df8c2afd97",
"src\\mcm26b\\geometry\\planning.py": "5d6a11b2c4633c4f27bb4a61f77f4fbd20cfdce653d839845a735f9f1d3be2d1",
"src\\mcm26b\\particles.py": "c2cfabb07154883d4293f5c739b8ab06bd4b467c773365e1d4c153a0bd0fc30b",
"src\\mcm26b\\planner\\__init__.py": "36620fb5d73b2b257bee1f7bc56f807b7180fc488950aa4c33d5354737f3568b",
"src\\mcm26b\\planner\\bayes_loop.py": "9bb2e46302aedc3d5b5eb8bb4167003624f111ee30e3af4b153af21a7855c145",
"src\\mcm26b\\planner\\seven.py": "cc143ce0703f231d8b5444ac6a2b2f4925cabf1556e58b0ea5166a510e6933f0",
"src\\mcm26b\\protocol\\__init__.py": "67423a0fe7f3ee3c7b1c0439da9554dab4bc30a09c5f3720d69e11076a36de0c",
"src\\mcm26b\\protocol\\client.py": "a486694b570bc00286ad30d4be04b01687ef3801d95154e75caa6209314dac36",
"src\\mcm26b\\protocol\\log.py": "0eb51302a0bdfa3c680b7726d0be59cebe6fdc6197fd9643a4d5cc0646e34ac3",
"src\\mcm26b\\protocol\\rules.py": "7941a4cddafd875dedf0c57aa90e640cb5e22201800d3eb300dac313db19e6a3",
"src\\mcm26b\\protocol\\state.py": "dc4c50f38cc1014af848f21d3f972b2f51fba28b0feb3320ce85bf51389d3d34",
"src\\mcm26b\\protocol\\timing.py": "49fb1ca99db9db273364ddb27281b95e6e76099c16ce7fccddccbfe105d604ac",
"src\\mcm26b\\protocol\\transport.py": "668a8ab280e5e42a7994d7cedc0f487af19b140622d76b04da0dbbea3ad4940f",
"src\\mcm26b\\sim\\__init__.py": "7adcbaab5b94d4006ff926306a43c1042182be14789026e71885ed69389a6d55",
"src\\mcm26b\\sim\\playback.py": "073b74c149334604cd678c218e112f69d64fe907ef7c3b6f42b69470e48fbb7a",
"src\\mcm26b\\sim\\scenes.py": "0647bd19409acb5160625dd39e71157aeb20f9e979e82a7fe86aaec75a1cbf32",
"src\\mcm26b\\sim\\simulator.py": "553bf9fbb9fd4875a6ec68792e90a08287e5b87c749ffda9a7556b582a5ecba3",
"src\\mcm26b\\sim\\transport.py": "889c06965fdb905f5d9fa8e947940ea68be216f60a487340c2f326b6e8a9a36d"
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,259 @@
{
"config": {
"field": {
"omega_radius_m": 1800.0,
"channel_min": 1,
"channel_max": 20,
"source_count_min": 10,
"source_count_max": 16,
"r_eff_min_m": 1000.0,
"r_eff_max_m": 1500.0,
"near_radius_m": 5.0,
"clear_radius_m": 20.0,
"bearing_error_half_deg": 1.0,
"bearing_decimals": 2,
"coord_abs_limit_m": 2000000.0,
"directional_half_angle_deg": 90.0,
"max_virtual_duration_s": 360000.0,
"max_real_duration_s": 1200.0,
"test_window_s": 1500.0
},
"cost": {
"speed_mps": 5.0,
"measure_s": 5.0,
"switch_s": 1.0,
"clear_success_s": 5.0,
"clear_fail_s": 3.0
},
"session": {
"arena_id": "default",
"base_url": "http://127.0.0.1:2026",
"robot_id_max_bytes": 64,
"request_id_max_bytes": 128,
"request_body_max_bytes": 65536,
"connect_timeout_s": 5.0,
"read_timeout_s": 15.0,
"max_attempts": 3,
"retry_backoff_s": 0.25,
"reserve_exit_s": 60.0,
"real_rtt_p95_s": 1.0,
"self_test_real_budget_s": 1800.0
},
"search": {
"grid_step_m": 700.0,
"grid_half_cells": 3,
"fallback_clear_grid_m": 20.0,
"bearing_rounding_margin_deg": 0.005,
"polygon_sides": 192,
"witness_spacing_m": 60.0,
"candidate_rings": [
0.0,
0.4,
0.75,
1.0
],
"candidate_angles": 12,
"clear_margin_m": 0.5,
"max_localize_steps": 8,
"max_anomalies_per_channel": 3,
"max_blocked_probes": 4,
"fallback_max_cells": 400,
"persistent_search": false,
"virtual_reserve_s": 10000.0
},
"bayes": {
"particle_spacing_m": 25.0,
"score_mode": "entropy",
"score_subsample": 800,
"mc_representatives": 7,
"lambda_move_s": 0.0105,
"wide_rings": [
1.0,
1.5,
2.0
],
"station_ring_radius_m": 1159.7,
"two_opt_enabled": true,
"two_opt_passes": 3,
"grid_cert_enabled": true,
"opportunistic_measure": true,
"opportunistic_radius_ratio": 0.65
}
},
"source": "local_simulator_only",
"rows": [
{
"case": "random-10-0",
"valid": true,
"virtual_s": 2958.5911,
"measures": 116,
"clears": 10,
"failed_clears": 0,
"distance_m": 11103.0,
"wall_s": 0.5848256000026595
},
{
"case": "random-10-1",
"valid": true,
"virtual_s": 3473.150338,
"measures": 119,
"clears": 10,
"failed_clears": 0,
"distance_m": 13610.8,
"wall_s": 1.056755899990094
},
{
"case": "random-10-2",
"valid": true,
"virtual_s": 3024.484542,
"measures": 112,
"clears": 10,
"failed_clears": 0,
"distance_m": 11547.4,
"wall_s": 1.0590423999965424
},
{
"case": "random-10-3",
"valid": true,
"virtual_s": 3197.856813,
"measures": 117,
"clears": 10,
"failed_clears": 0,
"distance_m": 12264.3,
"wall_s": 0.7646372000017436
},
{
"case": "random-10-4",
"valid": true,
"virtual_s": 3201.6552,
"measures": 122,
"clears": 10,
"failed_clears": 0,
"distance_m": 12143.3,
"wall_s": 1.044187100007548
},
{
"case": "random-10-5",
"valid": true,
"virtual_s": 2940.099079,
"measures": 112,
"clears": 10,
"failed_clears": 0,
"distance_m": 11130.5,
"wall_s": 0.7773485999932745
},
{
"case": "boundary-10",
"valid": true,
"virtual_s": 4144.807971,
"measures": 144,
"clears": 10,
"failed_clears": 0,
"distance_m": 16239.0,
"wall_s": 0.49276029999600723
},
{
"case": "random-16-0",
"valid": true,
"virtual_s": 3833.288563,
"measures": 95,
"clears": 16,
"failed_clears": 0,
"distance_m": 15951.4,
"wall_s": 1.8353732999967178
},
{
"case": "random-16-1",
"valid": true,
"virtual_s": 3749.587742,
"measures": 97,
"clears": 16,
"failed_clears": 0,
"distance_m": 15457.9,
"wall_s": 1.6017328000016278
},
{
"case": "random-16-2",
"valid": true,
"virtual_s": 3554.338273,
"measures": 114,
"clears": 16,
"failed_clears": 0,
"distance_m": 14011.7,
"wall_s": 1.2566069999884348
},
{
"case": "random-16-3",
"valid": true,
"virtual_s": 3355.439323,
"measures": 98,
"clears": 16,
"failed_clears": 0,
"distance_m": 13472.2,
"wall_s": 1.8687091999890981
},
{
"case": "random-16-4",
"valid": true,
"virtual_s": 3854.458757,
"measures": 106,
"clears": 16,
"failed_clears": 0,
"distance_m": 15742.3,
"wall_s": 1.519354200005182
},
{
"case": "random-16-5",
"valid": true,
"virtual_s": 3839.746309,
"measures": 104,
"clears": 16,
"failed_clears": 0,
"distance_m": 15733.7,
"wall_s": 1.4910044999996899
},
{
"case": "boundary-16",
"valid": true,
"virtual_s": 4849.848511,
"measures": 139,
"clears": 16,
"failed_clears": 0,
"distance_m": 19709.2,
"wall_s": 0.5919216000038432
}
],
"mean_s": 3569.810894357143,
"median_s": 3513.7443055,
"max_s": 4849.848511,
"valid": 14,
"under_4000": 12,
"source_sha256": {
"src\\mcm26b\\__init__.py": "a1ea628e2b44a8b288c59fcda19a8f02b53f2d6fec675ef1e8c481ffdcbd7f35",
"src\\mcm26b\\belief\\__init__.py": "8613467122928e70dd2b07f14e1009a1edddb1d495d44f063f222fb118f78ba5",
"src\\mcm26b\\cli.py": "2fac81a16cecdf23ce1f91031009cd2817fd3f2b66cb5f66d0a31bdd16088a04",
"src\\mcm26b\\config.py": "deeb25419a7c7b7fba81b943fa25c32255d6607e6666f172c56893fe58addea0",
"src\\mcm26b\\coverage\\__init__.py": "ef24a48e91a099ca58a1fd9b5efa01b0bd76c21f63bd5febd444026281ec18c7",
"src\\mcm26b\\evaluation\\__init__.py": "3d7d9103675e4731f65ceacaac76c97096e244d0902e37d62376ea60b0a42217",
"src\\mcm26b\\geometry\\__init__.py": "c8f8d3e6320acb44fe9c14261116f8a668fdd59304e1d5b0318d8d50ea89b25c",
"src\\mcm26b\\geometry\\__main__.py": "41967f321b05abe515d2f0c10839b94c1e5c55a4c760b17345e0815f62acd676",
"src\\mcm26b\\geometry\\localization.py": "019a04a4205ca5cfb5832c7e2337e6ae3274ef9bdae1981c3764b8df8c2afd97",
"src\\mcm26b\\geometry\\planning.py": "5d6a11b2c4633c4f27bb4a61f77f4fbd20cfdce653d839845a735f9f1d3be2d1",
"src\\mcm26b\\particles.py": "c2cfabb07154883d4293f5c739b8ab06bd4b467c773365e1d4c153a0bd0fc30b",
"src\\mcm26b\\planner\\__init__.py": "bdd36737b2a8562612634d45290bf7165ee81c80fa8e7bcb9fcc9f4001390cda",
"src\\mcm26b\\planner\\bayes_loop.py": "dd7b92a91200a55fe9aa7b01f7063474fe13c19426a82a057b9e73992e534b5a",
"src\\mcm26b\\planner\\seven.py": "cc143ce0703f231d8b5444ac6a2b2f4925cabf1556e58b0ea5166a510e6933f0",
"src\\mcm26b\\protocol\\__init__.py": "67423a0fe7f3ee3c7b1c0439da9554dab4bc30a09c5f3720d69e11076a36de0c",
"src\\mcm26b\\protocol\\client.py": "a486694b570bc00286ad30d4be04b01687ef3801d95154e75caa6209314dac36",
"src\\mcm26b\\protocol\\log.py": "0eb51302a0bdfa3c680b7726d0be59cebe6fdc6197fd9643a4d5cc0646e34ac3",
"src\\mcm26b\\protocol\\rules.py": "7941a4cddafd875dedf0c57aa90e640cb5e22201800d3eb300dac313db19e6a3",
"src\\mcm26b\\protocol\\state.py": "dc4c50f38cc1014af848f21d3f972b2f51fba28b0feb3320ce85bf51389d3d34",
"src\\mcm26b\\protocol\\timing.py": "49fb1ca99db9db273364ddb27281b95e6e76099c16ce7fccddccbfe105d604ac",
"src\\mcm26b\\protocol\\transport.py": "668a8ab280e5e42a7994d7cedc0f487af19b140622d76b04da0dbbea3ad4940f",
"src\\mcm26b\\sim\\__init__.py": "7adcbaab5b94d4006ff926306a43c1042182be14789026e71885ed69389a6d55",
"src\\mcm26b\\sim\\playback.py": "073b74c149334604cd678c218e112f69d64fe907ef7c3b6f42b69470e48fbb7a",
"src\\mcm26b\\sim\\scenes.py": "0647bd19409acb5160625dd39e71157aeb20f9e979e82a7fe86aaec75a1cbf32",
"src\\mcm26b\\sim\\simulator.py": "553bf9fbb9fd4875a6ec68792e90a08287e5b87c749ffda9a7556b582a5ecba3",
"src\\mcm26b\\sim\\transport.py": "889c06965fdb905f5d9fa8e947940ea68be216f60a487340c2f326b6e8a9a36d"
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long

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