1)2)LU分解(是/否部分主元法)+
3)施密特(Schmidt)QR分解 +
4)吉文斯(Givens)QR分解 +
5)Household QR分解 代码详解
可直接运行版本复测试用例(java8版)
更改测试用例:更改主方法内数组数据,或直接重写I/O流
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class Fractorization {
public static void main(String args[]){
run(LUFractorization(new double[][]{
{2.0, 2.0, 2.0},
{4.0, 7.0, 7.0},
{6.0, 18.0, 22.0},
}, 0));
run(LUFractorization(new double[][]{
{1.0, 2.0, -3.0, 4.0},
{4.0, 8.0, 12.0, -8.0},
{2.0, 3.0, 2.0, 1.0},
{-3.0, -1.0, 1.0, -4.0}
}, 1));
run(SchmidtQR(new double[][]{
{1, 0, -1},
{1, 2, 1},
{1, 1, -3},
{0, 1, 1}
}));
run(GivensQR(new double[][]{
{0, -20, -14},
{3, 27, -4},
{4, 11, -2}
}));
run(HouseholdQR(new double[][]{
{1, 19, -34},
{-2, -5, 20},
{2, 8, 37}
}));
}
public static void run(List<double[][]> list){
if(list.size() == 3){
System.out.println("The matrix L of A is");
print(list.get(0));
System.out.println("The matrix U of A is");
print(list.get(1));
System.out.println("The matrix P of A is");
print(list.get(2));
System.out.println();
}
else{
System.out.println("The matrix Q of A is");
print(list.get(0));
System.out.println("The matrix R of A is");
print(list.get(1));
System.out.println();
}
}
public static List<double[][]> LUFractorization(double[][] matrix, int model){
List<double[][]> list = new ArrayList<>();
int length = matrix.length;
double[][] L = new double[length][length];
double[][] U = new double[length][length];
double[][] P = new double[length][length];
int[] indexP = new int[length];
for(int i = 0; i < length; i++)
indexP[i] = i;
for(int i = 0; i < length; i++){
if(model == 1)
exchange(matrix, L, indexP, i, findExchange(matrix, i));
for(int j = i+1; j < length; j++)
L[j][i] = eliminate(matrix, i, j);
}
for(int i = 0; i < length; i++) {
for(int j = length-1; j >= i; j--)
U[i][j] = matrix[i][j];
if(model == 1)
P[i][indexP[i]] = 1;
else
P[i][i] = 1;
L[i][i] = 1;
}
list.add(L);
list.add(U);
list.add(P);
return list;
}
public static List<double[][]> SchmidtQR(double[][] matrix){
int m = matrix.length;
int n = matrix[0].length;
double[][] R = new double[n][n];
List<double[][]> outList = new LinkedList<>();
for(int i = 0; i < n; i++){
double[][] u = new double[m][1];
for(int j = 0; j < m; j++)
u[j][0] = matrix[j][i];
for(int j = 0; j < i; j++) {
double[][] q = new double[m][1];
for(int k = 0; k < m; k++)
q[k][0] = matrix[k][j];
double r = matrixProduct(T(q), u)[0][0];
u = matrixPlus(u, matrixNumProduct(r, q), false);
R[j][i] = r;
}
double mode = 0;
for(int j = 0; j < m; j++)
mode += u[j][0]*u[j][0];
double r = Math.pow(mode, 0.5);
R[i][i] = r;
u = matrixNumProduct(1/r, u);
for(int j = 0; j < m; j++)
matrix[j][i] = u[j][0];
}
outList.add(matrix);
outList.add(R);
return outList;
}
public static List<double[][]> GivensQR(double[][] matrix){
int maxRow = matrix.length;
int maxCol = matrix[0].length;
int m = matrix.length;
int n = matrix[0].length;
List<double[][]> QList = new LinkedList<>();
List<double[][]> RList = new LinkedList<>();
List<double[][]> outList = new LinkedList<>();
while(maxRow > 1 && maxCol > 1){
int row = matrix.length;
double[][] u = new double[row][1];
for(int i = 0; i < row; i++)
u[i][0] = matrix[i][0];
List<double[][]> TList = new LinkedList<>();
for(int i = 1; i < row; i++){
if(Double.doubleToLongBits(u[i][0]) == Double.doubleToLongBits(0.00))
continue;
double c = u[0][0] / Math.pow((u[0][0]*u[0][0])+(u[i][0]*u[i][0]), 0.5);
double s = u[i][0] / Math.pow((u[0][0]*u[0][0])+(u[i][0]*u[i][0]), 0.5);
double[][] T = eye(row);
T[0][0] = T[i][i] = c;
T[0][i] = s;
T[i][0] = -s;
u = matrixProduct(T, u);
TList.add(T);
}
double[][] T = ((LinkedList<double[][]>)TList).poll();
while(!TList.isEmpty()){
double[][] temp = ((LinkedList<double[][]>)TList).poll();
T = matrixProduct(temp, T);
}
QList.add(T);
RList.add(matrixProduct(T, matrix));
matrix = nextStep(matrixProduct(T, matrix));
maxCol --;
maxRow --;
}
outList.add(T(repairQList(QList, m, n)));
outList.add(repairRList(RList, m, n));
return outList;
}
public static List<double[][]> HouseholdQR(double[][] matrix){
int maxRow = matrix.length;
int maxCol = matrix[0].length;
int m = matrix.length;
int n = matrix[0].length;
List<double[][]> QList = new LinkedList<>();
List<double[][]> RList = new LinkedList<>();
List<double[][]> outList = new LinkedList<>();
while(maxRow > 1 && maxCol > 1){
int row = matrix.length;
double[][] u = new double[row][1];
for(int i = 0; i < row; i++)
u[i][0] = matrix[i][0];
double mode = 0;
for(int i = 0; i < row; i++)
mode += u[i][0]*u[i][0];
mode = Math.pow(mode, 0.5);
u[0][0] -= mode;
double coff = 2 / matrixProduct(T(u),u)[0][0];
double[][] R = matrixPlus(eye(row), matrixNumProduct(coff, matrixProduct(u, T(u))), false);
double[][] mid = matrixProduct(R, matrix);
QList.add(R);
RList.add(mid);
matrix = nextStep(mid);
maxCol --;
maxRow --;
}
outList.add(T(repairQList(QList, m, n)));
outList.add(repairRList(RList, m, n));
return outList;
}
private static double[][] matrixProduct(double[][] A, double[][] B){
int y = A.length;
int x = B[0].length;
double C[][] = new double[y][x];
for (int i = 0; i < y; i++)
for (int j = 0; j < x; j++)
for (int k = 0; k < B.length; k++)
C[i][j] += A[i][k] * B[k][j];
return C;
}
private static double[][] matrixPlus(double[][] A, double[][] B, boolean positive){
int row = A.length;
int col = A[0].length;
double[][] C = new double[row][col];
for(int i = 0; i < row; i++){
for(int j = 0; j < col; j++){
if(positive)
C[i][j] = A[i][j] + B[i][j];
else
C[i][j] = A[i][j] - B[i][j];
}
}
return C;
}
private static double[][] matrixNumProduct(double b, double[][] A){
int row = A.length;
int col = A[0].length;
double[][] C = new double[row][col];
for(int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
C[i][j] = b * A[i][j];
}
}
return C;
}
private static double[][] repairQList(List<double[][]> QList, int m, int n){
double[][] Q = ((LinkedList<double[][]>)QList).poll();
while(!QList.isEmpty()){
double[][] temp = ((LinkedList<double[][]>)QList).poll();
int row = temp.length;
int col = temp[0].length;
double[][] productor = new double[m][n];
for(int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
productor[m-row+i][n-col+j] = temp[i][j];
for(int i = 0; i < m-row; i++)
productor[i][i] = 1;
Q = matrixProduct(productor, Q);
}
return Q;
}
private static double[][] repairRList(List<double[][]> RList, int m, int n){
double[][] R = ((LinkedList<double[][]>)RList).poll();
while(!RList.isEmpty()){
double[][] temp = ((LinkedList<double[][]>)RList).poll();
int row = temp.length;
int col = temp[0].length;
for(int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
R[m-row+i][n-col+j] = temp[i][j];
}
return R;
}
private static double[][] T(double[][] A){
int row = A.length;
int col = A[0].length;
double[][] C = new double[col][row];
for(int i = 0; i < col; i++) {
for (int j = 0; j < row; j++) {
C[i][j] = A[j][i];
}
}
return C;
}
private static double[][] eye(int x){
double[][] I = new double[x][x];
for(int i = 0; i < x; i++)
I[i][i] = 1;
return I;
}
private static double[][] nextStep(double[][] A){
int row = A.length;
int col = A[0].length;
double[][] C = new double[row-1][col-1];
for(int i = 0; i < col-1; i++)
for (int j = 0; j < row-1; j++)
C[i][j] = A[i+1][j+1];
return C;
}
private static int findExchange(double[][] matrix, int pivot){
int length = matrix.length;
double max = matrix[pivot][pivot];
int out = pivot;
for(int i = pivot; i < length; i++){
if(absoluteValue(matrix[i][pivot]) > absoluteValue(max)){
max = matrix[i][pivot];
out = i;
}
}
return out;
}
private static void exchange(double[][] matrix, double[][] L, int[]indexP, int i, int exchange){
double[] temp = matrix[i];
matrix[i] = matrix[exchange];
matrix[exchange] = temp;
double[] LTemp = L[i];
L[i] = L[exchange];
L[exchange] = LTemp;
int tempIndex = indexP[i];
indexP[i] = indexP[exchange];
indexP[exchange] = tempIndex;
}
private static double eliminate(double[][] matrix, int i, int j){
int length = matrix.length;
double coefficient = matrix[j][i]/matrix[i][i];
matrix[j][i] = 0;
for(int k = i+1; k < length; k++)
matrix[j][k] -= coefficient*matrix[i][k];
return coefficient;
}
private static double absoluteValue(double x){
return x >= 0 ? x : -x;
}
private static double[][] copy(double[][] matrix){
int length = matrix.length;
double[][] out = new double[length][length];
for(int i = 0; i < length; i++)
for(int j = 0; j < length; j++)
out[i][j] = matrix[i][j];
return out;
}
private static void print(double[][] matrix){
int row = matrix.length;
int col = matrix[0].length;
for(int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
BigDecimal bigDecimal = new BigDecimal(matrix[i][j]);
String out = String.valueOf(bigDecimal.setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue());
int add = 8 - out.length();
for(int k = 0; k < add; k++)
out += " ";
System.out.print(out);
}
System.out.println();
}
}
}