问题描述
信道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; import java.util.Random; /** *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];//记录每一个阶段的最短路的序号,X为1或-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; } } /** * 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; } } /** * 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();//记录枚举算法结束时间 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)); } }
运行结果