动态规划卷积码的Viterbi译码算法Word文件下载.docx
- 文档编号:22386657
- 上传时间:2023-02-03
- 格式:DOCX
- 页数:15
- 大小:126.93KB
动态规划卷积码的Viterbi译码算法Word文件下载.docx
《动态规划卷积码的Viterbi译码算法Word文件下载.docx》由会员分享,可在线阅读,更多相关《动态规划卷积码的Viterbi译码算法Word文件下载.docx(15页珍藏版)》请在冰豆网上搜索。
维特比译码中使用了汉明距离的概念,下面了解一下汉明距离的原理。
汉明距离是两个等长字符串对应位置的字符不同的个数,如01100100和00111000的汉明距离是4。
维比特译码的基本思想是把接收到的矢量,和网格图上诸种可能的路径比较,删去距离大的路径,保留距离小的路径,以距离最小路径作为发码的估值。
如输入信息比特1001,则(2,1,3)卷积码编码器输出的信息比特是11101111,假设经过信道干扰后接收到的信息比特是11001111,则维特比译码过程是:
1.从T0时刻的全零状态开始,零状态初始度量(汉明距离)为0,其它状态初始度量为正无穷;
2.在任一时刻t向t+1时刻前进,对每一个状态只记录到达路径中度量最小的一个(残留路径)及其度量;
3.前进过程中,对t时刻的每个状态作延伸,即在状态度量基础上加上分支度量,得到8条路径;
4.在t+1时刻,对到达每一个状态的2条路径进行比较,找到一个度量最小的作为残留路径;
5.直到码的终点,如果终点是一个确定状态,则最终保留的路径就是译码结果。
维特比译码算法执行过程
三、卷积码的Viterbi译码算法
1.算法
●输入比特流个数、比特流和有噪信道的误码率(0~1);
●对比特流数据进行补0操作(在比特流的最后编码器中仍保存着2个之前输入比特的状态,因此需要进行补0操作,即给输入比特流加上2个0比特);
●对补0后的比特流进行(2,1,3)卷积码编码操作,编码输出的第一个结果是输入、第一个编码器存储的值和第二个编码器存储的值逻辑加操作的结果,第二个结果是输入和第二个编码器存储的值逻辑加操作的结果;
●对(2,1,3)卷积码编码输出的数据进行传输(加上误码);
●对从信道得到的有误码的比特流进行维特比译码:
•对比特流进行分组,2个一组循环;
•根据这2个比特对当前的4个状态(StateNode)计算从它出发到它可能到达的2个状态对应路径的汉明距离,并保存对应的译码序列和汉明距离;
•根据上一步的结果,取汉明距离小的更新这4个状态;
•最后,第1个状态(0状态)对应的译码序列就是维特比译码的结果(因为补零操作保证了最后肯定会回到0状态)。
2.算法复杂度
假设输入比特流序列的长度为L。
由于(2,1,3)卷积码的状态数是4,对每个时刻要做4次“加-比-选”操作得到4个状态的残留路径,每次“加-比-选”操作包括2次加法和1次比较,因此总运算量约为4L次“加-比-选”操作。
同时要能保存4条残留路径,因此需要4L个存贮单元。
由此可见,(2,1,3)卷积码的维特比译码算法的时间和空间复杂度均与比特流序列长度呈线性关系,但维特比译码算法的时间空间复杂度与卷积码的约束长度呈指数关系。
3.可能的改进
由于维特比译码算法的时间空间复杂度与卷积码的约束长度呈指数关系,因此对状态数很大的卷积码编码,维特比算法要经一定的修正后才可能实用,常用的算法是缩减状态的维特比译码,即在每一时刻,只处理部分的状态。
四、算法实现框架
本次实验使用的语言是java,具体的算法实现包含4个类:
ViterbiDecode、StateNode、ConvEncode和Channel。
ViterbiDecode类用于实现维特比译码,它有一个静态的decode()方法用于译码和一个静态的hammingDistance()方法用于计算汉明距离,ViterbiDecode的main方法是程序的入口;
StateNode是一个实体类,它用于保存状态,有value(状态,如“00”)、distance(汉明距离)和solution(对应译码序列)属性;
ConvEncode类用于实现(2,1,3)卷积码编码,它只有一个静态的encode()方法用于编码和一个静态的addZero()方法用于补0操作;
Channel类用于模拟有噪信道,它只有一个静态的transfer()方法用于给比特流序列加上误码。
五、总结
本科的时候曾经学习过卷积码编码和维特比译码的知识,考研的时候也复习了该方面知识,在理解题目上没有遇到困难。
但由于从未尝试编程实现维特比译码,因此在本次实验的过程中还是遇到了许多问题。
经过查看课件及网上查找资料,我对如何编码实现卷积码的维特比译码算法有了一个较好的理解,知道了算法主要应该包括补0、卷积编码、信道传输和维特比译码4步操作,并使用了java语言自主完成了该实验。
由于该实验完成的比较仓促,程序中仍有许多地方能进行优化,但总的来说,通过本次试验,我对维特比译码有了一个直观的理解,同时锻炼了使用java语言编程的能力,有不小的收获。
附录
程序运行示例:
源程序:
importjava.util.Random;
importjava.util.Scanner;
publicclassViterbiDecode{
publicstaticbyte[]decode(byte[]inBytes){
StateNode[]stateNodes=newStateNode[4];
StateNode[]tmpNodes=newStateNode[4];
stateNodes[0]=newStateNode("
00"
0,"
"
);
for(inti=0;
i<
inBytes.length-4;
i=i+2){
byte[]twoBytes={inBytes[i],inBytes[i+1]};
for(intj=0;
j<
stateNodes.length;
j++){
if(stateNodes[j]!
=null){
Stringvalue=stateNodes[j].value;
byte[]byteValue={
Byte.parseByte(value.substring(0,
value.length()-1)),
Byte.parseByte(value.substring(value.length()-1))};
byte[][]possibleNextValue={{0,byteValue[0]},
{1,byteValue[0]}};
//String[]possibleNextOutput={};
byte[][]possibleNextOutput={
{
(byte)((byteValue[0]+byteValue[1]+possibleNextValue[0][0])%2),
(byte)((byteValue[1]+possibleNextValue[0][0])%2)},
(byte)((byteValue[0]+byteValue[1]+possibleNextValue[1][0])%2),
(byte)((byteValue[1]+possibleNextValue[1][0])%2)}};
int[]distances={
stateNodes[j].distance
+ViterbiDecode.hammingDistance(twoBytes,
possibleNextOutput[0]),
possibleNextOutput[1])};
for(intk=0;
k<
possibleNextValue.length;
k++){
byte[]next=possibleNextValue[k];
StateNodetmpNode=tmpNodes[next[1]+2*next[0]];
if(tmpNode!
intd=tmpNode.distance;
if(distances[k]<
d){
tmpNode.distance=distances[k];
tmpNode.solution=stateNodes[j].solution
+possibleNextValue[k][0];
}
}else{
tmpNodes[next[1]+2*next[0]]=newStateNode(
next[0]+"
+next[1],distances[k],
stateNodes[j].solution
+possibleNextValue[k][0]);
}
}
}
}
for(intm=0;
m<
tmpNodes.length;
m++){
stateNodes[m]=tmpNodes[m];
tmpNodes[m]=null;
}
for(inti=inBytes.length-4;
inBytes.length;
byte[]possibleNextValue={0,byteValue[0]};
byte[]possibleNextOutput={
(byte)((byteValue[0]+byteValue[1])%2),
(byte)((byteValue[1])%2)};
intdistance=stateNodes[j].distance
+ViterbiDecode.hammingDistance(twoBytes,
possibleNextOutput);
StateNodetmpNode=tmpNodes[possibleNextValue[1]+2
*possibleNextValue[0]];
if(tmpNode!
intd=tmpNode.distance;
if(distance<
tmpNode.distance=distance;
tmpNode.solution=stateNodes[j].solution
+possibleNextValue[0];
}else{
tmpNodes[possibleNextValue[1]+2
*possibleNextValue[0]]=newStateNode(
possibleNextValue[0]+"
+possibleNextValue[1],distance,
stateNodes[j].solution+possibleNextValue[0]);
byte[]outBytes=newbyte[stateNodes[0].solution.length()];
outBytes.length;
i++){
outBytes[i]=Byte.parseByte(stateNodes[0].solution.substring(i,
i+1));
returnoutBytes;
}
//a和b都是01,且ab等长
publicstaticinthammingDistance(byte[]a,byte[]b){
intdistance=0;
a.length;
if(a[i]!
=b[i])
distance++;
returndistance;
publicstaticvoidmain(String[]args){
//输入参数
Scannerin=newScanner(System.in);
while(true){
System.out
.println("
********模拟实现比特流的(2,1,3)卷积编码->
经过有噪信道->
维特比译码********"
System.out.println("
请输入比特流的长度并回车:
intn=in.nextInt();
请输入比特流(0或者1,空格隔开)并回车:
byte[]a=newbyte[n];
for(inti=0;
a[i]=in.nextByte();
请输入有噪信道误码率(0~1)并回车:
doubler=in.nextDouble();
//记录信道传输造成的误码个数err1和维特比译码还原结果的误码个数err2
interr1=0;
interr2=0;
//输出原始比特流数据
原始比特流数据:
System.out.print(a[i]+"
"
//输出卷及编码结果
经过(2,1,3)卷积编码后的比特流数据:
byte[]b=ConvEncode.encode(a);
b.length;
System.out.print(b[i]+"
//输出信道传输结果
经过误码率为"
+r+"
的有噪信道后的比特流数据:
byte[]c=Channel.transfer(b,r);
c.length;
System.out.print(c[i]+"
if(c[i]!
=b[i]){
err1++;
//输出有噪信道造成的误码个数
经过有噪信道后造成的误码个数是"
+err1);
//输出维特比译码结果
经过维特比译码还原的比特流数据:
byte[]d=ViterbiDecode.decode(c);
d.length-2;
System.out.print(d[i]+"
if(d[i]!
=a[i]){
err2++;
//输出维特比译码还原结果的误码个数
经过维特比译码还原后,与原始比特流数据相比的误码个数是"
+err2);
}
classStateNode{
Stringvalue;
intdistance;
Stringsolution;
publicStateNode(Stringvalue,intdistance,Stringsolution){
this.value=value;
this.distance=distance;
this.solution=solution;
//模拟实现(2,1,3)卷积码
classConvEncode{
//输入只能是01,编码器的顺序是输入->
s1->
s2->
丢弃
publicstaticbyte[]encode(byte[]inBytes){
byte[]actualBytes=ConvEncode.addZero(inBytes);
byte[]outBytes=newbyte[2*actualBytes.length];
bytes1=0;
bytes2=0;
actualBytes.length;
outBytes[2*i]=(byte)((s1+s2+actualBytes[i])%2==0?
0
:
1);
outBytes[2*i+1]=(byte)((s2+actualBytes[i])%2==0?
s2=s1;
s1=actualBytes[i];
privatestaticbyte[]addZero(byte[]inBytes){
byte[]outBytes=newbyte[inBytes.length+2];
outBytes.length-2;
outBytes[i]=inBytes[i];
outBytes[outBytes.length-2]=0;
outBytes[outBytes.length-1]=0;
//模拟传输信道,为比特增加误码
classChannel{
//输入只能是01,errorRate取值0(包含)~1(不包含)
publicstaticbyte[]transfer(byte[]inBytes,doubleerrorRate){
byte[]outBytes=newbyte[inBytes.length];
Randomr=newRandom();
doublerandomDouble;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 动态 规划 卷积码 Viterbi 译码 算法