LDPC
LDPC码:低密度奇偶校验码(Low Density Parity Check Code),最初由 Gallager 提出,后被Mackay、Spielman、Wiberg 等人重新发现。
LDPC码可以从稀疏二部图(sparse bipartite graphs)
G
=
(
{
M
,
C
}
,
E
)
\mathbb G = (\{\mathbb M,\mathbb C\},\mathbb E)
G=({M,C},E)中得到:图的一边的
n
n
n个点叫做消息点(message nodes)
M
\mathbb M
M,另一边的
r
r
r个点叫做校验点(check nodes)
C
\mathbb C
C,两部之间有稀疏的边
E
\mathbb E
E。LDPC码的码字集合为:
C
=
{
c
∈
G
F
(
2
)
n
:
∀
i
=
1
,
⋯
,
r
,
∑
(
M
j
,
C
i
)
∈
E
c
j
=
0
}
\mathscr C = \{ c \in GF(2)^n: \forall i=1,\cdots,r, \sum_{(\mathbb M_j,\mathbb C_i) \in \mathbb E} c_j = 0 \}
C={c∈GF(2)n:∀i=1,⋯,r,(Mj,Ci)∈E∑cj=0}
如果二部图是正则的(regular,同一部点的度数相同),那么得到的LDPC码叫做正则LDPC码;否则叫做非正则的(irregular)。任意线性码都对应某个二部图,但不一定稀疏。LDPC码的稀疏性导致解码复杂度是线性的(一般线性码的解码复杂度是指数级,属于
N
P
−
h
a
r
d
NP-hard
NP−hard类)。
如果将二部图用连接矩阵
H
H
H来表示,
H
∈
G
F
(
2
)
r
×
n
H \in GF(2)^{r \times n}
H∈GF(2)r×n,其中
H
i
j
=
1
⟺
(
M
j
,
C
i
)
∈
E
H_{ij}=1 \iff (\mathbb M_j,\mathbb C_i) \in \mathbb E
Hij=1⟺(Mj,Ci)∈E
于是我们就获得了LDPC码的校验矩阵。正则码校验矩阵
H
H
H的每一行的行重都相等,同时每一列的列重也都相等。可以计算
H
H
H对应的生成矩阵
G
G
G用于编码。校验矩阵
H
H
H包含稀疏二部图结构,可用于快速纠错。注意,不要对
H
H
H做变换,否则就变成一般解码问题了。
在译码算法里要求信息的独立性,如果图 G \mathbb G G中的最小圈长为 g i r t h = 2 L girth=2L girth=2L,那么算法只在前 L L L轮迭代满足独立性假设。因此如果存在小圈,那么算法中从某节点发出的消息最终会影响其本身,严重影响译码性能。LDPC码的稀疏性,使得出现小圈的可能性减小,不过在设计中还是要仔细删除小圈。
二部图中的圈,可以直接在连接矩阵 H H H中看到:从某个 1 1 1出发,依次水平移动、竖直移动到下一个 1 1 1,最终回到起始点。对于 4 4 4长的圈,就是一个矩形,它的四个顶点位置都是 H H H里的 1 1 1。
QC-LDPC
实际运用中的码长 n n n往往非常大,且随机的构造方法不利于硬件实现。因此可以用代数方法精确地构造LDPC校验矩阵,其性能分析更加容易,同时译码也更方便。这就是拟循环LDPC码。
令
e
i
∈
G
F
(
2
)
L
e_i \in GF(2)^L
ei∈GF(2)L表示第
i
i
i位是
1
1
1的单位行向量,定义循环子矩阵:
I
1
=
[
e
2
e
3
⋮
e
n
e
1
]
∈
G
F
(
2
)
L
×
L
I_1 = \begin{bmatrix} e_2\\ e_3\\ \vdots\\ e_n\\ e_1\\ \end{bmatrix} \in GF(2)^{L \times L}
I1=⎣⎢⎢⎢⎢⎢⎡e2e3⋮ene1⎦⎥⎥⎥⎥⎥⎤∈GF(2)L×L
定义母矩阵
H
b
=
(
h
i
j
)
∈
G
F
(
2
)
r
×
n
H_b = (h_{ij}) \in GF(2)^{r \times n}
Hb=(hij)∈GF(2)r×n以及移位次数矩阵
P
=
(
p
i
j
)
∈
Z
r
×
n
P = (p_{ij}) \in \mathbb Z^{r \times n}
P=(pij)∈Zr×n,构造校验矩阵:
H
=
[
h
11
I
1
p
11
h
12
I
1
p
12
⋯
h
1
n
I
1
p
1
n
h
21
I
1
p
21
h
22
I
1
p
22
⋯
h
2
n
I
1
p
2
n
⋮
h
r
1
I
1
p
r
1
h
r
2
I
1
p
r
2
⋯
h
r
n
I
1
p
r
n
]
∈
G
F
(
2
)
r
L
×
n
L
H = \begin{bmatrix} h_{11}I_1^{p_{11}} & h_{12}I_1^{p_{12}} & \cdots & h_{1n}I_1^{p_{1n}}\\ h_{21}I_1^{p_{21}} & h_{22}I_1^{p_{22}} & \cdots & h_{2n}I_1^{p_{2n}}\\ \vdots\\ h_{r1}I_1^{p_{r1}} & h_{r2}I_1^{p_{r2}} & \cdots & h_{rn}I_1^{p_{rn}}\\ \end{bmatrix} \in GF(2)^{rL \times nL}
H=⎣⎢⎢⎢⎡h11I1p11h21I1p21⋮hr1I1pr1h12I1p12h22I1p22hr2I1pr2⋯⋯⋯h1nI1p1nh2nI1p2nhrnI1prn⎦⎥⎥⎥⎤∈GF(2)rL×nL
其中的
h
i
j
I
1
p
i
j
h_{ij}I_1^{p_{ij}}
hijI1pij,当
h
i
j
=
0
h_{ij}=0
hij=0时是零矩阵,当
h
i
j
=
1
h_{ij}=1
hij=1时是循环右移
p
i
j
p_{ij}
pij次的单位矩阵。如果令
h
i
j
=
0
h_{ij}=0
hij=0时对应的
p
i
j
=
∞
p_{ij}=\infty
pij=∞,那么就只需要存储矩阵
P
P
P,不必存储稀疏矩阵
H
H
H中的
1
1
1的位置。
在母矩阵 H b H_b Hb的基础上,需要使用各种算法,仔细地确定 P P P的值,来避免二部图中出现小圈。
译码算法
Message-Passing算法
消息传递算法是一种迭代算法,每轮迭代中在二部图的消息节点和校验节点之间有着消息的传递。从消息节点发出的消息,是关于“这个消息节点的值、以及它的邻居校验节点发给它的消息”的函数值(消息节点认为这个比特应该是什么);反之亦然(校验节点认为这个比特应该是什么)。经过多轮迭代,收敛到一个满足 c H T = 0 cH^T=0 cHT=0的码字;若无法收敛,则译码失败。重要的是,消息节点 m m m发送给校验节点 c c c的消息中,不应包含在前一轮里从 c c c返回到到 m m m的消息;反之亦然。
它的一个子类算法:Belief Propagation算法,二部图之间传递的消息是置信度(Belief)。用于在BEC信道(the binary erasure channel,擦除信道)上的LDPC译码。要使用似然函数 L ( x ) = P r [ x = 0 ] / P r [ x = 1 ] L(x) = Pr[x=0]/Pr[x=1] L(x)=Pr[x=0]/Pr[x=1],具体如何计算本文暂且搁置(作者没仔细看( ̄︶ ̄*)),以后需要时再说。
Bit-Flipping算法
这是一种硬判决的译码方案(hard decision decoding),即二部图中传输的消息是 0 , 1 0,1 0,1比特值,而非概率。用于在BSC信道(the binary symmetric channel ,对称信道)上的LDPC译码。
- 在每一轮迭代中,每个消息节点 v v v将自己的比特值发送给所有的邻居校验节点
- 然后,邻居校验节点计算除了 v v v以外的邻居消息节点发送的比特值的加和,发送给节点 v v v
- 如果消息节点 v v v接收到的所有返回值都是相同的比特 b b b,那么就设置自己的比特值为 b b b,否则保持自己的比特值
- 判断 c ′ H T = 0 c'H^T=0 c′HT=0是否满足,或者是否达到预设的最大迭代轮数。否则,继续迭代。
上述算法虽然很简单,但译码效果较差,且容易陷入死循环。改进版本:对第 i i i轮迭代中度(degree)为 j j j的点的设置阈值 b i j b_{ij} bij,只要有超过阈值的邻居校验节点的返回值相同,那么就修改自己的比特;其他的过程不变。这个改进版本 slightly more powerful,如果设置 b i j = j − 1 b_{ij}=j-1 bij=j−1就退化为原始版本。一种方案是设置 b i j = j / 2 b_{ij}=j/2 bij=j/2,简单地少数服从多数。
Sum-Product算法
将BP算法里的概率信息都使用对数条件似然函数 ln L ( x ) \ln L(x) lnL(x),于是乘法运算就变成了加法运算,解码速度大幅提升。