资讯动态

CA-SCL译码实战:从polar.zip到误块率曲线

发布时间:2026/10/23 4:54:16 来源:尧图企业网站定制
简介这份资源围绕极化码Polar Code与CA-SCL解码器展开面向无线通信、信道编码方向的学习者与研究人员帮助理解从信道极化理论到级联SCL解码的完整实现思路。压缩包共16个文件约19KB以12个MATLAB脚本.m为核心涵盖极化编码、SCL/CA-SCL解码、CRC校验、路径度量与AWGN信道仿真等模块另有2个C源文件及配套mexw64动态库用于加速似然率计算并附一份运行日志便于排查环境问题。已有216人学习下载。读者可据此复现极化码编码、冻结位构造、列表解码与回溯判决等关键流程对照代码理解列表大小与回溯深度对性能的影响并借助CRC辅助机制观察误码率变化适合作为5G NR极化码入门实践与算法验证的参考素材。1. 从 polar.zip 说起CA-SCL 译码为什么值得你花一个周末跑通如果你最近在搜polar.zip_CA SCL_polar code大概率是手里已经有一份 Polar 码的仿真工程或者正准备从 SC 译码往 CA-SCL 方向迁移。Polar 码在 5G 控制信道里被采用之后SCSuccessive Cancellation译码的短板就暴露得很明显码长一长、信噪比一低误块率曲线掉得不够快。CA-SCLCRC-Aided Successive Cancellation List就是在这个背景下成为工程默认选项的——它把 CRC 校验位当作“后悔药”在列表里保留多条候选路径最后用 CRC 挑出最像的那条。这个标题对应的不是一篇论文而是一类可复现的工程包一个能跑通 Polar 编码、AWGN 信道、SC/SCL/CA-SCL 译码对比的仿真目录。适合谁适合正在做链路级仿真、需要给 Polar 码选译码方案、或者要复现 CA-SCL 性能曲线的工程师和学生。它解决的核心问题是让你在本地用几十行 Python 或 C 代码把 CA-SCL 相对 SCL 的增益跑出来而不是只停留在公式推导。下面我按“先立住原理、再动手复现、最后避坑”的顺序把这条路走一遍。2. CA-SCL 译码的工程拆解从 SC 到列表再到 CRC 筛选2.1 SC 译码的递归结构决定了后面所有优化SC 译码的本质是按比特逐个判决每个比特的判决依赖前面所有已判决比特。工程上通常用递归的 f 和 g 函数在因子图上做软信息传递。f 函数处理两个似然比的合并g 函数在已知一个比特后修正另一个分支的软信息。这个结构决定了 SC 的复杂度是 O(N log N)也决定了它一旦前面判错后面无法回退。我一般会先写一个最朴素的 SC 递归版本确认因子图索引和冻结位位置没错再往上叠列表。因为 SCL 的所有路径扩展都建立在 SC 的软信息计算之上SC 写错SCL 的曲线会整体偏移后面调参数就是玄学。import numpy as np def f_func(a, b): # 两个似然比的 f 合并对应因子图上半部分 return np.sign(a) * np.sign(b) * min(abs(a), abs(b)) def g_func(a, b, u): # u 为已判决比特对下分支做修正 return b (1 - 2 * u) * a def sc_decode(llr, frozen_pos): # llr: 信道对数似然比frozen_pos: 冻结位索引集合 N len(llr) u_hat np.zeros(N, dtypeint) # 这里省略递归展开实际工程用迭代或递归树实现 # 关键点冻结位强制判 0信息位按 llr 符号判 for i in range(N): if i in frozen_pos: u_hat[i] 0 else: u_hat[i] 0 if llr[i] 0 else 1 return u_hat上面这段是骨架真实工程里 llr 会随递归层级更新不能直接用信道 llr 判所有位。参数说明frozen_pos来自 Polar 码构造常用高斯近似或巴氏参数法生成llr的符号约定要统一我习惯正数判 0、负数判 1换约定会让曲线完全对不上。2.2 SCL 的列表扩展路径数 L 不是越大越好SCL 在每个信息位同时保留 0 和 1 两个分支路径数翻倍然后按路径度量PM排序保留最好的 L 条。PM 的更新和 llr 的绝对值有关判决与 llr 符号一致时 PM 不变不一致时 PM 增加 |llr|。这个设计让 PM 越小路径越可靠。L 的选取是工程折中。L1 退化成 SCL4 或 8 在短码下已经能拿到大部分增益L32 以上收益递减但内存和排序开销线性涨。我一般先在 L8 上把曲线跑通再扫 L1/2/4/8/16/32 看拐点。def scl_decode(llr, frozen_pos, L8): # 路径用 (pm, u_hat, llr_state) 表示pm 越小越好 paths [(0.0, [], llr.copy())] N len(llr) for i in range(N): new_paths [] for pm, u_hat, state in paths: if i in frozen_pos: # 冻结位只扩展 0 分支 new_paths.append((pm, u_hat [0], state)) else: # 信息位扩展 0 和 1 两个分支 for bit in (0, 1): # 简化 PM 更新按 llr 符号与 bit 是否一致累加 penalty 0 if (state[i] 0) (bit 0) else abs(state[i]) new_paths.append((pm penalty, u_hat [bit], state)) # 按 PM 升序保留前 L 条 new_paths.sort(keylambda x: x[0]) paths new_paths[:L] return min(paths, keylambda x: x[0])[1]这段代码把路径扩展和排序逻辑写清楚了但真实工程里state要随递归更新不能一直用初始 llr。参数说明L是列表宽度直接决定复杂度和内存penalty的计算依赖 llr 的数值尺度如果信道 llr 做了归一化PM 的绝对值会变但排序相对关系不变。2.3 CRC 辅助把列表里的候选路径用校验位筛一遍CA-SCL 的关键增量是在信息位后面附上 CRC 校验位译码结束后对每条候选路径做 CRC 校验第一条通过校验的路径就是输出。如果所有路径都没通过通常回退到 PM 最小的那条。CRC 长度常见 6、11、16、24 位长度越长虚警概率越低但占用的信息位也越多。工程上要注意CRC 校验的是译码后的信息比特不是编码前的。所以路径的u_hat里要先把信息位提取出来再做 CRC。我见过有人直接对全零填充后的码字做校验曲线看着对实际误块率偏高这就是黑匣子没打开。def crc_check(u_hat, info_pos, crc_len, poly0x1021): # 提取信息位和 CRC 位做模 2 除法校验 info_bits [u_hat[i] for i in info_pos] msg info_bits[:-crc_len] crc_recv info_bits[-crc_len:] # 简化 CRC 计算实际用查表或位运算 crc_calc 0 for bit in msg: crc_calc ((crc_calc 1) | bit) ((1 crc_len) - 1) return crc_calc int(.join(map(str, crc_recv)), 2) def ca_scl_decode(llr, frozen_pos, info_pos, L8, crc_len16): paths scl_decode(llr, frozen_pos, L) # 这里应返回多条路径 # 实际工程中 scl_decode 要返回排序后的路径列表 for u_hat in paths: if crc_check(u_hat, info_pos, crc_len): return u_hat return paths[0] # 全部失败则回退 PM 最小参数说明poly是 CRC 生成多项式不同标准用的不一样选错会导致校验永远失败info_pos是信息位索引必须和冻结位集合互补且不重叠。这段代码的scl_decode需要改成返回多条路径否则 CA-SCL 没有意义。3. 在本地跑通 CA-SCL从 polar.zip 到误块率曲线3.1 目录结构和依赖先把环境钉死拿到一个polar.zip类似的工程包我第一件事不是跑主程序而是看依赖和目录。常见结构是src/放编码译码sim/放仿真脚本config/放码长、码率、信噪比扫描配置。依赖通常只有 numpy 和 matplotlib少数用 C 加速的会带 pybind11 或 ctypes。我一般会建一个干净的虚拟环境把 numpy 版本钉在 1.24 左右避免新版本 API 变动导致np.sign行为差异。然后先跑一个最小用例N64K32SNR2dBL8看能不能出比特。这一步过了再上误块率扫描。python -m venv polar_env source polar_env/bin/activate # Windows 用 polar_env\Scripts\activate pip install numpy1.24.3 matplotlib3.7.1 python -c import numpy; print(numpy.__version__)逻辑说明虚拟环境隔离系统包避免和已有工程冲突版本钉死是为了复现曲线numpy 大版本升级有时会改随机数生成器默认行为导致 SNR 扫描结果不可比。3.2 编码和构造冻结位位置决定性能上限Polar 编码本身很简单把信息位放在可靠度高的位置冻结位放 0然后做比特反转和异或。难点在构造——怎么知道哪些位置可靠。工程上常用高斯近似GA或巴氏参数法。GA 在 AWGN 下更准但计算量大巴氏参数法快短码下够用。我一般先用巴氏参数法生成冻结位跑通后再换 GA 对比。构造错了SCL 的曲线会整体差 1dB 以上而且 L 越大差距越明显因为列表在错误的位置上扩展。def construct_frozen(N, K, design_snr2.0): # 巴氏参数法简化版按信道容量排序选 K 个最可靠的位置 # 实际工程用递归计算巴氏参数或高斯近似 reliabilities np.zeros(N) for i in range(N): # 这里用索引的二进制表示近似可靠度仅作示例 reliabilities[i] bin(i).count(1) # 占位逻辑真实实现需替换 order np.argsort(reliabilities)[::-1] info_pos set(order[:K]) frozen_pos set(range(N)) - info_pos return frozen_pos, info_pos参数说明design_snr是构造时假设的信噪比设高了会偏向高可靠位置设低了会保守K是信息位数量包括 CRC 位。这段的可靠度计算是占位真实工程必须用 GA 或巴氏参数递推否则曲线不可信。3.3 误块率扫描SNR 点怎么取、多少帧才够跑误块率曲线SNR 点一般从 0dB 到 4dB步长 0.5dB。每个点至少 1000 个块误块率到 1e-3 以下要 10000 块以上。我习惯先跑 200 块看趋势曲线形状对了再补帧数。帧数不够时曲线会抖尤其是 CA-SCL 在低误块率区CRC 筛选让有效样本变少。def simulate_fer(N, K, snr_db, L, crc_len, frames1000): frozen_pos, info_pos construct_frozen(N, K) errors 0 for _ in range(frames): msg np.random.randint(0, 2, K - crc_len) # 编码、加噪、译码流程省略核心是调用 ca_scl_decode # 比较译码结果和原始 msg统计误块 pass return errors / frames逻辑说明frames是每个 SNR 点的块数直接决定曲线平滑度snr_db是符号信噪比换算成 llr 时要乘 2/方差。这段没写完整编码是因为编码部分和构造强相关建议先单独验证编码器输出和标准一致。4. CA-SCL 调参和排错那些让曲线对不上的坑4.1 现象CA-SCL 曲线和 SCL 完全重合原因通常是 CRC 校验没生效。检查info_pos是否包含了 CRC 位crc_check是否真的在筛选路径。如果scl_decode只返回一条路径CA-SCL 就退化成 SCL。解决让scl_decode返回排序后的路径列表逐条做 CRC打印通过校验的路径索引。4.2 现象L 增大后误块率反而变差一般是 PM 更新符号反了。PM 应该越小越好如果排序时取了降序保留的是最差路径。检查new_paths.sort(keylambda x: x[0])是否升序以及penalty是否在判决与 llr 不一致时增加。另一个可能是 llr 符号约定和 PM 更新不匹配。4.3 现象高 SNR 下曲线出现错误平台CRC 长度不够或生成多项式选错。CRC-16 在块长 64 时虚警概率约 1/65536如果曲线在 1e-4 附近压不下去先换 CRC-24 试试。另外检查 CRC 计算是否覆盖了所有信息位漏掉最后几位会导致校验形同虚设。4.4 现象仿真速度慢到跑不完Python 递归实现 SCL 在 N1024、L32 时每帧要几百毫秒。常见优化是把递归改成迭代用 numpy 向量化路径扩展或者把译码核心用 C 重写。我一般先用 N256 跑通逻辑再上大码长。如果只是验证算法不必一上来就 N1024。5. 把 CA-SCL 用对从仿真到链路级验证的几个习惯CA-SCL 的仿真跑通只是第一步真正要用到链路里我习惯做三件事。第一固定随机种子把编码、加噪、译码的随机源分开这样换 L 或 CRC 长度时曲线可比。第二单独验证编码器全零信息位编码后应该得到全零码字全一信息位编码后和标准表对一遍。第三画曲线时同时画 SC、SCL、CA-SCL 三条确认增益方向符合预期——CA-SCL 应该在 SCL 基础上再降而不是重合或更差。进阶用法上可以试 CRC 长度和 L 的联合扫描。我一般列一个表行是 L4/8/16/32列是 CRC6/11/16/24每个格子跑 2000 帧看哪个组合在目标误块率下复杂度最低。常见结论是 L8、CRC16 在短码下性价比最高但码长到 512 以上时 L16 开始有优势。L \ CRC61116244增益小可用推荐过设计8可用推荐推荐可用16一般可用推荐推荐32一般可用可用推荐验证方法上除了误块率我还会看平均列表路径数和 CRC 通过率。如果 CRC 通过率在高 SNR 下不到 90%说明 CRC 太短或路径排序有问题。这些指标比单看曲线更能定位问题。最后说个血泪经验别在没验证编码器的情况下调译码参数。我见过太多人花两天调 L 和 CRC最后发现是冻结位构造错了。先让 SC 在无噪下误块率为零再上 SCL再上 CA-SCL每一步都确认前一步是对的。这个习惯帮我省了至少三个周末。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑