Hello All,
Not sure if this is stepping on toes, but here is what I thought of to deal
with pivoting. I would only need to modify the constructor of the
QRDecompImpl class:
public QRDecompositionPivotImpl(RealMatrix matrix) {
final int m = matrix.getRowDimension();
final int n = matrix.getColumnDimension();
final int mn = FastMath.min(m, n);
qrt = matrix.transpose().getData();
rDiag = new double[FastMath.min(m, n)];
cachedQ = null;
cachedQT = null;
cachedR = null;
cachedH = null;
/*
* The QR decomposition of a matrix A is calculated using
Householder
* reflectors by repeating the following operations to each minor
* A(minor,minor) of A:
*/
pivots = new int[n];
for (int i = 0; i < n; i++) {
pivots[i] = i;
}
int pivotIdx = -1;
double bestNorm = 0.0;
for (int minor = 0; minor < mn; minor++) {
bestNorm = 0.0;
pivotIdx = 0;
for (int i = minor; i < n; i++) {
final double[] qrtMinor = qrt[i];
double xNormSqr = 0.0;
for (int row = minor; row < m; row++) {
final double c = qrtMinor[row];
xNormSqr += c * c;
}
if (xNormSqr > bestNorm) {
bestNorm = xNormSqr;
pivotIdx = i;
}
}
if( pivotIdx != minor){
int pvt = pivots[minor];
pivots[minor] = pivots[pivotIdx];
double[] qswp = qrt[minor];
qrt[minor] = qrt[pivotIdx];
for( int i = minor + 1; i < n; i++){
if( i <= pivotIdx ){
final int itmp = pivots[i];
pivots[i] = pvt;
pvt = itmp;
final double[] tmp = qrt[i];
qrt[i] = qswp;
qswp=tmp;
}
}
}
final double[] qrtMinor = qrt[minor];
/*
* Let x be the first column of the minor, and a^2 = |x|^2.
* x will be in the positions qr[minor][minor] through
qr[m][minor].
* The first column of the transformed minor will be (a,0,0,..)'
* The sign of a is chosen to be opposite to the sign of the
first
* component of x. Let's find a:
*/
final double a = (qrtMinor[minor] > 0) ?
-FastMath.sqrt(bestNorm) : FastMath.sqrt(bestNorm);
rDiag[minor] = a;
if (a != 0.0) {
/*
* Calculate the normalized reflection vector v and
transform
* the first column. We know the norm of v beforehand: v =
x-ae
* so |v|^2 = <x-ae,x-ae> = <x,x>-2a<x,e>+a^2<e,e> =
* a^2+a^2-2a<x,e> = 2a*(a - <x,e>).
* Here <x, e> is now qr[minor][minor].
* v = x-ae is stored in the column at qr:
*/
qrtMinor[minor] -= a; // now |v|^2 = -2a*(qr[minor][minor])
/*
* Transform the rest of the columns of the minor:
* They will be transformed by the matrix H = I-2vv'/|v|^2.
* If x is a column vector of the minor, then
* Hx = (I-2vv'/|v|^2)x = x-2vv'x/|v|^2 = x - 2<x,v>/|v|^2
v.
* Therefore the transformation is easily calculated by
* subtracting the column vector (2<x,v>/|v|^2)v from x.
*
* Let 2<x,v>/|v|^2 = alpha. From above we have
* |v|^2 = -2a*(qr[minor][minor]), so
* alpha = -<x,v>/(a*qr[minor][minor])
*/
for (int col = minor + 1; col < n; col++) {
final double[] qrtCol = qrt[col];
double alpha = 0;
for (int row = minor; row < m; row++) {
alpha -= qrtCol[row] * qrtMinor[row];
}
alpha /= a * qrtMinor[minor];
// Subtract the column vector alpha*v from x.
for (int row = minor; row < m; row++) {
qrtCol[row] -= alpha * qrtMinor[row];
}
}
}
}
}
All I am doing is looking forward and taking the next column with the
largest norm. Then I rearrange the Q's. Is this what you had in mind Chris?
The result will be Q,R and the pivot array for which we can implement a
getter?
-Greg