记录时间:
2026-05-23 17:59:26 CST
之前的 parallel 对比实验使用过:
a_solve_size = 5 或 9
b_width = 3
这种设置可以说明扩大 A solve window 会提高 A boundary 的可靠性,但和 sliding baseline 的对比不够严谨。原因是 parallel 的 A 局部上下文被增大, 而 B window 和 sliding 的 buffer 尺度没有同步对齐。
本次实验改为 buffer-aligned 策略:
buffer = 2
a_solve_size = 5
b_width = 5
step = 6
这样每个局部窗口的 buffer 厚度和 sliding baseline 保持一致。需要注意的是, parallel 的 interior A window 有左右两个 buffer,因此 A solve window 的总 宽度会更大:
A solve = left buffer + center + right buffer
= 2 + 1 + 2
= 5
修改文件:
ParallelWindowDecoder/parallel_window_decoder.py
当参数满足:
--a-size 3
--a-solve-size 5
--b-width 5
时,decode_staggered_ab 自动使用新的 buffer_aligned schedule。
新 schedule 生成:
A1 solve: s1-s3
B1 solve: s2-s6
A2 solve: s5-s9
B2 solve: s8-s12
A3 solve: s11-s15
在 N=144, num_repeat=12 的实际 detector history 中,诊断输出为:
schedule: buffer_aligned
A rows: ['s1-s3', 's5-s9', 's11-s13']
B rows: ['s2-s6', 's8-s12']
A commit: ['e0-e1', 'e11-e13', 'e23-e24']
B commit: ['e2-e10', 'e14-e22']
step: 6
最后一个 A window 被截断为 s11-s13,因为 detector blocks 总数为 13。
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--p-list 0.003,0.004,0.005 \
--num-repeat 12 \
--num-shots 100 \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 5 \
--osd-order 10 \
--max-iter 200 \
--parallel-workers 4 \
--parallel-backend process \
--decoders sliding,parallel,oracle \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_buffer_aligned_a_solve5_b5_process_workers4.csv输出文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_buffer_aligned_a_solve5_b5_process_workers4.csv
| p | decoder | LER | flagged | logical_or_flagged | elapsed |
|---|---|---|---|---|---|
| 0.003 | sliding | 0.00 | 0/100 | 0/100 | 6.853s |
| 0.003 | parallel | 0.01 | 1/100 | 1/100 | 3.180s |
| 0.003 | oracle | 0.00 | 0/100 | 0/100 | 0.918s |
| 0.004 | sliding | 0.02 | 0/100 | 2/100 | 9.871s |
| 0.004 | parallel | 0.07 | 6/100 | 7/100 | 3.889s |
| 0.004 | oracle | 0.01 | 0/100 | 1/100 | 1.340s |
| 0.005 | sliding | 0.06 | 0/100 | 6/100 | 13.756s |
| 0.005 | parallel | 0.18 | 17/100 | 18/100 | 5.444s |
| 0.005 | oracle | 0.01 | 0/100 | 1/100 | 1.370s |
本次结果和学长的判断一致:在 buffer 对齐之后,parallel 的准确率并不高。
具体表现为:
p = 0.003: parallel LER 0.01, flagged 1/100
p = 0.004: parallel LER 0.07, flagged 6/100
p = 0.005: parallel LER 0.18, flagged 17/100
相比 sliding:
p = 0.003: sliding LER 0.00
p = 0.004: sliding LER 0.02
p = 0.005: sliding LER 0.06
parallel 速度更快,但准确率明显更差。oracle 结果仍然较好,说明 A/B residual stitching 的代数结构基本成立;主要瓶颈仍然是 decoded A boundary 的可靠性。
上面的 100-shot 结果已经说明趋势。为了进一步确认,并加入更高错误率
p = 0.007,重新运行 1000-shot 实验。
注意:这里 sliding baseline 必须使用:
sliding_width = 3
因为 sliding 的 window 大小为 3 时,对应的 buffer 厚度才是 2,才能和 parallel 的:
a_solve_size = 5
b_width = 5
buffer = 2
严格对齐。曾短暂启动过 sliding_width = 5 的实验,但该设置不符合这一定义,
已中止,不作为正式结果。
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--p-list 0.003,0.004,0.005,0.007 \
--num-repeat 12 \
--num-shots 1000 \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--osd-order 10 \
--max-iter 200 \
--parallel-workers 4 \
--parallel-backend process \
--decoders sliding,parallel,oracle \
--out ParallelWindowDecoder/results/N144_repeat12_shots1000_buffer_aligned_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv输出文件:
ParallelWindowDecoder/results/N144_repeat12_shots1000_buffer_aligned_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv
parallel diagnostics 确认仍然使用 buffer-aligned 排布:
schedule: buffer_aligned
A rows: ['s1-s3', 's5-s9', 's11-s13']
B rows: ['s2-s6', 's8-s12']
A commit: ['e0-e1', 'e11-e13', 'e23-e24']
B commit: ['e2-e10', 'e14-e22']
step: 6
| p | decoder | LER | flagged | logical_or_flagged | elapsed |
|---|---|---|---|---|---|
| 0.003 | sliding | 0.003 | 0/1000 | 3/1000 | 58.705s |
| 0.003 | parallel | 0.014 | 11/1000 | 14/1000 | 21.166s |
| 0.003 | oracle | 0.001 | 0/1000 | 1/1000 | 6.607s |
| 0.004 | sliding | 0.023 | 0/1000 | 23/1000 | 69.483s |
| 0.004 | parallel | 0.052 | 42/1000 | 52/1000 | 30.141s |
| 0.004 | oracle | 0.004 | 0/1000 | 4/1000 | 7.534s |
| 0.005 | sliding | 0.107 | 0/1000 | 107/1000 | 82.850s |
| 0.005 | parallel | 0.161 | 123/1000 | 161/1000 | 42.166s |
| 0.005 | oracle | 0.026 | 0/1000 | 26/1000 | 10.499s |
| 0.007 | sliding | 0.561 | 0/1000 | 561/1000 | 120.528s |
| 0.007 | parallel | 0.665 | 500/1000 | 665/1000 | 68.944s |
| 0.007 | oracle | 0.257 | 0/1000 | 257/1000 | 21.331s |
1000-shot 结果进一步确认:
parallel 的 wall-clock 更短,但准确率低于 sliding;
错误率越高,parallel 的 decoded A boundary 问题越明显。
尤其在 p = 0.007 时:
sliding LER = 0.561
parallel LER = 0.665
parallel flagged = 500/1000
oracle 仍然比 decoded parallel 好很多,说明如果 A boundary 给对,B residual 结构仍有较强闭合能力;但真实 decoded A boundary 在该 buffer-aligned 设置下 不够可靠。
尝试 Top-K 前,已备份当前代码:
ParallelWindowDecoder/backups/parallel_window_decoder.before_topk.py
ParallelWindowDecoder/backups/run_experiments.before_topk.py
新增参数:
--top-k-boundary
默认值为:
--top-k-boundary 1
因此不传该参数时,仍保持原来的 hard-boundary 行为。
当使用:
--top-k-boundary 2
且 schedule 为 buffer_aligned 时,A window 不只输出一个 commit 结果,而是输出
2 个候选。
候选生成方式:
- A window 先正常 BP+OSD 解码,得到 top-1 commit;
- 读取
BpOsdDecoder.log_prob_ratios; - 在 A commit 区域中找到最低可靠度的 bit;
- 修改该 bit 的 prior 后重新解 A window,得到另一个候选;
- B window 枚举左右 A 候选组合;
- 用 B 局部 residual 是否闭合和 channel cost 选择总代价最低的拼接。
这不是完整的 OSD top-K list,而是一个工程上较小的 top-K 近似版本。它的目的 是验证:
A boundary hard decision 是否确实是主要瓶颈
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--p-list 0.003,0.004,0.005,0.007 \
--num-repeat 12 \
--num-shots 100 \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--osd-order 10 \
--max-iter 200 \
--parallel-workers 4 \
--parallel-backend process \
--top-k-boundary 2 \
--decoders parallel \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_buffer_aligned_topk2_redecode_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv输出文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_buffer_aligned_topk2_redecode_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv
| p | hard parallel LER | hard flagged | Top-K=2 LER | Top-K=2 flagged | Top-K=2 elapsed |
|---|---|---|---|---|---|
| 0.003 | 0.01 | 1/100 | 0.00 | 0/100 | 7.385s |
| 0.004 | 0.07 | 6/100 | 0.06 | 5/100 | 10.606s |
| 0.005 | 0.18 | 17/100 | 0.14 | 11/100 | 16.023s |
| 0.007 | - | - | 0.60 | 42/100 | 30.806s |
其中 hard parallel 的 100-shot baseline 来自:
ParallelWindowDecoder/results/N144_repeat12_shots100_buffer_aligned_a_solve5_b5_process_workers4.csv
该 baseline 当时只跑到:
p = 0.003, 0.004, 0.005
所以表中 p = 0.007 没有对应的 hard 100-shot baseline。
Top-K=2 有改善信号:
p = 0.003: flagged 1/100 -> 0/100
p = 0.004: flagged 6/100 -> 5/100
p = 0.005: flagged 17/100 -> 11/100
但代价也明显:
runtime 明显增加
准确率仍然低于 sliding
这说明方向是有价值的:A boundary 的 hard decision 的确会损失信息,给 B 一点 重新选择边界的空间可以降低 flagged/LER。
不过当前实现还只是近似 Top-K:它只围绕低可靠 bit 重新解 A,而不是枚举真正的 多个低代价 syndrome-satisfying A 解。后续若继续推进,应该尝试更正式的:
OSD-derived top-K boundary candidates
或 reliability-aware Top-K candidate generation
在不采用 Top-K 的情况下,尝试 soft boundary message:
--soft-boundary-message
核心变化:
原 hard boundary:
A 先 commit 边界,B 用 residual syndrome 固定接受这些边界。
naive soft boundary:
A 仍先给出边界估计;
B 解码时把左右边界变量放回 B 的局部矩阵;
根据 A 的输出修改这些边界变量的 prior;
B 可以选择和 A 不同的边界值。
本次使用较强的 soft prior:
--soft-boundary-one-prior 0.49
--soft-boundary-zero-prior 0.000001
也就是说:
A 说 e_j = 1 时,B 中该变量 prior 设为 0.49;
A 说 e_j = 0 时,B 中该变量 prior 设为 1e-6。
这样仍不是 hard constraint,因为 B 可以根据 syndrome 反驳 A。
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--p-list 0.003,0.004,0.005,0.007 \
--num-repeat 12 \
--num-shots 100 \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--osd-order 10 \
--max-iter 200 \
--parallel-workers 1 \
--parallel-backend thread \
--soft-boundary-message \
--soft-boundary-one-prior 0.49 \
--soft-boundary-zero-prior 0.000001 \
--decoders parallel \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_buffer_aligned_soft_boundary_a_solve5_b5_sliding3_thread_p003_to_007.csv输出文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_buffer_aligned_soft_boundary_a_solve5_b5_sliding3_thread_p003_to_007.csv
| p | hard parallel LER | hard flagged | naive soft LER | naive soft flagged | naive soft elapsed |
|---|---|---|---|---|---|
| 0.003 | 0.01 | 1/100 | 0.09 | 9/100 | 3.971s |
| 0.004 | 0.07 | 6/100 | 0.14 | 14/100 | 5.474s |
| 0.005 | 0.18 | 17/100 | 0.24 | 22/100 | 7.696s |
| 0.007 | - | - | 0.70 | 60/100 | 13.946s |
这个 naive soft boundary 版本明显变差。
主要原因是:B 虽然可以反驳 A 的边界变量,但 A commit block 中间的变量没有随之 重新优化。例如:
A2 commit: e11,e12,e13
如果 B1 soft-decode 后改写了 e11,B2 soft-decode 后改写了 e13,那么
e12 仍然是 A 原先 hard decode 的结果。这样 A2 的局部一致性可能被破坏,
最终全局 residual 更容易不闭合。
因此,soft boundary 不能只让 B 单方面改边界。更合理的版本应该是:
A -> B soft boundary
B 改边界后
再做一次 A-center repair / A-B-A 迭代
也就是说,soft boundary message 需要配合 boundary repair 或一轮 A-B-A 消息传递,否则会破坏 A commit block 的内部一致性。
之前的 Top-K=4 使用的是 re-decode 近似:
为每个候选修改 prior
重新跑一次 BP+OSD
这会导致 A 侧开销约随 K 线性增长,B 侧还要枚举 K^2 个边界组合。
本次尝试把候选提取改成:
one BP run
one OSD basis
extract top-K candidates
即只跑一次 BP+OSD,然后根据 BP/OSD 的 reliability order,在 GF(2) 消元后的 OSD basis 上枚举低可靠自由位翻转,生成 top-K 候选。
新增 Cython 文件:
ParallelWindowDecoder/osd_list.pyx
ParallelWindowDecoder/setup_osd_list.py
编译命令:
cd ParallelWindowDecoder
../SlidingWindowDecoder/.conda-gdg/bin/python setup_osd_list.py build_ext --inplace生成本地扩展:
ParallelWindowDecoder/osd_list.cpython-312-darwin.so
parallel_window_decoder.py 中优先使用:
from osd_list import osd_list_candidates
如果扩展不存在,则 fallback 到 Python 版本。
osd_list_candidates 做:
- 按 reliability 从高到低排列列;
- 对排列后的局部矩阵做 GF(2) 消元;
- 用 BP+OSD 输出作为 seed;
- 选最低可靠的自由位;
- 枚举单 bit / 双 bit 翻转;
- 解出 pivot 位;
- 取 channel cost 最低的 top-K 个候选。
调试时发现一个关键 bug:
rhs = np.ascontiguousarray(syndrome)
在 syndrome 已连续时不会复制,导致 Cython 消元原地修改传入 syndrome, 污染后续 residual。已修复为:
rhs = np.array(syndrome, dtype=np.uint8, copy=True, order="C")
一致性检查通过:
seed residual before: 0
seed residual after: 0
candidate residuals: 0,0,0,0
运行命令:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--p-list 0.003,0.004,0.005,0.007 \
--num-repeat 12 \
--num-shots 20 \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--osd-order 10 \
--max-iter 200 \
--parallel-workers 4 \
--parallel-backend process \
--top-k-boundary 4 \
--decoders parallel \
--out ParallelWindowDecoder/results/N144_repeat12_shots20_buffer_aligned_topk4_cython_osdlist_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv输出文件:
ParallelWindowDecoder/results/N144_repeat12_shots20_buffer_aligned_topk4_cython_osdlist_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv
结果:
| p | LER | flagged | logical_or_flagged | elapsed |
|---|---|---|---|---|
| 0.003 | 0.00 | 0/20 | 0/20 | 24.176s |
| 0.004 | 0.00 | 0/20 | 0/20 | 29.469s |
| 0.005 | 0.05 | 1/20 | 1/20 | 33.686s |
| 0.007 | 0.75 | 11/20 | 15/20 | 49.312s |
Cython 版比 Python OSD-list 有明显加速:
p=0.003, 20 shots:
Python OSD-list: 44.247s
Cython OSD-list: 24.176s
大约快了:
45%
但它仍然比 re-decode Top-K=4 的 100-shot 版本按比例更慢,不适合作为当前主线。
原因是:
每个 shot / A window 仍然要做一次 dense GF(2) 消元
局部矩阵列数很大
当前 Cython 版本没有缓存同一个 window 的消元结构
如果继续这个方向,下一步需要:
1. 缓存每个 A window 的 reliability-independent 结构;
2. 或直接 patch ldpc 的 C++ OsdDecoder,让它在内部 OSD 搜索时返回 candidate list;
3. 或只在低 reliability 的 A window 上触发 OSD-list。
当前结论:
Cython OSD-list 可行,但仍太慢;
更适合后续作为底层优化方向,不适合作为当前实验主线。
为避免外部 Python/Cython OSD-list 重复做 dense GF(2) 消元,改为直接 patch ldpc 的 C++ OsdDecoder:
source: /private/tmp/ldpc_repo
installed env: SlidingWindowDecoder/.conda-gdg
ldpc version: 2.4.1
saved patch: ParallelWindowDecoder/patches/ldpc_osd_candidate_list.patch
在 src_cpp/osd.hpp 中新增:
osd_candidate_decodings
osd_candidate_weights
osd_candidate_list_size
set_osd_candidate_list_size(...)
在 OSD 内部搜索循环中,每生成一个完整 candidate_solution,立即计算 weight 并维护 top-K candidate list。
默认 osd_candidate_list_size=0,普通 decode() 不收集 candidate,因此默认路径没有额外 candidate-list 开销。
在 src_python/ldpc/bposd_decoder/_bposd_decoder.pyx 中新增:
BpOsdDecoder.decode_list(syndrome, top_k=4, force_osd=False)
BpOsdDecoder.osd_candidate_weights
其中:
force_osd=False:
BP 收敛时只返回 BP 解
force_osd=True:
强制运行一次 OSD,并返回 C++ 内部 OSD 搜索得到的 top-K candidate
ParallelWindowDecoder/parallel_window_decoder.py 的 Top-K A-window candidate 路径已改为:
优先使用 patched ldpc BpOsdDecoder.decode_list(..., force_osd=True)
若当前 ldpc 没有 decode_list,则回退到外部 Cython/Python OSD-list
这样 Top-K 不再需要在 parallel decoder 外部重新实现一套 OSD-list 搜索。
小矩阵测试确认:
has_decode_list True
candidates_shape (4, 6)
syndromes_ok [True, True, True, True]
说明返回的 4 个 candidate 都满足:
H @ candidate = syndrome mod 2
运行命令:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 5 \
--p-list 0.003 \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 4 \
--parallel-workers 1 \
--parallel-backend thread \
--out ParallelWindowDecoder/results/native_ldpc_decode_list_smoke.csv结果:
| decoder | LER | flagged | elapsed |
|---|---|---|---|
| global | 0 | 0/5 | 0.105s |
| sliding | 0 | 0/5 | 0.681s |
| parallel | 0 | 0/5 | 0.903s |
| oracle | 0 | 0/5 | 0.093s |
输出文件:
ParallelWindowDecoder/results/native_ldpc_decode_list_smoke.csv
运行命令:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 4 \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_native_ldpc_topk4_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv输出文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_native_ldpc_topk4_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv
结果:
| p | global LER/time | sliding LER/time | parallel Top-K=4 LER/time | oracle LER/time | parallel/sliding time | parallel flagged |
|---|---|---|---|---|---|---|
| 0.003 | 0.000/4.752s | 0.000/11.574s | 0.010/23.016s | 0.000/1.793s | 1.99x | 1/100 |
| 0.004 | 0.000/7.951s | 0.050/13.902s | 0.060/39.437s | 0.010/2.401s | 2.84x | 5/100 |
| 0.005 | 0.050/19.991s | 0.150/16.083s | 0.180/72.209s | 0.010/2.692s | 4.49x | 16/100 |
| 0.007 | 0.490/40.590s | 0.600/23.421s | 0.630/167.108s | 0.190/5.109s | 7.13x | 39/100 |
结论:
patched ldpc native Top-K=4 可以正常运行;
但在 100-shot 对比中,parallel Top-K=4 没有优于 sliding 的准确率;
同时延迟随 p 增大显著上升,约为 sliding 的 2x 到 7x。
因此当前 Top-K=4 不适合作为主线对比方案。它更适合作为后续研究边界候选机制的工具,而不是当前严谨对比实验中的高效 decoder。
运行命令:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 2 \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_native_ldpc_topk2_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv输出文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_native_ldpc_topk2_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv
与 K=4 对比:
| p | sliding LER/time | K=2 parallel LER/time | K=2 ratio | K=4 parallel LER/time | K=4 ratio |
|---|---|---|---|---|---|
| 0.003 | 0.000/11.626s | 0.010/11.251s | 0.97x | 0.010/23.016s | 1.98x |
| 0.004 | 0.050/14.717s | 0.070/17.150s | 1.17x | 0.060/39.437s | 2.68x |
| 0.005 | 0.150/16.083s | 0.180/22.845s | 1.42x | 0.180/72.209s | 4.49x |
| 0.007 | 0.600/23.060s | 0.640/46.786s | 2.03x | 0.630/167.108s | 7.25x |
结论:
K=2 将 B 层组合从 K^2=16 降到 K^2=4;
延迟明显下降,p=0.005 从 72.209s 降到 22.845s,p=0.007 从 167.108s 降到 46.786s;
但准确率没有明显改善,整体仍略差于 sliding。
这说明当前 Top-K 的主要收益不足以抵消 boundary stitching 的复杂度;K=2 是更合理的延迟点,但不是更好的准确率点。
本轮将 SlidingWindowDecoder 中两个窗口优化机制接入当前对比实验:
1. noisy syndrome boundary
2. shortening trick
新增 CLI 参数:
--sliding-method
--window-shorten
--shorten-pre-max-iter
--b-noisy-boundary
已有参数:
--a-noisy-boundary
当前含义:
sliding:
--sliding-method 1 使用 noisy syndrome boundary
--window-shorten 使用 src.osd_window 的 shortening trick
parallel:
--a-noisy-boundary 给 A window 加 noisy boundary columns
--b-noisy-boundary 给 B window 加 noisy boundary columns
--window-shorten 对 A/B window 使用 src.osd_window
注意:
top_k_boundary > 1 暂不和 window_shorten / b_noisy_boundary 同时使用;
因为 shortening decoder 不返回 candidate list,B 的 top-K stitching 也需要额外处理 noisy columns。
运行命令:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--b-noisy-boundary \
--window-shorten \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_noisy_boundary_shorten_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv输出文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_noisy_boundary_shorten_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv
与 baseline K=2 对比:
| p | baseline sliding LER/time | noisy+shorten sliding LER/time | baseline parallel LER/time | noisy+shorten parallel LER/time |
|---|---|---|---|---|
| 0.003 | 0.000/11.626s | 0.000/11.323s | 0.010/11.251s | 0.010/4.224s |
| 0.004 | 0.050/14.717s | 0.020/12.561s | 0.070/17.150s | 0.060/5.122s |
| 0.005 | 0.150/16.083s | 0.120/13.926s | 0.180/22.845s | 0.200/7.324s |
| 0.007 | 0.600/23.060s | 0.450/18.113s | 0.640/46.786s | 0.590/10.609s |
对 sliding:
noisy syndrome boundary + shortening 明显有帮助。
p=0.004: LER 0.050 -> 0.020
p=0.005: LER 0.150 -> 0.120
p=0.007: LER 0.600 -> 0.450
对 parallel:
速度明显改善。
p=0.007: 46.786s -> 10.609s
但准确率改善不稳定:
p=0.004: 0.070 -> 0.060
p=0.005: 0.180 -> 0.200
p=0.007: 0.640 -> 0.590
说明 shortening 可以降低窗口内部解码成本,noisy boundary 可以缓解局部边界截断;但 parallel 的 A/B hard commit 错误传播仍然存在,尤其 A commit 错后 B 仍会在错误残差下解码。
当前更严谨的 baseline 应该使用:
sliding method=1 + shortening
parallel A/B noisy boundary + shortening
而不是之前的 plain BP+OSD window。
为支持:
parallel top-k=2 + shortening
修改了 SlidingWindowDecoder/src/osd_window.pyx 和 SlidingWindowDecoder/src/osd_window.pxd:
新增 osd_window.decode_list(input_vector, top_k=2, force_osd=False)
新增 osd_window.candidate_weights
内部修改:
1. 在 osd_window 内部维护 candidate_decodings / candidate_weights;
2. OSD_0 解和 OSD_CS/OSD_E 搜索中的每个候选都会 push 到 top-K list;
3. force_osd=True 时,即使 BP 已经收敛,也继续执行 OSD candidate extraction。
重新编译:
cd SlidingWindowDecoder
.conda-gdg/bin/python setup.py build_ext --inplaceAPI 验证:
shape (2, 6)
weights [2.9444389791664403, 5.8888779583328805]
ok [True, True]
运行命令:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 2 \
--a-noisy-boundary \
--window-shorten \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_parallel_topk2_a_noisy_shorten_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv输出文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_parallel_topk2_a_noisy_shorten_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv
对比:
| p | sliding noisy+shorten LER/time | parallel noisy+shorten LER/time | parallel top-k=2 + shorten LER/time |
|---|---|---|---|
| 0.003 | 0.000/11.289s | 0.010/4.224s | 0.000/7.458s |
| 0.004 | 0.020/12.547s | 0.060/5.122s | 0.050/11.173s |
| 0.005 | 0.120/16.677s | 0.200/7.324s | 0.190/20.100s |
| 0.007 | 0.450/18.628s | 0.590/10.609s | 0.580/44.355s |
结论:
top-k=2 + shortening 可以正常运行;
低 p=0.003 时准确率改善到 0;
但 p>=0.004 时仍明显差于 sliding noisy+shorten;
高 p 下延迟增加明显,p=0.007 达到 44.355s。
说明:
shortening 解决的是单个窗口内部复杂度;
top-k 增加的是 A 边界候选;
但 B 仍然要做 K^2 stitching,且 A/B hard commit 的结构性错误传播仍未根除。
为避免全量 Top-K 的 K^2 stitching 延迟,新增低延迟 repair 策略:
1. A layer 正常 top-1 解码,并记录 A commit 区域 reliability;
2. B layer 正常 top-1 解码;
3. 若 B 不 flagged,直接提交;
4. 若 B flagged,只选择相邻 A boundary 中 reliability 最低且影响该 B syndrome 的一个变量;
5. 翻转该 boundary 变量,更新 B residual,并只重跑该 B window 一次;
6. 只有 residual weight 下降时才接受该 repair。
新增参数:
--flag-triggered-single-flip
当前限制:
只用于 top_k_boundary=1;
不和 soft_boundary_message / b_noisy_boundary 同时使用;
oracle 不启用该 repair。
运行命令:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--window-shorten \
--flag-triggered-single-flip \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_flag_single_flip_a_noisy_shorten_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv输出文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_flag_single_flip_a_noisy_shorten_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv
对比:
| p | sliding noisy+shorten | parallel noisy+shorten | parallel top-k=2+shorten | flag-triggered single-flip | repair attempts/accepted/success |
|---|---|---|---|---|---|
| 0.003 | 0.000/5.874s | 0.010/4.224s | 0.000/7.458s | 0.010/3.138s | 2/1/1 |
| 0.004 | 0.020/6.398s | 0.060/5.122s | 0.050/11.173s | 0.040/3.771s | 10/5/4 |
| 0.005 | 0.120/7.136s | 0.200/7.324s | 0.190/20.100s | 0.190/5.869s | 34/18/5 |
| 0.007 | 0.450/10.323s | 0.590/10.609s | 0.580/44.355s | 0.590/11.097s | 86/31/2 |
延迟方面:
flag-triggered single-flip 明显优于全量 Top-K=2。
p=0.007: Top-K=2+shorten 44.355s, single-flip 11.097s
准确率方面:
p=0.004 有收益: 0.060 -> 0.040
p=0.005 有小收益: 0.200 -> 0.190
p=0.007 基本无收益: 0.590 -> 0.590
repair 统计显示高 p 下虽然 triggered 多,但真正修成 unflagged 的次数很少:
p=0.007: attempts=86, accepted=31, success=2
这说明高 p 下 B flagged 往往不是单个 A boundary bit 错误造成的,而是多个 boundary / B 内部局部解共同出错。single-flip 是很好的低延迟 repair baseline,但它不能替代更强的边界联合优化。
当前最严谨的 sliding-vs-parallel 对比应固定:
N=144
num_repeat=12
shots=100
p-list=0.003,0.004,0.005,0.007
same random seeds
max_iter=200
osd_order=10
sliding_width=3
a_solve_size=5
b_width=5
buffer=2
sliding method=1
window shortening enabled
然后只改变 parallel 的 boundary policy:
plain top-1
flag-triggered single-flip
top-k=2
这样能保证比较的是 boundary 策略本身,而不是 window size、buffer size、inner decoder 或 noise sample 的差异。
在 flag-triggered single-flip 框架下,新增 flip 选择规则:
--single-flip-rule reliability
--single-flip-rule residual
其中 residual 规则对每个候选 A boundary bit 计算:
|r_B + H_boundary,j|
选择翻转后 B residual weight 最小的 bit;若有并列,再用 A reliability 做 tie-break。
运行命令:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--window-shorten \
--flag-triggered-single-flip \
--single-flip-rule residual \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_residual_single_flip_a_noisy_shorten_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv输出文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_residual_single_flip_a_noisy_shorten_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv
对比:
| p | sliding noisy+shorten | reliability single-flip | residual-aware single-flip | residual repair attempts/accepted/success |
|---|---|---|---|---|
| 0.003 | 0.000/5.859s | 0.010/3.138s | 0.010/3.232s | 2/2/2 |
| 0.004 | 0.020/6.304s | 0.040/3.771s | 0.060/3.917s | 10/10/0 |
| 0.005 | 0.120/7.234s | 0.190/5.869s | 0.200/5.885s | 34/34/4 |
| 0.007 | 0.450/9.078s | 0.590/11.097s | 0.590/10.752s | 86/86/26 |
residual-aware rule 没有优于 reliability rule:
p=0.004: reliability 0.040, residual-aware 0.060
p=0.005: reliability 0.190, residual-aware 0.200
p=0.007: 两者都是 0.590
原因可能是:
residual-aware 只优化当前 B 的 syndrome residual;
但翻转 A boundary 变量会影响相邻 B window 或全局 logical class;
所以局部 residual weight 降低不等于最终 logical error 降低。
从 repair 统计看,residual-aware 会更激进地接受 repair:
p=0.007: attempts=86, accepted=86, success=26
但最终 LER 没变,说明它主要修了 syndrome flagged,而没有稳定改善 logical class。
当前结论:
保留 reliability single-flip 作为低延迟 repair baseline;
residual-aware single-flip 不作为主路线。
按后续判断,删除运行代码中的 residual-aware single-flip 分支,保留 reliability single-flip,并新增:
--bounded-two-flip
--two-flip-candidates 4
策略:
1. 只在 B flagged 时触发;
2. 从相邻 A boundary 中选 reliability 最低的前 m 个变量;
3. 先试最低 reliability 的 1-flip;
4. 若仍 flagged,则枚举前 m 个变量里的 2-flip;
5. 只接受 residual weight 下降的 repair。
本次使用:
m = 4
最多 C(4,2)=6 个 2-flip
运行命令:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--window-shorten \
--flag-triggered-single-flip \
--bounded-two-flip \
--two-flip-candidates 4 \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_bounded2flip_m4_a_noisy_shorten_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv输出文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_bounded2flip_m4_a_noisy_shorten_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv
| p | sliding flagged | plain parallel flagged | single-flip flagged | bounded-2flip flagged | bounded repair attempts/accepted/success | twoflip attempts/accepted/success |
|---|---|---|---|---|---|---|
| 0.003 | 0/100 | 1/100 | 1/100 | 1/100 | 2/2/1 | 1/1/0 |
| 0.004 | 0/100 | 5/100 | 3/100 | 3/100 | 10/9/5 | 6/5/1 |
| 0.005 | 0/100 | 17/100 | 16/100 | 15/100 | 34/28/11 | 29/18/6 |
| 0.007 | 0/100 | 43/100 | 43/100 | 43/100 | 86/60/6 | 84/45/4 |
| p | sliding noisy+shorten | single-flip | bounded-2flip |
|---|---|---|---|
| 0.003 | 0.000/5.954s | 0.010/3.138s | 0.010/3.287s |
| 0.004 | 0.020/6.415s | 0.040/3.771s | 0.040/4.943s |
| 0.005 | 0.120/7.173s | 0.190/5.869s | 0.190/11.677s |
| 0.007 | 0.450/9.202s | 0.590/11.097s | 0.590/29.654s |
从 flagged 看:
p=0.004: plain 5 -> single 3 -> bounded2 3
p=0.005: plain 17 -> single 16 -> bounded2 15
p=0.007: plain 43 -> single 43 -> bounded2 43
bounded-2flip 对中等 p 有很小的 flagged 改善,但高 p 下没有降低最终 flagged。
原因:
p=0.007 虽然 twoflip accepted=45, success=4,
但最终 flagged 仍是 43/100。
说明很多高 p flagged 不是两个 A boundary bit 就能修掉,或者 repair 降低了当前 B residual 但全局 residual / 相邻窗口仍然不一致。
当前判断:
bounded-2flip 是合理诊断实验;
但作为主路线,它的 flagged 收益太小,延迟增加明显。
下一步更值得尝试 A boundary penalty,从源头减少坏 boundary。
Top-K=2 使用已有结果:
ParallelWindowDecoder/results/N144_repeat12_shots100_parallel_topk2_a_noisy_shorten_a_solve5_b5_sliding3_process_workers4_p003_to_007.csv
flagged 对比:
| p | sliding flagged | plain parallel | single-flip | bounded-2flip | Top-K=2 |
|---|---|---|---|---|---|
| 0.003 | 0/100 | 1/100 | 1/100 | 1/100 | 0/100 |
| 0.004 | 0/100 | 5/100 | 3/100 | 3/100 | 4/100 |
| 0.005 | 0/100 | 17/100 | 16/100 | 15/100 | 15/100 |
| 0.007 | 0/100 | 43/100 | 43/100 | 43/100 | 41/100 |
Top-K=2 的 LER/time:
| p | Top-K=2 LER/time | Top-K=2 flagged |
|---|---|---|
| 0.003 | 0.000/7.458s | 0/100 |
| 0.004 | 0.050/11.173s | 4/100 |
| 0.005 | 0.190/20.100s | 15/100 |
| 0.007 | 0.580/44.355s | 41/100 |
结论:
Top-K=2 对 flagged 有小幅改善:
p=0.007: 43/100 -> 41/100
p=0.003: 1/100 -> 0/100
但它的延迟代价很大:
p=0.007: Top-K=2 44.355s
bounded-2flip 29.654s
single-flip 11.097s
plain noisy+shorten 10.609s
因此 Top-K=2 能说明“更多边界候选确实可能减少 flagged”,但性价比不高。bounded-2flip 达到部分 Top-K 的 flagged 改善,但仍不足以明显降低高 p flagged。
目标是从源头减少坏的 A boundary,而不是在 B flagged 后再 repair。
对 A window 中会影响相邻 B residual 的 commit 变量提高 LLR 绝对值:
LLR_j' = scale * LLR_j, j in A/B boundary commit variables
由于 p < 0.5,放大 LLR 等价于降低这些 boundary 变量被置 1 的先验概率。直观上:
除非 A window 内证据足够强,否则不要轻易把错误解释成跨 A/B boundary。
本轮控制变量:
N=144, repeat=12, shots=100
p = 0.003,0.004,0.005,0.007
sliding_width = 3
a_solve_size = 5
b_width = 5
A noisy boundary = on
B noisy boundary = on
window shortening = on
top_k_boundary = 1
只改变 a_boundary_weight_scale
命令示例:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 --num-repeat 12 --num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--decoders parallel \
--a-size 3 --a-solve-size 5 --b-width 5 --sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary --b-noisy-boundary --window-shorten \
--a-boundary-weight-scale 1.2 \
--parallel-workers 4 --parallel-backend process结果文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_a_boundary_penalty_scale1p1_ab_noisy_shorten_parallel_only.csv
ParallelWindowDecoder/results/N144_repeat12_shots100_a_boundary_penalty_scale1p2_ab_noisy_shorten_parallel_only.csv
ParallelWindowDecoder/results/N144_repeat12_shots100_a_boundary_penalty_scale1p5_ab_noisy_shorten_parallel_only.csv
ParallelWindowDecoder/results/N144_repeat12_shots100_a_boundary_penalty_scale2p0_ab_noisy_shorten_parallel_only.csv
flagged / LER / time 对比:
| p | scale=1.0 baseline | scale=1.1 | scale=1.2 | scale=1.5 | scale=2.0 |
|---|---|---|---|---|---|
| 0.003 | 1/100, 0.010, 4.224s | 0/100, 0.000, 3.210s | 0/100, 0.000, 3.158s | 2/100, 0.020, 3.299s | 8/100, 0.080, 4.251s |
| 0.004 | 5/100, 0.060, 5.122s | 8/100, 0.080, 3.620s | 8/100, 0.090, 3.537s | 10/100, 0.100, 5.698s | 20/100, 0.250, 4.246s |
| 0.005 | 17/100, 0.200, 7.324s | 15/100, 0.180, 5.461s | 8/100, 0.130, 5.039s | 25/100, 0.310, 5.434s | 55/100, 0.630, 6.387s |
| 0.007 | 43/100, 0.590, 10.609s | 43/100, 0.630, 9.397s | 48/100, 0.620, 9.976s | 53/100, 0.720, 7.597s | 82/100, 0.920, 6.690s |
A boundary penalty 的效果不是单调的。
有效的地方:
p=0.003: scale 1.1/1.2 把 flagged 从 1/100 降到 0/100
p=0.005: scale 1.2 把 flagged 从 17/100 降到 8/100,LER 从 0.200 降到 0.130
失效的地方:
p=0.004: 所有 penalty 都比 baseline 更差
p=0.007: scale 1.2 以后 flagged 明显变差,scale 2.0 直接恶化到 82/100
解释:
boundary penalty 只是在 A 层降低 boundary bit 被置 1 的倾向。
如果真实错误确实落在 boundary 上,过强 penalty 会迫使 A 选择错误的局部解释,
然后 B 得到更差的 residual。
所以当前判断:
A boundary penalty 可以作为一个可调 regularizer,
但不能单独作为降低 high-p flagged 的主路线。
如果继续使用,比较合理的是只保留较小 scale:
scale = 1.1 或 1.2
并且需要做 p-dependent 或 reliability-dependent 的自适应版本,而不是固定强惩罚。
这个实验尝试让 B 反过来影响 A boundary,但仍然保持 layer-wise parallel:
并行 A
-> 并行 B
-> 根据 stitched global residual 生成 B -> A feedback
-> 翻转被接受的 A boundary variables
-> 并行重跑受影响的 B
第一版实现是 flagged-only、保守搜索:
1. A 正常解码并 commit。
2. B 正常解码并 commit。
3. 计算 stitched global residual。
4. 如果某个 B rows 上 residual 非零,则在相邻 A commit boundary columns 中找候选 flip。
5. 枚举最多 max_flips 个 boundary flip。
6. 接受能降低该 B rows residual weight 的 feedback。
7. 对受影响的 B window 重跑一次。
注意:最开始尝试用 B local decoder residual 作为触发条件,但在 B noisy boundary + shortening 下,B local residual 全部为 0,因此不会触发 feedback。后来改为使用 stitched global residual 触发,这才对应最终 flagged 的来源。
新增参数:
--aba-boundary-feedback
--aba-max-flips
--aba-candidate-cols
控制变量:
N=144, repeat=12, shots=100
p = 0.003,0.004,0.005,0.007
a_solve_size = 5
b_width = 5
sliding_width = 3
A noisy boundary = on
B noisy boundary = on
window shortening = on
top_k_boundary = 1
结果文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_aba_feedback_global_m2_c16_ab_noisy_shorten_parallel_only.csv
ParallelWindowDecoder/results/N144_repeat12_shots100_aba_feedback_global_m3_c24_ab_noisy_shorten_parallel_only.csv
普通 parallel vs A-B-A feedback:
| p | baseline flagged/LER/time | ABA m2 c16 flagged/LER/time | ABA m3 c24 flagged/LER/time |
|---|---|---|---|
| 0.003 | 1/100, 0.010, 4.224s | 1/100, 0.010, 3.449s | 1/100, 0.010, 3.328s |
| 0.004 | 5/100, 0.060, 5.122s | 5/100, 0.060, 3.971s | 5/100, 0.060, 4.023s |
| 0.005 | 17/100, 0.200, 7.324s | 17/100, 0.200, 5.932s | 17/100, 0.200, 5.653s |
| 0.007 | 43/100, 0.590, 10.609s | 43/100, 0.590, 10.595s | 43/100, 0.590, 9.937s |
feedback diagnostics:
| p | m2 attempts/proposed/accepted/rerun | m3 attempts/proposed/accepted/rerun |
|---|---|---|
| 0.003 | 2/2/2/2 | 2/2/2/2 |
| 0.004 | 10/10/10/10 | 10/10/10/10 |
| 0.005 | 34/34/34/34 | 34/34/34/34 |
| 0.007 | 86/86/86/86 | 86/86/86/86 |
A-B-A feedback 在这个实现下没有降低 final flagged:
p=0.003: 1/100 -> 1/100
p=0.004: 5/100 -> 5/100
p=0.005: 17/100 -> 17/100
p=0.007: 43/100 -> 43/100
关键诊断是:
所有 stitched global residual 都触发了 feedback;
所有 feedback 都产生了 proposal;
所有 proposal 都被接受并触发 B rerun;
但 final flagged 没变。
这说明当前 flagged 不是简单的:
某个 A boundary bit 错了
-> 翻回来
-> B 重跑
-> residual 消失
而更像是:
A/B 各自局部都能满足自己的窗口方程,
但拼接后的 correction 落在全局不一致或错误等价类中。
因此,单个 B 对相邻 A boundary 的局部反馈仍然不够。若不增大 A/B 矩阵大小,下一步更可能有效的是:
把所有 flagged rows 周围的 boundary variables 收集起来,
做一次小型 global boundary system repair,
而不是每个 B 独立反馈、独立重跑。
也就是从:
B_i -> A_left/A_right
升级为:
all flagged B rows -> shared boundary repair system
这仍然不扩大 A/B window,但会把多个窗口的边界修正作为一个整体求解。
这一版把上一节的 local B feedback 升级为 shared repair:
1. A layer 正常并行解码。
2. B layer 正常并行解码。
3. 计算 stitched global residual。
4. 找出所有 residual 非零的 B rows。
5. 收集这些 flagged B rows 相邻的 A commit boundary columns。
6. 建立一个小型 GF(2) repair system:
H_boundary x = r_flagged
7. 用 BP+OSD 解 boundary flip x。
8. 临时翻转这些 A boundary variables。
9. 重跑受影响的 B windows。
10. 只有 global residual weight 下降时才接受。
和上一节区别:
上一节:每个 B 独立反馈给左右 A。
这一节:所有 flagged B rows 共享一个 boundary repair system。
这仍然不扩大 A/B window,只是在窗口解码后加入一个 flagged-only boundary 协调层。
新增参数:
--shared-boundary-repair
--shared-boundary-max-cols
控制变量:
N=144, repeat=12, shots=100
p = 0.003,0.004,0.005,0.007
a_solve_size = 5
b_width = 5
sliding_width = 3
A noisy boundary = on
B noisy boundary = on
window shortening = on
top_k_boundary = 1
结果文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_shared_boundary_repair_c512_ab_noisy_shorten_parallel_only.csv
ParallelWindowDecoder/results/N144_repeat12_shots100_shared_boundary_repair_c2048_ab_noisy_shorten_parallel_only.csv
普通 parallel vs shared boundary repair:
| p | baseline flagged/LER/time | shared c512 flagged/LER/time | shared c2048 flagged/LER/time |
|---|---|---|---|
| 0.003 | 1/100, 0.010, 4.224s | 1/100, 0.010, 3.125s | 1/100, 0.010, 2.810s |
| 0.004 | 5/100, 0.060, 5.122s | 5/100, 0.060, 3.621s | 5/100, 0.060, 3.357s |
| 0.005 | 17/100, 0.200, 7.324s | 17/100, 0.200, 4.813s | 17/100, 0.200, 4.802s |
| 0.007 | 43/100, 0.590, 10.609s | 43/100, 0.590, 7.164s | 43/100, 0.590, 7.271s |
diagnostics:
| p | c512 init/attempt/accepted/success | c2048 init/attempt/accepted/success |
|---|---|---|
| 0.003 | 1/1/0/0 | 1/1/0/0 |
| 0.004 | 5/5/0/0 | 5/5/0/0 |
| 0.005 | 17/17/0/0 | 17/17/0/0 |
| 0.007 | 43/43/0/0 | 43/43/0/0 |
平均参与 repair 的 boundary columns:
c512: 512 columns per attempted shot
c2048: about 2016 columns per attempted shot
shared boundary repair 仍然没有降低 final flagged:
p=0.003: 1/100 -> 1/100
p=0.004: 5/100 -> 5/100
p=0.005: 17/100 -> 17/100
p=0.007: 43/100 -> 43/100
重要诊断:
所有 flagged shot 都触发了 shared repair attempt;
但没有任何一次 trial repair 能让 global residual weight 下降;
把候选列从 512 增加到约 2016 后仍然没有改善。
这说明当前 final flagged 不是简单的:
只改 A boundary variables 就能修复。
更可能是:
1. B window 内部 committed variables 也需要和 A boundary 一起联合变化;
2. 或者 residual 对应的是更长程的 qLDPC coupling,不在当前 boundary variable span 内;
3. 或者 BP+OSD 给出的局部解已经满足 local window,但 global stitching 落入了错误的整体一致性结构。
因此,在不扩大 A/B 矩阵大小的前提下,只修改 A boundary 的策略目前看起来不够。
如果继续沿着“不扩大 window”做,下一步应该从:
repair only A boundary variables
升级为:
repair A boundary variables + adjacent B edge variables
也就是 shared repair system 的变量集合不仅包含 A commit boundary,还要包含每个 flagged B window 两端的一小部分 B committed variables。这样仍然不扩大 A/B 解码矩阵,但 repair 层拥有足够自由度去真正改变 stitching residual。
这个实验对应新的边界决策方向:
不要等 B flagged 后 repair;
而是在 A commit 前,让 A 的候选选择参考相邻 B residual risk。
普通 parallel 的 A 选择是:
A candidate = argmin W_A
本实验改成:
A candidate = argmin [ W_A + beta * R_neighbor ]
其中:
R_neighbor = 相邻 B rows 上 raw syndrome 加上该 A candidate boundary contribution 后的 popcount
实现方式:
1. A window 生成 top-2 candidates。
2. 不做 B 的 K^2 stitching。
3. 对每个 A candidate 计算 neighbor residual risk。
4. A 只 commit rerank 后的一个 candidate。
5. B window 正常只解码一次。
新增参数:
--a-neighbor-rerank
--a-rerank-top-k 2
--a-neighbor-beta
这和 full Top-K stitching 的区别:
Top-K stitching:
A top-K -> B 枚举左右 K^2 -> B 多次 decode
A neighbor rerank:
A top-2 -> A 内部 rerank -> B decode 一次
控制变量:
N=144, repeat=12, shots=100
p = 0.003,0.004,0.005,0.007
a_solve_size = 5
b_width = 5
sliding_width = 3
A noisy boundary = on
B noisy boundary = on
window shortening = on
top_k_boundary = 1
结果文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_a_neighbor_rerank_top2_beta0p25_ab_noisy_shorten_parallel_only.csv
ParallelWindowDecoder/results/N144_repeat12_shots100_a_neighbor_rerank_top2_beta0p5_ab_noisy_shorten_parallel_only.csv
ParallelWindowDecoder/results/N144_repeat12_shots100_a_neighbor_rerank_top2_beta1p0_ab_noisy_shorten_parallel_only.csv
ParallelWindowDecoder/results/N144_repeat12_shots100_a_neighbor_rerank_top2_beta2p0_ab_noisy_shorten_parallel_only.csv
flagged / LER / time 对比:
| p | baseline | beta=0.25 | beta=0.5 | beta=1.0 | beta=2.0 |
|---|---|---|---|---|---|
| 0.003 | 1/100, 0.010, 4.224s | 1/100, 0.010, 4.635s | 1/100, 0.010, 4.658s | 1/100, 0.010, 4.637s | 0/100, 0.000, 4.523s |
| 0.004 | 5/100, 0.060, 5.122s | 4/100, 0.050, 5.312s | 5/100, 0.060, 5.366s | 5/100, 0.060, 5.332s | 5/100, 0.060, 5.452s |
| 0.005 | 17/100, 0.200, 7.324s | 17/100, 0.200, 7.038s | 17/100, 0.200, 7.057s | 17/100, 0.200, 6.839s | 17/100, 0.200, 6.846s |
| 0.007 | 43/100, 0.590, 10.609s | 43/100, 0.600, 10.406s | 43/100, 0.600, 10.080s | 43/100, 0.600, 10.763s | 44/100, 0.610, 10.712s |
A rerank 选择非 top-1 candidate 的次数:
| p | beta=0.25 | beta=0.5 | beta=1.0 | beta=2.0 |
|---|---|---|---|---|
| 0.003 | 2 | 3 | 5 | 7 |
| 0.004 | 5 | 9 | 10 | 9 |
| 0.005 | 6 | 8 | 12 | 12 |
| 0.007 | 13 | 14 | 15 | 20 |
A top-2 neighbor residual rerank 有轻微信号,但整体没有稳定降低 flagged。
有效的地方:
p=0.003: beta=2.0 把 flagged 从 1/100 降到 0/100
p=0.004: beta=0.25 把 flagged 从 5/100 降到 4/100
无效或变差的地方:
p=0.005: 所有 beta 都保持 17/100,没有改善
p=0.007: beta=0.25/0.5/1.0 flagged 不变,但 LER 轻微变差;
beta=2.0 flagged 从 43/100 变成 44/100
诊断:
rerank 确实会选择非 top-1 的 A candidate;
但这些改动没有稳定降低 final flagged。
说明当前使用的 neighbor risk:
R_neighbor = popcount(s_B + H_boundary b)
作为 B 代价代理太粗。它能改变 A 边界选择,但不一定让最终 stitched correction 更一致。
因此,这个实验支持如下判断:
边界决策方向是对的;
但简单 residual popcount 不是足够好的 M_B(b) 近似。
如果继续优化 A boundary decision,下一步需要更强的 neighbor score,例如:
1. 只看 B 的真正左右 boundary rows,而不是整个 B rows;
2. 用 B pre-decoder 的 syndrome weight / BP convergence 信息作为 score;
3. 在 A top-2 中加入 A-boundary penalty + neighbor rerank 的组合 score;
4. 用 top-2 margin 判断是否启用 rerank,避免高 p 下过度改动。
这个实验不再继续修 A/B boundary,而是尝试给 parallel 恢复一部分 sliding 的 residual 因果传播。
普通 parallel:
A_all -> B_all
two-color parallel:
A_odd -> residual update -> A_even -> residual update -> B_all
或:
A_even -> residual update -> A_odd -> residual update -> B_all
这里的 odd/even 按文档中的 A 编号理解:
odd-first: A1,A3,... -> A2,A4,... -> B
even-first: A2,A4,... -> A1,A3,... -> B
实现注意:
residual update 只使用 A window 最终 commit 的变量;
不会使用 A solve window 内部未 commit 的临时变量;
B 解码时直接使用被所有 A commit 更新后的 residual syndrome。
新增参数:
--a-two-color-order odd-first
--a-two-color-order even-first
控制变量:
N=144, repeat=12, shots=100
p = 0.003,0.004,0.005,0.007
a_solve_size = 5
b_width = 5
sliding_width = 3
A noisy boundary = on
B noisy boundary = on
window shortening = on
top_k_boundary = 1
结果文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_a_two_color_odd_first_ab_noisy_shorten_parallel_only.csv
ParallelWindowDecoder/results/N144_repeat12_shots100_a_two_color_even_first_ab_noisy_shorten_parallel_only.csv
flagged / LER / time 对比:
| p | baseline | odd-first | even-first |
|---|---|---|---|
| 0.003 | 1/100, 0.010, 4.224s | 1/100, 0.010, 3.720s | 1/100, 0.010, 3.625s |
| 0.004 | 5/100, 0.060, 5.122s | 5/100, 0.060, 4.229s | 5/100, 0.060, 4.243s |
| 0.005 | 17/100, 0.200, 7.324s | 17/100, 0.200, 5.433s | 17/100, 0.200, 5.428s |
| 0.007 | 43/100, 0.590, 10.609s | 43/100, 0.590, 7.440s | 43/100, 0.590, 7.459s |
A/B local flagged diagnostics:
| p | odd first/second A flagged | even first/second A flagged | B local flagged odd/even |
|---|---|---|---|
| 0.003 | 0/0 | 0/0 | 0/0 |
| 0.004 | 0/0 | 0/0 | 0/0 |
| 0.005 | 0/0 | 0/0 | 0/0 |
| 0.007 | 0/0 | 0/0 | 0/0 |
A two-color residual propagation 没有改善 final flagged:
p=0.003: 1/100 -> 1/100
p=0.004: 5/100 -> 5/100
p=0.005: 17/100 -> 17/100
p=0.007: 43/100 -> 43/100
odd-first 和 even-first 完全一致,说明:
A layer 缺少 odd/even 级别的 residual 因果传播,
不是当前 final flagged 的主要来源。
更重要的诊断是:
A local flagged = 0
B local flagged = 0
final flagged > 0
这意味着每个局部 window 在自己的方程中都能闭合,但拼接成全局 correction 后仍然有 residual / logical failure。换句话说,问题不是 A 或 B 单个窗口“解不出来”,也不是 A-A 的两色传播缺失,而是:
局部窗口解都成立,但 global stitching 不成立。
因此 two-color 是一个有价值的 negative result。它排除了一个假设:
parallel 主要差在 A_all 同时解码、缺少一层 A-to-A causal residual。
下一步如果继续找结构性方向,更应该考虑:
B-first / B-centered ownership
或者重新定义最终 commit 的变量归属,而不是继续在现有 A-boundary ownership 下做局部 residual 修正。
这个实验不改变 decoder,只增加 diagnostics,用来解释:
A local flagged = 0
B local flagged = 0
但 final flagged 很高
新增参数:
--seam-diagnostics
诊断内容:
1. A commit 后 residual:
rA = s + H e_A
2. final residual:
rFinal = s + H(e_A + e_B)
3. 按 seam row ownership 统计 residual:
A-owned rows
B-owned rows
boundary rows
unowned rows
4. 比较 B local real residual 和 final global residual 在 B rows 上是否 mismatch。
本次 row ownership 识别为:
A-owned rows: s1, s7, s13
B-owned rows: s2-s6, s8-s12
boundary rows: s1, s13
unowned rows: none
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--decoders parallel \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--b-noisy-boundary \
--window-shorten \
--seam-diagnostics \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_plain_parallel_seam_diagnostics_ab_noisy_shorten.csv结果文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_plain_parallel_seam_diagnostics_ab_noisy_shorten.csv
residual 分类统计:
| p | flagged | LER | rA weight A/B/boundary/unowned | final weight A/B/boundary/unowned | final flagged A/B/boundary/unowned | B local-global mismatch |
|---|---|---|---|---|---|---|
| 0.003 | 1/100 | 0.010 | 0/6247/0/0 | 0/6/0/0 | 0/1/0/0 | 0 |
| 0.004 | 5/100 | 0.060 | 0/8272/0/0 | 0/28/0/0 | 0/5/0/0 | 0 |
| 0.005 | 17/100 | 0.200 | 0/9937/0/0 | 0/106/0/0 | 0/17/0/0 | 0 |
| 0.007 | 43/100 | 0.590 | 0/13297/0/0 | 0/274/0/0 | 0/43/0/0 | 0 |
final residual block histogram:
| p | nonzero final residual blocks |
|---|---|
| 0.003 | s2:3, s8:3 |
| 0.004 | s2:14, s8:14 |
| 0.005 | s2:55, s8:51 |
| 0.007 | s2:137, s8:137 |
这个 diagnostics 回答了当前问题:
A local flagged = 0
B local flagged = 0
final flagged > 0
原因不是 A-owned seam rows 没清掉:
final residual on A-owned rows = 0
也不是 B local real residual 和 final global residual 不一致:
B local-global mismatch = 0
真正的问题是:
final residual 全部落在 B-owned rows,
而且集中在每个 B window 的第一行:
s2, s8
这说明 b_noisy_boundary 的 augmented/noisy boundary columns 让 B 的 augmented local problem 可以闭合,所以 B local flagged = 0;但这些 noisy boundary columns 不会被写回全局 correction,因此真实 global residual 仍然留在 B rows 上。
换句话说:
B local flagged=0 是 augmented local equation 的成功;
final flagged>0 是真实 global equation 中 noisy boundary contribution 没有对应 physical correction。
因此当前 final flagged 高的直接来源不是 A seam row,而是:
B noisy boundary 吸收了 B 左边界 residual,
但该吸收项没有进入最终 global correction。
下一步如果要降低 flagged,应该先验证:
1. 关闭 b_noisy_boundary 后,B local flagged 与 final flagged 是否一致;
2. 或者把 noisy boundary columns 的使用改成只用于 BP/shortening 辅助,
不允许它们吸收最终必须由真实变量解释的 residual;
3. 或者把 noisy boundary 的被选中情况记录并转化为明确的边界 failure,而不是 local success。
上一节发现:
B local flagged = 0
final flagged > 0
主要来自 b_noisy_boundary 的 augmented/noisy boundary columns。为了确认这一点,这里做两个实验:
实验 A:关闭 --b-noisy-boundary,只保留 --a-noisy-boundary 和 --window-shorten
实验 B:保留 --b-noisy-boundary,并统计 B 解码中 noisy tail z_B 是否非零
两个实验都使用同样参数:
N=144
num_repeat=12
shots=100
p-list=0.003,0.004,0.005,0.007
a_solve_size=5
b_width=5
sliding_width=3
top_k_boundary=1
parallel_workers=4
parallel_backend=process
seam_diagnostics=True
结果文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_parallel_seam_diagnostics_a_noisy_shorten_no_b_noisy.csv
| p | final flagged | LER | A local flagged | B local flagged | final B-row flagged | final residual blocks |
|---|---|---|---|---|---|---|
| 0.003 | 1/100 | 0.010 | 0 | 2 | 1 | s6:2, s12:2 |
| 0.004 | 5/100 | 0.060 | 0 | 10 | 5 | s6:15, s12:15 |
| 0.005 | 17/100 | 0.200 | 0 | 34 | 17 | s6:50, s12:50 |
| 0.007 | 43/100 | 0.590 | 0 | 86 | 43 | s6:128, s12:128 |
这里 B local flagged 是按 B window-shot 计数;当前每个 failed shot 通常两个 B window 都失败,所以它正好是 2 * final flagged。
结论:
关掉 b_noisy_boundary 后,B local flagged 不再是 0,
而是和 final flagged 完全对齐。
因此之前的 B local flagged=0 不是物理 B 方程真的成功,而是 noisy boundary slack 把物理 residual 吃掉了。
结果文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_parallel_seam_diagnostics_ab_noisy_shorten_zstats.csv
| p | final flagged | B local flagged | z_B used shots | z_B final-overlap | final without z_B | z_B without final | z_B total weight | z_B left/right weight |
|---|---|---|---|---|---|---|---|---|
| 0.003 | 1/100 | 0 | 1 | 1 | 0 | 0 | 6 | 6/0 |
| 0.004 | 5/100 | 0 | 5 | 5 | 0 | 0 | 28 | 28/0 |
| 0.005 | 17/100 | 0 | 17 | 17 | 0 | 0 | 106 | 106/0 |
| 0.007 | 43/100 | 0 | 43 | 43 | 0 | 0 | 274 | 274/0 |
window-level 统计显示,z_B 全部来自两个 B window 的左侧 noisy boundary:
p=0.007:
B1=s2-s6 used_shots=43, left_weight=137, right_weight=0
B2=s8-s12 used_shots=43, left_weight=137, right_weight=0
结论非常明确:
z_B 非零 shot 与 final flagged shot 100% 重合。
也就是说:
final flagged 的准确触发信号就是 B noisy boundary tail z_B != 0。
这组实验说明,当前 flagged 高不是一个普通的 A/B 拼接 bug,也不是 A seam row 未清零。更准确的解释是:
B 的物理变量无法解释某些 seam residual;
如果打开 b_noisy_boundary,B 会用 z_B 把这些 residual 局部吞掉;
但 z_B 不属于物理 correction,所以 final global check 仍然失败。
因此后续优化不应该继续把 b_noisy_boundary 当作成功条件,而应该把它当作 boundary-conflict detector。
优先方向:
1. 修改统计口径:
B augmented local pass 但 z_B != 0 时,不再记作真正 B physical pass。
2. 用 z_B 触发 targeted repair:
只在 z_B != 0 的 B window 上修边界,不再盲目 single-flip。
3. 优先修左侧边界:
当前 z_B weight 全在 left boundary,说明冲突集中在 B window 左边界。
4. 如果实验目标包含 noisy syndrome:
可以把 z_B 显式纳入全局 syndrome-noise correction;
但这会改变最终校验目标,从 H e = s 变成 H e + m = s。
短期最合理的下一步是:
parallel + b_noisy_boundary
→ B 解码
→ 如果 z_B == 0,正常接受
→ 如果 z_B != 0,把该 B window 记为 boundary conflict
→ 只针对 z_B 支持的边界行做 targeted A-boundary / B-boundary repair
本实验实现上一节的最小 physical repair:
--z-boundary-repair
--z-repair-edge-width 2/3
核心思想:
b_noisy_boundary 仍然用于定位 seam conflict;
但 z_B 不再被当作真实 correction。
当 z_B != 0 时,收集真实物理变量做局部 seam repair。
对每个触发的 B window-shot:
left z_B:
left A boundary region
B window left edge_width regions
right z_B:
B window right edge_width regions
right A boundary region
然后进一步只保留会影响 z_B 支持 detector rows 的物理列,构造:
H[R_ext, C_z] Delta e = r[R_ext]
其中:
C_z = A boundary + B edge physical variables
R_ext = C_z 中所有变量会影响到的 detector rows
接受条件:
只在 global final residual weight 下降时接受 repair。
edge width 2:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--decoders parallel \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--b-noisy-boundary \
--window-shorten \
--z-boundary-repair \
--z-repair-edge-width 2 \
--seam-diagnostics \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_z_boundary_repair_edge2_ab_noisy_shorten_parallel_only.csvedge width 3:
ParallelWindowDecoder/results/N144_repeat12_shots100_z_boundary_repair_edge3_ab_noisy_shorten_parallel_only.csv
baseline 使用:
ParallelWindowDecoder/results/N144_repeat12_shots100_parallel_seam_diagnostics_ab_noisy_shorten_zstats.csv
flagged / LER / runtime:
| p | baseline | z-repair edge=2 | z-repair edge=3 |
|---|---|---|---|
| 0.003 | 1/100, 0.010, 3.493s | 1/100, 0.010, 3.609s | 1/100, 0.010, 3.603s |
| 0.004 | 5/100, 0.060, 3.973s | 5/100, 0.060, 3.973s | 5/100, 0.060, 3.992s |
| 0.005 | 17/100, 0.200, 4.785s | 17/100, 0.200, 5.020s | 17/100, 0.200, 5.055s |
| 0.007 | 43/100, 0.590, 8.015s | 43/100, 0.590, 6.943s | 43/100, 0.590, 7.565s |
repair diagnostics:
| p | edge | attempts | accepted | success-to-zero | final B residual weight | final residual blocks |
|---|---|---|---|---|---|---|
| 0.003 | 2 | 2 | 0 | 0 | 6 | s2:3, s8:3 |
| 0.004 | 2 | 10 | 4 | 0 | 24 | s2:7, s3:5, s8:7, s9:5 |
| 0.005 | 2 | 34 | 11 | 0 | 81 | s2:29, s3:13, s8:30, s9:9 |
| 0.007 | 2 | 86 | 36 | 0 | 202 | s2:64, s3:37, s8:64, s9:37 |
| 0.003 | 3 | 2 | 0 | 0 | 6 | s2:3, s8:3 |
| 0.004 | 3 | 10 | 4 | 0 | 24 | s2:7, s3:5, s8:7, s9:5 |
| 0.005 | 3 | 34 | 11 | 0 | 81 | s2:29, s3:13, s8:30, s9:9 |
| 0.007 | 3 | 86 | 36 | 0 | 202 | s2:64, s3:37, s8:64, s9:37 |
z_B-triggered physical seam repair 没有降低 final flagged:
p=0.003: 1/100 -> 1/100
p=0.004: 5/100 -> 5/100
p=0.005: 17/100 -> 17/100
p=0.007: 43/100 -> 43/100
但它确实改变了 residual 结构:
baseline p=0.007 final B residual weight = 274
z-repair p=0.007 final B residual weight = 202
也就是说,repair 能降低一部分 residual weight,但不能把任何 failed shot 修到 zero residual:
success-to-zero = 0
同时 residual 从:
s2, s8
被推到了:
s2, s3, s8, s9
这说明当前最小候选集合:
A boundary + B edge variables
可以局部移动 seam residual,但自由度仍然不够,不能形成完整的物理闭合 correction。
edge width 2 和 3 结果完全一致,是因为本实现先过滤到“会影响 z_B 支持 rows 的物理列”;额外 edge region 没有直接作用到这些 z rows,因此没有进入实际 repair candidate set。
这个实验排除了一个窄假设:
final flagged 不能只靠 z_B 支持行附近的少量 A-boundary + B-edge variables 修掉。
如果继续利用 z_B,下一步不应该只扩大 edge_width,而应该改变 repair system 的目标:
从 local z-row repair
升级为 flagged B window 的 physical joint retry。
也就是对 z_B != 0 的 B window,联合重解:
left A boundary
+ full B committed variables
+ right A boundary
并且检查整个 B rows 或更大的 affected rows,而不是只围绕 z_B 支持行。这个方向更接近:
B window 不再被 A boundary hard condition 完全锁死;
但只在 z_B 触发时开放额外自由度。
这仍然不改变常规 A/B window size,也不做全量 Top-K;它只是把 z_B flagged shot 作为少量 fallback case 处理。
上一节的窄版 seam repair 只使用:
A boundary + B edge variables
它可以降低 residual weight,但无法把 failed shot 清零。因此本实验升级为:
z_B != 0
→ 对该 B window 做一次 physical joint retry
候选变量集合为:
left A boundary variables
+ full B committed variables
+ right A boundary variables
注意这里的 A boundary variables 不是整个 A commit,而是相邻 A commit 中真正作用到该 B rows 的物理列。
实现参数:
--z-joint-retry
流程:
1. A layer 正常 decode + commit。
2. B layer 使用 b_noisy_boundary decode,并记录 z_B。
3. 若 z_B == 0,则接受 B physical part。
4. 若 z_B != 0,则构造 joint variable set:
C_joint = E_B ∪ E_A_boundary_left ∪ E_A_boundary_right
5. 固定其它变量,重新解:
H[B_rows, C_joint] x = s_B + H_other e_other
6. 用解出的 x 替换当前 C_joint 上的 physical correction。
7. 只有 global residual weight 下降时才接受。
这个策略和 full Top-K 不同:
不是所有 B 都多次 decode;
只在 z_B != 0 的 B window-shot 上触发一次 joint retry。
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--decoders parallel \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--b-noisy-boundary \
--window-shorten \
--z-joint-retry \
--seam-diagnostics \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_z_joint_retry_ab_noisy_shorten_parallel_only.csv结果文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_z_joint_retry_ab_noisy_shorten_parallel_only.csv
flagged / LER / runtime 对比:
| p | baseline | z-row repair edge=2 | z-joint retry |
|---|---|---|---|
| 0.003 | 1/100, 0.010, 3.493s | 1/100, 0.010, 3.609s | 1/100, 0.010, 3.879s |
| 0.004 | 5/100, 0.060, 3.973s | 5/100, 0.060, 3.973s | 4/100, 0.050, 4.321s |
| 0.005 | 17/100, 0.200, 4.785s | 17/100, 0.200, 5.020s | 17/100, 0.200, 5.980s |
| 0.007 | 43/100, 0.590, 8.015s | 43/100, 0.590, 6.943s | 43/100, 0.590, 9.560s |
joint retry diagnostics:
| p | attempts | accepted | success-to-zero | local flagged | final B residual weight | final residual blocks |
|---|---|---|---|---|---|---|
| 0.003 | 2 | 0 | 0 | 0 | 6 | s2:3, s8:3 |
| 0.004 | 10 | 4 | 1 | 0 | 13 | s2:3, s7:4, s8:10 |
| 0.005 | 34 | 2 | 0 | 0 | 97 | s2:46, s7:2, s8:51 |
| 0.007 | 86 | 2 | 0 | 0 | 266 | s2:129, s7:3, s8:137 |
z-joint retry 有一个小幅正信号:
p=0.004:
flagged 5/100 -> 4/100
LER 0.060 -> 0.050
success-to-zero = 1
这说明:
把 full B committed variables 和 A boundary 一起开放,
确实可以修掉一部分低 p 的 seam conflict。
但高 p 下没有明显改善:
p=0.005: 17/100 -> 17/100
p=0.007: 43/100 -> 43/100
诊断上,joint retry 的 local B equation 都能闭合:
z_joint_local_flagged = 0
但接受后的 residual 会出现在 A seam row:
s7
这说明只按单个 B window 重解时,B rows 可以被修好,但会把不一致转移到相邻 A seam row。也就是说,问题已经不是:
B 内部变量是否足够
而是:
单个 B window retry 没有同时约束相邻 A seam equation。
如果继续沿着 z_B 触发优化,下一步不应该只对单个 B window 做 retry,而应该做:
z_B-triggered A-B-A joint patch
对一个 flagged B_i,联合变量应该包含:
left A boundary/seam variables
+ full B_i variables
+ right A boundary/seam variables
联合 rows 不只包含 B rows,还应包含:
left A seam row
+ B rows
+ right A seam row
这样可以避免当前现象:
B rows 修好了,但 residual 被推到 A seam row s7。
换句话说,本实验说明:
z_B 是有效触发器;
full B joint retry 比窄版 z-row repair 更有信息;
但单个 B window 的约束仍然不够,需要把相邻 A seam rows 一起纳入 joint patch。
说明:这个尝试结果较差,相关代码入口已经移除;本节只保留 negative result 记录。
这个实验测试新的 ownership 方向:
A 不再 hard commit 左右边界变量;
A 只 commit 最中心 seam/gap 变量;
B 负责更多物理变量,包括原来由 A 提供给 B 的左右边界。
原始 ownership:
A1 commit: e0,e1
B1 commit: e2-e10
A2 commit: e11,e12,e13
B2 commit: e14-e22
A3 commit: e23,e24
新 ownership:
A1 commit: e0
B1 commit: e1-e11
A2 commit: e12
B2 commit: e13-e23
A3 commit: e24
也就是 interior A 从:
A2 commit: e11,e12,e13
变成:
A2 commit: e12
同时 B 从:
B1 commit: e2-e10
变成:
B1 commit: e1-e11
这个不是纯 B-first,因为 A 仍然先解并给出 center commit。为了检查 “A seam 太窄” 的担心,同时测试两个版本:
1. --a-center-b-expanded
A center commit + B expanded ownership,不做后处理。
2. --a-center-b-expanded --a-center-refine
B expanded 后,再根据 B 给出的左右边界重新解 A center seam。
无 refine:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--decoders parallel \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--b-noisy-boundary \
--window-shorten \
--a-center-b-expanded \
--seam-diagnostics \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_a_center_b_expanded_ab_noisy_shorten_parallel_only.csv带 A-center refine:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--decoders parallel \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--b-noisy-boundary \
--window-shorten \
--a-center-b-expanded \
--a-center-refine \
--seam-diagnostics \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_a_center_b_expanded_refine_ab_noisy_shorten_parallel_only.csvflagged / LER / runtime 对比:
| p | baseline | A-center+B-expanded | A-center+B-expanded+refine |
|---|---|---|---|
| 0.003 | 1/100, 0.010, 3.493s | 92/100, 0.920, 3.632s | 1/100, 0.020, 4.544s |
| 0.004 | 5/100, 0.060, 3.973s | 98/100, 0.980, 3.971s | 10/100, 0.170, 5.203s |
| 0.005 | 17/100, 0.200, 4.785s | 99/100, 0.990, 4.273s | 21/100, 0.320, 5.858s |
| 0.007 | 43/100, 0.590, 8.015s | 100/100, 1.000, 4.954s | 74/100, 0.860, 6.641s |
diagnostics:
| p | mode | A commit | B commit | z_B used | final residual owner | main residual blocks |
|---|---|---|---|---|---|---|
| 0.003 | no-refine | e0,e12,e24 | e1-e11,e13-e23 | 0 | A-owned rows | s1:171, s7:352, s13:220 |
| 0.004 | no-refine | e0,e12,e24 | e1-e11,e13-e23 | 0 | A-owned rows | s1:189, s7:491, s13:378 |
| 0.005 | no-refine | e0,e12,e24 | e1-e11,e13-e23 | 0 | A-owned rows | s1:290, s7:717, s13:529 |
| 0.007 | no-refine | e0,e12,e24 | e1-e11,e13-e23 | 0 | A-owned rows | s1:587, s7:1067, s13:669 |
| 0.003 | refine | e0,e12,e24 | e1-e11,e13-e23 | 0 | A-owned rows | s1:2, s7:2 |
| 0.004 | refine | e0,e12,e24 | e1-e11,e13-e23 | 0 | A-owned rows | s1:9, s7:24, s13:15 |
| 0.005 | refine | e0,e12,e24 | e1-e11,e13-e23 | 0 | A-owned rows | s1:13, s7:65, s13:52 |
| 0.007 | refine | e0,e12,e24 | e1-e11,e13-e23 | 0 | A-owned rows | s1:144, s7:231, s13:145 |
A-center refine 统计:
| p | refine attempts | refine flagged | center changed |
|---|---|---|---|
| 0.003 | 300 | 2 | 159 |
| 0.004 | 300 | 20 | 194 |
| 0.005 | 300 | 42 | 236 |
| 0.007 | 300 | 165 | 272 |
这个实验非常明确:
把 A commit 缩小、让 B 负责更多,确实解决了 B rows 的 residual;
但 residual 直接转移到了 A-owned seam rows。
无 refine 版本几乎全失败:
p=0.003: 92/100 flagged
p=0.007: 100/100 flagged
原因是 B 现在能完整闭合自己的 B rows:
B final residual = 0
z_B used = 0
但 A 只 commit 一个 center 变量块,无法保证:
s_A = H_left e_left + H0 e_center + H_right e_right
在 B 选完左右边界后仍然可解。
加上 --a-center-refine 后,A seam rows 明显减少,但仍然比 baseline 差:
p=0.004: baseline 5/100, refine 10/100
p=0.007: baseline 43/100, refine 74/100
这验证了之前的担心:
A seam 太窄。
也就是说,单独把 A 从 3 个 commit 变量块缩成 1 个,会让 B 的局部一致性变好,但 A seam equation 失去足够自由度。
这个方向不应该继续用:
A commit only center 1 block
作为主方案。
更合理的折中是:
A 不 hard commit 会直接作为 B residual boundary 的最外侧变量;
但 A seam 至少保留 2 个或更多 center-side 变量块。
例如把 interior A 从:
旧:A2 commit e11,e12,e13
过窄:A2 commit e12
改成 asymmetric ownership:
方案 A: A2 commit e12,e13,B1 owns e11
方案 B: A2 commit e11,e12,B2 owns e13
方案 C: A2 commit e12 plus a small A-seam auxiliary retry with adjacent A/B rows
从 diagnostics 看,A-center+B-expanded 已经把问题从 B rows 转移到 A rows,因此下一步如果继续改 ownership,需要给 A seam 多一点自由度,而不是把 A 压到只剩一个 center block。
测试:
a_solve_size = 9
时,A solve windows 是否可以保持不重叠。
结论先写在前面:
可以,但需要 b_width 也同步设为 9。
如果:
a_solve_size=9
b_width=9
代码会走 buffer-aligned schedule:
step = a_solve_size + 1 = 10
A windows 不重叠。
如果:
a_solve_size=9
b_width=5
代码会走 staggered schedule,A windows 会重叠。
结果文件:
ParallelWindowDecoder/results/schedule_check_a9_b9.csv
schedule:
schedule = buffer_aligned
step = 10
A rows:
A1 solve s1-s5
A2 solve s7-s13
B rows:
B1 solve s2-s10
B2 solve s12-s13
A commit:
A1 commit e0-e1
A2 commit e19-e21
B commit:
B1 commit e2-e18
B2 commit e22-e24
所以 A rows:
s1-s5
s7-s13
没有重叠,中间隔着 s6。
结果文件:
ParallelWindowDecoder/results/schedule_check_a9_b5.csv
schedule:
schedule = staggered
step = 6
A rows:
A1 solve s1-s5
A2 solve s3-s11
A3 solve s9-s13
B rows:
B1 solve s2-s6
B2 solve s8-s12
这里 A windows 明显重叠:
A1: s1-s5
A2: s3-s11
overlap: s3-s5
A2: s3-s11
A3: s9-s13
overlap: s9-s11
因此若实验要求 A 之间不重叠,不能使用 a_solve=9,b_width=5。
运行命令:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--decoders parallel \
--a-size 3 \
--a-solve-size 9 \
--b-width 9 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--b-noisy-boundary \
--window-shorten \
--seam-diagnostics \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_a_solve9_b9_ab_noisy_shorten_parallel_only.csv结果:
| p | flagged | LER | runtime | z_B used |
|---|---|---|---|---|
| 0.003 | 0/100 | 0.000 | 4.115s | 0 |
| 0.004 | 0/100 | 0.000 | 5.113s | 0 |
| 0.005 | 0/100 | 0.040 | 7.710s | 0 |
| 0.007 | 0/100 | 0.430 | 15.516s | 0 |
和 a_solve=5,b_width=5 baseline 对比:
| p | a5/b5 flagged/LER/time | a9/b9 flagged/LER/time |
|---|---|---|
| 0.003 | 1/100, 0.010, 3.493s | 0/100, 0.000, 4.115s |
| 0.004 | 5/100, 0.060, 3.973s | 0/100, 0.000, 5.113s |
| 0.005 | 17/100, 0.200, 4.785s | 0/100, 0.040, 7.710s |
| 0.007 | 43/100, 0.590, 8.015s | 0/100, 0.430, 15.516s |
diagnostics:
A local flagged = 0
B local flagged = 0
z_B used = 0
final residual = 0
a_solve=9,b_width=9 下,A windows 可以不重叠,而且 final flagged 降到 0:
p=0.003: 1/100 -> 0/100
p=0.004: 5/100 -> 0/100
p=0.005: 17/100 -> 0/100
p=0.007: 43/100 -> 0/100
这说明大 A context 确实解决了 seam residual / z_B 问题。
但代价也明显:
p=0.007 runtime: 8.015s -> 15.516s
并且 high-p 下 LER 仍然不低:
p=0.007 LER = 0.430
所以结论是:
如果允许 b_width 也设为 9,A 可以保持不重叠;
但这已经不是小 window 对比,矩阵规模和 runtime 都明显增大。
上一节说明:
a_solve=9,b_width=9
→ A windows 可以不重叠
→ final flagged = 0
→ 但单个局部矩阵变大,runtime 增加明显
本实验尝试把大的 A solve 拆成多个小 A solve。后续把这个策略命名为:
TSAE = Tri-Shift A Ensemble
中文:三偏移 A 集成
含义是:对同一个 interior A commit,同时使用 left / center / right 三个同规模 shifted A 小窗口给出候选,然后选择一个 candidate commit。
不用一个 9-row A 矩阵;
而是用多个 5-row shifted A 矩阵提供不同上下文。
新增参数:
--a-shifted-ensemble
--a-shift-offsets -2,0,2
--a-shifted-beta
baseline A2 是:
A2 solve: s5-s9
A2 commit: e11-e13
TSAE 使用同样大小的 5-row 小窗口:
A2-left solve: s3-s7
A2-center solve: s5-s9
A2-right solve: s7-s11
每个窗口都只输出同一个 commit:
e11,e12,e13
然后在每个 shot 上选择一个 shifted candidate:
score = local_cost + beta * neighbor_B_residual_risk
其中:
neighbor_B_residual_risk
= candidate 对相邻 B rows 造成的 residual popcount
边界 A1/A3 因为 commit 变量必须落在 solve cols 内,只有原始 offset:
A1 valid offsets: 0
A2 valid offsets: -2,0,2
A3 valid offsets: 0
所以总 candidate 数为:
每个 shot: 1 + 3 + 1 = 5 个 A 小窗口候选
单个 A 子矩阵行数仍然不超过:
a_solve_size = 5
TSAE beta=1:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--decoders parallel \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--b-noisy-boundary \
--window-shorten \
--a-shifted-ensemble \
--a-shift-offsets=-2,0,2 \
--a-shifted-beta 1.0 \
--seam-diagnostics \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_TSAE_tri_shift_A_beta1_ab_noisy_shorten_parallel_only.csvbeta=0 ablation:
ParallelWindowDecoder/results/N144_repeat12_shots100_a_shifted_ensemble_m2_0_p2_beta0_ab_noisy_shorten_parallel_only.csv
flagged / LER / runtime:
| p | baseline a5/b5 | shifted beta=0 | shifted beta=1 | a9/b9 |
|---|---|---|---|---|
| 0.003 | 1/100, 0.010, 3.493s | 0/100, 0.000, 3.786s | 0/100, 0.000, 3.610s | 0/100, 0.000, 4.115s |
| 0.004 | 5/100, 0.060, 3.973s | 3/100, 0.040, 4.062s | 3/100, 0.040, 3.964s | 0/100, 0.000, 5.113s |
| 0.005 | 17/100, 0.200, 4.785s | 4/100, 0.150, 4.798s | 4/100, 0.140, 4.675s | 0/100, 0.040, 7.710s |
| 0.007 | 43/100, 0.590, 8.015s | 24/100, 0.570, 6.661s | 25/100, 0.560, 6.402s | 0/100, 0.430, 15.516s |
z_B / residual diagnostics:
| p | baseline z_B used/weight | shifted beta=0 z_B used/weight | shifted beta=1 z_B used/weight |
|---|---|---|---|
| 0.003 | 1 / 6 | 0 / 0 | 0 / 0 |
| 0.004 | 5 / 28 | 3 / 14 | 3 / 14 |
| 0.005 | 17 / 106 | 4 / 14 | 4 / 14 |
| 0.007 | 43 / 274 | 24 / 152 | 25 / 166 |
shift 选择统计:
| p | beta=0 selected nonzero shift | beta=1 selected nonzero shift |
|---|---|---|
| 0.003 | 67 | 63 |
| 0.004 | 76 | 74 |
| 0.005 | 79 | 74 |
| 0.007 | 74 | 68 |
这里 selected nonzero shift 说明 ensemble 确实经常选择 left/right shifted A,而不是只退化成原始 center A。
TSAE 明显优于 baseline:
p=0.003: flagged 1/100 -> 0/100
p=0.004: flagged 5/100 -> 3/100
p=0.005: flagged 17/100 -> 4/100
p=0.007: flagged 43/100 -> 24/100 或 25/100
它没有达到 a_solve=9,b_width=9 的 zero-flagged 效果,但资源代价更小:
单个 A 子矩阵仍然是 5-row;
runtime 接近 baseline,远低于 a9/b9 的 high-p runtime。
尤其在 p=0.005:
baseline flagged = 17/100
shifted flagged = 4/100
a9/b9 flagged = 0/100
说明这个策略确实在用多个小 A 近似大 A context。
beta=0 和 beta=1 差别很小,说明主要收益来自:
shifted 多视角 A evidence
而不是当前简单的:
neighbor_B_residual_risk
下一步如果继续优化 shifted ensemble,可以尝试:
1. 改进 selection score,而不是只用 local cost + B residual popcount;
2. 只对边界变量 e11/e13 使用 shifted estimate,中间 e12 仍用 center;
3. 增加 offset -1,+1 或比较 [-1,0,1] 与 [-2,0,2];
4. 和 z_B-triggered C layer 组合,只在 shifted 后仍 z_B != 0 时进入 C repair。
为了把 TSAE 放到更清楚的位置,补跑同样 repeat=12, shots=100 的:
sliding width = 3 + shortening
parallel a_solve=9,b_width=9 + noisy boundary + shortening
命令:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--decoders sliding,parallel \
--a-size 3 \
--a-solve-size 9 \
--b-width 9 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--b-noisy-boundary \
--window-shorten \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_compare_sliding_vs_a9b9_ab_noisy_shorten.csv综合对比:
| p | mode | flagged | LER | logical/flagged | runtime |
|---|---|---|---|---|---|
| 0.003 | baseline a5/b5 | 1/100 | 0.010 | 1/100 | 3.493s |
| 0.003 | TSAE a5 tri-shift | 0/100 | 0.000 | 0/100 | 3.610s |
| 0.003 | sliding w3 | 0/100 | 0.000 | 0/100 | 5.637s |
| 0.003 | parallel a9/b9 | 0/100 | 0.000 | 0/100 | 3.511s |
| 0.004 | baseline a5/b5 | 5/100 | 0.060 | 6/100 | 3.973s |
| 0.004 | TSAE a5 tri-shift | 3/100 | 0.040 | 4/100 | 3.964s |
| 0.004 | sliding w3 | 0/100 | 0.020 | 2/100 | 6.283s |
| 0.004 | parallel a9/b9 | 0/100 | 0.000 | 0/100 | 4.468s |
| 0.005 | baseline a5/b5 | 17/100 | 0.200 | 20/100 | 4.785s |
| 0.005 | TSAE a5 tri-shift | 4/100 | 0.140 | 14/100 | 4.675s |
| 0.005 | sliding w3 | 0/100 | 0.120 | 12/100 | 7.051s |
| 0.005 | parallel a9/b9 | 0/100 | 0.040 | 4/100 | 7.213s |
| 0.007 | baseline a5/b5 | 43/100 | 0.590 | 59/100 | 8.015s |
| 0.007 | TSAE a5 tri-shift | 25/100 | 0.560 | 56/100 | 6.402s |
| 0.007 | sliding w3 | 0/100 | 0.450 | 45/100 | 9.089s |
| 0.007 | parallel a9/b9 | 0/100 | 0.430 | 43/100 | 14.791s |
结论:
1. sliding 和 a9/b9 都能把 final flagged 降到 0/100。
2. a9/b9 的 LER 在 p=0.005 和 p=0.007 都优于 sliding。
3. TSAE 明显降低 flagged,但仍没有达到 sliding / a9/b9 的 physical closure。
4. TSAE 的价值在于单个 A 子矩阵仍是 5-row,资源形态更接近 FPGA 小核并行;
a9/b9 的价值在于准确率最好,但单个局部矩阵明显变大。
代码状态:该分支已从当前代码中移除,仅保留实验记录;当前主线保留最初的 TSAE。
上面的 TSAE 只对 interior A2 做三偏移:
A1: center
A2: left / center / right
A3: center
进一步尝试边界感知版本:
Boundary-aware TSAE
A1: center / right
A2: left / center / right
A3: left / center
对应矩阵:
A1-center solve: s1-s3 -> commit e0-e1
A1-right solve: s1-s5 -> commit e0-e1
A2-left solve: s3-s7 -> commit e11-e13
A2-center solve: s5-s9 -> commit e11-e13
A2-right solve: s7-s11 -> commit e11-e13
A3-left solve: s9-s13 -> commit e23-e24
A3-center solve: s11-s13 -> commit e23-e24
新增参数:
--boundary-aware-tsae
运行命令:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--decoders parallel \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--b-noisy-boundary \
--window-shorten \
--a-shifted-ensemble \
--boundary-aware-tsae \
--a-shift-offsets=-2,0,2 \
--a-shifted-beta 1.0 \
--seam-diagnostics \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_boundary_aware_TSAE_beta1_ab_noisy_shorten_parallel_only.csv结果:
| p | baseline a5/b5 | TSAE | Boundary-aware TSAE | sliding w3 | a9/b9 |
|---|---|---|---|---|---|
| 0.003 | 1/100, 0.010, 3.493s | 0/100, 0.000, 3.610s | 0/100, 0.000, 4.562s | 0/100, 0.000, 5.637s | 0/100, 0.000, 3.511s |
| 0.004 | 5/100, 0.060, 3.973s | 3/100, 0.040, 3.964s | 4/100, 0.060, 4.907s | 0/100, 0.020, 6.283s | 0/100, 0.000, 4.468s |
| 0.005 | 17/100, 0.200, 4.785s | 4/100, 0.140, 4.675s | 16/100, 0.230, 5.597s | 0/100, 0.120, 7.051s | 0/100, 0.040, 7.213s |
| 0.007 | 43/100, 0.590, 8.015s | 25/100, 0.560, 6.402s | 49/100, 0.660, 8.075s | 0/100, 0.450, 9.089s | 0/100, 0.430, 14.791s |
diagnostics:
valid offsets:
A1: center,right
A2: -2,0,2
A3: left,center
candidate count:
7 per shot
selected_nonzero:
200 / 100 shots
解释:
Boundary-aware TSAE 的 naive selection 反而变差。
主要原因是 A1/A3 的 center 是 3-row,而 anchored right/left 是 5-row;
当前 score = local_cost + beta * neighbor_B_residual_risk
没有对不同 row-count / 不同局部矩阵规模做归一化,
导致边界 A 的 anchored 候选被系统性选中。
因此这个版本暂时不作为主结果。若继续尝试,需要先修正 selection rule,例如:
1. 对 A1/A3 的 center/right/left 候选使用归一化 cost;
2. 对 boundary A 的 anchored 候选加 penalty;
3. 只允许 anchored 候选在 center local flagged 或 z_B 触发时参与选择;
4. 分别统计 A1/A2/A3 的 selected label,再做 ablation。
代码状态:该分支已从当前代码中移除,仅保留实验记录。
上一节的问题是 A1-right / A3-left 直接替换 center commit 后会污染 B residual。 因此改成更保守的版本:
1. A1/A3 最终 commit 永远来自 center;
2. A1-right / A3-left 仍然并行解码;
3. anchored 候选只作为 reliability / veto 诊断,不直接写入 correction。
新增参数:
--boundary-anchor-veto-only
运行命令:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--decoders parallel \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--b-noisy-boundary \
--window-shorten \
--a-shifted-ensemble \
--boundary-aware-tsae \
--boundary-anchor-veto-only \
--a-shift-offsets=-2,0,2 \
--a-shifted-beta 1.0 \
--seam-diagnostics \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_boundary_anchor_veto_only_TSAE_beta1_ab_noisy_shorten_parallel_only.csv结果:
| p | TSAE | Boundary-aware commit | Boundary anchor veto-only |
|---|---|---|---|
| 0.003 | 0/100, 0.000, 3.610s | 0/100, 0.000, 4.562s | 0/100, 0.000, 4.433s |
| 0.004 | 3/100, 0.040, 3.964s | 4/100, 0.060, 4.907s | 3/100, 0.040, 4.873s |
| 0.005 | 4/100, 0.140, 4.675s | 16/100, 0.230, 5.597s | 4/100, 0.140, 5.671s |
| 0.007 | 25/100, 0.560, 6.402s | 49/100, 0.660, 8.075s | 25/100, 0.560, 7.660s |
anchor disagreement:
| p | A1/A3 anchor disagree |
|---|---|
| 0.003 | 7/200 |
| 0.004 | 10/200 |
| 0.005 | 23/200 |
| 0.007 | 54/200 |
结论:
Boundary anchor veto-only 的 correction 与原 TSAE 完全一致;
flagged 和 LER 没有改善,只增加了 A1-right/A3-left 的额外解码成本。
但 disagreement 统计有用:
p 越高,A1/A3 的 anchored view 越经常和 center view 不一致。
这说明 A1/A3 的辅助窗口确实能提供“边界不确定性”信息,但不能直接替换 commit。 后续如果继续利用它,应把 disagreement 作为触发信号,例如:
if A1-center != A1-right or A3-center != A3-left:
标记 boundary unreliable
只在对应 B window z_B != 0 时触发 C repair / rerank
代码状态:该分支已从当前代码中移除,仅保留实验记录。
继续尝试一个介于 whole-commit 和 veto-only 之间的版本:
A1-right 只允许覆盖 e1,不覆盖 e0;
A3-left 只允许覆盖 e23,不覆盖 e24。
也就是说:
A1:
e0 <- A1-center
e1 <- A1-right
A3:
e23 <- A3-left
e24 <- A3-center
A2 仍然使用原 TSAE:
A2-left / A2-center / A2-right 选择一个 candidate commit e11-e13
新增参数:
--boundary-anchor-partial-commit
运行命令:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--decoders parallel \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--b-noisy-boundary \
--window-shorten \
--a-shifted-ensemble \
--boundary-aware-tsae \
--boundary-anchor-partial-commit \
--a-shift-offsets=-2,0,2 \
--a-shifted-beta 1.0 \
--seam-diagnostics \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_boundary_anchor_partial_commit_TSAE_beta1_ab_noisy_shorten_parallel_only.csv结果:
| p | TSAE | Boundary-aware whole commit | Boundary anchor veto-only | Boundary anchor partial commit |
|---|---|---|---|---|
| 0.003 | 0/100, 0.000, 3.610s | 0/100, 0.000, 4.562s | 0/100, 0.000, 4.433s | 4/100, 0.040, 4.577s |
| 0.004 | 3/100, 0.040, 3.964s | 4/100, 0.060, 4.907s | 3/100, 0.040, 4.873s | 8/100, 0.080, 4.919s |
| 0.005 | 4/100, 0.140, 4.675s | 16/100, 0.230, 5.597s | 4/100, 0.140, 5.671s | 10/100, 0.160, 5.658s |
| 0.007 | 25/100, 0.560, 6.402s | 49/100, 0.660, 8.075s | 25/100, 0.560, 7.660s | 39/100, 0.600, 7.608s |
diagnostics:
partial_used = 200 / 100 shots
每个 shot 都会对 A1 的 e1 和 A3 的 e23 使用 anchored partial commit。
结论:
partial commit 比 whole commit 温和,但仍明显差于原 TSAE。
说明问题不是只来自 e0/e24 这些最外侧变量;即使只改:
A1-right -> e1
A3-left -> e23
仍然会污染相邻 B residual。当前结果支持一个判断:
A1/A3 anchored view 可以作为不确定性诊断,
但不应该无条件写入 physical correction。
因此边界 anchored 信息后续更适合作为 gated repair 的触发条件,而不是直接 commit。
代码状态:该分支已从当前代码中移除,仅保留实验记录。
上一节 partial commit 使用的是 anchored 大小:
A1-right solve: s1-s5 -> e1 only
A3-left solve: s9-s13 -> e23 only
进一步按同规模窗口改成:
A1-center solve: s1-s3 -> e0,e1
A1-right solve: s2-s4 -> e1 only
A3-left solve: s10-s12 -> e23 only
A3-center solve: s11-s13 -> e23,e24
这样 A1-right / A3-left 和 A1/A3 center 一样都是 3-row 矩阵。
整体变量来源:
e0 <- A1-center
e1 <- A1-right partial
e2-e10 <- B1
e11-e13 <- selected A2 TSAE
e14-e22 <- B2
e23 <- A3-left partial
e24 <- A3-center
结果:
| p | TSAE | partial anchored 5-row | partial same-size |
|---|---|---|---|
| 0.003 | 0/100, 0.000, 3.610s | 4/100, 0.040, 4.577s | 71/100, 0.720, 4.481s |
| 0.004 | 3/100, 0.040, 3.964s | 8/100, 0.080, 4.919s | 89/100, 0.890, 5.057s |
| 0.005 | 4/100, 0.140, 4.675s | 10/100, 0.160, 5.658s | 99/100, 0.990, 6.134s |
| 0.007 | 25/100, 0.560, 6.402s | 39/100, 0.600, 7.608s | 99/100, 0.990, 7.967s |
disagreement:
| p | partial anchored 5-row | partial same-size |
|---|---|---|
| 0.003 | 7/200 | 97/200 |
| 0.004 | 10/200 | 128/200 |
| 0.005 | 23/200 | 156/200 |
| 0.007 | 54/200 | 177/200 |
结论:
same-size partial commit 明显不可行。
原因是:
A1-right: s2-s4 -> e1 only
A3-left: s10-s12 -> e23 only
这些窗口不包含 A boundary 的完整 center equation:
A1 center row s1 couples e0,e1
A3 center row s13 couples e23,e24
因此 partial 窗口给出的 e1/e23 和 center 给出的 e0/e24 拼接后,往往不再满足 A seam 自身的一致性。
这直接把 residual 留在 A/B 边界附近,导致 final flagged 极高。
这个实验说明:
边界变量不能从缺少配对 seam equation 的 shifted partial 窗口中无条件抽取。
所以 A1/A3 的 right/left 小窗口仍然更适合作为 reliability diagnostic,而不是 commit source。
回到最初 TSAE,只改变 interior A2 的 shifted offsets:
方案 A: -1,0,1
方案 B: -2,0,2
方案 C: -2,-1,0,1,2
其它参数保持一致:
N=144
repeat=12
shots=100
a_solve=5
b_width=5
sliding_width=3
a_noisy_boundary=True
b_noisy_boundary=True
window_shorten=True
beta=1.0
结果:
| p | baseline a5/b5 | TSAE -1,0,1 | TSAE -2,0,2 | TSAE -2,-1,0,1,2 |
|---|---|---|---|---|
| 0.003 | 1/100, 0.010, 3.493s | 1/100, 0.010, 4.778s | 0/100, 0.000, 3.610s | 0/100, 0.000, 5.606s |
| 0.004 | 5/100, 0.060, 3.973s | 4/100, 0.050, 4.932s | 3/100, 0.040, 3.964s | 3/100, 0.040, 5.546s |
| 0.005 | 17/100, 0.200, 4.785s | 9/100, 0.120, 5.760s | 4/100, 0.140, 4.675s | 4/100, 0.140, 6.903s |
| 0.007 | 43/100, 0.590, 8.015s | 30/100, 0.540, 8.092s | 25/100, 0.560, 6.402s | 24/100, 0.550, 8.650s |
candidate 统计:
| offsets | valid offsets | candidates / shot | p=0.007 selected nonzero |
|---|---|---|---|
| -1,0,1 | A1: 0, A2: -1/0/1, A3: 0 | 5 | 74 |
| -2,0,2 | A1: 0, A2: -2/0/2, A3: 0 | 5 | 68 |
| -2,-1,0,1,2 | A1: 0, A2: -2/-1/0/1/2, A3: 0 | 7 | 86 |
结论:
1. -1,0,1 明显弱于 -2,0,2。
2. -2,-1,0,1,2 与 -2,0,2 的 flagged 很接近;
只在 p=0.007 从 25/100 降到 24/100。
3. 五偏移 candidate 更多,runtime 明显增加。
4. 当前最好的性价比仍然是 -2,0,2。
解释:
-2,0,2 提供了更分散的上下文视角:
s3-s7, s5-s9, s7-s11
-1,0,1 的三个视角更接近:
s4-s8, s5-s9, s6-s10
所以 -1,0,1 的 ensemble 多样性不足,不能像 -2,0,2 那样明显降低 boundary hard decision 错误。
继续尝试不增加 BP-OSD 次数,只在 TSAE 已有候选上做更细的 stitching。
原 TSAE 是:
A2-left, A2-center, A2-right
-> 选一个完整 candidate commit e11,e12,e13
新增两个模式:
--tsae-stitch-mode component
--tsae-stitch-mode pairwise
分量级选择:
e11 从 left/center 中按左 B boundary residual 选择;
e12 固定从 center 取;
e13 从 center/right 中按右 B boundary residual 选择。
然后检查 A seam row:
s7 = H2 e11 + H0 e12 + H1 e13
如果 A seam residual 为 0,则接受拼接;否则 fallback 到原 TSAE 的完整 candidate。
枚举小组合:
e11 source in {left, center}
e12 source = center
e13 source in {center, right}
打分:
score = wt(A_center_residual) + beta * wt(left_B_boundary + right_B_boundary)
选择 score 最小的组合。
| p | baseline | TSAE | TSAE-component | TSAE-pairwise |
|---|---|---|---|---|
| 0.003 | 1/100, 0.010, 3.493s | 0/100, 0.000, 3.610s | 0/100, 0.000, 4.815s | 0/100, 0.000, 4.872s |
| 0.004 | 5/100, 0.060, 3.973s | 3/100, 0.040, 3.964s | 4/100, 0.050, 5.631s | 5/100, 0.060, 5.534s |
| 0.005 | 17/100, 0.200, 4.785s | 4/100, 0.140, 4.675s | 4/100, 0.140, 6.423s | 15/100, 0.180, 6.447s |
| 0.007 | 43/100, 0.590, 8.015s | 25/100, 0.560, 6.402s | 26/100, 0.550, 8.338s | 44/100, 0.600, 8.725s |
stitch diagnostics:
| p | component accepted/fallback/non-payload | pairwise accepted/fallback/non-payload |
|---|---|---|
| 0.003 | 95 / 5 / 63 | 100 / 0 / 66 |
| 0.004 | 88 / 12 / 66 | 100 / 0 / 71 |
| 0.005 | 68 / 32 / 49 | 100 / 0 / 64 |
| 0.007 | 37 / 63 / 19 | 100 / 0 / 39 |
结论:
1. component stitching 没有明显改善;
p=0.005 与 TSAE 相同,p=0.007 略差。
2. pairwise stitching 明显变差;
p=0.007 甚至 44/100,接近 baseline 43/100。
3. 当前 residual-only stitching score 不够可靠。
解释:
完整 TSAE candidate 来自同一个 BP-OSD 局部解,内部一致性较强;
component/pairwise 把不同局部解的 e11/e12/e13 拼起来,
即使 A seam residual 或 B boundary residual 局部较小,
也可能破坏更大范围的 correction consistency。
因此当前主线仍然保持:
TSAE -2,0,2,完整 candidate 三选一。
继续尝试:
TSAE 提供 shifted context diversity;
Top-K 提供每个 context 内的 solution diversity。
实现方式:
--tsae-top-k 2
--tsae-boundary-top-k 1
也就是:
A1: top1
A2-left: top2
A2-center: top2
A2-right: top2
A3: top1
每个 shot 的 A candidate 数从:
TSAE top1: 1 + 3 + 1 = 5
TSAE top2: 1 + 3*2 + 1 = 8
保持完整 candidate 粒度,不做 bit-level stitching。
命令:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--decoders parallel \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--b-noisy-boundary \
--window-shorten \
--a-shifted-ensemble \
--a-shift-offsets=-2,0,2 \
--a-shifted-beta 1.0 \
--tsae-top-k 2 \
--tsae-boundary-top-k 1 \
--seam-diagnostics \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_TSAE_topk2_offsets_m2_0_p2_beta1_ab_noisy_shorten_parallel_only.csv结果:
| p | baseline | TSAE top1 | TSAE top2 | sliding | a9/b9 |
|---|---|---|---|---|---|
| 0.003 | 1/100, 0.010, 3.493s | 0/100, 0.000, 3.610s | 0/100, 0.000, 3.724s | 0/100, 0.000, 5.637s | 0/100, 0.000, 3.511s |
| 0.004 | 5/100, 0.060, 3.973s | 3/100, 0.040, 3.964s | 3/100, 0.040, 4.067s | 0/100, 0.020, 6.283s | 0/100, 0.000, 4.468s |
| 0.005 | 17/100, 0.200, 4.785s | 4/100, 0.140, 4.675s | 4/100, 0.140, 4.621s | 0/100, 0.120, 7.051s | 0/100, 0.040, 7.213s |
| 0.007 | 43/100, 0.590, 8.015s | 25/100, 0.560, 6.402s | 25/100, 0.550, 6.672s | 0/100, 0.450, 9.089s | 0/100, 0.430, 14.791s |
candidate 统计:
| mode | candidates / shot | p=0.007 selected nonzero | p=0.007 z_B used |
|---|---|---|---|
| TSAE top1 | 5 | 68 | 25 |
| TSAE top2 | 8 | 68 | 25 |
结论:
TSAE + Top-K=2 没有降低 flagged。
虽然候选数从 5 增加到 8,但:
p=0.004: 3/100 -> 3/100
p=0.005: 4/100 -> 4/100
p=0.007: 25/100 -> 25/100
说明 per-shift top2 没有提供当前 selector 能利用的有效新 commit diversity。 可能原因:
1. OSD-list 的 top2 在 commit 区域 e11-e13 上经常和 top1 相同或等价;
2. 新 candidate 虽然不同,但 local_cost + neighbor_B_risk 没有选中;
3. 剩余失败可能不是单个 A2 候选池扩大能解决,而需要 A/B 联合一致性或更大上下文。
目的:
不扩大单个 A 小窗口;
只在 interior A 的左右 interface region 中各选 1 个最相关物理列;
对这两个 interface bit 做 0/1 hard-fix branching;
每个 branch 下仍然用 shifted 小 A window 解码;
最后用原 TSAE score 选择 candidate。
参数:
--a-shifted-ensemble
--a-shift-offsets=-2,0,2
--a-shifted-beta 1.0
--tsae-interface-branch
--tsae-interface-cols-per-side 1结果文件:
ParallelWindowDecoder/results/N144_repeat12_shots100_TSAE_baseline_after_interface_branch_refactor.csv
ParallelWindowDecoder/results/N144_repeat12_shots100_TSAE_interface_branch_c1_ab_noisy_shorten_parallel_only.csv
结果:
| p | TSAE baseline | TSAE interface branch | runtime baseline | runtime branch |
|---|---|---|---|---|
| 0.003 | 0/100, LER 0.000 | 0/100, LER 0.000 | 4.975s | 8.500s |
| 0.004 | 3/100, LER 0.040 | 3/100, LER 0.050 | 4.926s | 9.248s |
| 0.005 | 4/100, LER 0.140 | 4/100, LER 0.130 | 5.776s | 10.449s |
| 0.007 | 25/100, LER 0.560 | 21/100, LER 0.530 | 8.692s | 10.873s |
candidate 统计:
TSAE baseline candidate count: 500
TSAE interface branch candidate count: 1400
interface branch payloads: 12
结论:
interface branching 在 p=0.007 有小幅改善:
flagged 25/100 -> 21/100
LER 0.560 -> 0.530
但 p=0.003/0.004/0.005 基本没有改善,runtime 增加明显。
说明“在 interface bit 上主动制造 diversity”有一点有效信号,
但当前每侧只选 1 个物理列的 hard-fix branch 仍然不足以模拟 a_solve=9 的大上下文。
普通 parallel、普通 TSAE、TSAE interface、sliding、oracle 使用同一组参数和 seeds 对比。
普通 parallel、sliding、oracle 使用同一组参数重新运行:
ParallelWindowDecoder/results/N144_repeat12_shots100_compare_sliding_plain_parallel_oracle_after_interface_branch.csv
普通 TSAE 和 TSAE interface branch 使用:
ParallelWindowDecoder/results/N144_repeat12_shots100_TSAE_baseline_after_interface_branch_refactor.csv
ParallelWindowDecoder/results/N144_repeat12_shots100_TSAE_interface_branch_c1_ab_noisy_shorten_parallel_only.csv
对比:
| p | mode | flagged | LER | runtime |
|---|---|---|---|---|
| 0.003 | sliding | 0/100 | 0.000 | 7.168s |
| 0.003 | plain parallel | 1/100 | 0.010 | 3.676s |
| 0.003 | TSAE | 0/100 | 0.000 | 4.975s |
| 0.003 | TSAE interface | 0/100 | 0.000 | 8.500s |
| 0.003 | oracle parallel | 0/100 | 0.000 | 2.300s |
| 0.004 | sliding | 0/100 | 0.020 | 6.459s |
| 0.004 | plain parallel | 5/100 | 0.060 | 4.072s |
| 0.004 | TSAE | 3/100 | 0.040 | 4.926s |
| 0.004 | TSAE interface | 3/100 | 0.050 | 9.248s |
| 0.004 | oracle parallel | 0/100 | 0.000 | 3.082s |
| 0.005 | sliding | 0/100 | 0.120 | 7.923s |
| 0.005 | plain parallel | 17/100 | 0.200 | 4.578s |
| 0.005 | TSAE | 4/100 | 0.140 | 5.776s |
| 0.005 | TSAE interface | 4/100 | 0.130 | 10.449s |
| 0.005 | oracle parallel | 0/100 | 0.020 | 2.760s |
| 0.007 | sliding | 0/100 | 0.450 | 9.023s |
| 0.007 | plain parallel | 43/100 | 0.590 | 6.377s |
| 0.007 | TSAE | 25/100 | 0.560 | 8.692s |
| 0.007 | TSAE interface | 21/100 | 0.530 | 10.873s |
| 0.007 | oracle parallel | 0/100 | 0.130 | 3.832s |
结论:
普通 TSAE 已经相比 plain parallel 明显降低 flagged:
p=0.005: 17/100 -> 4/100
p=0.007: 43/100 -> 25/100
TSAE interface branch 相比普通 TSAE 只在高 p 有小幅额外改善:
p=0.003: 0/100 -> 0/100
p=0.004: 3/100 -> 3/100
p=0.005: 4/100 -> 4/100
p=0.007: 25/100 -> 21/100
但它仍然没有接近 sliding/oracle 的 0 flagged,
并且 runtime 已经高于 sliding。
这说明主要收益仍来自 TSAE 的 shifted context; interface branching 确实缓解了一部分高 p 的 A boundary hard decision 错误, 但当前实现的额外收益有限,且代价偏高。
目的:
把 num_repeat 从 12 改成 18,
保持 N=144、shots=100、p-list=0.003,0.004,0.005,0.007、
a_solve=5、b_width=5、sliding_width=3、noisy boundary + shorten 不变。
结果文件:
ParallelWindowDecoder/results/N144_repeat18_shots100_compare_sliding_plain_parallel_oracle.csv
ParallelWindowDecoder/results/N144_repeat18_shots100_TSAE_baseline.csv
ParallelWindowDecoder/results/N144_repeat18_shots100_TSAE_interface_branch_c1.csv
结果:
| p | mode | flagged | LER | runtime |
|---|---|---|---|---|
| 0.003 | sliding | 0/100 | 0.000 | 34.652s |
| 0.003 | plain parallel | 3/100 | 0.030 | 8.122s |
| 0.003 | TSAE | 0/100 | 0.000 | 11.403s |
| 0.003 | TSAE interface | 0/100 | 0.000 | 17.896s |
| 0.003 | oracle parallel | 0/100 | 0.000 | 10.867s |
| 0.004 | sliding | 0/100 | 0.020 | 30.504s |
| 0.004 | plain parallel | 6/100 | 0.060 | 7.387s |
| 0.004 | TSAE | 4/100 | 0.050 | 10.579s |
| 0.004 | TSAE interface | 5/100 | 0.060 | 20.010s |
| 0.004 | oracle parallel | 0/100 | 0.000 | 5.236s |
| 0.005 | sliding | 0/100 | 0.150 | 25.032s |
| 0.005 | plain parallel | 32/100 | 0.350 | 7.696s |
| 0.005 | TSAE | 14/100 | 0.270 | 12.738s |
| 0.005 | TSAE interface | 13/100 | 0.270 | 25.785s |
| 0.005 | oracle parallel | 0/100 | 0.020 | 5.532s |
| 0.007 | sliding | 0/100 | 0.620 | 28.301s |
| 0.007 | plain parallel | 68/100 | 0.830 | 9.571s |
| 0.007 | TSAE | 43/100 | 0.800 | 19.873s |
| 0.007 | TSAE interface | 38/100 | 0.780 | 23.445s |
| 0.007 | oracle parallel | 0/100 | 0.220 | 6.557s |
结论:
repeat=18 后,plain parallel 的 flagged 明显上升:
p=0.005: 32/100
p=0.007: 68/100
TSAE 仍然能明显降低 flagged:
p=0.005: 32/100 -> 14/100
p=0.007: 68/100 -> 43/100
TSAE interface branch 只有小幅额外改善:
p=0.005: 14/100 -> 13/100
p=0.007: 43/100 -> 38/100
sliding 和 oracle 仍保持 0 flagged,
但 sliding runtime 随 repeat 增长明显,约 25-35s。
目的:
用 1000 shots 重新测试 repeat=12,
比较 sliding、普通 parallel、普通 TSAE。
参数:
N=144
num_repeat=12
shots=1000
p-list=0.003,0.004,0.005,0.007
a_solve=5
b_width=5
sliding_width=3
a_noisy_boundary=True
b_noisy_boundary=True
window_shorten=True
parallel_workers=4
parallel_backend=process
结果文件:
ParallelWindowDecoder/results/N144_repeat12_shots1000_compare_sliding_plain_parallel.csv
ParallelWindowDecoder/results/N144_repeat12_shots1000_TSAE_baseline.csv
结果:
| p | mode | flagged | logical_or_flagged | LER | runtime |
|---|---|---|---|---|---|
| 0.003 | sliding | 0/1000 | 1/1000 | 0.001 | 71.426s |
| 0.003 | plain parallel | 10/1000 | 11/1000 | 0.011 | 29.389s |
| 0.003 | TSAE | 4/1000 | 7/1000 | 0.007 | 29.244s |
| 0.004 | sliding | 0/1000 | 21/1000 | 0.021 | 75.332s |
| 0.004 | plain parallel | 32/1000 | 38/1000 | 0.038 | 31.263s |
| 0.004 | TSAE | 11/1000 | 22/1000 | 0.022 | 40.071s |
| 0.005 | sliding | 0/1000 | 93/1000 | 0.093 | 70.182s |
| 0.005 | plain parallel | 119/1000 | 148/1000 | 0.148 | 33.977s |
| 0.005 | TSAE | 38/1000 | 111/1000 | 0.111 | 42.902s |
| 0.007 | sliding | 0/1000 | 513/1000 | 0.513 | 92.773s |
| 0.007 | plain parallel | 423/1000 | 585/1000 | 0.585 | 56.715s |
| 0.007 | TSAE | 275/1000 | 556/1000 | 0.556 | 67.522s |
结论:
1000 shots 下,TSAE 相比 plain parallel 持续降低 flagged:
p=0.003: 10/1000 -> 4/1000
p=0.004: 32/1000 -> 11/1000
p=0.005: 119/1000 -> 38/1000
p=0.007: 423/1000 -> 275/1000
TSAE 的 LER 在 p=0.004 和 p=0.005 接近 sliding:
p=0.004: sliding 0.021, TSAE 0.022
p=0.005: sliding 0.093, TSAE 0.111
但高 p=0.007 下,TSAE 仍明显有 final flagged,
LER 也没有接近 sliding。
目的:
围绕当前 TSAE 的最强诊断信号 z_B 做 targeted physical seam correction。
触发条件:
B noisy boundary z_B != 0
候选变量:
z_B 对应 seam 附近的 A boundary vars + B edge vars
接受条件:
global final residual weight 下降;
记录 success_to_zero 表示是否真正把 final residual 清零。
实现补充:
在原 z_boundary_repair 基础上增加 residual-gain 的 1/2-flip 小枚举;
如果枚举不能清零,再回退到小 BP-OSD repair。
允许 z_boundary_repair 与 TSAE 同时使用。
参数:
--a-shifted-ensemble
--a-shift-offsets=-2,0,2
--a-shifted-beta 1.0
--z-boundary-repair
--z-repair-edge-width 2结果文件:
ParallelWindowDecoder/results/N144_repeat12_shots1000_TSAE_z_boundary_repair_edge2.csv
对比:
| p | mode | flagged | logical_or_flagged | LER | runtime |
|---|---|---|---|---|---|
| 0.003 | sliding | 0/1000 | 1/1000 | 0.001 | 71.426s |
| 0.003 | plain parallel | 10/1000 | 11/1000 | 0.011 | 29.389s |
| 0.003 | TSAE | 4/1000 | 7/1000 | 0.007 | 29.244s |
| 0.003 | TSAE + zRepair | 4/1000 | 7/1000 | 0.007 | 29.531s |
| 0.004 | sliding | 0/1000 | 21/1000 | 0.021 | 75.332s |
| 0.004 | plain parallel | 32/1000 | 38/1000 | 0.038 | 31.263s |
| 0.004 | TSAE | 11/1000 | 22/1000 | 0.022 | 40.071s |
| 0.004 | TSAE + zRepair | 11/1000 | 22/1000 | 0.022 | 32.834s |
| 0.005 | sliding | 0/1000 | 93/1000 | 0.093 | 70.182s |
| 0.005 | plain parallel | 119/1000 | 148/1000 | 0.148 | 33.977s |
| 0.005 | TSAE | 38/1000 | 111/1000 | 0.111 | 42.902s |
| 0.005 | TSAE + zRepair | 38/1000 | 111/1000 | 0.111 | 40.830s |
| 0.007 | sliding | 0/1000 | 513/1000 | 0.513 | 92.773s |
| 0.007 | plain parallel | 423/1000 | 585/1000 | 0.585 | 56.715s |
| 0.007 | TSAE | 275/1000 | 556/1000 | 0.556 | 67.522s |
| 0.007 | TSAE + zRepair | 275/1000 | 556/1000 | 0.556 | 61.377s |
z repair diagnostics:
| p | attempts | accepted | success_to_zero | decode_flagged | weight_before | weight_after | delta |
|---|---|---|---|---|---|---|---|
| 0.003 | 8 | 2 | 0 | 8 | 23 | 25 | -2 |
| 0.004 | 22 | 15 | 0 | 22 | 84 | 71 | 13 |
| 0.005 | 76 | 60 | 0 | 76 | 396 | 312 | 84 |
| 0.007 | 550 | 428 | 0 | 550 | 2920 | 2376 | 544 |
结论:
z_B targeted repair 能降低部分 residual weight,
但 success_to_zero 始终为 0,
所以 final flagged 和 LER 完全没有改善。
这说明当前候选集合和小 BP-OSD repair 只能减轻 seam residual,
不能把 z_B witness 转化成完整的物理闭合 correction。
下一步判断:
不能继续只做 residual-weight 降低型 repair;
如果目标是降低 flagged,acceptance 应该要求 residual 清零,
或者改成重新求解相关 B window + A boundary 的 joint physical problem。
前面的 TSAE / chain-DP / micro-sliding / joint-score 说明:
1. shifted A 多视角本身有效;
2. 只看 A candidate 对 B syndrome 的 popcount 还不够;
3. z_B repair 能降 residual weight,但不能把 residual 清零;
4. 继续优化应该让 A candidate 选择直接看到 B 小窗口是否能物理闭合。
因此新增:
--a-shifted-joint-b-dp
--a-shifted-joint-flag-penalty
策略:
A 仍然只用 5-row shifted 小窗口产生 candidate;
对每个相邻 A candidate pair,真正运行对应的 B 小窗口解码;
边权 = B 解码 cost + penalty * physical B residual weight;
最后用 chain DP 选整条 A/B candidate path。
这里的 physical B residual 不包含 noisy boundary 虚拟列的贡献, 所以它直接惩罚 z_B witness,而不是事后再 repair。
命令:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--p-list 0.003,0.004,0.005,0.007 \
--decoders parallel \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--b-noisy-boundary \
--window-shorten \
--a-shifted-ensemble \
--a-shift-offsets=-2,0,2 \
--a-shifted-beta 1.0 \
--a-shifted-joint-b-dp \
--seam-diagnostics \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_TSAE_joint_b_dp_ab_noisy_shorten_parallel_only.csv结果:
| p | TSAE baseline | TSAE joint-B-DP | sliding w3 | a9/b9 |
|---|---|---|---|---|
| 0.003 | 0/100, LER 0.000 | 0/100, LER 0.000, 4.758s | 0/100, LER 0.000 | 0/100, LER 0.000 |
| 0.004 | 3/100, LER 0.040 | 0/100, LER 0.010, 6.163s | 0/100, LER 0.020 | 0/100, LER 0.000 |
| 0.005 | 4/100, LER 0.140 | 0/100, LER 0.090, 9.628s | 0/100, LER 0.120 | 0/100, LER 0.040 |
| 0.007 | 25/100, LER 0.560 | 14/100, LER 0.470, 19.824s | 0/100, LER 0.450 | 0/100, LER 0.430 |
diagnostics:
| p | joint B decodes | physical residual | selected nonzero shift |
|---|---|---|---|
| 0.003 | 600 | 0 | 59 |
| 0.004 | 600 | 0 | 68 |
| 0.005 | 600 | 0 | 69 |
| 0.007 | 600 | 70 | 63 |
结论:
轻量版 joint-B-DP 明显优于 TSAE baseline。
p=0.004: flagged 3/100 -> 0/100, LER 0.040 -> 0.010
p=0.005: flagged 4/100 -> 0/100, LER 0.140 -> 0.090
p=0.007: flagged 25/100 -> 14/100, LER 0.560 -> 0.470
它没有扩大单个 A/B 窗口,只增加了 small-window candidate pair 的 B 解码次数。 这说明“先生成多个小窗口视角,再用真实 B 解码闭合能力做联合选择”比 residual popcount score 更接近大窗口信息。
进一步把已有 interface branching 和 joint-B-DP 组合:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--seed 2 \
--p-list 0.005,0.007 \
--decoders parallel \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--b-noisy-boundary \
--window-shorten \
--a-shifted-ensemble \
--a-shift-offsets=-2,0,2 \
--a-shifted-beta 1.0 \
--tsae-interface-branch \
--tsae-interface-cols-per-side 1 \
--a-shifted-joint-b-dp \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_TSAE_interface_joint_b_dp_seed2_ab_noisy_shorten_parallel_only.csv结果使用 seed 2,使 p=0.005 对应原四点 sweep 的 seed 2, p=0.007 对应 seed 3:
| p | TSAE baseline | joint-B-DP | interface + joint-B-DP | sliding w3 | a9/b9 |
|---|---|---|---|---|---|
| 0.005 | 4/100, LER 0.140 | 0/100, LER 0.090 | 0/100, LER 0.060, 37.603s | 0/100, LER 0.120 | 0/100, LER 0.040 |
| 0.007 | 25/100, LER 0.560 | 14/100, LER 0.470 | 8/100, LER 0.400, 77.605s | 0/100, LER 0.450 | 0/100, LER 0.430 |
diagnostics:
| p | joint B decodes | physical residual | branch payloads |
|---|---|---|---|
| 0.005 | 2400 | 0 | 12 |
| 0.007 | 2400 | 24 | 12 |
结论:
interface + joint-B-DP 进一步降低 LER,
并且 p=0.007 达到 LER 0.400,低于 sliding 和 a9/b9 的本轮 100-shot 结果。
代价是 runtime 明显增加:
p=0.005: 9.628s -> 37.603s
p=0.007: 19.824s -> 77.605s
推荐后续方向:
1. 默认候选使用轻量 joint-B-DP;
2. 只在 joint-B-DP 仍存在 physical residual 的 shot 上触发 interface branch;
3. 对 p=0.007 的 8 个 flagged shot 做 oracle diag,判断是 candidate pool 不含正确 A commit,
还是 DP score 在含正确 candidate 时选错。
实现 gated 版本:
--tsae-interface-branch
--tsae-interface-gated
--a-shifted-joint-b-dp
策略:
1. 先跑轻量 joint-B-DP;
2. 记录每个 shot 的 selected physical B residual;
3. 只对 residual > 0 的 shot 构造 interface branch candidate;
4. 对这些 shot 重跑 joint-B-DP;
5. 只有 branch 后 residual 更低,或者 residual 相同但 score 更低,才覆盖轻量结果。
这样保留原来的全量 --tsae-interface-branch 行为,
gated 是额外开关,不改变旧实验语义。
可比 100-shot 命令:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 100 \
--seed 2 \
--p-list 0.005,0.007 \
--decoders parallel \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--b-noisy-boundary \
--window-shorten \
--a-shifted-ensemble \
--a-shift-offsets=-2,0,2 \
--a-shifted-beta 1.0 \
--tsae-interface-branch \
--tsae-interface-gated \
--tsae-interface-cols-per-side 1 \
--a-shifted-joint-b-dp \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots100_TSAE_gated_interface_joint_b_dp_seed2_ab_noisy_shorten_parallel_only.csv结果:
| p | joint-B-DP | full interface + joint-B-DP | gated interface + joint-B-DP |
|---|---|---|---|
| 0.005 | 0/100, LER 0.090, 9.628s | 0/100, LER 0.060, 37.603s | 0/100, LER 0.090, 8.952s |
| 0.007 | 14/100, LER 0.470, 19.824s | 8/100, LER 0.400, 77.605s | 8/100, LER 0.450, 33.039s |
diagnostics:
| p | total B pair decodes | gated shots | accepted | improved to zero | gated B decodes | final physical residual |
|---|---|---|---|---|---|---|
| 0.005 | 600 | 0 | 0 | 0 | 0 | 0 |
| 0.007 | 936 | 14 | 12 | 6 | 336 | 24 |
结论:
gated 版本显著降低 runtime:
p=0.007 full interface 77.605s -> gated 33.039s
它保留了 full interface 对 flagged 的改善:
p=0.007 joint-B-DP 14/100 -> gated 8/100
但 LER 没有完全达到 full interface:
full interface LER 0.400
gated interface LER 0.450
解释:
gated 只处理 physical residual > 0 的 shot;
full interface 还能改变一些 already-closed shot 的 logical class。
因此 gated 是 runtime/accuracy 折中:
它主要保留了 physical closure 收益,
但不会捕获 zero-residual shot 上的 logical-only improvement。
目的:
用 1000 shots 对比:
1. 普通 parallel
2. 普通 TSAE
3. sliding
4. gated interface + joint-B-DP
参数保持和 1000-shot baseline 一致:
N=144
repeat=12
shots=1000
p-list=0.003,0.004,0.005,0.007
seed=0,1,2,3
a_solve=5
b_width=5
noisy boundary + shorten
gated 命令:
SlidingWindowDecoder/.conda-gdg/bin/python ParallelWindowDecoder/run_experiments.py \
--N 144 \
--num-repeat 12 \
--num-shots 1000 \
--p-list 0.003,0.004,0.005,0.007 \
--decoders parallel \
--a-size 3 \
--a-solve-size 5 \
--b-width 5 \
--sliding-width 3 \
--top-k-boundary 1 \
--a-noisy-boundary \
--b-noisy-boundary \
--window-shorten \
--a-shifted-ensemble \
--a-shift-offsets=-2,0,2 \
--a-shifted-beta 1.0 \
--tsae-interface-branch \
--tsae-interface-gated \
--tsae-interface-cols-per-side 1 \
--a-shifted-joint-b-dp \
--parallel-workers 4 \
--parallel-backend process \
--out ParallelWindowDecoder/results/N144_repeat12_shots1000_TSAE_gated_interface_joint_b_dp_ab_noisy_shorten_parallel_only.csv结果:
| p | parallel | TSAE | sliding | gated interface+joint |
|---|---|---|---|---|
| 0.003 | 10/1000, LER 0.011, 29.4s | 4/1000, LER 0.007, 29.2s | 0/1000, LER 0.001, 71.4s | 0/1000, LER 0.001, 30.7s |
| 0.004 | 32/1000, LER 0.038, 31.3s | 11/1000, LER 0.022, 40.1s | 0/1000, LER 0.021, 75.3s | 0/1000, LER 0.010, 50.5s |
| 0.005 | 119/1000, LER 0.148, 34.0s | 38/1000, LER 0.111, 42.9s | 0/1000, LER 0.093, 70.2s | 1/1000, LER 0.050, 90.9s |
| 0.007 | 423/1000, LER 0.585, 56.7s | 275/1000, LER 0.556, 67.5s | 0/1000, LER 0.513, 92.8s | 77/1000, LER 0.449, 339.8s |
gated diagnostics:
| p | B pair decodes | gated shots | accepted | improved to zero | gated B decodes | final physical residual |
|---|---|---|---|---|---|---|
| 0.003 | 6000 | 0 | 0 | 0 | 0 | 0 |
| 0.004 | 6024 | 1 | 1 | 1 | 24 | 0 |
| 0.005 | 6144 | 6 | 5 | 5 | 144 | 6 |
| 0.007 | 9912 | 163 | 146 | 86 | 3912 | 200 |
结论:
gated interface + joint-B-DP 在 1000 shots 下持续降低 LER:
p=0.004: sliding 0.021, TSAE 0.022, gated 0.010
p=0.005: sliding 0.093, TSAE 0.111, gated 0.050
p=0.007: sliding 0.513, TSAE 0.556, gated 0.449
runtime tradeoff:
低/中 p 下 gated 仍可接受;
p=0.007 runtime 变为 339.8s,
因为 gated shots 达到 163/1000,并额外触发 3912 次 B pair decode。
目的:
把 repeat 从 12 提高到 18;
shots 降到 100 以加快测试;
比较普通 parallel、TSAE、sliding、gated interface + joint-B-DP。
gated 结果文件:
ParallelWindowDecoder/results/N144_repeat18_shots100_TSAE_gated_interface_joint_b_dp_ab_noisy_shorten_parallel_only.csv
结果:
| p | parallel | TSAE | sliding | gated interface+joint |
|---|---|---|---|---|
| 0.003 | 3/100, LER 0.030, 8.1s | 0/100, LER 0.000, 11.4s | 0/100, LER 0.000, 34.7s | 0/100, LER 0.000, 10.1s |
| 0.004 | 6/100, LER 0.060, 7.4s | 4/100, LER 0.050, 10.6s | 0/100, LER 0.020, 30.5s | 0/100, LER 0.000, 15.6s |
| 0.005 | 32/100, LER 0.350, 7.7s | 14/100, LER 0.270, 12.7s | 0/100, LER 0.150, 25.0s | 0/100, LER 0.140, 54.3s |
| 0.007 | 68/100, LER 0.830, 9.6s | 43/100, LER 0.800, 19.9s | 0/100, LER 0.620, 28.3s | 13/100, LER 0.680, 228.2s |
gated diagnostics:
| p | B pair decodes | gated shots | accepted | improved to zero | gated B decodes | final physical residual |
|---|---|---|---|---|---|---|
| 0.003 | 1500 | 0 | 0 | 0 | 0 | 0 |
| 0.004 | 1500 | 0 | 0 | 0 | 0 | 0 |
| 0.005 | 2340 | 5 | 5 | 5 | 840 | 0 |
| 0.007 | 6036 | 27 | 25 | 14 | 4536 | 38 |
结论:
repeat=18 下,gated 在 p=0.004 / p=0.005 继续优于 sliding;
p=0.007 下仍显著优于 plain parallel / TSAE,
但本轮 100-shot 没有超过 sliding。
高 p 的 runtime 明显增加:
p=0.007 gated shots = 27/100,
额外 gated B decodes = 4536。