信息论与编码-(java实现信道容量的计算)

package schoolwork;
import java.util.*;

public class schoolwork2{
	public static Double log(Double data) {
		return Math.log(data)/Math.log(2);
	}
	
	//检验矩阵是否满足格式
	public static boolean check_format(int[][] arr,int m) {
		ArrayList<Integer> Array = new ArrayList();
		for(int i=0;i<m;i++) {
			int tag = 0;
			int index = 0;
			for(int j=0;j<m;j++) {
				if(arr[i][j] == 1) {
					tag++;
					index = j;
				}
				if(tag>1)
					return false;
			}
			if(tag != 1)
				return false;
			else {
				if(Array.contains(index))
					return false;
				else {
					Array.add(index);		
				}
			}
				
		}
		return true;
	}
	
	//扩展性的无损信道
	public static boolean expand(double[][] arr,int n,int m) {
		ArrayList<Integer> arrs = new ArrayList<Integer>();
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++) {
				if(arr[i][j] != 0)
					if(arrs.contains(j)) {
						return false;
					}else {
						arrs.add(j);
					}
			}
		}
		return true;
	}
	
	//归并性的无噪信道
	public static boolean conflation(int[][] arr,int n,int m) {
		//数据只能是1或者0
		for(int i=0;i<n;i++) {
			int sum = 0;
			for(int j=0;j<m;j++) {
					if(arr[i][j] == 0 || arr[i][j] == 1) {
						sum += arr[i][j];
					}else {
						return false;
				}
			}
			if(sum !=1)
				return false;
		}
		return true;
	}
	
	//打印信道矩阵
	public static void Print_All(int[][] arr,int n,int m) {
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++) {
				System.out.print(arr[i][j] + "\t");
			}
			System.out.println("");
		}
	}
	
	public static String Cal_PointToPoint(int m) {
		double m1 = Double.valueOf(m);
		m1 = log(m1);
		String str_1 = String.format("%.4f", m1);
		return str_1;
		
	}
	
	// 强对称信道
	public static void Init(double[][] arr,int n,double p) {		//自动生成强对称信道矩阵
		double p1 = 1-p;
		double p2 = p1/(n-1);
		String tmp_p1 = String.format("%.3f", p2);
		double p3 = Double.valueOf(tmp_p1);
		for(int i=0;i<n;i++) {
			for(int j=0;j<n;j++) {
				if(i == j)
					arr[i][j] = p;
				else
					arr[i][j] = p3;
			}
		}
	}
	 
	//打印信道矩阵
	public static void Print_All(double[][] arr,int n,int m) {
		for(int i=0;i<n;i++) {
			for(int j=0;j<m;j++) {
				System.out.print(arr[i][j] + "\t");
			}
			System.out.println("");
		}
	}
	
	//计算信道容量
	public static void Calculate_2(double[][] arr,int n,double p) {
		double p1 = 1-p;
		double part1 = log(Double.valueOf(n));
		double part2 = p*log(p);
		double tmp_data = p1/(n-1);
		double part3 = p1*log(tmp_data);
		String data = String.format("%.4f", (part1+part2+part3));
		System.out.println("信道容量C = "+ data + "(bit/sign)");
	}
	
	// 离散对称信道
	//输入数据
	public static void Input_Data(double[][] arr,int n,int m) {
		Scanner in = new Scanner(System.in);
		for(int i=0;i<n;i++) {
			System.out.println("第" + (i+1) + "行信道矩阵的数");
			String tmp = in.nextLine();
			String[] tmp_data = tmp.split(" ");
			
			if(tmp_data.length != m) {
				System.out.println("Error!");
				System.exit(-1);
			}
			
			//处理输入的分数
			for(int j=0;j<m;j++) {
				String[] tmps = tmp_data[j].split("/");
				if(tmps.length == 2) {
					String a1 = tmps[0];
					String a2 = tmps[1];
					Double s1 = Double.valueOf(a1);
					Double s2 = Double.valueOf(a2);
					Double tmps_datas = s1/s2;
					String deal = String.format("%.3f", tmps_datas);
					tmp_data[j] = deal;
				}else if(tmps.length == 1){
					tmp_data[j] = tmps[0];
				}else {
					System.out.println("Error!");
					System.exit(-1);
				}
			}
			
			for(int j=0;j<m;j++) {
				
				double tmp_double = Double.valueOf(tmp_data[j]);
				if(tmp_double > 0 && tmp_double < 1) {
					arr[i][j] = tmp_double;
				}else {
					System.out.println("Error!");
					System.exit(-1);
				}
						
			}
		}
	}
	
	//检查输入的信道矩阵是否满足行和列可排列
	public static boolean check_all(double[][] arr,int n,int m) {
		//step1:取第一行的数据作为集合1, step2:取第二行的数据作为集合2
		ArrayList<Double> arr1 = new ArrayList<Double>();
		ArrayList<Double> arr2 = new ArrayList<Double>();
		for(int i=0;i<m;i++) {
			arr1.add(arr[0][i]);
		}
		for(int i=0;i<n;i++) {
			arr2.add(arr[i][0]);
		}
		//遍历行
		for(int i=0;i<n;i++) {
			ArrayList<Double> tmp_arr = new ArrayList<Double>();
			for(int j=0;j<m;j++) {
				tmp_arr.add(arr[i][j]);
			}
			if(!arr1.containsAll(tmp_arr)) {
				return false;
			}
		}
		for(int i=0;i<m;i++) {
			ArrayList<Double> tmp_arr = new ArrayList<Double>();
			for(int j=0;j<n;j++) {
				tmp_arr.add(arr[j][i]);
			}
			if(!arr2.containsAll(tmp_arr))
				return false;
		}
		return true;
	}
	
	//计算信道容量
	public static void Cal_All(double[][] arr,int n,int m) {
		double part1 = log(Double.valueOf(m));
		double part2 = 0;
		for(int i=0;i<m;i++) {
			part2 += arr[0][i]*log(arr[0][i]);
		}
		String data = String.format("%.4f", part1+part2);
		System.out.println("信道容量C = " + data + "(sign/bit)");
		
		
	}
	
	//准对称离散信道
	
	//寻找分割位置,返回m
	public static int find_location(double[][] arr,int n,int m) {
		for(int i=0;i<=m;i++) {		//从一列开始分割
			double[][] tmp1 = new double[n][i+1];
			double[][] tmp2 = new double[n][m-i-1];
			//分别给两部分赋值
			for(int k=0;k<n;k++) {
			for(int j=0;j<i+1;j++) {
				tmp1[k][j] = arr[k][j];
			}
			}
			
			
			for(int k=0;k<n;k++) {
				int index = i+1;
				for(int j=0;j<m-i-1;j++) {
					if(index < m) { 
					tmp2[k][j] = arr[k][index];
					index++;
					}else
						break;
				}
			}
			if(check_all(tmp1,n,i+1) && check_all(tmp2,n,m-i-1)) {
				System.out.println("划分信道矩阵如下:");
				System.out.println("第一部分");
				Print_All(tmp1,n,i+1);
				System.out.println("第二部分");
				Print_All(tmp2,n,m-i-1);
				return i;
			}
		}
		return 0;
	}
	
	//计算第一部分的值
	public static double cal_part_one(double[][] arr,int n,int m,int point) {
		//计算pb1
		double pb1 = 0.0;
		for(int i=0;i<n;i++) {
			pb1 += arr[i][0]/n;
		}
		return pb1;
	}
	
	//计算第二部分的值
	public static double cal_part_two(double[][] arr,int n,int m,int point) {
		//计算pb2
		double pb2 = 0;
		for(int i=0;i<n;i++) {
			pb2 += arr[i][point+1]/n;
		}
		return pb2;
	}
	
	public static void Cal(double[][]arr,int n,int m,double pb1,double pb2,int point) {
		int m1 = point+1;
		int m2 = m-(point+1);
		double part1 = -1*m1*pb1*log(pb1)-1*m2*pb2*log(pb2);
		double part2 = 0;
		for(int i=0;i<m;i++) {
			part2 += arr[0][i]*log(arr[0][i]);
		}
		double data = part1 + part2;
		String datas = String.format("%.4f", data);
		System.out.println("信道容量C = " + datas + "(bit/sign)");
	}
	
	// 离散信道容量的一般计算
	//计算多元一次方程组的解
	public static double[] Mulcal(double[][] a) {
		int rows = a.length;
		int cols = a[0].length;
		int L = rows - 1;
		int i,j,l,m,n,k=0;
		double[] tmp1 = new double[rows];
		do {
			n = 0;
			for(l = k;l < L;l++) {
				tmp1[n++] = a[l+1][k]/a[k][k];
			}
			for(m = 0,i = k+1;i<rows;i++,m++) {
				for(j=k;j<cols;j++)
					a[i][j] -= tmp1[m] * a[k][j];
			}
			k++;
		}
		while(k<rows);
		
		k = L -1;
		do {
			n=0;
			for(l=k;l>=0;l--) {
				tmp1[n++] = a[k-l][k+1]/a[k+1][k+1];
			}
			for(m=0,i=k;i>=0;i--,m++) {
				for(j=k;j<cols;j++)
					a[k-i][j] -= tmp1[m]*a[k+1][j];
			}
			k--;
		}
		while(k>=0);
		double[] result = new double[rows];
		for(i=0;i<rows;i++) {
			result[i] = a[i][rows] / a[i][i];
		}
		return result;
	}
	
	//赋值
	public static double[][] Cover(double[][] a,int n,int m){
		double[][] tmp_data = new double[n][m+1];
		for(int i=0;i<n;i++) {
			double total = 0.0;
			for(int j=0;j<m+1;j++) {
				if(j==m) {
					tmp_data[i][j] = total;
				}else {
					total += a[i][j]*log(a[i][j]);
					tmp_data[i][j] = a[i][j];
				}
			}
				
		}
		return tmp_data;
	}
	
	//求解信道容量
	public static double Cal_A(double[] result) {
		double tmp_data = 0.0;
		for(int i=0;i<result.length;i++) {
			tmp_data += Math.pow(2, result[i]);
		}
		double C = log(tmp_data);
		String C1 = String.format("%.4f", C);
		System.out.println("信道容量C = " + C1 + "(bit/sign)");
		return C;
	}
	
	//求解pb
	public static double[] Cal_pb(double[] result,double C) {
		double[] tmp_Data = new double[result.length];
		for(int i=0;i<result.length;i++) {
			double mid_tmp = result[i]-C;
			double tmp = Math.pow(2,mid_tmp);
			tmp_Data[i] = tmp;
		}
		return tmp_Data;
		
		
	}
	
	public static double[] Cal_pa(double[][] arr,double[] result,int n,int m) {
		double[][] a = new double[m][n+1];
		for(int i=0;i<m;i++) {
			for(int j=0;j<n+1;j++) {
				if(j==n)
					a[i][j] = result[i];
				else
					a[i][j] = arr[j][i];
			}
		}
		double[] results = Mulcal(a);
		return results;
	}
	
	public static void main(String[] args) {
		
		while(true) {
		System.out.println("************************************************");
		System.out.println("#	1、计算无噪信道的信道容量");
		System.out.println("#	2、计算强对称(均匀)离散信道的信道容量");
		System.out.println("#	3、计算离散对称信道的信道容量");
		System.out.println("#	4、计算准对称离散信道的信道容量");
		System.out.println("#	5、计算一般离散信道的信道容量");
		System.out.println("************************************************");
		Scanner in = new Scanner(System.in);
		int select = in.nextInt();
		
		switch(select) {
		case 1:
			int m,n;
			String inputs;
			String [] tmp;
			System.out.print("请输入信源符号个数:");
			n = in.nextInt();
			System.out.print("请输入信宿符号个数:");
			m = in.nextInt();
			if(n==m) {			//一一对应
				int[][] arr_one = new int[n][m];
				for(int i=0;i<n;i++) {
					System.out.print("请输入第" + (i+1) + "行数:");
					Scanner inpus = new Scanner(System.in);
					String[] tmp_data = inpus.nextLine().split(" ");
					if(tmp_data.length != m) {
						System.out.println("Error!");
						System.exit(-1);
					}
					for(int j=0;j<m;j++) {
						arr_one[i][j] = Integer.parseInt(tmp_data[j]);
					}
				}
				if(check_format(arr_one,n)) {
					System.out.println("输出信道矩阵:");
					Print_All(arr_one,n,m);
					String C = Cal_PointToPoint(n);
					System.out.println("信道容量C = " + C + "(bit/sign)");
				}
				
			}else if(n<m) {		//扩展的无损信道
				double[][] arr_one = new double[n][m];
				for(int i=0;i<n;i++) {
					System.out.print("第" + (i+1) + "行数:");
					Scanner inpus = new Scanner(System.in);
					String[] tmp_data = inpus.nextLine().split(" ");
					if(tmp_data.length != m) {
						System.out.println("Error!");
						System.exit(-1);
					}
					double sum = 0.0;
					for(int j=0;j<m;j++) {
						double tmps = Double.parseDouble(tmp_data[j]);
						if(tmps>=0 &&tmps <=1) {
							arr_one[i][j] = tmps;
							sum += tmps;
						}else {
							System.out.println("Error!");
							System.exit(-1);
						}
					}
					if(sum != 1.0) {
						System.out.println("Error!");
						System.exit(-1);
					}
				}
				if(expand(arr_one,n,m)) {
					System.out.println("输出信道矩阵:");
					Print_All(arr_one,n,m);
					String C = Cal_PointToPoint(n);
					System.out.println("信道容量C = " + C + "(bit/sign)");
				}else {
					System.out.println("不符合扩展无噪信道的特征!!");
					System.exit(-1);
				}
				
				
				
				
			}else {			//归并的无损信道
				int[][] arr_one = new int[n][m];
				for(int i=0;i<n;i++) {
					System.out.print("第" + (i+1) + "行数:");
					Scanner inpus = new Scanner(System.in);
					String[] tmp_data = inpus.nextLine().split(" ");
					if(tmp_data.length != m) {
						System.out.println("Error!");
						System.exit(-1);
					}
					for(int j=0;j<m;j++) {
						arr_one[i][j] = Integer.valueOf(tmp_data[j]);
					}
				}
				if(conflation(arr_one,n,m)) {
					System.out.println("输出信道矩阵:");
					Print_All(arr_one,n,m);
					String C = Cal_PointToPoint(m);
					System.out.println("信道容量C = " + C + "(bit/sign)");
				}else {
					System.out.println("不符合归并无噪信道的特征!!");
					System.exit(-1);
				}
			}
			
			
		break;
		
		case 2:
			int n1;
			double p;
			System.out.println("请输入信源符号个数");
			n1 = in.nextInt();
			double[][] arr2 = new double[n1][n1];
			System.out.println("请输入符号正确传输概率");
			p = in.nextDouble();
			if(p>0&&p<=1) {
				Init(arr2,n1,p);
				System.out.println("打印信道矩阵:");
				Print_All(arr2,n1,n1);
				Calculate_2(arr2,n1,p);
			}
			
			break;
			
		//离散对称信道容量
		case 3:
			int n2,m2;
			System.out.println("请输入信源符号个数");
			n2 = in.nextInt();
			System.out.println("请输入信宿符号个数");
			m2 = in.nextInt();
			double[][] arr3 = new double[n2][m2];
			Input_Data(arr3,n2,m2);
			Print_All(arr3,n2,m2);
			if(check_all(arr3,n2,m2)) {
				Cal_All(arr3,n2,m2);
			}else {
				System.out.println("不符合对称信道的特征");
				System.exit(-1);
			}
			
			break;
		
		
		case 4:
			int n3,m3;
			System.out.println("请输入信源符号个数");
			n3 = in.nextInt();
			System.out.println("请输入信宿符号个数");
			m3 = in.nextInt();
			double[][] arr4 = new double[n3][m3];
			Input_Data(arr4,n3,m3);
			Print_All(arr4,n3,m3);
			int point = find_location(arr4,n3,m3);
			double pb1,pb2;
			pb1 = cal_part_one(arr4,n3,m3,point);
			pb2 = cal_part_two(arr4,n3,m3,point);
			Cal(arr4,n3,m3,pb1,pb2,point);
			break;
			
		case 5:
			int n4,m4;
			System.out.println("请输入信源符号个数");
			n4 = in.nextInt();
			System.out.println("请输入信宿符号个数");
			m4 = in.nextInt();
			double[][] arr5 = new double[n4][m4];
			Input_Data(arr5,n4,m4);
			Print_All(arr5,n4,m4);
			double[][] tmp_arr5 = Cover(arr5,n4,m4);		//使用矩阵存储多元一次方程
			double[] result = Mulcal(tmp_arr5);
			/*
			for(double i : result) {
				System.out.println(i);
			}
			*/
			double C = Cal_A(result);
			//pb的值
			double[] result2 = Cal_pb(result,C);
			//最佳输入分布
			double[] result3 = Cal_pa(arr5,result2,n4,m4);
			System.out.println("最佳输入分布概率:");
			int tag = 1;
			for(double i : result3) {
				String tmps = String.format("%.3f", i);
				System.out.println("P(x" + tag + ") = " + tmps);
				tag++;
			}
			
			
			break;
		default:break;
		}
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值