(3) 从二阶核F到生成矩阵:Polar编码蝶形图怎么来的

从二阶核F到生成矩阵:Polar编码蝶形图怎么来的

前两篇文章里,我们先建立了 Polar 码的大图景,又补齐了 B-DMC、码率、容量和 LLR 这些预备概念。从这一篇开始,正式看 Polar 编码本身:给定一个长度为 N 的极化输入向量 \underline{u}_0^{N-1},怎样得到发送前的二元码字向量 \underline{c}_0^{N-1}

这篇只讨论编码结构,不讨论哪些位置放信息、哪些位置冻结。也就是说,本文先回答:

  • 二阶核 \mathbf{F}_2 到底在做什么。
  • \mathbf{G}_N 为什么可以由 Kronecker 幂构造。
  • 为什么有的资料写 \mathbf{F}_2^{\otimes n},有的资料写 \mathbf{B}_N\mathbf{F}_2^{\otimes n}
  • 生成矩阵和蝶形图之间怎样一一对应。

本文统一使用 0-based 索引,所有比特运算都在二元域 \mathbb{F}_2=\{0,1\} 上进行。异或写作 \oplus。编码向量采用行向量约定:

\underline{c}_0^{N-1}=\underline{u}_0^{N-1}\mathbf{G}_N

其中 N=2^n 是码长,\underline{u}_0^{N-1}\in\mathbb{F}_2^N 是极化输入向量,\underline{c}_0^{N-1}\in\mathbb{F}_2^N 是编码后的二元码字向量,\mathbf{G}_N 是本文要讲清楚的生成矩阵。

为什么从一个 2×2 核开始

Polar 编码最小的变换来自极化二阶核:

\mathbf{F}_2= \begin{bmatrix} 1 & 0\\ 1 & 1 \end{bmatrix}

把长度为 2 的行向量 (u_0,u_1) 右乘这个矩阵,得到:

(c_0,c_1)=(u_0,u_1)\mathbf{F}_2=(u_0\oplus u_1,\ u_1)

这就是 Polar 编码的最小单元。第一个输出 c_0 同时依赖 u_0u_1,第二个输出 c_1 保留 u_1。如果只看编码结构,这个核做的事情可以说是“耦合”:它用一次异或把两个输入比特混在一起。

这里先不要把它和后面信道极化里的 channel combining / channel splitting 混成一件事。本文讲的是编码端的矩阵和蝶形结构;第 5 篇再从信道角度正式讲 combining 和 splitting。

如果把这个最小单元写成“文字版蝶形图”,可以看成下面两条输出线:

\begin{array}{ccc} u_0 & \longrightarrow & c_0=u_0\oplus u_1\\ u_1 & \longrightarrow & c_1=u_1 \end{array}

这两条线里,只有 u_1 会向上参与一次异或;这就是二阶核里最小的耦合关系。上面的“文字版蝶形图”和矩阵乘法是同一个关系:

c_0=u_0\oplus u_1,\qquad c_1=u_1

如果把 \mathbf{F}_2 换成单位矩阵,两个输入比特不会发生这种耦合,也就失去了 Polar 编码后面能够形成递归结构的基础。

\mathbf{F}_2 到 Kronecker 幂

码长为 N=2^n 时,最直接的生成矩阵来自 Kronecker 幂:

\mathbf{G}_N^{\mathrm{nat}}=\mathbf{F}_2^{\otimes n}

这里上标 \mathrm{nat} 表示 natural order,也就是暂时不加入 bit-reversal 的自然顺序写法。Kronecker 幂的递推定义是:

\mathbf{F}_2^{\otimes n} = \begin{bmatrix} \mathbf{F}_2^{\otimes(n-1)} & \mathbf{0}\\ \mathbf{F}_2^{\otimes(n-1)} & \mathbf{F}_2^{\otimes(n-1)} \end{bmatrix}, \qquad \mathbf{F}_2^{\otimes 1}=\mathbf{F}_2

这条式子非常重要。它说明长码的生成矩阵不是凭空写出来的,而是把两个更短的生成矩阵按块拼起来:左下角多出来的一块 \mathbf{F}_2^{\otimes(n-1)},正是“下半部分输入也会影响上半部分输出”的来源。

N=4,也就是 n=2,有:

\mathbf{G}_4^{\mathrm{nat}} =\mathbf{F}_2^{\otimes 2} = \begin{bmatrix} 1 & 0 & 0 & 0\\ 1 & 1 & 0 & 0\\ 1 & 0 & 1 & 0\\ 1 & 1 & 1 & 1 \end{bmatrix}

于是:

\underline{c}_0^3 =\underline{u}_0^3\mathbf{G}_4^{\mathrm{nat}}

逐位展开就是:

\begin{aligned} c_0&=u_0\oplus u_1\oplus u_2\oplus u_3,\\ c_1&=u_1\oplus u_3,\\ c_2&=u_2\oplus u_3,\\ c_3&=u_3. \end{aligned}

这就是 N=4 的最小完整编码例子。它已经包含了 Polar 编码的两个关键特征:递归结构和蝶形异或网络。

N=4 的蝶形图怎么对应矩阵

直接做矩阵乘法当然可以得到 \underline{c}_0^3,但 Polar 编码通常不会真的存一个完整的 \mathbf{G}_N 再相乘。原因是 \mathbf{G}_N 很有结构,可以用类似 FFT 的蝶形网络完成同样的运算。

N=4,自然顺序下的蝶形结构可以直接写成两层变量更新。

第一层在相邻 pair 内做二阶核:

(u_0,u_1)\mapsto (u_0\oplus u_1,\ u_1), \qquad (u_2,u_3)\mapsto (u_2\oplus u_3,\ u_3)

记第一层输出为 \underline{a}_0^3,则:

a_0=u_0\oplus u_1,\quad a_1=u_1,\quad a_2=u_2\oplus u_3,\quad a_3=u_3

第二层把两个长度为 2 的部分再耦合起来:

c_0=a_0\oplus a_2,\qquad c_1=a_1\oplus a_3,\qquad c_2=a_2,\qquad c_3=a_3

把这两层合在一起,就是下面这个“公式版蝶形图”:

\begin{array}{ccccc} u_0 & \longrightarrow & a_0=u_0\oplus u_1 & \longrightarrow & c_0=a_0\oplus a_2\\ u_1 & \longrightarrow & a_1=u_1 & \longrightarrow & c_1=a_1\oplus a_3\\ u_2 & \longrightarrow & a_2=u_2\oplus u_3 & \longrightarrow & c_2=a_2\\ u_3 & \longrightarrow & a_3=u_3 & \longrightarrow & c_3=a_3 \end{array}

代回去,就正好得到前面矩阵乘法展开出来的四条式子:

c_0=u_0\oplus u_1\oplus u_2\oplus u_3,\quad c_1=u_1\oplus u_3,\quad c_2=u_2\oplus u_3,\quad c_3=u_3

所以蝶形图不是另一种编码定义,而是 \underline{u}_0^{N-1}\mathbf{G}_N 的快速实现方式。矩阵告诉你“谁影响谁”,蝶形图告诉你“怎样用分层异或高效算出来”。

生成矩阵的两种常见形式

初学 Polar 码时,一个很容易混乱的点是:不同资料里的生成矩阵不总是长得一模一样。最常见的是下面两种。

写法本系列中的记号含义
自然顺序\mathbf{G}_N^{\mathrm{nat}}=\mathbf{F}_2^{\otimes n}先忽略 bit-reversal,直接使用 Kronecker 幂
bit-reversal 顺序\mathbf{G}_N^{\mathrm{br}}=\mathbf{B}_N\mathbf{F}_2^{\otimes n}先按 bit-reversal 重排输入索引,再进入同一个 Kronecker 蝶形核心

这里 \mathbf{B}_N 是 bit-reversal 置换矩阵。本文采用行向量约定,所以 \mathbf{B}_N 写在 \mathbf{F}_2^{\otimes n} 左侧:

\underline{c}_0^{N-1} =\underline{u}_0^{N-1}\mathbf{B}_N\mathbf{F}_2^{\otimes n}

如果某本书或某篇论文采用列向量约定,置换矩阵可能出现在另一侧。遇到这种差异时,先看清楚它的向量是行向量还是列向量,不要只盯着矩阵符号本身。

N=4,bit-reversal 把索引二进制反转。两位二进制索引的反转关系是:

原索引 i二进制反转后
0000
1012
2101
3113

在本文的行向量写法下,可以定义:

(\underline{u}_0^3\mathbf{B}_4)_0^3=(u_0,u_2,u_1,u_3)

对应的置换矩阵可以写为:

\mathbf{B}_4= \begin{bmatrix} 1 & 0 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}

因此:

\mathbf{G}_4^{\mathrm{br}} =\mathbf{B}_4\mathbf{F}_2^{\otimes 2} = \begin{bmatrix} 1 & 0 & 0 & 0\\ 1 & 0 & 1 & 0\\ 1 & 1 & 0 & 0\\ 1 & 1 & 1 & 1 \end{bmatrix}

这和 \mathbf{G}_4^{\mathrm{nat}} 不是同一个矩阵。差别不在二阶核本身,而在进入蝶形网络之前,输入索引有没有先做 bit-reversal。

bit-reversal 和蝶形图的对应关系

从结构上看,bit-reversal 形式可以理解为:先做一个输入重排,再进入和自然顺序相同的 Kronecker 核心。

这个对应关系可以直接写成:

\underline{u}_0^3 \xrightarrow{\ \mathbf{B}_4\ } (u_0,u_2,u_1,u_3) \xrightarrow{\ \mathbf{F}_2^{\otimes 2}\ } \underline{c}_0^3

有些资料或图示会把这个重排模块写成 R_N,也有资料写成 B_N。本系列公开文章统一把 bit-reversal 矩阵写作 \mathbf{B}_N。如果图中出现 R_N,可以把它理解为“重排模块”的图形标注,而不是新的编码核心。

N=4,bit-reversal 约定下等价于先把输入顺序变成:

(u_0,u_1,u_2,u_3)\mathbf{B}_4=(u_0,u_2,u_1,u_3)

然后对这个新顺序运行自然顺序蝶形。于是输出变为:

\begin{aligned} c_0&=u_0\oplus u_1\oplus u_2\oplus u_3,\\ c_1&=u_2\oplus u_3,\\ c_2&=u_1\oplus u_3,\\ c_3&=u_3. \end{aligned}

和自然顺序相比,c_1c_2 的表达式交换了位置。这不是错误,而是索引约定不同导致的结果。

这个差异在短例子里看起来只是两个位置互换,但后面涉及信息位集合 \mathcal{A}、可靠性序列 \boldsymbol{\pi}、译码顺序和工程实现时,就不能随便忽略。只要一篇文章第一次出现 \mathbf{G}_N,就应该明确采用哪一种约定。

本系列后续默认采用下面的写法:

  • 如果文章不讨论 bit-reversal 细节,优先写 \mathbf{G}_N=\mathbf{F}_2^{\otimes n},把注意力放在核心递归结构上。
  • 如果文章需要讨论 bit-reversal,则显式写 \mathbf{G}_N^{\mathrm{br}}=\mathbf{B}_N\mathbf{F}_2^{\otimes n},并说明输入索引如何重排。
  • 不把两种 \mathbf{G}_N 写法混在同一段推导里。

一般 N 的蝶形结构

N=2^n 时,\mathbf{F}_2^{\otimes n} 对应 n 层蝶形异或。自然顺序下可以这样理解:

  • 第 1 层:每隔 2 个位置做一次长度为 2 的核。
  • 第 2 层:每隔 4 个位置,把两个长度为 2 的部分耦合。
  • 第 3 层:每隔 8 个位置,把两个长度为 4 的部分耦合。
  • 继续下去,直到长度为 N 的整体被耦合完成。

每一层只做异或和连线,所以总复杂度是:

O(N\log N)

这也是 Polar 编码很适合实现的原因之一:它的生成矩阵虽然是 N\times N,但真正编码时不需要做普通矩阵乘法。只要按照蝶形图逐层更新,就可以完成同样的线性变换。

更形式化地说,蝶形图是在执行同一个矩阵乘法:

\underline{c}_0^{N-1}=\underline{u}_0^{N-1}\mathbf{F}_2^{\otimes n}

如果采用 bit-reversal 约定,则只是多了输入重排:

\underline{c}_0^{N-1}=\underline{u}_0^{N-1}\mathbf{B}_N\mathbf{F}_2^{\otimes n}

因此看 Polar 编码图时,不要把“矩阵形式”和“蝶形形式”当成两套理论。它们描述的是同一个线性编码器:矩阵形式适合推导,蝶形形式适合实现。

容易混淆的几个点

第一,不要把普通加法和二元域加法混在一起。本文所有比特之间的相加都写成 \oplus,表示 mod 2 加法。

第二,不要把 \underline{c}\underline{x} 混用。本文的 \underline{c}_0^{N-1} 是二元码字向量;如果后面进入 BPSK 调制,才会用 \underline{x}_0^{N-1} 表示实数发送符号。

第三,不要把 \mathbf{G}_N^{\mathrm{nat}}\mathbf{G}_N^{\mathrm{br}} 当成完全相同的矩阵。它们共享同一个二阶核和蝶形核心,但输入索引约定不同。

第四,不要把编码端的“耦合”提前等同于信道端的“分裂”。二阶核把输入比特耦合起来;信道 combining / splitting 是下一阶段从接收观测和逐位判决角度定义的东西。

小结

这一篇把 Polar 编码的结构根基搭起来了。

最小单元是二阶核 \mathbf{F}_2,它把 (u_0,u_1) 变成 (u_0\oplus u_1,u_1)。把这个核做 Kronecker 幂,就得到自然顺序生成矩阵 \mathbf{G}_N^{\mathrm{nat}}=\mathbf{F}_2^{\otimes n}。如果采用 Arikan 原始论文里常见的 bit-reversal 约定,在本文行向量写法下则写作 \mathbf{G}_N^{\mathrm{br}}=\mathbf{B}_N\mathbf{F}_2^{\otimes n}

矩阵形式和蝶形图不是两套东西。矩阵形式说明线性变换是什么,蝶形图说明怎样用 O(N\log N) 次结构化异或把它算出来。

下一篇我们会把这些符号真正放进一个完整的短码长例子里:给定 NK、信息位和冻结位,手算一遍 Polar 编码全过程。

参考

  • E. Arikan, “Channel polarization: A method for constructing capacity-achieving codes for symmetric binary-input memoryless channels,” IEEE Trans. Inf. Theory, vol. 55, no. 7, pp. 3051-3073, Jul. 2009, doi: 10.1109/TIT.2009.2021379.
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇