LT编码与后向传播译码实验及报告

无损编码只是第一个实验,还有LDPC编码,说实话我不太擅长编码解码的东西。‘’在网上找还是找不到太满意的,主要是看不懂,所以只能自己动手编。

具体的LT码的原理,可以百度大佬的博客,要不我的报告里也包含这部分。

有关LT码的翻译文章见http://www.docin.com/p-506096999.html
这是此次实验的具体章节分布,我会在最后位置提供百度网盘的具体代码和实验报告,希望大家多多支持。

LT码是在编码史上的一个重要的里程碑,其作为无码率码的第一种实现。有较高的研究价值。本文在课程上选择的就是LT码。为了更加简洁明了,本次报告将从以下三个方面进行汇报,包括LT码的简介,LT码的仿真与心得体会等。具体组织结构安排如下:
在第一章中,将对喷泉码的概念进行简单的介绍,然后分析LT码的原理和应用,最后将对LT码最关键的度分布与编码解码的过程简要介绍。
在第二章,主要汇报本人仿真的思路,以及在仿真的过程中遇到的问题和仿真的结果。
第三章,发现在仿真过程中发现的不足与问题,寻找新的更好的编码译码方案,使得LT码的性能得以提升。
在第四章介绍一下Raptor码,其作为LT码的重要的改进有进一步了解和学习的价值。
在第五章,撰写本课程和本次仿真的心得体会。

其中关键的代码先贴上来一下,其与的请大家下载文件自行查看,基于matlab
首先是产生孤子分部的函数,设计了两种,一个理想,一个鲁棒的

function Degree= Soliton_degree(k,Ideal_or_Robust)
%UNTITLED 理想孤子分布0 鲁棒孤子分布1
%   用于根据编码数量产生相应的孤子分布
%   k代表输入符号个数


%理想分布虽然很好,恰好刚好k个编码符号覆盖K个输入符号 但是
%纹波的预期大小只有一个,即使最小的方差也会导致波纹消失,因
%此整个过程由于不能覆盖和处理所有的输入符号而失败。
length=1:100; %控制绘图长度
%-------------------理想分布------------------------
    p=zeros(1,k);   %理想分布结果保存矩阵
    p(1)=1/k;
    for i=2:k 
        p(i)=1/(i*(i-1));
    end
%     subplot(2,1,1);  %绘制结果
%     plot(length,p(length));
%     xlabel('度'),ylabel('概率');
%     title('理想孤子分布');
    %如果是理想分布则结束函数
    if Ideal_or_Robust==0  %理想分布 
            Degree=p;
            return; 
    end
%---------------------鲁棒分布------------------------
   %鲁棒分布 在理想的基础上进行修正
    %由于添加了一部分数值 使得鲁棒分布再2为峰值之外还有另外一个峰值M
    c=0.05;  %合适的大于0的常数
    delta=0.05;  %误码率
    R=c*log(k/delta)*sqrt(k); %需要的常数R
    u=zeros(1,k); %结果保存矩阵   u(i)=(p(i)+t(i))/b  b=(1:k)的累加和
    t=zeros(1,k);  %t函数值保存矩阵

    t_split=fix(k/R);  %t函数的分界值 取向0整数
    for j=1:t_split-1
        t(j)=R/j/k;
    end
    t(t_split)=R*log(R/delta)/k;    %在分界点有一个峰值? 不理解为什么要这样

    all=sum(p)+sum(t); %累加和保存变量 用于归一化
    for i=1:k    %计算所有的分布系数
        u(i)=(p(i)+t(i))/all;
    end
    Degree=u;
%     subplot(2,1,2);  %绘制结果
%     plot(length,u(length));
%     xlabel('度'),ylabel('概率');
%     title('鲁棒孤子分布

    %s=vpa(p,4);
    %ss=vpa(u,4);
end

产生输入符号的函数

function Inputarray= inputsymbols( K,L )
%INPUTSYMBOLS 产生K个L位的输入符号
%   K=1000;   %输入符号个数
%   L=10;     %每个输入符号位数
Inputarray=round(rand(K,L)); 

end

设计的思想中包含两种模式,一个是完美的信道不会丢包,那么根据LT后向解码原理可以100%很快的解码,第二种则是丢包信道,这个需要多少个包才能解码就看脸了,有的时候甚至无法解码。代码如下:

clearvars -except resulttra resultrec Rec_1000_50 Tra_1000_50 Rec_1000_var  %几个变量不清除
clc

%-------------------------------------------------
%带有信道误码率 并且邻居是从所有符号中随机选择
failrate=0.01;   %模拟差信道的丢包率
%模拟两种模式 0是理想完美信道及编码的模拟  1是普通编码和丢包率模拟信道
typeset=0;   %默认模式0 即完美信道
%--------------------------------------------------
if typeset==0
    failrate=0;
end
%------------------产生输入符号------------------
inputsymbolnumber=1000;
inputsymbolbit=50;   %随机产生100个输入符号,每个符号10位
msg=inputsymbols(inputsymbolnumber,inputsymbolbit); % msg保存产生的输入符号

%------------------设计度分布-------------------
Du=Soliton_degree(inputsymbolnumber,1);   %孤子分布
Du_Splite=find(Du>0.1/inputsymbolnumber, 1, 'last' );  %截取适当的大小,太大的度没有意义
Du=Du(1:Du_Splite);

%-------------------记录参数-------------------------
codenumber=0;  %存储编码符号的数量
receivenumber=0; %接收的编码符号数量

%----------------------标志位--------------------
coverall=0;      %普通编码是否覆盖全部输入符号 
codefinish=0;    %此次编码是否成功 没成功继续下一次循环
finish=0;  %由译码器操控,完成译码置1
order=[];  %用于存储编码的邻居
new=[];    %上一次的引入的未被覆盖的输入符号 下一次编码需要 存储起来
coverinputs=zeros(1,inputsymbolnumber);     %记录被覆盖的输入符号
%----------------解码部分----------------------
L=inputsymbolbit; %获取的输入符号bit位  原本可以在译码器端从编码符号L=length(msg_coded{1})
K=inputsymbolnumber; %需要恢复的输入符号个数
msg_decoded=cell(K,3);    %初始化关系图
%定义三元包 第一个为是否解出 第二个为有关编码符号的序号 第三个存储解码的数据
for i=1:K
    msg_decoded{i,1}=0; % 初始化为1,表示未解出
    msg_decoded{i,2}=[]; %初始化为空
    msg_decoded{i,3}=zeros(1,L); % 初始化为0行向量
end
%编码符号保存矩阵 二元 同编码符号砼结构
code_store=[];
%--------------------编码解码大循环---------------
 while(~finish)
    %---------------编码大循环--------------------
        while(~codefinish)
            if codenumber==0   %第一个编码符号度为1
              order=round(inputsymbolnumber*rand(1)); %随机选择一个度为1的释放
              coverinputs(order)=1;   %覆盖输入符号的标志位改变
              new=order;              %保存新的邻居下次使用
              msg_code{1}=msg(order,:);   %编码符号信息
              msg_code{2}=order;
              codenumber=codenumber+1;
              codefinish=1;
            else %其他的编码符号 服从度的分布
                   Degree=randsample([1:length(Du)], 1, true, Du); %按照度分布概率获取新的度
                   limit=length(find(coverinputs==1));
                   if Degree<=limit+1  %度的分布满足要求 因为每次至多有一个邻居是未被覆盖的 所以由这个关系
                               if typeset==1
                                           if Degree==1   %度为1就直接释放
                                                 %什么都不变 直接释放上次的new记录的输入符号
                                           else   % Degree
                                                  %释放上次new的加D-1个随机的 必有仅一个是未被覆盖的
                                                  search=find(coverinputs==0);
                                                  covered=find(coverinputs==1); %从输入符号中随机选取另一个符号
                                                  covered(covered==new)=[];    %去掉上次新的那个
                                                  allsearch=randperm(K);
                                                  choose=allsearch(1);
                                                  if find(search==choose)>0
                                                        if Degree==2
                                                            order=[choose,new];  
                                                            new=order(1);
                                                        else
                                                             coveredpos=randperm(length(covered));
                                                             coveredpos=coveredpos(1:Degree-2); 
                                                             order=[choose,covered(coveredpos),new];    
                                                             new=order(1);
                                                        end
                                                  else
                                                         coveredpos=randperm(length(covered));
                                                         coveredpos=coveredpos(1:Degree-1);                                 
                                                         order=[covered(coveredpos),new];  %加上上次的组成邻居
                                                         new=order(1);

                                                  end
%                                                   if isempty(search) %如果全部被覆盖 那么随机挑选
%                                                       %空的 就直接在波纹中选D-1个
%                                                   else
%                                                       %非空 就添加一个未被覆盖的 随机选择D-1个 
%                                                       searchpos=randperm(length(search));
%                                                       covered=[covered,search(searchpos(1))]; %加上随机未覆盖的
%                                                   end                                 
%                                                   %search(searchpos(1)); %未被覆盖的随机的一个                                
%                                                   coveredpos=randperm(length(covered));
%                                                   coveredpos=coveredpos(1:Degree-1);                                 
%                                                   order=[covered(coveredpos),new];  %加上上次的组成邻居
%                                                   if isempty(search) %根据未覆盖数量是否为0 选择此次的new
%                                                       new=covered(1);
%                                                   else
%                                                       if find(order==search(searchpos(1)))>0
%                                                          new=search(searchpos(1));  
%                                                       else
%                                                           new=covered(1);
%                                                       end
%                                                   end
                                           end  %邻居选择完毕  开始编码
                               else
                                        if Degree==1   %度为1就直接释放
                                             %什么都不变 直接释放上次的new记录的输入符号
                                        elseif Degree==2
                                             %释放上次new的加一个未被覆盖的中的一个
                                             uncovered=find(coverinputs==0);         %从未覆盖的输入符号中随机选择一个覆盖
                                             position=randperm(length(uncovered));     % 即uncovered(search(1))
                                                      if isempty(position)   %全被覆盖了 结束LT过程
                                                          break;
                                                      end
                                             uncovered=uncovered(position(1));         %复制给uncoverd 新的未被覆盖的符号
                                             order=[uncovered,new];
                                             new=uncovered;
                                         else
                                             %度大于2的情况,d-2个是已被覆盖的 1个是上次的 一个是未被覆盖的
                                             %先选D-2已经覆盖过的
                                             coverd=find(coverinputs==1);  %已经被覆盖的输入符号合集
                                             pos=find(coverd==new);        
                                             coverd(pos)=[];               %抠去上次的
                                             %再从中选择d-2个
                                             limit=length(coverd);           %还有多少个已经被覆盖的符号
                                             position=randperm(limit);          %随机排序
                                             position=position(1:Degree-2);     %选择好D-2个位置
                                             order=[new,coverd(position)];
                                             %从未被覆盖的再选一个
                                             uncovered=find(coverinputs==0);         %从未覆盖的输入符号中随机选择一个覆盖
                                             position=randperm(length(uncovered));     % 即uncovered(search(1))
                                                      if isempty(position)   %全被覆盖了 结束LT过程
                                                          break;
                                                      end
                                             uncovered=uncovered(position(1));         %复制给uncoverd 新的未被覆盖的符号
                                             order=[order,uncovered];
                                             new=uncovered;  
                                        end
                                end %模式选择
                                coverinputs(new)=1;   %新加入的符号 标志置1
                                msg_code=cell(1,2);  %编码符号 cell1存储信息  cell2存储邻居
                                code=zeros(1,L);
                                for i=1:length(order)
                                    code=bitxor(msg(order(i),:),code);
                                end
                                msg_code{1}=code;
                                msg_code{2}=order;
                                codenumber=codenumber+1;                                
                                %编码成功
                                codefinish=1;
                   else  %不符合度分配要求  
                        codefinish=0;
                   end                      
            end  %第一个码 度为1              
        end


        codefinish=0;  %使得可以进行下次编码
        if rand(1)>=failrate  %随机模拟是否被丢弃

                    %---------------------解码大循环----------------
                    receivenumber=receivenumber+1;
                    %传递过来的新的编码符号为msg_code,二元包 1是信息 二是邻居
                    %msg_decoded=cell(K,3)   关系图三元 第一个为是否解出 第二个为有关编码符号的序号 第三个存储解码的数据 
                    %code_store     编码符号保存矩阵二元 同结构 第一个是信息  第二个是邻居
                    donew=[];  %保存刚接出来的码 因为它可能使得其他编码符号可解
                    code_store=[code_store,msg_code];
                    p=length(code_store)/2;
                    cal=0;
                    neighbour=code_store{2*p};  %邻居矩阵
                    for i=1:length(neighbour)   %遍历该符号的所有邻居   
                          if msg_decoded{neighbour(i),1}==1   %如果已知则进行解码
                              cal=cal+1;
                          end
                    end
                    if cal==length(neighbour)  %如果所有邻居都已知就是无用信息 不用管了
                        cal=0;
                    else  %如果是有用信息 则进行解码
                            if length(msg_code{2})==1  %如果度1 直接解码
                                    number=msg_code{2};      %获取唯一的邻居
                                    msg_decoded{number,1}=1; %将信息保存到输入符号中 同时标志位置1
                                    msg_decoded{number,3}=msg_code{1};
                                    donew=number;
                            else    %如果度大于1就直接解码 看最后剩下几个邻居
                                    for i=1:length(neighbour)   %遍历该符号的所有邻居
                                          if msg_decoded{neighbour(i),1}==1   %如果已知则进行解码
                                                  code_store{2*p-1}=bitxor(code_store{2*p-1},msg_decoded{neighbour(i),3}) ;
                                                  pos=find(code_store{2*p}==neighbour(i));  %去掉该邻居
                                                  code_store{2*p}(pos)=[];
                                          end
                                    end
                                    %判断解码之后是否只有一个邻居了 这样的话就可以解码了
                                    if  length(code_store{2*p})==1
                                            number=code_store{2*p};      %获取唯一的邻居
                                            msg_decoded{number,1}=1; %将信息保存到输入符号中 同时标志位置1
                                            msg_decoded{number,3}=code_store{2*p-1};
                                            donew=number;
                                    else %否则添加到关系图中
                                            neighbour=code_store{2*p};
                                            for j=1:length(neighbour)  %将编码符号对应的序列值添加到输入符号的关系图中
                                                msg_decoded{neighbour(j),2}=[msg_decoded{neighbour(j),2},p];                                    
                                            end                            
                                    end
                            end
                    end
                    %解码过程完毕 如果得到了新的输入符号 解码有关的其他符号
                    while(~isempty(donew))  %如果持续有信服好解码则继续运行 尝试解码新的符号
                             origianlength=length(donew);
                             for a=1:length(donew)
                                     newinput=donew(a); %解码出来的输入符号
                                     if ~isempty(msg_decoded{newinput,2})   %如果关联的编码符号不是空 进行解码                                          
                                             realate=msg_decoded{newinput,2};   %获取相关的编码符号合集 逐个解码
                                             len=length(realate);  
                                             for s=1:len
                                                     p=realate(s); %编码符号的序号,将其与进行异或并去除邻居
                                                     code_store{2*p-1}=bitxor(code_store{2*p-1},msg_decoded{newinput,3}) ;
                                                     nb=code_store{2*p};  %编码符号的邻居 去除
                                                     %将输入符号的相关去除
                                                     nb(nb==newinput)=[];
                                                     code_store{2*p}=nb;
                                                     %如果操作过后邻居为1 直接解码
                                                       if  length(code_store{2*p})==1
                                                            tt=code_store{2*p};      %获取唯一的邻居
                                                            msg_decoded{tt,1}=1; %将信息保存到输入符号中 同时标志位置1
                                                            msg_decoded{tt,3}=code_store{2*p-1};
                                                            donew=[donew,tt];
                                                       end
                                             end  %相关的编码符号循环
                                             msg_decoded{newinput,2}=[]; %将所有已经去除的编码符号清0
                                     end %有关的编码符号不为空的话                                   
                             end %新解码的符号个数 每个都进行解码循环
                              donew(1:origianlength)=[];  %解码完成后清除这个新解的码
                    end %新解码个数不为空

                    %判断是否全部解码完毕
                    for i=1:K
                        if msg_decoded{i,1}==1
                            finish=1;
                        else
                            finish=0;
                            break;
                        end
                    end
        end %是否被模拟丢弃了
 end
receivenumber
% resulttra=[resulttra,codenumber];
% resultrec=[resultrec,receivenumber];
%Draw(Rec_1000_50,'实验次数','编码符号数','丢包率与所需编码符号数量的关系',0);
% h=legend('0','0.01','0.05','0.1','0.2','0.5','location','best');

注意这个Draw函数使我嫌自己每次画图麻烦,弄的一个画图函数,输入本实验的矩阵就可以自动化出彩色的比较图,这个矩阵长什么样子看看文件里的实例就好了
最后提供报告和源码在百度云,报告共23页,1.6W字
链接: https://pan.baidu.com/s/1R4r6ZJEUia-BMeWJquDJ9g 密码: f7wm

猜你喜欢

转载自blog.csdn.net/iamsongyu/article/details/82627556