LDPC编码译码方法研究及误码率实现

1.1  LDPC码介绍

    低密度校验码(LDPC码)是一种前向纠错码,它最初在 1962年由麻省理工学院的Galfager在其博士论文中提出。那时候,世界才刚刚脱离真空管,进入第一代晶体管时代,实验仿真所要求的的计算能力并不发达,所以LDPC码无与伦比的潜能没能引起人们的重视,而被长久地忽视了35年。同一时期,主流的前向纠错技

术是高度结构化的代数分组码和卷积码。尽管上述这些纠错码技术在实际中获得了巨大的成功,但是它们的性能却远没有达到Shalmon在其 1948年发表的开创性论文中所指出的理论可达限。到了20实际80年代末,经过几十年的尝试,学者们已经接受了这个理论与实际之间无法逾越的鸿沟。

    编码学研究经过了相当的一段沉寂之后,被“turbo码”的出现彻底唤醒。turbo码由B~u,Glavieux和Thitimajshima在1993年提出,它彻底颠覆了所有人们认为成功的纠错码所要具备的因素:turbo码涉及非常少的代数,运用迭代,分布的算法,专注于平均(而非最差)性能,同时仰赖从信道中获取的软(或者似然)信

息。一夜之间,在复杂度可控的译码器的协助下,达到Shannon限所要越过的鸿沟已不复存在。

LDPC码不仅蕴含有很高的理论价值,而且已经为卫星数字视频广播标准和长途光通信标准所采纳,还极有可能被吸收入IEEE无线局域网标准中,人们还正在考虑把LDPC码应用到第四代移动电话系统的长期发展规划中。

1.2   LDPC码的特点

LDPC码是一种分组码,其校验矩阵只含有很少量非零元素。正是校验矩阵H的这种稀疏性,保证了译码复杂度和最小码距都只随码长呈现线性增加。

除了校验矩阵H是稀疏矩阵外,LDPC码本身与任何其它的分组码并无二致。其实如果现有的分组码可以被稀疏矩阵所表达,那么用于LDPC码的迭代译码算法也可以成功的移植到它身上。然而,一般来说,为现有的分组码找到一个稀疏矩阵并不实际。不同的是,LDPC码的设计是以构造一个校验矩阵开始的,然后才通过它确定一个生成矩阵进行后续编码。而LDPC的编码就是本论文所要讨论的主体内容。

译码方法是LDPC码与经典的分组码之间的最大区别。经典的分组码一般是用ML类的译码算法进行译码的,所以它们一般码长较小,并通过代数设计以减低译码工作的复杂度。但是LDPC码码长较长,并通过其校验矩阵H的图像表达而进行迭代译码,所以它的设计以校验矩阵H的特性为核心考虑之一。

目前的研究均表明LDPC码是信道编码中纠错能力最强的一种码,而且由于其译码器结构简单,可以用较少的资源消耗获得极高的吞吐量,因此应用前景相当广泛。

1.3  LDPC 码的历史和现状

LDPC 码于 1962 年由 Gallager 提出,因此它也被称为 Gallager 码,它是Turbo 码之外的另一种逼近香农极限的码字。虽然 Gallager 证明了 LDPC 码是渐进好码,但是受限于当时的计算能力,LDPC 码一度被认为是一种无法实现的信道编码方式,在很长一段时间内没有得到人们的重视。1981 年随着 Tanner 著作的出现,LDPC 码可以用图论的角度进行新的理解和诠释,然而不幸的是这一理论成果依然没有得到人们的重视。知道 90 年代初,随着 Turbo 码的出现,这才引发了学者们对于 LDPC 码研究的热情。Mackay和 Neal 在上世纪九十年代利用随机构造的 Tanner 图研究了 LDPC 码的性能,采用 Belief Propagation(BP 算法)译码算法的 LDPC 码字具有与 Turbo 码相似的译码性能,长的 LDPC 码在 BP 译码算法下性能甚至超过了 Turbo 码,它可以达到距离香农限只有 0.1dB 的距离。这个发现是的 LDPC 码比 Turbo 码在需要高度可靠性的通信和存储系统纠错中更具有竞争力。从此以后,有关 LDPC码的文献大量涌现。

2.1 LDPC码的编码方法

 

2.1.1  LDPC码的标准编码方法

    设LDPC码的码长为n,信息码长度为k,校验码长度为m=n-k.已经讨论过,校验矩阵H经过高斯消元可以化为:

H=[H  Im*m]

    其中H:是尺寸为mxk的二进制矩阵,可以得到:Imxm是尺寸为m、m的单位矩阵。于是可以得到:

G=[Ik*k  H1]

    通过生成矩阵G就可以进行编码。以下用一个例子说明如何由校验矩阵H得到生成矩阵G.

2.1.2  LU分解编码算法

  首先推导出根据校验矩阵直接编码的等式。将尺寸为mxn校验矩阵H写成如下形式:

H=[H1,H2]

其中H1的尺寸为M*K,H2的尺寸为m* m ,设编码后的码字行向量为x,它的长度为n,把它写成如下形式:

            c=[s p]

其中s是信息码行向量,长度为k,p为校验码行向量,长度为m.根据校验等式有H×CT=O

上式展开得:

展开该矩阵方程,并考虑到运算是在GF(2)中进行,得到:

p·H2T=S·HT                    (2.1)

如果校验矩阵H是非奇异,则HZ满秩,所以有:

p=s·HT·H T                     (2.2)

  式 (2.1)和式 (2.2)就是不通过生成矩阵而直接由校验矩阵进行编码的等式,一切只依赖校验矩阵的编码都是通过这两个式子实现的。

从式(2.1)可以看出,一般来说,只要校验矩阵具有下三角结构,它总是能够通过迭代方法进行编码的。引入了迭代,就大大降低了编码的复杂度。LU分解编码算法就是以这个思想为基础的。2.2 LDPC译码算法

2.2.1消息传递算法:

  在消息传递 (MessagePassing,MP)算法中,概率信息依据二分图在变量节点和校验节点之间传递,逐步进行迭代译码。节点沿边发送的信息与上次从接收到的信息无关,而取决于和相连的其它边上接收的信息。目的在于使得任一条边上,只有外来信息传递,从而保证译码性能。如果 1DPC码对应的二分图中不存在环,则任一节点接受的信息都与从该节点发出的信息无关,从而保证了迭代译码的性能。如果二分图中存在环,经过一定次数的迭代之后,节点收到的信息将将与其发出的信息存在相关性,这将影响译码算法的性能。

2.2.2最小和译码算法:

  最小和(Min一sum)译码算法是根据对数域BP译码算法提出的一种近似简化算法,它利用求最小值的运算简化了函数运算,大大降低了运算复杂度且不需要对信道噪声进行估计,但其性能也有一定程度的降低。

2.2.3比特翻转译码算法:

比特翻转(Bit一Flipping,BF)译码算法首先将输入译码器的数据进行硬判决,然后将得到的“O”、“1”序列代入所有的校验方程,找出使校验方程不成立数目最多的变量节点,最后将该变量节点所对应的比特位翻转,至此完成一次迭代。整个译码过程不断地进行迭代,直到所有的校验方程都成立或者达到了设定的最大迭代次数。比特翻转译码算法只进行比特位的翻转等儿种简单的运算,没有复杂的操作,因此非常适合硬件实现,但其性能相对于BP译码算法有所降低,适用于硬件条件受限而性能要求较低的场合。

附一部分关于比特翻转译码仿真程序:

function vHat = decodeBitFlipping(rx, H, iteration)

%  rx        : Received signal vector (column vector)

%  H         : LDPC matrix

%  iteration : Number of iteration

%  vHat      : Decoded vector (0/1)

[M N] = size(H);

% Prior hard-decision

ci = 0.5*(sign(rx') + 1);

% Initialization

rji = zeros(M, N);

% Asscociate the ci matrix with non-zero elements of H

qij = H.*repmat(ci, M, 1);

for n = 1:iteration

   % ----- Horizontal step -----

   for i = 1:M

      c1 = find(H(i, :));

      for k = 1:length(c1)

         rji(i, c1(k)) = mod(sum(qij(i, c1)) + qij(i, c1(k)), 2);       

      end

   end  

   % ------ Vertical step ------

   for j = 1:N

      r1 = find(H(:, j));

      numOfOnes = length(find(rji(r1, j)));

      for k = 1:length(r1)       

         % Update qij, set '1' for majority of 1s else '0', excluding r1(k)

         if numOfOnes + ci(j) >= length(r1) - numOfOnes + rji(r1(k), j)

            qij(r1(k), j) = 1;

         else

            qij(r1(k), j) = 0;

         end     

      end

      if numOfOnes + ci(j) >= length(r1) - numOfOnes

         vHat(j) = 1;

      else

         vHat(j) = 0;

      end      

   end

end

 

附一部分编码程序:

function [c, newH] = makeParityChk(dSource, H, strategy)

% Generate parity check vector bases on LDPC matrix H using sparse LU decomposition

%

%  dSource : Binary source (0/1)

%  H       : LDPC matrix

%  strategy: Strategy for finding the next non-zero diagonal elements

%            {0} First  : First non-zero found by column search

%            {1} Mincol : Minimum number of non-zeros in later columns

%            {2} Minprod: Minimum product of:

%                         - Number of non-zeros its column minus 1

%                         - Number of non-zeros its row minus 1

%          

%  c       : Check bits

%  newH    : Rearrange H

 

% Get the matric dimension

[M, N] = size(H);

% Set a new matrix F for LU decomposition

F = H;

% LU matrices

L = zeros(M, N - M);

U = zeros(M, N - M);

 

% Re-order the M x (N - M) submatrix

for i = 1:M

 

   % strategy {0 = First; 1 = Mincol; 2 = Minprod}

   switch strategy

     

      % Create diagonally structured matrix using 'First' strategy

      case {0}

         

         % Find non-zero elements (1s) for the diagonal

         [r, c] = find(F(:, i:end));

        

         % Find non-zero diagonal element candidates

         rowIndex = find(r == i);

           

         % Find the first non-zero column

         chosenCol = c(rowIndex(1)) + (i - 1);

           

      % Create diagonally structured matrix using 'Mincol' strategy

      case {1}

        

         % Find non-zero elements (1s) for the diagonal

         [r, c] = find(F(:, i:end));

         colWeight = sum(F(:, i:end), 1);

        

         % Find non-zero diagonal element candidates

         rowIndex = find(r == i);

        

         % Find the minimum column weight

         [x, ix] = min(colWeight(c(rowIndex)));

         % Add offset to the chosen row index to match the dimension of the...

         % original matrix F

         chosenCol = c(rowIndex(ix)) + (i - 1);

            

      % Create diagonally structured matrix using 'Minprod' strategy  

      case {2}

           

         % Find non-zero elements (1s) for the diagonal

         [r, c] = find(F(:, i:end));

         colWeight = sum(F(:, i:end), 1) - 1;

         rowWeight = sum(F(i, :), 2) - 1;

        

         % Find non-zero diagonal element candidates

         rowIndex = find(r == i);

           

         % Find the minimum product

         [x, ix] = min(colWeight(c(rowIndex))*rowWeight);

         % Add offset to the chosen row index to match the dimension of the...

         % original matrix F

         chosenCol = c(rowIndex(ix)) + (i - 1);

        

      otherwise

         fprintf('Please select columns re-ordering strategy!\n');

     

   end % switch

 

   % Re-ordering columns of both H and F

   tmp1 = F(:, i);

   tmp2 = H(:, i);

   F(:, i) = F(:, chosenCol);

   H(:, i) = H(:, chosenCol);

   F(:, chosenCol) = tmp1;

   H(:, chosenCol) = tmp2;

                    

   % Fill the LU matrices column by column

   L(i:end, i) = F(i:end, i);

   U(1:i, i) = F(1:i, i);

        

   % There will be no rows operation at the last row

   if i < M          

           

      % Find the later rows with non-zero elements in column i

      [r2, c2] = find(F((i + 1):end, i));         

      % Add current row to the later rows which have a 1 in column i

      F((i + r2), :) = mod(F((i + r2), :) + repmat(F(i, :), length(r2), 1), 2);

                                                          

   end % if

        

end % for i

 

% Find B.dsource

z = mod(H(:, (N - M) + 1:end)*dSource, 2);

 

% Parity check vector found by solving sparse LU

c = mod(U\(L\z), 2);

 

% Return the rearrange H

newH = H;

 

fprintf('Message encoded.\n');

基本仿真结果:

猜你喜欢

转载自blog.csdn.net/ccsss22/article/details/114118602