Viterbi算法信号处理Demo

本文通过一个具体的通信信号处理示例,详细介绍了如何使用Viterbi算法来处理信道中的噪声。Viterbi算法是一种动态规划方法,用于在存在噪声的通信系统中找到最有可能的信号序列。在实验中,信道长度为3,基本信号为10或-10,噪声是高斯分布的随机数。通过算法思路和实现代码,展示了Viterbi算法的有效性,并给出了运行结果。
摘要由CSDN通过智能技术生成


  • 问题描述
    • 问题要求

信道H长度L=3,H = (h0,h1,h2),其中h0=,h1=,h2=; 基本信号类型 x =10或-10,一个完整的信号序列为X = (x0,x1,x2,...,x9);噪声W = (w0,w1,w2,...,w11)是满足高斯分布的(0,1)范围内的随机数;按照

Y = H·X + W公式转换得到一个完整的信号序列Y = (y0,y1,y2,...,y11)。信号接收端需要在已知Y,H的情况下通过Viterbi算法得到满足 min (W)即 min(Y - H·X)的X`序列。
  • 算法思路

将问题转换为的篱笆图,通过动态规划算法,以min(Y - H·X)为图中每一条边的权值计算公式,从显性序列 Y 推导得到隐性序列 X。

  • 实现代码
package cn.edu.karel.algorithm.wirelesschannel;

/**
 *Decoder类
 * 
 * @author Karel Zuo
 * @time 2015.5.18
 * @version 1.0
 * @description 
 *   该类模拟无线通信过程,接收信息后采用维特比算法或者枚举算法消除噪音并解码。
 */

public class Decoder
{
	/** 接收到的信号*/
	double receive[];
	/** 去噪解码后的信息 */
	int[] message;
	/** 接收信号的通信信道*/
	double h[];
	/** 接收信号的基本信号类型*/
	int signal[];
	/**信道矩阵*/
	double H[][];
			
	/** 
	 * @param receive 接收到的信号(Y)
	 * @return message 除噪并解码后得到的信号
	 */
	public void decodeByViterbi( double receive[])
	{
		int len = receive.length-(h.length-1);//原信号长度
		int n = signal.length;//信号基本类型数
		int minRoadIndex[][] = new int[len][n];//记录每一个阶段的最短路的序号,1表示前一个X为1,-1表示前一个X为-1
		double minRoadValue[][] = new double[len][n];//记录每一个阶段的从原点到该点最短路的权值
		
		/**计算每一个阶段的最短路权值和选择最短路*/
		int i,j;
		for(i=0;i<len;i++)
		{		
			/**初始化原顶点层 */
			if(i==0)
			{
				minRoadIndex[i][0] = 0;
				minRoadIndex[i][1] = 0;
				
				minRoadValue[i][0] = h[0]*-10;
				minRoadValue[i][1] = h[0]*10;
			}
			else
			{
				/**计算各个路径的距离和该Xi到原点S的距离*/
				int q,p;
				for(q=0;q<n;q++)//遍历第Xi的所有可能取值
				{
					double temp[] = new double[2];
					for(p=0;p<n;p++)//遍历Xi-1的所有可能取值
					{
						temp[p] = getValue(i, q, p, minRoadIndex)+minRoadValue[i-1][p];
					}
					
					if(temp[0] <temp[1])
					{
						minRoadIndex[i][q] = -1;
						minRoadValue[i][q] = temp[0];
					}
					else
					{
						minRoadIndex[i][q] = 1;
						minRoadValue[i][q] = temp[1];
					}
				}
			}
		}
		
		/** 输出解码结果 */
		message = new int[len];
		if(minRoadValue[len-1][0] < minRoadValue[len-1][1])
			message[len-1] = -10;
		else
			message[len-1] = 10;
		for(j=len-2;j>=0;j--)
		{
			if(message[j+1] == -10)
				message[j] = minRoadIndex[j+1][0]*10;
			else
				message[j] = minRoadIndex[j+1][1]*10;
		}
		
		System.out.println("");
		System.out.println("");
		System.out.print("Viterbi算法解码后的信号 :");
		for(j=0;j<len;j++)
			System.out.print(message[j] + " , ");	
	}
	
	/** 
	 * @param receive 接收到的信号(Y)
	 * @return message 除噪并解码后得到的信号
	 */
	public void decodeByEnum(double receive[])
	{
		int len_y = receive.length;//接收信号长度
		int len_x = len_y-(h.length-1);//原信号长度
		int num = (int) Math.pow(signal.length, len_x );
		int x[][] = new int[num][len_x ]; 
		double value[] = new double[num];
		
		/** 枚举所有信号组合形式及其路径长度*/
		x = enmuSignal(len_x ,num);
		
		int p,q,k;
		for(p=0;p<num;p++)
		{
			double temp = 0;
			for(q=0;q<len_y;q++)
			{
				temp = 0;
				for(k=0;k<len_x ;k++)
				{
					temp += x[p][k]*H[q][k];
				}
				value[p] += Math.pow((receive[q]-temp), 2); 
			}
		}
		
		/** 搜索到最短路径的组合 */
		int minRoad = 0;
		double minValue = value[minRoad];
		int n;
		for(n=1;n<num;n++)
		{
			if(value[n]<minValue)
			{
				minRoad = n;
				minValue = value[n];
			}
		}
		/**输出,测试 */
		System.out.println("枚举算法结果:  ");
		for(n=0;n<len_x;n++)
			System.out.print(x[minRoad][n] + " , ");	
		System.out.println("");
	}
	
	/** 
	 * 接收信号及其他参数
	 * @param en 发送方类对象
	 */
	public void getSignal(Encoder en)
	{
		this.receive = new double[(Encoder.sendMessage.length)];
		this.receive = Encoder.sendMessage;
		this.h = new double[Encoder.h.length];
		this.h = Encoder.h;
		this.signal = new int[Encoder.signal.length];
		this.signal = Encoder.signal;
		
		/**初始化信道矩阵*/
		int len = receive.length-(h.length-1);
		H = new double[receive.length][len];//信道矩阵
		int i,j;
		for(i=0;i<len;i++)
		{
			for(j=i;j<(i+h.length);j++)
				H[j][i] = h[(j-i)];
		}
	}
	
	/**
	 * 计算Xi到Xi-1的边长
	 * @param index 当前x的下标
	 * @param cur_X 当前xi的取值序号(0,1)
	 * @param per_X 当前xi-1的取值序号(0,1)
	 * @param minRoadIndex 记录Xi到Xi-1的最短路时,Xi-1的取值
	 * @return value 边长
	 */
	public double getValue(int index, int cur_X, int per_X, int minRoadIndex[][])
	{
		double value = 0;
		int x[] = new int[10];//x的序列
		
		if(cur_X == 0)
			x[index] = -10;
		else 
			x[index] =10;
		
		if(per_X == 0)
			x[index-1] = -10;
		else
			x[index-1] = 10;
		
		
		if(index >= 2)
		{
			int i;
			for(i=(index-2);i>=0;i--)
			{
				if(x[i+1] == -10)
					x[i] = minRoadIndex[i][0]*10;
				else
					x[i] = minRoadIndex[i][1]*10;	
			}
		}
		
		int i;
		for(i=0;i<10;i++)
			value += x[i]*H[index][i];
		value = Math.pow((receive[index]-value),2); 
		
		return value;
	}
	
	/**递归实现信号转态的枚举 
	 * @param len X序列的长度
	 * @param num X的组合总数
	 * @return x 所有枚举组合
	 * */
	public int[][] enmuSignal(int len,int num)
	{
		int m = 0;
		int i[] = new int[len];
		int x[][] = new int[num][len];
		int n = signal.length;
		
		for(i[0]=0;i[0]<n;i[0]++){
			for(i[1]=0;i[1]<n;i[1]++){
				for(i[2]=0;i[2]<n;i[2]++){
					for(i[3]=0;i[3]<n;i[3]++){
						for(i[4]=0;i[4]<n;i[4]++){
							for(i[5]=0;i[5]<n;i[5]++){
								for(i[6]=0;i[6]<n;i[6]++){
									for(i[7]=0;i[7]<n;i[7]++){
										for(i[8]=0;i[8]<n;i[8]++){
											for(i[9]=0;i[9]<n;i[9]++){
												int j;
												for(j=0;j<len;j++)
													x[m][j]=signal[(i[j])];
												m++;
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
		
		return x;
	}
}

package cn.edu.karel.algorithm.wirelesschannel;

import java.util.Random;

/**
 * Encoder类
 * 
 * @author Karel Zuo
 * @time 2015.5.18
 * @version 1.0
 * @description 
 *   该类模拟无线通信过程,发送信息 X 经过编码得到H·X ,在传输过程中受到干扰变成 H·X + W ,并被接收。
 */

public class Encoder 
{
	/** 信道总数 */
	static final int L = 3;
	/** 基本信号 */
	static final int signal[] = {10,-10};
	/** H */
	static final double h[] = {0.8, 0.4, 0.2};
	/** 信号长度  */
	static final int SUM_X = 10;
	/** 噪声数量 */
	static final int SUM_W = 12;
	/** 最终发送的信号 */
	public static double sendMessage[];
	
	public Encoder()
	{
		sendMessage = new double[SUM_W];
		sendMessage = getMessage(creatMessage());
	}
	
	/**
	 * @param signal[] 基本信号
	 * @return message[] 随机产生的一段信号
	 */
	public int[] creatMessage()
	{
		int message[] = new int[SUM_X];//随机产生并返回的一段信号信息
		int i;
		Random r = new Random(); 
		
		for(i=0;i<SUM_X;i++)
		{
			if(r.nextInt(10) < 5)
				message[i] = signal[0];
			else
				message[i] = signal[1];
		}
		
		/**输出,测试结果*/
		System.out.println(" 随机生成的发送序列 X:");
		for(i=0;i<SUM_X;i++)
			System.out.print(message[i]+" , ");
		System.out.println(" ");
		
		return message;
	}
	
	/**
	 * @param message[] 原始信号
	 * @return receive[] 接收到的信号
	 */
	public double[] getMessage(int message[])
	{
		double H[][] = new double[SUM_W][SUM_X];//信道矩阵
		double receive[] = new double[SUM_W];//接收信号矩阵
		int i,j;
		Random r = new Random();
		
		/** 初始化 H 矩阵 */
		for(i=0;i<SUM_X;i++)
			for(j=i;j<(i+h.length);j++)
				H[j][i] = h[(j-i)];
			
		/** 矩阵运算 Y = H·X +W */
		for(i=0;i<SUM_W;i++)
		{
			for(j=0;j<SUM_X;j++)
				receive[i] += H[i][j]*message[j];
			receive[i] += r.nextGaussian();
		}
		
		/** 输出,测试 */
		System.out.println("");
		System.out.println("");
		System.out.println(" 输出信号 Y :");
		for(i=0;i<SUM_W;i++)
			System.out.println(receive[i] + " , ");
		System.out.println("");
		
		return receive;
	}
}
package cn.edu.karel.algorithm.wirelesschannel;

/**
 * Test类
 * 
 * @author Karel Zuo
 * @time 2015.5.18
 * @version 1.0
 * @description 
 *   该类模拟无线通信过程。
 */
public class Test {

	public static void main(String[] args) {
		
		/** 随机生成信号并用Viterbi算法和枚举算法分别还原信号 */
		Encoder en = new Encoder();
		Decoder de = new Decoder();
		de.getSignal(en);
	
		long startEnum = System.currentTimeMillis();//记录枚举算法开始时间
		de.decodeByEnum(de.receive);
		long endEnum = System.currentTimeMillis();//记录枚举算法结束时间(Viterbi算法开始时间)
		long startViterbi = System.currentTimeMillis();//Viterbi算法开始时间
		de.decodeByViterbi(de.receive);
		long endViterbi = System.currentTimeMillis();//记录Viterbi算法结束时间
		
		
		/**输出程序运行时间 */
		System.out.println(" ");
		System.out.println("枚举算法执行时间: " + (endEnum - startEnum));
		System.out.println("Viterbi算法执行时间: " + (endViterbi - startViterbi));
	}

}
  • 运行结果







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值