无损编码只是第一个实验,还有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