/** * <p> * A = (I + W Y<sup>T</sup>)<sup>T</sup>A<BR> * A = A + Y (W<sup>T</sup>A)<BR> * <br> * where A is a submatrix of the input matrix. * </p> */ protected void updateA(FSubmatrixD1 A) { setW(); A.row0 = Y.row0; A.row1 = Y.row1; A.col0 = Y.col1; A.col1 = Y.original.numCols; WTA.row0 = 0; WTA.col0 = 0; WTA.row1 = W.col1 - W.col0; WTA.col1 = A.col1 - A.col0; WTA.original.reshape(WTA.row1, WTA.col1, false); if (A.col1 > A.col0) { BlockHouseHolder_FDRB.computeW_Column(blockLength, Y, W, temp, gammas, Y.col0); MatrixMult_FDRB.multTransA(blockLength, W, A, WTA); BlockHouseHolder_FDRB.multAdd_zeros(blockLength, Y, WTA, A); } else if (saveW) { BlockHouseHolder_FDRB.computeW_Column(blockLength, Y, W, temp, gammas, Y.col0); } }
public virtual bool decompose(FMatrixRBlock orig) { setup(orig); int m = Math.Min(orig.numCols, orig.numRows); // process the matrix one column block at a time and overwrite the input matrix for (int j = 0; j < m; j += blockLength) { Y.col0 = j; Y.col1 = Math.Min(orig.numCols, Y.col0 + blockLength); Y.row0 = j; // compute the QR decomposition of the left most block column // this overwrites the original input matrix if (!BlockHouseHolder_FDRB.decomposeQR_block_col(blockLength, Y, gammas)) { return(false); } // Update the remainder of the matrix using the reflectors just computed updateA(A); } return(true); }
/** * <p> * Computes the householder vector that is used to create reflector for the column. * The results are stored in the original matrix. * </p> * * <p> * The householder vector 'u' is computed as follows:<br> * <br> * u(1) = 1 <br> * u(i) = x(i)/(τ + x(1))<br> * </p> * * The first element is implicitly assumed to be one and not written. * * @return If there was any problems or not. true = no problem. */ public static bool computeHouseHolderCol(int blockLength, FSubmatrixD1 Y, float[] gamma, int i) { float max = BlockHouseHolder_FDRB.findMaxCol(blockLength, Y, i); if (max == 0.0f) { return(false); } else { // computes tau and normalizes u by max float tau = computeTauAndDivideCol(blockLength, Y, i, max); // divide u by u_0 float u_0 = Y.get(i, i) + tau; divideElementsCol(blockLength, Y, i, u_0); gamma[Y.col0 + i] = u_0 / tau; tau *= max; // after the reflector is applied the column would be all zeros but be -tau in the first element Y.set(i, i, -tau); } return(true); }
/** * <p> * Computes the householder vector from the specified row * </p> * * <p> * The householder vector 'u' is computed as follows:<br> * <br> * u(1) = 1 <br> * u(i) = x(i)/(τ + x(1))<br> * </p> * * The first element is implicitly assumed to be one and not written. * * @return If there was any problems or not. true = no problem. */ public static bool computeHouseHolderRow(int blockLength, FSubmatrixD1 Y, float[] gamma, int i) { float max = BlockHouseHolder_FDRB.findMaxRow(blockLength, Y, i, i + 1); if (max == 0.0f) { return(false); } else { // computes tau and normalizes u by max float tau = computeTauAndDivideRow(blockLength, Y, i, i + 1, max); // divide u by u_0 float u_0 = Y.get(i, i + 1) + tau; VectorOps_FDRB.div_row(blockLength, Y, i, u_0, Y, i, i + 1, Y.col1 - Y.col0); gamma[Y.row0 + i] = u_0 / tau; // after the reflector is applied the column would be all zeros but be -tau in the first element Y.set(i, i + 1, -tau * max); } return(true); }
/** * Specialized version of applyQ() that allows the zeros in an identity matrix * to be taken advantage of depending on if isIdentity is true or not. * * @param B * @param isIdentity If B is an identity matrix. */ public void applyQ(FMatrixRBlock B, bool isIdentity) { int minDimen = Math.Min(dataA.numCols, dataA.numRows); FSubmatrixD1 subB = new FSubmatrixD1(B); W.col0 = W.row0 = 0; Y.row1 = W.row1 = dataA.numRows; WTA.row0 = WTA.col0 = 0; int start = minDimen - minDimen % blockLength; if (start == minDimen) { start -= blockLength; } if (start < 0) { start = 0; } // (Q1^T * (Q2^T * (Q3^t * A))) for (int i = start; i >= 0; i -= blockLength) { Y.col0 = i; Y.col1 = Math.Min(Y.col0 + blockLength, dataA.numCols); Y.row0 = i; if (isIdentity) { subB.col0 = i; } subB.row0 = i; setW(); WTA.row1 = Y.col1 - Y.col0; WTA.col1 = subB.col1 - subB.col0; WTA.original.reshape(WTA.row1, WTA.col1, false); // Compute W matrix from reflectors stored in Y if (!saveW) { BlockHouseHolder_FDRB.computeW_Column(blockLength, Y, W, temp, gammas, Y.col0); } // Apply the Qi to Q BlockHouseHolder_FDRB.multTransA_vecCol(blockLength, Y, subB, WTA); MatrixMult_FDRB.multPlus(blockLength, W, WTA, subB); } }
/** * <p> * Multiplies the provided matrix by Q<sup>T</sup> using householder reflectors. This is more * efficient that computing Q then applying it to the matrix. * </p> * * <p> * Q = Q*(I - γ W*Y^T)<br> * QR = A ≥ R = Q^T*A = (Q3^T * (Q2^T * (Q1^t * A))) * </p> * * @param B Matrix which Q is applied to. Modified. */ public void applyQTran(FMatrixRBlock B) { int minDimen = Math.Min(dataA.numCols, dataA.numRows); FSubmatrixD1 subB = new FSubmatrixD1(B); W.col0 = W.row0 = 0; Y.row1 = W.row1 = dataA.numRows; WTA.row0 = WTA.col0 = 0; // (Q3^T * (Q2^T * (Q1^t * A))) for (int i = 0; i < minDimen; i += blockLength) { Y.col0 = i; Y.col1 = Math.Min(Y.col0 + blockLength, dataA.numCols); Y.row0 = i; subB.row0 = i; // subB.row1 = B.numRows; // subB.col0 = 0; // subB.col1 = B.numCols; setW(); // W.original.reshape(W.row1,W.col1,false); WTA.row0 = 0; WTA.col0 = 0; WTA.row1 = W.col1 - W.col0; WTA.col1 = subB.col1 - subB.col0; WTA.original.reshape(WTA.row1, WTA.col1, false); // Compute W matrix from reflectors stored in Y if (!saveW) { BlockHouseHolder_FDRB.computeW_Column(blockLength, Y, W, temp, gammas, Y.col0); } // Apply the Qi to Q MatrixMult_FDRB.multTransA(blockLength, W, subB, WTA); BlockHouseHolder_FDRB.multAdd_zeros(blockLength, Y, WTA, subB); } }