Viterbi算法信号处理Demo

来源:互联网 发布:卖家怎么淘宝客推广 编辑:程序博客网 时间:2024/05/17 23:01


  • 问题描述
    • 问题要求

信道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为-1double 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;elsemessage[len-1] = 10;for(j=len-2;j>=0;j--){if(message[j+1] == -10)message[j] = minRoadIndex[j+1][0]*10;elsemessage[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;elsex[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;elsex[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];elsemessage[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
原创粉丝点击