Matrix y = qt.times(B); Matrix r = getR(); for (int k = Math.min(columns, rows) - 1; k >= 0; k--) {
@Test public void rank1() { Matrix x = new DenseMatrix(3, 3); x.viewRow(0).assign(new double[]{1, 2, 3}); x.viewRow(1).assign(new double[]{2, 4, 6}); x.viewRow(2).assign(new double[]{3, 6, 9}); QRDecomposition qr = new QRDecomposition(x); assertFalse(qr.hasFullRank()); assertEquals(0, new DenseVector(new double[]{3.741657, 7.483315, 11.22497}).aggregate(qr.getR().viewRow(0), Functions.PLUS, new DoubleDoubleFunction() { @Override public double apply(double arg1, double arg2) { return Math.abs(arg1) - Math.abs(arg2); } }), 1.0e-5); }
@Test public void randomMatrix() { Matrix a = new DenseMatrix(60, 60).assign(Functions.random()); QRDecomposition qr = new QRDecomposition(a); // how close is Q to actually being orthornormal? double maxIdent = qr.getQ().transpose().times(qr.getQ()).viewDiagonal().assign(Functions.plus(-1)).norm(1); assertEquals(0, maxIdent, 1.0e-13); // how close is Q R to the original value of A? Matrix z = qr.getQ().times(qr.getR()).minus(a); double maxError = z.aggregate(Functions.MIN, Functions.ABS); assertEquals(0, maxError, 1.0e-13); }
0.923669647838536, 1.76679276072492, 0.637690104222683, -0.225890909498753, -1.35732293800944}, 5, 5); Matrix r = qr.getR();
Matrix y = qt.times(B); Matrix r = getR(); for (int k = Math.min(columns, rows) - 1; k >= 0; k--) {
/** * Least squares solution of <tt>A*X = B</tt>; <tt>returns X</tt>. * * @param B A matrix with as many rows as <tt>A</tt> and any number of columns. * @return <tt>X</tt> that minimizes the two norm of <tt>Q*R*X - B</tt>. * @throws IllegalArgumentException if <tt>B.rows() != A.rows()</tt>. */ public Matrix solve(Matrix B) { if (B.numRows() != originalRows) { throw new IllegalArgumentException("Matrix row dimensions must agree."); } int columns = B.numCols(); Matrix x = B.like(originalColumns, columns); // this can all be done a bit more efficiently if we don't actually // form explicit versions of Q^T and R but this code isn't soo bad // and it is much easier to understand Matrix qt = getQ().transpose(); Matrix y = qt.times(B); Matrix r = getR(); for (int k = Math.min(originalColumns, originalRows) - 1; k >= 0; k--) { // X[k,] = Y[k,] / R[k,k], note that X[k,] starts with 0 so += is same as = x.viewRow(k).assign(y.viewRow(k), Functions.plusMult(1 / r.get(k, k))); // Y[0:(k-1),] -= R[0:(k-1),k] * X[k,] Vector rColumn = r.viewColumn(k).viewPart(0, k); for (int c = 0; c < columns; c++) { y.viewColumn(c).viewPart(0, k).assign(rColumn, Functions.plusMult(-x.get(k, c))); } } return x; }
@Test public void rank1() { Matrix x = new DenseMatrix(3, 3); x.viewRow(0).assign(new double[]{1, 2, 3}); x.viewRow(1).assign(new double[]{2, 4, 6}); x.viewRow(2).assign(new double[]{3, 6, 9}); QRDecomposition qr = new QRDecomposition(x); assertFalse(qr.hasFullRank()); assertEquals(0, new DenseVector(new double[]{3.741657, 7.483315, 11.22497}).aggregate(qr.getR().viewRow(0), Functions.PLUS, new DoubleDoubleFunction() { @Override public double apply(double arg1, double arg2) { return Math.abs(arg1) - Math.abs(arg2); } }), 1.0e-5); }
0.923669647838536, 1.76679276072492, 0.637690104222683, -0.225890909498753, -1.35732293800944}, 5, 5); Matrix r = qr.getR(); assertEquals(rRef, r, 1.0e-8);
QRDecomposition qr = new QRDecomposition(x); assertFalse(qr.hasFullRank()); Matrix rActual = qr.getR();