exp: 轮次32——均匀细分认证一次调用可证段内碰撞,界经720项检验未证伪,但P50≤20ms的档只能证出54~63%

- certify_uniform:固定 n 个子段一次 gaps 调用,判据与二分同源(子段界=整段界/n),证不出即拒
- 确定界反证:48段×121点×15组对=720项检验 0 违例;有信息量仅 61 项,最紧仍高出 0.035 mm
  (是"未能在真实运动上证伪",不是证明;浮点误差仍未形式化)
- 第180题 1.08-1.10s 漏检段在每个 n>=8 均判碰撞;二次加密(2n+1)反证 0 误放行
- 更正轮次31的"自适应cap无收益":旧公式 bound/2+eps 会把本可通过的子段钳成不可证;
  改为 bound+2eps 后交错实测决策不变、快 1.36~1.65x(n=8 13.13→9.68,n=128 98.46→59.76 ms)
- 负结论:只有 n<=16 能把认证压进 20 ms,但该档仅证出 26-30/48 根,其余必须刹停;
  成本=log(bound/间隙) 决定,故下一步要在反馈后限幅并让安全层要求正余量(现 cap=0.5 会截掉余量)
- 测试 23→26 项:n=5拒/n=6受的解析对照、cap_required 公式、n 张量类型门
This commit is contained in:
cbb
2026-10-20 19:30:02 +08:00
parent 6de085fd37
commit c6b46b8bb1
6 changed files with 389 additions and 4 deletions
+35 -4
View File
@@ -271,7 +271,13 @@ class Kin:
return gm.view(B, len(gp))
@torch.no_grad()
def certify_segments(self, a, b, max_queries=32, max_depth=12, eps=1e-4, cap=20.0, adaptive_cap=True):
def certify_segments(self, a, b, max_queries=32, max_depth=12, eps=1e-4, cap=20.0):
"""逐层二分认证:每根段独立查询预算,未知(超预算/超深度/非有限/越界)一律拒绝。
判据对每条组对:子段两端间隙之和 > 该子段位移界 + 2eps(间隙取 min(gap,cap),钳制只会更保守)。
cap 必须 ≥ 该层子段界 + 2eps 才不会挡住本可通过的判定,故不做自适应收紧——同批其他段会改变
钳制程度、让结果随批次而变(实测也无耗时收益,见探索日志轮次 31)。
"""
if self.dtype != torch.float64 or a.dtype != torch.float64 or b.dtype != torch.float64:
raise ValueError('segment certification requires float64')
# 预算给成张量时 max_depth + 1 会在 uint8 这类窄类型上回绕成 0,循环整个跳过,把碰撞段当安全返回。
@@ -309,9 +315,7 @@ class Kin:
if not root.numel():
break
mid = a + 0.5 * (b - a)
# 子段的界是父段一半;宽相位只需覆盖到能被证明的最小间隙,层越深筛得越狠。
qc = min(cap, float(bound.max()) / 2 + eps) if adaptive_cap else cap
gm = self.gaps(mid, qc)['gm'][:, self.cert_groups]
gm = self.gaps(mid, cap)['gm'][:, self.cert_groups]
queries += torch.bincount(root, minlength=count)
a, b = torch.cat([a, mid]), torch.cat([mid, b])
ga, gb = torch.cat([ga, gm]), torch.cat([gm, gb])
@@ -320,6 +324,33 @@ class Kin:
return {'safe': status == 0, 'collision': status == 1, 'unresolved': status == 2,
'outside_box': status == 3, 'queries': queries}
@torch.no_grad()
def certify_uniform(self, a, b, n=64, eps=1e-4, cap=None):
"""固定层数的均匀细分认证:n 个子段只需一次 gaps 调用(n+1 个点),没有逐层依赖的往返。
判据与 certify_segments 完全相同;界对 Δq 线性,所以子段界 = 整段界 / n。未通过即 unproven
(拒绝),不存在“未知当安全”。cap=None 时取“最小不挡住可通过判定的宽相位”= 最大子段界 + 2eps:
小于它钳制会把本可证明的子段压成不可证(偏保守),大于它只是多算对(偏慢),不改正确性。
"""
if self.dtype != torch.float64 or a.dtype != torch.float64 or b.dtype != torch.float64:
raise ValueError('segment certification requires float64')
if type(n) is not int or n < 1 or eps <= 0 or (cap is not None and cap <= eps):
raise ValueError('invalid subdivision count or tolerance')
count = a.shape[0]
inside = (((a >= self.lo) & (a <= self.hi) & (b >= self.lo) & (b <= self.hi)) | self.cont).all(-1)
bound = (b - a).abs() @ self.cert_lever.T / n # [count,15] 子段界
required = float(bound.max()) + 2 * eps if count else 2 * eps
qc = required if cap is None else cap
alpha = torch.arange(n + 1, dtype=self.dtype, device=a.device) / n
points = (a[:, None] + (b - a)[:, None] * alpha[None, :, None]).reshape(-1, 6)
gm = self.gaps(points, qc)['gm'][:, self.cert_groups].view(count, n + 1, -1)
adjacent = gm[:, :-1] + gm[:, 1:] > bound[:, None, :] + 2 * eps
collision = (gm <= 0).any((1, 2))
safe = inside & (gm > eps).all((1, 2)) & adjacent.all((1, 2)) & ~collision
return {'safe': safe, 'collision': collision, 'unproven': (~safe & ~collision & inside),
'outside_box': ~inside, 'points': n + 1, 'queries': n + 1,
'cap_required_mm': required, 'cap_used_mm': qc}
def min_gap(self, q, cap=40.0):
return self.gaps(q, cap)['gm'].min(-1).values