viterbi译码算法C++实现

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Viterbi译码算法c++语言实现所对应的结构如下图所示:
已知接收序列y=-1,3,3-1,3,试求输入序列x=?用代码实现
所写函数包含两部分一个cpp一个h文件
Main.cpp如下所示:
#include"decode.h"
void main()
{
int re[]={-1,3,3,-1,3};
Decode vb;
cout<<"trellis图是:"<<endl;
vb.getpe(2,1,2,1);
vb.v(re,5);
cout<<"输入的x序列是:"<<endl;
for(int i=0;i<5;i++)
cout<<re[i]<<" ";
getchar();
cout<<endl;
}
Decode.h如下所示:
/*
对此进行简单的viterbi译码,将viterbi算法具体的细分,最后得到的函数,并且说明详细
by:molong
Xidian University
2013年月日23:12:04
*/
#include<iostream>
#include<vector>
using namespace std;
class Decode
{
public:
void gettrellis();
void getpe(int a,int b1,int b2,int b3);
void v(int *re,int n);
void get_pre(int now,int *pre);
int getcurrent(int j,int i,int in);
int min_path(int a,int b);
int get_out(int pre,int next);
private:
int trellis[4][4],s_number,multi1,multi2,multi3;
struct get_path
{
int pre;
int out;
};
};
/*
函数名称:getpe()
作用:作为构造类创建对象的时候进行传参,其中第一个参数a 代表的是存储器个数,第二个参数代表的是所看到的从左到右,输入,存储器,存储器所乘的系数,将这三个参数传给类的对象*/
void Decode::getpe(int a,int b1,int b2,int b3)
{
s_number=a;
multi1=b1;
multi2=b2;
multi3=b3;
}
/*
函数名称:gettrellis()
作用:得到基本的trellis转移图,存储器的个数为,所以有四个状态,定义trellis[4][4];
其中trellis[i][j]代表的是原来的状态是i,其中当j=0的时候表示的是输入为的时候所对应
的输出,j=1代表的是当输入为时转移到的下一个状态,j=2时代表的是输入为的时候
所对应的输出,j=3的时候表示的是当输入为的时候转移到的下一个状态,所得到的trellis图
在为类里面定义的私有变量,均可用
*/
void Decode::gettrellis()
{
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
{
int l,h;
l=i&1;
h=(i>>1)&1;
if(j%2==0)
trellis[i][j]=multi1*(j-1)+multi2*(2*h-1)+multi3*(2*l-1);//输入是或者的时候的输出
else
trellis[i][j]=(j&2)^h;//所转移到的下一状态
cout<<trellis[i][j]<<" ";
if(j==3)
cout<<endl;
}
}
/*
函数名称:v(int *re,int n)
输入参数:re为接收到的序列,对其进行直接操作,n为序列的个数
输出参数:re同样作为输出参数,来表示最后译码所输出来的结果
函数作用:对所接收到的序列进行viterbi译码
*/
void Decode::v(int *re,int n)
{
gettrellis();
vector<vector<int>>remb(4);
vector<vector<get_path>>path(4);
for(int i=0;i<4;i++)
{
remb[i].resize(n);
path[i].resize(n);
for(int j=0;j<n;j++)
{
remb[i][j]=0;
path[i][j].out=100;
path[i][j].pre=100;
//remb[i][j]=min_path(remb[pre1][j-1]+getcurrent(pre1,i,re[j]),remb[ pre2][j-1]+getcurrent(pre2,i,re[j]));
}
}
/*
remb[i][j]的作用是存储当接收第j个序列的时候,到i状态的路径最小值
path[i][j].out表示的是i所对应前一个状态pre到状态i时所对应的输出
path[i][j].pre表示的是第i个状态所对应的前一个状态是哪一个
通过path的存储,最后在remb里面找到路径的最小值,顺着path来输出最

的译码结果
*/
for(int i=0;i<4;i++)
{
remb[i][0]=getcurrent(0,i,re[0]);
path[i][0].pre=0;
path[i][0].out=get_out(0,i);
}/* 对remb的首列以及path的首列进行初始化操作*/
for(int j=1;j<n;j++)
{
for(int i=0;i<4;i++)
{
int pre[2];/*有两个前状态转移到状态i,定义pre[2]*/
get_pre(i,pre);/*得到i所对应的前一状态所对应的两个值*/
int a=getcurrent(pre[0],i,re[j]);
int b=getcurrent(pre[1],i,re[j]);
remb[i][j]=min_path(remb[pre[0]][j-1]+getcurrent(pre[0],i,re[j]),remb [pre[1]][j-1]+getcurrent(pre[1],i,re[j]));/*存储到i的最小距离*/
if(remb[i][j]==(remb[pre[0]][j-1]+getcurrent(pre[0],i,re[j])))
{
path[i][j].pre=pre[0];
path[i][j].out=get_out(pre[0],i);
/*判断前一状态到底是哪一个,删除一条路径,只剩下最小路径*/
}
else
{
path[i][j].pre=pre[1];
path[i][j].out=get_out(pre[1],i);
}
}
}
int minimum;
int min=1000;
for(int i=0;i<4;i++)
{
if(remb[i][4]<min)
{
min=remb[i][4];
minimum=i;
}
/*通过对最后一列的寻找得到最小距离*/ }
for(int j=n-1;j>=0;j--)
{
re[j]=path[minimum][j].out;
minimum=path[minimum][j].pre;
/*通过path倒序得到译码所对应的输出*/ }
}
/*
函数名称:get(int pre,int now)
输入参数:pre表示前一个状态,now表示当前的状态输出参数:从状态pre转移到状态now所对应的输出函数作用:通过前一状态以及当前状态,来确定输出*/
int Decode::get_out(int pre,int now)
{
int out,count=0;
for(int j=0;j<2;j++)
if(trellis[pre][2*j+1]==now)
{
out=2*j-1;
count++;
}
if(count==0)
out=1000;
return out;
}
/*
函数名称:get_pre(int now,int *pre)
输入参数:当前状态now,*pre代表的是now所对应的前一状态的两个值
输出参数:得到前一状态的两个值,即得到是哪两个状态可以转移到状态now 函数作用:得到可以转移到当前状态的前一状态的两个值,
例如状态->2,0->2那么这就是得到和这两个值
*/
void Decode::get_pre(int now, int *pre)
{
int count=0;
for(int i=0;i<4;i++)
for(int k=0;k<2;k++)
{
if(trellis[i][2*k+1]==now&&count==0)
{
pre[0]=i;
count++;
}
if(trellis[i][2*k+1]==now&&count!=0)
{
pre[1]=i;
}
}
}
/*
函数名称:getcurrent(int j,int i,int in)
输入参数:j表示的是前一状态,i表示的是当前状态,in表示的是接收到的数字输出参数:result表示从状态j到状态i所对应的输出和接收参数in的汉明距离函数作用:得到每一个分支的汉明距离,返回的值是绝对值
*/
int Decode::getcurrent(int j,int i,int in)//j代表前一个,i表示后一个,in表示输入接收到的数字
{
int result;
int count=0;
for(int k=0;k<2;k++)
{
if(trellis[j][2*k+1]==i)
{
result=in-trellis[j][2*k];
count++;
}
}
if(count==0)
result=10000;
return abs(result);
}//在此处应该返回的是绝对值,不能是单纯的带符号的值/*
函数名称:min_path(int a,int b)
输入参数:a和b两个数值
输出参数:a和b之间的最小值
函数作用:取两条转移路径的最小值
*/
int Decode::min_path(int a,int b)
{
if(a>b)
return b;
else
return a; }。

相关文档
最新文档