规则LDPC和不规则LDPC译码算法MATLAB仿真
up目录
一、理论基础
LDPC(Low-Density Parity-Check)编码是一种纠错码技术,分为规则LDPC编码和不规则LDPC编码两种类型,它们在纠错性能和结构上有所不同。下面详细介绍这两种类型的LDPC编码:
规则LDPC编码: 规则LDPC编码的特点是每个校验节点和信息节点连接的数量都是固定的,因此在整个编码矩阵中,节点的度数是相同的。这种编码的结构相对简单,通常采用常见的几何结构,如正则图、正则矩阵等。规则LDPC编码的校验矩阵通常具有良好的解码性能和较低的复杂度。
不规则LDPC编码: 不规则LDPC编码的特点是校验节点和信息节点之间的连接数量是可变的,导致整个编码矩阵中节点的度数不同。不规则LDPC编码的设计更加灵活,可以根据需要优化纠错性能和译码复杂度。不规则LDPC编码在某些情况下可以获得更好的性能,特别是在高信噪比下。
编码和译码过程: LDPC编码过程是基于稀疏校验矩阵的线性运算,将输入数据与校验位进行异或运算,生成编码数据。LDPC译码过程是基于图论和迭代译码算法,如Belief Propagation(BP)算法或Sum-Product Algorithm(SPA)等,通过在校验节点和信息节点之间传递信息,进行迭代反馈,逐步纠正和恢复接收到的数据。
性能比较:
- 规则LDPC编码具有结构简单、解码性能稳定、硬件实现方便等特点。它在相对低的迭代次数下就能获得良好的纠错性能。
- 不规则LDPC编码具有更好的纠错性能潜力,特别是在高信噪比下。它可以通过适当的设计来优化解码性能,但也可能在一些情况下需要更多的迭代次数来达到最佳性能。
总之,规则LDPC编码和不规则LDPC编码在结构和性能上有一些不同,可以根据应用需求和性能要求来选择合适的编码类型。不规则LDPC编码通常能够获得更好的性能,但相应地可能需要更高的计算复杂度。
LDPC码是根据低密度稀疏校验矩阵H来构造的。假设需要发送一组信息T{t_1,t_2,⋯,t_n},在发送前先使用生成矩阵G做线性变换,得到发送码字S=GTT,而校验矩阵H与生成矩阵G满足的关系为HGT=0,可以看到发送的码字是一组线性校验方程的解。
LDPC码与分组码的最大区别:在于译码方式的不同。LDPC码采用迭代译码,校验矩阵H使用Tanner图表示。
LDPC码的核心:围绕校验矩阵Hm×n的特性进行设计。
LDPC码本身的结构引入了交织(interleaving)。
不同LDPC码的构造方法都是为了实现如下的目标:① 增大Girth值;② 减小编码复杂度。
根据H构造不同,分成了LDPC规则码和LDPC不规则码。直观地说,稀疏矩阵每行每列1的个数固定的LDPC码称为LDPC规则码。稀疏矩阵每行每列1的个数或者行和列的重量不固定的LDPC码称为LDPC不规则码。根据LDPC的码元是否为二进制,分成了二元LDPC码和高阶域LDPC码。高阶域LDPC码定义在GF(q)上,其中q= 2m。
LDPC译码采用BP译码算法,该方法通过校验节点向变量节点传递信息以及变量节点向校验节点传递信息的方式,并经过迭代,得到近似ML的译码结果。
这里说说自己的理解,LDPC编码的时候发送的原始比特会存在于多个校验方程中,一个校验方程中也会包含多个比特,这样就可以互相校验。对于某个校验方程,其他比特为1的个数为偶数,为使得校验结果为0,则本比特位置为0,反之则为1。而我们需要计算的是其他比特为偶数个1和奇数个1的概率。对于某个比特,由于其存在于多个校验方程中,因此,其他校验方程是可以给出本比特取值的概率的。在迭代过程中就是反复利用以上关系更新各节点的概率,最后得到译码结果的。
根据H[c w]T=0以及上述矩阵结构,可以将w写成[p1 p2]两部分组成。其中p1的长度为4,p2的长度为42。那么式子H[s w]T=0可改写成,此处为便于区分用s指代以上的c。
可求得p1和p2的结果如下:
那么问题的关键是如何计算B-1。协议中Graph=1的情况下,B矩阵的形式如下:
以上1表示对单位阵循环右移,0表示单位阵,X表示全0阵,那么根据逆矩阵的定义即可求得B-1,如下式:
求取上述矩阵中的x1~x16即可得到逆矩阵。由于计算是定义在GF(2)上的,因此两个相同的矩阵相加为0,这样就能简便地计算出结果。另外,需要注意的是,在译码的时候,需要人为地在译码结果前面加上2Zc长度的0来补齐长度。
二、核心程序
function x_hat = func_Dec(y,sigma,H,max_iter)
f1 = 1./(1+exp(-2*y/(sigma^2)));
f0 = 1-f1;
[m,n] = size(H);
if m>n
H = H';
[m,n] = size(H);
end
%如果不是稀疏矩阵,将H变为稀疏矩阵
if ~issparse(H)
[ii,jj,sH] = find(H);
H = sparse(ii,jj,sH,m,n);
end
%初始化
[ii,jj] = find(H);
%将非零元素标上
indx = sub2ind(size(H),ii,jj);
q0 = H * spdiags(f0(:),0,n,n);
sq0 = full(q0(indx));
sff0 = sq0;
q1 = H * spdiags(f1(:),0,n,n);
sq1 = full(q1(indx));
sff1 = sq1;
k=0;
success = 0;
while ((success == 0) & (k < max_iter)),
k = k+1;
%若先验概率一样的话,令sdq为一个很小很小的数
sdq = sq0 - sq1;
sdq(find(sdq==0)) = 1e-20;
%用概率差sdq构成m*n的稀疏矩阵
dq = sparse(ii,jj,sdq,m,n);
%将dq在对数域求和,即将dq相乘,构成数组
Pdq_v = full(real(exp(sum(spfun('log',dq),2))));
%更新了rij
Pdq = spdiags(Pdq_v(:),0,m,m) * H;
sPdq = full(Pdq(indx));
sr0 = (1+sPdq./sdq)./2;
sr0(find(abs(sr0) < 1e-20)) = 1e-20;%将每个元素的rij都归一化,更新rij。概率译码的第一步完成
sr1 = (1-sPdq./sdq)./2;
sr1(find(abs(sr1) < 1e-20)) = 1e-20;%若比值非常小,则设为1e-20
%将更新完的rij存入对应的位置,方便后面要用
r0 = sparse(ii,jj,sr0,m,n);
r1 = sparse(ii,jj,sr1,m,n);
Pr0_v = full(real(exp(sum(spfun('log',r0),1))));
Pr0 = H * spdiags(Pr0_v(:),0,n,n);
sPr0 = full(Pr0(indx));
Q0 = full(sum(sparse(ii,jj,sPr0.*sff0,m,n),1))';
sq0 = sPr0.*sff0./sr0;
Pr1_v = full(real(exp(sum(spfun('log',r1),1))));
Pr1 = H * spdiags(Pr1_v(:),0,n,n);
sPr1 = full(Pr1(indx));
Q1 = full(sum(sparse(ii,jj,sPr1.*sff1,m,n),1))';
sq1 = sPr1.*sff1./sr1;
sqq = sq0+sq1;
sq0 = sq0./sqq;
sq1 = sq1./sqq;
%伪后验概率
QQ = Q0+Q1;
Q0 = Q0./QQ;
Q1 = Q1./QQ;
%判决输出
x_hat = (sign(Q1-Q0)+1)/2;
if rem(H*x_hat,2) == 0, success = 1; end
end
up102
三、测试结果
在matlab2021a中仿真得到如下的效果: