/* ------------------------ Constructor * ------------------------ */ /** QR Decomposition, computed by Householder reflections. @param A Rectangular matrix @return Structure to access R and the Householder vectors and compute Q. */ public QRDecomposition(CoreMatrix A) { // Initialize. QR = A.getArrayCopy(); m = A.getRowDimension(); n = A.getColumnDimension(); Rdiag = new double[n]; // Main loop. for (int k = 0; k < n; k++) { // Compute 2-norm of k-th column without under/overflow. double nrm = 0; for (int i = k; i < m; i++) { nrm = Maths.hypot(nrm, QR[i, k]); } if (nrm != 0.0) { // Form k-th Householder vector. if (QR[k, k] < 0) { nrm = -nrm; } for (int i = k; i < m; i++) { QR[i, k] /= nrm; } QR[k, k] += 1.0; // Apply transformation to remaining columns. for (int j = k + 1; j < n; j++) { double s = 0.0; for (int i = k; i < m; i++) { s += QR[i, k] * QR[i, j]; } s = -s / QR[k, k]; for (int i = k; i < m; i++) { QR[i, j] += s * QR[i, k]; } } } Rdiag[k] = -nrm; } }
/* ------------------------ Constructor * ------------------------ */ /** LU Decomposition @param A Rectangular matrix @return Structure to access L, U and piv. */ public LUDecomposition(CoreMatrix A) { // Use a "left-looking", dot-product, Crout/Doolittle algorithm. LU = A.getArrayCopy(); m = A.getRowDimension(); n = A.getColumnDimension(); piv = new int[m]; for (int i = 0; i < m; i++) { piv[i] = i; } pivsign = 1; double[] LUrowi = new double[m]; double[] LUcolj = new double[m]; // Outer loop. for (int j = 0; j < n; j++) { // Make a copy of the j-th column to localize references. for (int i = 0; i < m; i++) { LUcolj[i] = LU[i, j]; } // Apply previous transformations. for (int i = 0; i < m; i++) { for (int h = 0; i < m; i++) LUrowi[h] = LU[i, h]; // Most of the time is spent in the following dot product. int kmax = Math.Min(i, j); double s = 0.0; for (int k = 0; k < kmax; k++) { s += LUrowi[k] * LUcolj[k]; } LUrowi[j] = LUcolj[i] -= s; } // Find pivot and exchange if necessary. int p = j; for (int i = j + 1; i < m; i++) { if (Math.Abs(LUcolj[i]) > Math.Abs(LUcolj[p])) { p = i; } } if (p != j) { for (int ki = 0; ki < n; ki++) { double t = LU[p, ki]; LU[p, ki] = LU[j, ki]; LU[j, ki] = t; } int k = piv[p]; piv[p] = piv[j]; piv[j] = k; pivsign = -pivsign; } // Compute multipliers. if (j < m & LU[j, j] != 0.0) { for (int i = j + 1; i < m; i++) { LU[i, j] /= LU[j, j]; } } } }
/** Least squares solution of A*X = B @param B A Matrix with as many rows as A and any number of columns. @return X that minimizes the two norm of Q*R*X-B. @exception IllegalArgumentException Matrix row dimensions must agree. @exception RuntimeException Matrix is rank deficient. */ public CoreMatrix solve(CoreMatrix B) { if (B.getRowDimension() != m) { throw new Exception("Matrix row dimensions must agree."); } if (!this.isFullRank()) { throw new Exception("Matrix is rank deficient."); } // Copy right hand side int nx = B.getColumnDimension(); double[,] X = B.getArrayCopy(); // Compute Y = transpose(Q)*B for (int k = 0; k < n; k++) { for (int j = 0; j < nx; j++) { double s = 0.0; for (int i = k; i < m; i++) { s += QR[i, k] * X[i, j]; } s = -s / QR[k, k]; for (int i = k; i < m; i++) { X[i, j] += s * QR[i, k]; } } } // Solve R*X = Y; for (int k = n - 1; k >= 0; k--) { for (int j = 0; j < nx; j++) { X[k, j] /= Rdiag[k]; } for (int i = 0; i < k; i++) { for (int j = 0; j < nx; j++) { X[i, j] -= X[k, j] * QR[i, k]; } } } return (new CoreMatrix(X, n, nx).getMatrix(0, n - 1, 0, nx - 1)); }
/** Solve A*X = B @param B A Matrix with as many rows as A and any number of columns. @return X so that L*U*X = B(piv,:) @exception IllegalArgumentException Matrix row dimensions must agree. @exception RuntimeException Matrix is singular. */ public CoreMatrix solve(CoreMatrix B) { if (B.getRowDimension() != m) { throw new Exception("Matrix row dimensions must agree."); } if (!this.isNonsingular()) { throw new Exception("Matrix is singular."); } // Copy right hand side with pivoting int nx = B.getColumnDimension(); CoreMatrix Xmat = B.getMatrix(piv, 0, nx - 1); double[,] X = Xmat.getArray(); // Solve L*Y = B(piv,:) for (int k = 0; k < n; k++) { for (int i = k + 1; i < n; i++) { for (int j = 0; j < nx; j++) { X[i, j] -= X[k, j] * LU[i, k]; } } } // Solve U*X = Y; for (int k = n - 1; k >= 0; k--) { for (int j = 0; j < nx; j++) { X[k, j] /= LU[k, k]; } for (int i = 0; i < k; i++) { for (int j = 0; j < nx; j++) { X[i, j] -= X[k, j] * LU[i, k]; } } } return Xmat; }