SC算法及matlab仿真
1、内容目录
- 开篇1-内容介绍&参考文献
- 概述2-什么是极化码?
- 原理3-Arikan原版论文学习总结
- 编码算法4-巴氏参数、GA算法以及matlab仿真
- 译码算法5-SC算法及matlab仿真
- 译码算法6-SCL、CA-SCL及matlab仿真
2、引言
上一章叙述了极化码的编码过程和针对不同信道的经典构造算法,本章对极化码的几种不同的译码算法进行详细介绍。首先介绍的是SC译码算法,该译码算法是E.Arikan针对极化码的递归编码结构所提出的,可以很好的反映编码过程,是下面几种译码的基础,需要详细介绍和研究。之后介绍目前使用范围最广的SCL译码算法,该算法原理是基于SC译码算法的,增加了译码器列表这一个参数,可以解决SC译码器的一些不足。最后介绍CA-SCL译码算法,这种算法是针对SCL译码算法,在纠错性能上的一个改进,即利用CRC辅助译码,提高对译码结果的纠错性能。接下来,就对这三种算法进行详细介绍。
3、串行抵消(SC)译码算法
3.1、算法介绍
该译码算法是极化码的经典译码算法之一。对于长度为N = 2 n 2^n 2n的极化码,SC译码器接收到的信号为 y 1 N y_1^N y1N,该信号是发送端发出的经BPSK调制的信息比特,并且通过高斯信道加噪之后的信号。译码时首先利用接收信号 y 1 N y_1^N y1N译码 u 1 u_1 u1,然后再利用接收信号和 u 1 u_1 u1的译码结果(这里假设 u 1 u_1 u1译码正确)继续译码 u 2 u_2 u2,之后利用接收信号和 u 1 u_1 u1, u 2 u_2 u2,…, u i u_i ui − _- − 1 _1 1 的译码结果去译码 u i u_i ui,直到译码 u N u_N uN为止。在本节中,我们先介绍长度为2的极化码的SC译码,然后推广至长度为 2 n 2^n 2n的极化码。
3.2、长度为2的极化码的SC译码过程
3.2.1、数学计算过程
让我们来考虑一个联合分布Pr(u1,u2,y1,y2),这些随机变量的关系为:u1,u2是生成概率均为1/2的(0,1)变量,x1,x2表示经过极化码编码后的比特,则有如下等式:
它们经过二进制输入无记忆离散信道W的传输,分别形成接收信号y1,y2。现在想用观测值 y1,y2 估计原信息比特的值u1,u2。
用条件概率Pr (y1y2|u1)作为判决u1的依据:如果Pr (y1y2|u1=0)≥Pr (y1y2|u1=1),则u1判决为0;反之,将u1判决为1。结合条件概率的含义,这一点十分好理解。那么如何计算该条件概率呢?
计算过程如下:
上式中之所以得到(a)式,是因为对于任意u1,u2,Pr(u1)=0.5, Pr(u1u2)=0.25,且发送u1,u2与发送x1,x2的概率一一对应。得到等号(b)处是因为W是无记忆信道,即从信道发出x1,对应收到的信号则对应y1,同理x2与y2对应。因此可以根据以上结果,来计算该条件概率的对数似然比为:
上式在各个文献中常被称为 f 运算,其中L1和L2的表达式如下所示,他们分别表示接收信号y1和y2的LLR,若我们能计算得到L1和L2的值,则可以计算得到上式的对数似然比的值。如何计算呢?
二元输入AWGN信道是连续输出信道,如果使用BPSK调制,即s=1-2x,其中x∈{0,1},s∈{-1,1},s是发送的调制信号,y=s + n是接收信号,其中n是均值为0,方差为
δ
2
δ^2
δ2的高斯加性白噪声,则Pr(
y
i
y_i
yi)是均值为{-1,+1},方差为
δ
2
δ^2
δ2的函数,故
y
i
y_i
yi的对数似然比的形式为,将该计算公式命名为 2.2.1式 :
由以上公式可得,当我们已知接收的信号以及信道的噪声方差时,便可计算每一个接收信号的对数似然比,这一点是极化码译码的起点,理解这一点很重要。
由于f运算的计算非常复杂,同时包括指数和对数的运算,不利于硬件实现,故常常使用它的近似式,其中sign表示取符号位,将该式命名为 2.2.2式 :
到此,基本的计算公式都已经介绍完毕。下面举例来说明如何利用以上公式来进行译码。
3.2.2、译码举例
首先完成u1的译码:
当我们接收到y1和y2,就结合信道噪声方差,利用2.2.1式计算y1,y2对应的对数似然比L1,L2。再把L1和L2代入2.2.2式中进行计算得到接收信号条件概率的对数似然比 。如果u1是冻结比特,直接把它判决为预设的值;否则,如果计算结果≥0,说明Pr(y1y2|u1=0)≥Pr(y1y2|u1=1),那么将u1判决为0;反之,u1判决为1。
下面再开始判决u2的值。我们利用接收信号y1、y2与u1的值来判决u2,考虑条件概率为Pr(y1y2u1|u2),它的计算过程与计算Pr (y1y2|u1)类似,读者可自行推演,可得:
上式中代入前面判决所得到的u1的值,可求得对数似然比为,该式最后的结果在文献中被称为 g运算,该结果的推导需结合前面的推导结果才能得到正确的结果,若读者推导有困难,可私信我为你解答:
得到了该结果后,我们就可以对u2进行译码:
在第一步中获得L1,L2,u1后,代入式g运算的式子中,得到u2对应的条件概率的对数似然比的值。若u2是冻结比特,直接把它判决为预设值;若计算结果≥0,说明 Pr(y1y2u1|u2=0)≥Pr(y1y2u1|u2=1),将u2判决为0,反之,u2判决为1。
通过两步操作,我们已经完成了长度为2的极化码的译码工作。
3.3、长度为 2 n 2^n 2n的极化码的SC译码过程
通过上一章极化码的编码过程可知,长度为
2
n
2^n
2n的极化码是用n
2
n
2^n
2n
−
^-
−
1
^1
1个2*2的基本极化码模块按照一定规则拼凑成的,于是可得,长度为
2
n
2^n
2n的极化码的SC译码也是用n
2
n
2^n
2n
−
^-
−
1
^1
1个2*2基本极化码模块按照一定规则拼凑起来的。下面,以一个长度N=8的极化码为例,来进行极化码译码演示。
(高能预警:下面的内容需要在充分理解2.2节内容的基础上再来阅读)
例:先设置传输基本参数:AWGN信道,信噪比Eb/N0=4dB;
码长N=8,信息比特长度K=4,码率R=K/N=0.5;
信息位集合A={4,6,7,8},冻结比特全部取0;
四个信息比特为(1,1,1,1),则u18=(00010111),编码后 =(01101001)。
x18进行BPSK调制s=1-2x后得s18=(1,-1,-1,1,-1,1,1,-1)。
调制序列通过高斯信道后得到接收序列y18=(-0.4,-0.5,-0.8,0.2,-1.3,1.2,3.3,0.7)。
计算对数似然比 =(-2.0,-2.5,-4.0,1.0,-6.5,6.0,16.6,3.5)。
接下来开始译码工作(所有标红的元素都是对应步骤所计算得到的结果):
1、第一步如图所示,第4级所有元素为接收信号的LLR值,对第3级所有22模块执行f运算,得到第3级对应的LLR值。
2、第二步如图所示,对第2级前两个22模块运行f函数;
3、第三步如图所示,第1级第一个22模块运行f函数,判决u1。由于u1是冻结比特,故直接判决为0。
4、第四步如图4所示,第1级第一个22模块运行g函数,判决u2。由于u2是冻结比特,直接判决为0。
5、第五步如图所示,第2级前两个22模块运行g函数。
6、第六步如图所示,第1级第2个22模块运行f函数,判决u3。由于u3是冻结比特,直接判决为0。
7、第七步如图所示,第1级第2个22模块运行g函数,判决u4。由于u4是信息比特,其L值为-3.5,小于零,故判决u4=1。
8、第八步如图所示,第3级所有22模块运行g函数
9、第九步如图所示,第2级下两个22模块运行f函数。
10、第十步如图所示,第1级第3个22模块运行f函数,判决u5。由于u5是冻结比特,故直接将其判决为0。
11、第十一步如图所示,第1级第3个模块运行g函数,判决u6。由于u6是信息比特,其对应的LLR值小于0,故判决u6=1。
12、第十二步如图所示,第2级下两个22模块运行g函数。
13、第十三步如图所示,第1级第4个22模块运行f函数,判决u7。由于u7是信息比特,其对应的LLR值小于0,故u7判决为1。
14、第十四步如图所示,第1级第4个2*2模块运行g函数,判决u8。由于u8是信息比特,其对应的LLR值小于0,故u8判决为1。
通过以上十四步的SC译码步骤,我们最终获得了译码结果为(00010111),该结果与发送的信息比特是相同的,译码正确。经过该例的SC译码推算,可以获得更加一般的SC译码步骤,无非就是将上述译码表扩展为N*(log
2
_2
2N+1)的一个矩阵,按照上述流程一步步推算,最终译码得出所有的结果。
4、SC译码算法matlab仿真代码
在这里我仅提供SC译码算法的代码,供大家理解,若要运行该函数,需要搭配极化码编码算法来使用,完整的项目代码我将会在之后上传至CSDN上。
function polar_info_esti = SC_decoder(llr,K, frozen_bits, lambda_offset, llr_layer_vec, bit_layer_vec)
N = length(llr);%llr refers to channel LLR.
n = log2(N);
P = zeros(N - 1, 1);%channel llr is not include in P.
C = zeros(N - 1, 2);%C stores internal bit values
polar_info_esti = zeros(K, 1);
cnt_K = 1;
for phi = 0 : N - 1
switch phi
case 0%for decoding u_1
index_1 = lambda_offset(n);
for beta = 0 : index_1 - 1%use llr vector
P(beta + index_1) = sign(llr(beta + 1)) * sign(llr(beta + 1 + index_1)) * min(abs(llr(beta + 1)), abs(llr(beta + 1 + index_1)));
end
for i_layer = n - 2 : -1 : 0%use P vector
index_1 = lambda_offset(i_layer + 1);
index_2 = lambda_offset(i_layer + 2);
for beta = index_1 : index_2 - 1
P(beta) = sign(P(beta + index_1)) * sign(P(beta + index_2)) * min(abs(P(beta + index_1)), abs(P(beta + index_2)));
end
end
case N/2%for deocding u_{N/2 + 1}
index_1 = lambda_offset(n);
for beta = 0 : index_1 - 1%use llr vector. g function.
P(beta + index_1) = (1 - 2 * C(beta + index_1, 1)) * llr(beta + 1) + llr(beta + 1 + index_1);
end
for i_layer = n - 2 : -1 : 0%use P vector. f function
index_1 = lambda_offset(i_layer + 1);
index_2 = lambda_offset(i_layer + 2);
for beta = index_1 : index_2 - 1
P(beta) = sign(P(beta + index_1)) * sign(P(beta + index_2)) * min(abs(P(beta + index_1)), abs(P(beta + index_2)));
end
end
otherwise
llr_layer = llr_layer_vec(phi + 1);
index_1 = lambda_offset(llr_layer + 1);
index_2 = lambda_offset(llr_layer + 2);
for beta = index_1 : index_2 - 1%g function is first implemented.
P(beta) = (1 - 2 * C(beta, 1)) * P(beta + index_1) + P(beta + index_2);
end
for i_layer = llr_layer - 1 : -1 : 0%then f function is implemented.
index_1 = lambda_offset(i_layer + 1);
index_2 = lambda_offset(i_layer + 2);
for beta = index_1 : index_2 - 1
P(beta) = sign(P(beta + index_1)) * sign(P(beta + index_2)) * min(abs(P(beta + index_1)), abs(P(beta + index_2)));
end
end
end
phi_mod_2 = mod(phi, 2);
if frozen_bits(phi + 1) == 1%frozen bit
C(1, 1 + phi_mod_2) = 0;
else%information bit
C(1, 1 + phi_mod_2) = P(1) < 0;%store internal bit values
polar_info_esti(cnt_K) = P(1) < 0;
cnt_K = cnt_K + 1;
end
if phi_mod_2 == 1 && phi ~= N - 1
bit_layer = bit_layer_vec(phi + 1);
for i_layer = 0 : bit_layer - 1%give values to the 2nd column of C
index_1 = lambda_offset(i_layer + 1);
index_2 = lambda_offset(i_layer + 2);
for beta = index_1 : index_2 - 1
C(beta + index_1, 2) = mod(C(beta, 1) + C(beta, 2), 2);
C(beta + index_2, 2) = C(beta, 2);
end
end
index_1 = lambda_offset(bit_layer + 1);
index_2 = lambda_offset(bit_layer + 2);
for beta = index_1 : index_2 - 1%give values to the 1st column of C
C(beta + index_1, 1) = mod(C(beta, 1) + C(beta, 2), 2);
C(beta + index_2, 1) = C(beta, 2);
end
end
end
end
当运行完整的项目代码时,将会有如下图所示效果:
5、总结
在本节中,我们主要介绍了极化码三种常见译码算法中的最基础,也是最经典的一种译码算法—串行译码(SC)。这一节有两大难点:
第一点是推导与理解SC译码的数学推导公式,这是该算法的基础,若大家理解并可以自己推导出文中提到的所有公式,相信对你理解后面的内容将十分有帮助。
第二点如何将推导出的公式,应用到实际的译码过程中,长度为2的极化码译码与长度为8的极化码译码,对于其译码过程的理解难度是指数级增长的,但是如果大家跟着我的推导思路走一遍,理解我对每个环节的描述,相信到最后也不会特别的难。
最后,给大家提供了SC译码算法的matlab仿真代码,读者可以根据前面的内容,去理解代码所表示的意思。但是,要运行该代码,还需要结合我的整个系列的文章,才能真正将该极化码编码和译码的过程演示出来。
相信通过本节的学习,大家可以对极化码的SC译码算法过程有一个很直观的理解和认识,在下一节中,我会为各位读者介绍其余的两种极化码译码算法SCL与CA-SCL。
欢迎大家与我进行交流,新人博主写帖子不易,如果你觉得对你有帮助,多多点赞分享关注打赏,给我更多创作动力。祝大家都能有所学,有所获,加油!
闲言:由于去年开始工作后,比较忙碌,一直没有时间和精力去更新这个系列的帖子,停滞了大概半年左右没有更新。近期,有很多读者私信我催更,说我写的内容有帮助到他们理解极化码及其算法是怎么一回事,我十分开心,因为这就是我当初写这个系列的帖子的初衷。非常感谢大家的支持,因此我打算在工作之余忙里偷闲,继续更新这个系列的帖子,争取把这个系列完结,给大家一个交代,希望大家继续给我支持。有任何内容上的问题可以私信或者评论,我看到一定回复。