package util.linalg;
/**
* A class for performing the QR decomposition with
* householder reflections. Decomposes a square
* matrix A into Q*R where R is upper triangular
* and Q is a matrix composed of a series
* of householder reflections.
* @author Andrew Guillory gtg008g@mail.gatech.edu
* @version 1.0
*/
public class QRDecomposition {
/**
* The matrix of reflections, q
*/
private RectangularMatrix q;
/**
* The upper triangular r
*/
private UpperTriangularMatrix r;
/**
* Construct a new QRDecomposition
* @param matrix the matrix being decomposed
*/
public QRDecomposition(Matrix matrix) {
q = RectangularMatrix.eye(matrix.m());
decompose((Matrix) matrix.copy());
}
/**
* Run the decomposition.
* Zeros out the elements below the diagonal with
* householder reflections, accumulating these
* reflections as it goes.
* @param a the matrix to decompose
*/
private void decompose(Matrix a) {
int mnmin = Math.min(a.n(), a.m());
// we have to zero out the last column if
// there are more rows than columns
if (a.m() > a.n()) {
mnmin++;
}
// loop through each of the columns of r
for (int i = 0; i < mnmin - 1; i++) {
// extract the column
Vector column = a.getColumn(i);
// extract out the porition we want to reflect
// into e1
Vector x = column.get(i, column.size());
// calculate the householder reflection for
// this vector
HouseholderReflection h = new HouseholderReflection(x);
// update the r by multiplying by it
h.applyLeft(a, i, a.m(), i, a.n());
// update the q as well
h.applyRight(q, 0, q.m(), i, q.n());
}
r = new UpperTriangularMatrix(a);
}
/**
* Get the matrix of reflections, Q
* @return the Q matrix
*/
public RectangularMatrix getQ() {
return q;
}
/**
* Get the decomposed, upper triangular matrix, R
* @return the R matrix
*/
public UpperTriangularMatrix getR() {
return r;
}
}