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;
}
}
}
}
信息论与编码-(java实现信道容量的计算)
最新推荐文章于 2023-12-09 20:30:12 发布