import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.StringTokenizer;
import java.util.Vector;
public class 解矩阵方程 {
/**
* 法1:高斯消元法
* 法2:高斯-若当法
* 法3:LLT(正定对称矩阵)
* 法4:LDLT(对称矩阵)
*/
public static void main(String[] args)
{/*
double a[][]=new double[2][2];
double b[]=new double[2];
readText(a, b,"高斯法解方程.txt");
double c[]=GaoSi(a,b);
for(int i=0;i<2;i++)
System.out.println(c[i]);
*/
//高斯法
//double a[][]={{21,67,88,73},{76,63,7,20},{0,85,56,54},{19.3,43,30.2,29.4}};
//double b[]={141,109,218,93.7};
double a[][]={{370.0 ,34.0} ,{ 34.0 , 5}};
double b[]={563.0 ,58.3};
double c[]=GaoSi(a,b);
SaveDoubleMatrix(c,4);
System.out.println("高斯法,解方程组:");
for(int i=0;i<2;i++)
System.out.print(c[i]+", ");
//LDLT(对称矩阵)
double a2[][]={{1,2,3},{2,1,-2},{3,-2,1}};
double b2[]={-3,10,7};
double c2[]=LDLT(a2,b2);
System.out.println();
System.out.println("LDLT法,解方程组:");
for(int i=0;i<3;i++)
System.out.print(c2[i]+", ");
/*
double a[][]=new double[2][2];
double b[]=new double[2];
readText(a, b,"高斯法解方程.txt");
double c[]=Gaosi(a,b);
for(int i=0;i<2;i++)
System.out.println(c[i]);
double a2[][]=new double[3][3];
double b2[]=new double[3];
readText(a2, b2,"LDLT解方程.txt");
double c2[]=LDLT(a2,b2);
for(int i=0;i<3;i++)
System.out.println(c2[i]);
*/
/*
double a[][]={{3,-1,-1},{-1,3,-1},{-1,-1,3}};
double b[]={1,5,8};
double c[]=LLT(a,b);
SaveDoubleMatrix(c,4);
for(int i=0;i<3;i++)
System.out.println(c[i]);
/*
/*
double a[][]={{2,1},{1,1}};
double b[]={3,2};
b=GaoSi_ruoDang(a,b);
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
System.out.print(a[i][j]+" ");
}
System.out.println();
}
for(int i=0;i<2;i++)
{
System.out.println(b[i]);
}
*/
}
public static void readText(double [][]a, double []c,String fileName)
{
int size=c.length;
try
{
BufferedReader read=new BufferedReader(new FileReader("src/"+fileName));
String line;
StringTokenizer token;
for(int i=0;i<size;i++)
{
line=read.readLine();
token=new StringTokenizer(line);
for(int j=0;j<size;j++)
a[i][j]=Double.parseDouble(token.nextToken());
}
for(int i=0;i<size;i++)
c[i]=Double.parseDouble(read.readLine());
read.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
//高斯法,求解矩阵
//不改变系数矩阵、常量矩阵的值,返回解矩阵
public static double[] GaoSi(double[][]a, double []c)
{
int size=a.length;
double sa[][]=new double[size][size];//存储系数矩阵a
double sc[]=new double[size];//存储常数矩阵c
for(int i=0;i<size;i++)//对sa,c初始化
{
for(int j=0;j<size;j++)
sa[i][j]=a[i][j];
sc[i]=c[i];
}
for(int i=0;i<size-1;i++)//循环
{
for(int j=i+1;j<size;j++)//行循环
{
double bei=sa[j][i]/sa[i][i];
for(int k=i;k<size;k++)//列循环
sa[j][k] -= sa[i][k]*bei;
sc[j] -=sc[i]*bei;
}
}
sc=backFromBottom(sa,sc);
return sc;
}
//高斯-若当法
//不改变系数矩阵、常量矩阵的值,返回解矩阵
public static double [] GaoSi_ruoDang(double[][]a, double []c)
{
int size=a.length;
double sa[][]=new double[size][size];
double sc[]=new double[size];
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
sa[i][j]=a[i][j];
sc[i]=c[i];
}
for(int i=0;i<size;i++)//循环
{
for(int j=0;j<size;j++)//行循环
{
if(i!=j)
{
double bei=sa[j][i]/sa[i][i];
for(int k=i;k<size;k++)//列循环
sa[j][k] -= sa[i][k]*bei;
sc[j] -= sc[i]*bei;
}
}
}
for(int i=0;i<size;i++)//得到最终的解
sc[i] /= sa[i][i];
return sc;
}
//回代,从上往下
public static double[] backFromTop(double [][]a,double [] c)
{
double sum=0;
int size=c.length;
double []r=new double[size];//r:存放结果
for(int i=0;i<size;i++)
r[i]=c[i];
for(int i=0;i<size;i++)//逐个求解r[i]
{
sum=0;
for(int j=0;j<i;j++)
sum += a[i][j] * r[j];
r[i] = (r[i]-sum)/a[i][i];
}
return r;
}
// 回代(从下往上)
public static double[] backFromBottom(double [][]a,double [] c)
{
double sum=0;
int size=c.length;
double []r=new double[size];//r:存放结果
for(int i=0;i<size;i++)
r[i]=c[i];
for(int i=size-1;i>=0;i--)//逐个求解r[i]
{
sum=0;
for(int j=size-1;j>i;j--)
sum += a[i][j] * r[j];
r[i] = (r[i]-sum)/a[i][i];
}
return r;
}
//实现对double类型的a,保留size位小数(最后一位,四舍五入)
public static double SaveDouble(double a, int size)
{
double sum=1;
for(int i=0;i<size;i++)
sum *= 10;
if(a>0)
return (int)(a*sum+0.5)/sum;
else
return (int)(a*sum-0.5)/sum;
}
public static void SaveDoubleMatrix(double []a, int size)
{
for(int i=0;i<a.length;i++)
a[i]=SaveDouble(a[i],size);
}
//LDLT方法(针对正定对称矩阵)
public static double[] LLT(double [][]a, double []c)
{
int size=a.length;
double sa[][]=new double[size][size];
double sc[]=new double[size];
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
sa[i][j]=a[i][j];
sc[i]=c[i];
}
for(int j=0;j<size;j++)//列循环
{
sa[j][j]=Math.pow(sa[j][j], 0.5);
for(int i=j+1;i<size;i++)//调整当前列
{
sa[i][j] /= sa[j][j];
}
for(int k=j+1;k<size;k++)
{
for(int i=k;i<size;i++)
{
sa[i][k] -= Math.pow(sa[i][j], 2);
}
}
}
sc=backFromTop(sa,sc);
for(int i=0;i<size;i++)//得到L的转置
{
for(int j=0;j<i;j++)
{
sa[j][i]=sa[i][j];
sa[i][j]=0;
}
}
sc=backFromBottom(sa,sc);
return sc;
}
//LDLT法求解对称正定矩阵
//不改变系数矩阵、常量矩阵的值,返回解矩阵
public static double[] LDLT(double [][]a, double []c)
{
int size=a.length;
double l[][]=new double[size][size];
double sc[]=new double[size];
double d[]=new double[size];
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
if(i==j)
l[i][j]=1;
else
l[i][j]=0;
}
sc[i]=c[i];
d[i]=1;
}
double sum=0;
for(int j=0;j<size;j++)//列循环
{
for(int i=j;i<size;i++)
{
if(i==j)
{
sum=0;
for(int k=0;k<j;k++)
{
sum += d[k]*l[i][k]*l[i][k];
}
d[j]=a[j][j]-sum;
}
else
{
sum=0;
for(int k=0;k<j;k++)
{
sum += l[i][k]*l[j][k]*d[k];
}
l[i][j]=(a[i][j]-sum)/d[j];
}
}
}
sc=backFromTop(l,sc);
for(int i=0;i<size;i++)//得到L的转置
{
for(int j=0;j<i;j++)
{
l[j][i]=l[i][j];
l[i][j]=0;
}
}
for(int i=0;i<size;i++)//得到 (D的逆)*y
sc[i]=sc[i]/d[i];
sc=backFromBottom(l,sc);
return sc;
}
}