matlab viterbi译码详解

思路详解

如何通俗地理解最小距离

卷积编码器模型

卷积编码器的子生成元:

g1=111, g2=101

生成码元的方程:

c 0 t = m 0 t + m 0 t − 1 + m 0 t − 2 c_0^t =m_0^t+m_0^{t-1}+m_0^{t-2} c0t=m0t+m0t1+m0t2
c 1 t = m 0 t + m 0 t − 2 c_1^t =m_0^t+m_0^{t-2} c1t=m0t+m0t2

图解:

0/00
1/11
0/00
1/11
0/10
1/01
0/00
1/11
0/10
1/01
0/11
1/00
0/01
1/10
00
10
01
11
00
10
00
10
01
11
00
10
01
11

以接收序列为1 1 1 0 1 1为例,可知最短路径对应的编码输入为100。

编码思路:

1.循环次数为接收数据长度的一般,也就是译码输出的长度。

2.对每一个时刻分别寻找到达四种状态的最短路径作为幸存路径,记录路径(编码输入)、编码输出、汉明距离。

3.循环结束后对到达四个状态的四种最短路径进行比较,选择汉明距离最小的作为最终的最短路径(译码输出)。

matlab代码

close all;clear all; clc;
%卷积编码器的子生成元g1=111,g2=101
%x为输入的待译码序列
x=importdata('data.txt');%长度不限,只需要长度为偶数
a=size(x);       %输入序列的长度
s=a(2)/2;        %译码后的m序列长度为x的一半
m=zeros(1,s);     %最终结果存放
ma=zeros(1,s);  
mb=zeros(1,s);  
mc=zeros(1,s);  
md=zeros(1,s);  %存放路径
tempma=zeros(1,s);
tempmb=zeros(1,s);
tempmc=zeros(1,s);
tempmd=zeros(1,s);%每个时刻的最小路径值

out=zeros(1,2*s);%最终编码输出
outa=zeros(1,2*s);
outb=zeros(1,2*s);
outc=zeros(1,2*s);
outd=zeros(1,2*s);%存放编码输出
tempouta=zeros(1,2*s);
tempoutb=zeros(1,2*s);
tempoutc=zeros(1,2*s);
tempoutd=zeros(1,2*s);%%储存每个时刻最小路径对应的编码输出
Fa=0;
Fb=0;
Fc=0;
Fd=0;%累计汉明距离
for i=1:s
    if i==1 
        d0=dis(x(1),x(2),0,0);%0-->00-->00 编码器输出00 0+0+0=0 0+0=0
        d3=dis(x(1),x(2),1,1);%1-->10-->00 编码器输出00 1+0+0=1 1+0=1
        
        Fa=Fa+d0;
        Fb=Fb+d3;
        
        ma(i)=0;
        mb(i)=0;%注意这里并不是真正对应当前的源码,而是考虑到i=2时候的整体源码输入
        mc(i)=1;
        md(i)=1;
        
        outa(2*i-1)=0; outa(2*i)=0;
        outb(2*i-1)=0; outb(2*i)=0;
        outc(2*i-1)=1; outc(2*i)=1;
        outd(2*i-1)=1; outd(2*i)=1;
        continue;
    elseif i==2 
        d0=dis(x(3),x(4),0,0);%d0=1
        d1=dis(x(3),x(4),0,1);%d1=2
        d2=dis(x(3),x(4),1,0);%d2=0
        d3=dis(x(3),x(4),1,1);%d3=1
        
        %注意下面的顺序,不能错,否则会产生数据相关,要么加中间变量。
        Fc=Fb+d2;   %0-->10-->01 0+1+0=1(高位) 0+0=0(低位) 编码器输出为:10
        Fd=Fb+d1;   %1-->10-->11 1+1+0=0 1+0=1 编码器出书为:01
        Fb=Fa+d3;
        Fa=Fa+d0;   
        
        ma(i)=0;
        mb(i)=1;
        mc(i)=0;
        md(i)=1;
        
        outa(2*i-1)=0; outa(2*i)=0;
        outb(2*i-1)=1; outb(2*i)=1;
        outc(2*i-1)=1; outc(2*i)=0;
        outd(2*i-1)=0; outd(2*i)=1;
        continue; 
    elseif i>2
        d0=dis(x(2*i-1),x(2*i),0,0);
        d1=dis(x(2*i-1),x(2*i),0,1);
        d2=dis(x(2*i-1),x(2*i),1,0);
        d3=dis(x(2*i-1),x(2*i),1,1);
        %下面开始进行加比较选,选F值小的路径
        tempa=Fa;
        tempb=Fb;
        tempc=Fc;
        tempd=Fd;
        if Fa+d0<Fc+d3 %到达00状态的两条路径比较大小
            tempa=Fa+d0; %0-->00-->00 编码器输出00 0+0+0=0 0+0=0
            tempma=ma;
            tempma(i)=0;
            tempouta=outa;
            tempouta(2*i-1)=0;
            tempouta(2*i)=0;
        else
            tempa=Fc+d3;%0-->01-->00 编码器输出11  0+0+1=1 0+1=1
            tempma=mc;
            tempma(i)=0;
            tempouta=outc;
            tempouta(2*i-1)=1;
            tempouta(2*i)=1;
        end
        
        if Fa+d3<Fc+d0 %到达10状态的两条路径比较大小
            tempb=Fa+d3;%1-->00-->10 编码器输出11  1+0+0=1 1+0=1
            tempmb=ma;
            tempmb(i)=1;
            tempoutb=outa;
            tempoutb(2*i-1)=1;
            tempoutb(2*i)=1;
        else
            tempb=Fc+d0;%1-->01-->10 编码器输出00  1+0+1=0 1+1=0
            tempmb=mc;
            tempmb(i)=1;
            tempoutb=outc;
            tempoutb(2*i-1)=0;
            tempoutb(2*i)=0;
        end
        
        if Fb+d2<Fd+d1 %到达01状态的两条路径比较大小
            tempc=Fb+d2;%0-->10-->01  编码器输出10  0+1+0=1 0+0=0  
            tempmc=mb;
            tempmc(i)=0;
            tempoutc=outb;
            tempoutc(2*i-1)=1;
            tempoutc(2*i)=0;
        else
            tempc=Fd+d1;%0-->11-->01  编码器输出01  0+1+1=0 0+1=1
            tempmc=md;
            tempmc(i)=0;
            tempoutc=outd;
            tempoutc(2*i-1)=0;
            tempoutc(2*i)=1;
        end
        
        if Fb+d1<Fd+d2 %到达11状态的两条路径比较大小
            tempd=Fb+d1;%1-->10-->11 编码器输出01  1+1+0=0 1+0=1
            tempmd=mb;
            tempmd(i)=1;
            tempoutd=outb;
            tempoutd(2*i-1)=0;
            tempoutd(2*i)=1;
        else
            tempd=Fd+d2;%1-->11-->11 编码器输出10  1+1+1=1 1+1=0
            tempmd=md;
            tempmd(i)=1;
            tempoutd=outd;
            tempoutd(2*i-1)=1;
            tempoutd(2*i)=0;
        end
        Fa=tempa;
        Fb=tempb;
        Fc=tempc;
        Fd=tempd;
        
        ma=tempma;
        mb=tempmb;
        mc=tempmc;
        md=tempmd;
        
        outa=tempouta;
        outb=tempoutb;
        outc=tempoutc;
        outd=tempoutd;
    end
end


temp=min([Fa,Fb,Fc,Fd]);
if temp==Fa
    F=Fa
    m=ma
    x%再显示一遍接收数据x,便于和下面的进行对比
    out=outa
elseif temp==Fb
    F=Fb
    m=mb
    x%再显示一遍接收数据x,便于和下面的进行对比
    out=outb
elseif temp==Fc
    F=Fc
    m=mc
    x%再显示一遍接收数据x,便于和下面的进行对比
    out=outc
else
    F=Fd
    m=md
    x%再显示一遍接收数据x,便于和下面的进行对比
    out=outd
end 

%向result文件中输出译码结果
fid=fopen('result.txt','w');

fprintf(fid,'%d ',out);

fclose(fid);
function d=dis(m,n,g,h)
		 d=xor(m,g)+xor(n,h);
end

结果

F = 1
m =1 0 0 0 1 0 0

x = 1 1 1 0 1 1 0 0 1 1 0 0 1 1

out = 1 1 1 0 1 1 0 0 1 1 1 0 1 1

C++代码

#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<math.h>
using namespace std;


int main()
{
	char a[3][100] = { 0 };
	int op[100];
	int i, k, n, j, x, y, t;
	int x1[100], x2[100], x3[100], x4[100], sign[100][4];
	x2[0] = 0; x4[0] = 0;
	k = 0, j = 0, x = 0;
	cin >> i; //i为个数
	for (k; k < i; k++)
	{
		for (j=0; j < 3; j++)
		{
			cin >> a[j][k];
		}
	}
	
	for (k = 0; k < i; k++)
	{
		if (k == 0)
		{
			x = 0;
			if (a[0][0] != '0')x++;
			if (a[1][0] != '0')x++;
			if (a[2][0] != '0')x++;
			x1[0] = x;

			x = 0;
			if (a[0][0] != '1')x++;
			if (a[1][0] != '0')x++;
			if (a[2][0] != '0')x++;
			x3[0] = x;

			continue;
		}

		if (k == 1)
		{
			x = 0;
			if (a[0][1] != '0')x++;
			if (a[1][1] != '0')x++;
			if (a[2][1] != '0')x++;
			x1[1] = x + x1[0];

			x = 0;
			if (a[0][1] != '1')x++;
			if (a[1][1] != '0')x++;
			if (a[2][1] != '1')x++;
			x2[1] = x + x3[0];

			x = 0;
			if (a[0][1] != '1')x++;
			if (a[1][1] != '0')x++;
			if (a[2][1] != '0')x++;
			x3[1] = x + x1[0];

			x = 0;
			if (a[0][1] != '0')x++;
			if (a[1][1] != '1')x++;
			if (a[2][1] != '0')x++;
			x4[1] = x + x3[0];

			continue;
		}

		x = 0, y = 0;
		if (a[0][k] != '0')x++;
		if (a[1][k] != '0')x++;
		if (a[2][k] != '0')x++;
		x = x + x1[k - 1];
		if (a[0][k] != '0')y++;
		if (a[1][k] != '1')y++;
		if (a[2][k] != '0')y++;
		y = y + x2[k - 1];
		if (x <= y)
		{
			x1[k] = x;
			sign[k][0] = 1;
		}
		if (x > y)
		{
			x1[k] = y;
			sign[k][0] = 2;
		}

		x = 0, y = 0;
		if (a[0][k] != '1')x++;
		if (a[1][k] != '0')x++;
		if (a[2][k] != '1')x++;
		x = x + x3[k - 1];
		if (a[0][k] != '1')y++;
		if (a[1][k] != '1')y++;
		if (a[2][k] != '1')y++;
		y = y + x4[k - 1];
		if (x <= y)
		{
			x2[k] = x;
			sign[k][1] = 3;
		}
		if (x > y)
		{
			x2[k] = y;
			sign[k][1] = 4;
		}

		x = 0, y = 0;
		if (a[0][k] != '1')x++;
		if (a[1][k] != '0')x++;
		if (a[2][k] != '0')x++;
		x = x + x1[k - 1];
		if (a[0][k] != '1')y++;
		if (a[1][k] != '1')y++;
		if (a[2][k] != '0')y++;
		y = y + x2[k - 1];
		if (x <= y)
		{
			x3[k] = x;
			sign[k][2] = 1;
		}
		if (x > y)
		{
			x3[k] = y;
			sign[k][2] = 2;
		}

		x = 0, y = 0;
		if (a[0][k] != '0')x++;
		if (a[1][k] != '1')x++;
		if (a[2][k] != '0')x++;
		x = x + x3[k - 1];
		if (a[0][k] != '0')y++;
		if (a[1][k] != '1')y++;
		if (a[2][k] != '1')y++;
		y = y + x4[k - 1];
		if (x <= y)
		{
			x4[k] = x;
			sign[k][3] = 3;
		}
		if (x > y)
		{
			x4[k] = y;
			sign[k][3] = 4;
		}
	}

	k--;
	if (x1[k] <= x2[k] && x1[k] <= x3[k] && x1[k] <= x4[k])t = 0;
	if (x2[k] <= x1[k] && x2[k] <= x3[k] && x2[k] <= x4[k])t = 1;
	if (x3[k] <= x1[k] && x3[k] <= x2[k] && x3[k] <= x4[k])t = 2;
	if (x4[k] <= x1[k] && x4[k] <= x3[k] && x4[k] <= x2[k])t = 3;

	for (k; k >= 2; k--)
	{
		if (t==0||t==1)
		{
			op[k] = 0;
			t = sign[k][t]-1;
		}

		if (t==2||t==3)
		{
			op[k] = 1;
			t = sign[k][t]-1;
		}
	}

	if (t == 0)
	{
		op[1] = 0;
		op[0] = 0;
	}
	if (t == 1)
	{
		op[1] = 0;
		op[0] = 1;
	}
	if (t == 2)
	{
		op[1] = 1;
		op[0] = 0;
	}
	if (t == 3)
	{
		op[1] = 1;
		op[0] = 1;
	}

	t = 1;
	for (k = 0; k < i; k++)
	{
		if (op[k] == 0)
		{
			if (t == 1) {
				cout << "000"; t = 1; continue;
			}
			if (t == 2) {
				cout << "010"; t = 1; continue;
			}
			if (t == 3) {
				cout << "101"; t = 2; continue;
			}
			if (t == 4) {
				cout << "111"; t = 2; continue;
			}
		}
		if (op[k] == 1)
		{
			if (t == 1) {
				cout << "100"; t = 3; continue;
			}
			if (t == 2) {
				cout << "110"; t = 3; continue;
			}
			if (t == 3) {
				cout << "010"; t = 4; continue;
			}
			if (t == 4) {
				cout << "011"; t = 4; continue;
			}
		}
	}

	system("pause");
	return 0;
}


评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值