Beispiel #1
0
        /**
         * <p>
         * Applies the reflectors that have been computed previously to the specified row.
         * <br>
         * A = A + u*v^T + v*u^T only along the specified row in A.
         * </p>
         *
         * @param blockLength
         * @param A Contains the reflectors and the row being updated.
         * @param V Contains previously computed 'v' vectors.
         * @param row The row of 'A' that is to be updated.
         */
        public static void applyReflectorsToRow(int blockLength,
                                                FSubmatrixD1 A,
                                                FSubmatrixD1 V,
                                                int row)
        {
            int height = Math.Min(blockLength, A.row1 - A.row0);

            float[] dataA = A.original.data;
            float[] dataV = V.original.data;

            int indexU, indexV;

            // for each previously computed reflector
            for (int i = 0; i < row; i++)
            {
                int width = Math.Min(blockLength, A.col1 - A.col0);

                indexU = A.original.numCols * A.row0 + height * A.col0 + i * width + row;
                indexV = V.original.numCols * V.row0 + height * V.col0 + i * width + row;

                float u_row = (i + 1 == row) ? 1.0f : dataA[indexU];
                float v_row = dataV[indexV];

                // take in account the leading one
                float before = A.get(i, i + 1);
                A.set(i, i + 1, 1);

                // grab only the relevant row from A = A + u*v^T + v*u^T
                VectorOps_FDRB.add_row(blockLength, A, row, 1, V, i, u_row, A, row, row, A.col1 - A.col0);
                VectorOps_FDRB.add_row(blockLength, A, row, 1, A, i, v_row, A, row, row, A.col1 - A.col0);

                A.set(i, i + 1, before);
            }
        }
Beispiel #2
0
        public virtual bool decompose(FMatrixRBlock orig)
        {
            if (orig.numCols != orig.numRows)
            {
                throw new ArgumentException("Input matrix must be square.");
            }

            init(orig);

            FSubmatrixD1 subA = new FSubmatrixD1(A);
            FSubmatrixD1 subV = new FSubmatrixD1(V);
            FSubmatrixD1 subU = new FSubmatrixD1(A);

            int N = orig.numCols;

            for (int i = 0; i < N; i += A.blockLength)
            {
//            Console.WriteLine("-------- triag i "+i);
                int height = Math.Min(A.blockLength, A.numRows - i);

                subA.col0 = subU.col0 = i;
                subA.row0 = subU.row0 = i;

                subU.row1 = subU.row0 + height;

                subV.col0 = i;
                subV.row1 = height;
                subV.original.reshape(subV.row1, subV.col1, false);

                // bidiagonalize the top row
                TridiagonalHelper_FDRB.tridiagUpperRow(A.blockLength, subA, gammas, subV);

                // apply Householder reflectors to the lower portion using block multiplication

                if (subU.row1 < orig.numCols)
                {
                    // take in account the 1 in the last row.  The others are skipped over.
                    float before = subU.get(A.blockLength - 1, A.blockLength);
                    subU.set(A.blockLength - 1, A.blockLength, 1);

                    // A = A + U*V^T + V*U^T
                    multPlusTransA(A.blockLength, subU, subV, subA);
                    multPlusTransA(A.blockLength, subV, subU, subA);

                    subU.set(A.blockLength - 1, A.blockLength, before);
                }
            }

            return(true);
        }
        private bool decomposeLower()
        {
            int blockLength = T.blockLength;

            subA.set(T);
            subB.set(T);
            subC.set(T);

            for (int i = 0; i < T.numCols; i += blockLength)
            {
                int widthA = Math.Min(blockLength, T.numCols - i);

                subA.col0 = i;
                subA.col1 = i + widthA;
                subA.row0 = subA.col0;
                subA.row1 = subA.col1;

                subB.col0 = i;
                subB.col1 = i + widthA;
                subB.row0 = i + widthA;
                subB.row1 = T.numRows;

                subC.col0 = i + widthA;
                subC.col1 = T.numRows;
                subC.row0 = i + widthA;
                subC.row1 = T.numRows;

                // cholesky on inner block A
                if (!InnerCholesky_FDRB.lower(subA))
                {
                    return(false);
                }

                // on the last block these operations are not needed.
                if (widthA == blockLength)
                {
                    // B = L^-1 B
                    TriangularSolver_FDRB.solveBlock(blockLength, false, subA, subB, false, true);

                    // C = C - B * B^T
                    InnerRankUpdate_FDRB.symmRankNMinus_L(blockLength, subC, subB);
                }
            }

            MatrixOps_FDRB.zeroTriangle(true, T);

            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)/(&tau; + 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)/(&tau; + 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);
        }
Beispiel #6
0
        private void replaceZeros(FSubmatrixD1 subU)
        {
            int N = Math.Min(A.blockLength, subU.col1 - subU.col0);

            for (int i = 0; i < N; i++)
            {
                // save the zeros
                for (int j = 0; j <= i; j++)
                {
                    subU.set(i, j, zerosM.get(i, j));
                }
                // save the one
                if (subU.col0 + i + 1 < subU.original.numCols)
                {
                    subU.set(i, i + 1, zerosM.get(i, i + 1));
                }
            }
        }
Beispiel #7
0
        /**
         * <p>
         * Final computation for a single row of 'v':<br>
         * <br>
         * v = y -(1/2)&gamma;(y^T*u)*u
         * </p>
         *
         * @param blockLength
         * @param A
         * @param V
         * @param row
         * @param gamma
         */
        public static void computeRowOfV(int blockLength,
                                         FSubmatrixD1 A,
                                         FSubmatrixD1 V,
                                         int row,
                                         float gamma)
        {
            // val=(y^T*u)
            float val = BlockHouseHolder_FDRB.innerProdRow(blockLength, A, row, V, row, 1);

            // take in account the one
            float before = A.get(row, row + 1);

            A.set(row, row + 1, 1);

            // v = y - (1/2)gamma*val * u
            VectorOps_FDRB.add_row(blockLength, V, row, 1, A, row, -0.5f * gamma * val, V, row, row + 1,
                                   A.col1 - A.col0);

            A.set(row, row + 1, before);
        }
Beispiel #8
0
        /**
         * <p>
         * Multiples the appropriate submatrix of A by the specified reflector and stores
         * the result ('y') in V.<br>
         * <br>
         * y = A*u<br>
         * </p>
         *
         * @param blockLength
         * @param A Contains the 'A' matrix and 'u' vector.
         * @param V Where resulting 'y' row vectors are stored.
         * @param row row in matrix 'A' that 'u' vector and the row in 'V' that 'y' is stored in.
         */
        public static void multA_u(int blockLength,
                                   FSubmatrixD1 A,
                                   FSubmatrixD1 V,
                                   int row)
        {
            int heightMatA = A.row1 - A.row0;

            for (int i = row + 1; i < heightMatA; i++)
            {
                float val = innerProdRowSymm(blockLength, A, row, A, i, 1);

                V.set(row, i, val);
            }
        }
        public static void add_row(int blockLength,
                                   FSubmatrixD1 A, int rowA, float alpha,
                                   FSubmatrixD1 B, int rowB, float beta,
                                   FSubmatrixD1 C, int rowC,
                                   int zeroOffset, int end)
        {
            int offset = rowA + zeroOffset;

            if (C.col0 + offset >= C.col1)
            {
                return;
            }
            // handle leading one
            C.set(rowC, offset, alpha + B.get(rowB, offset) * beta);

            VectorOps_FDRB.add_row(blockLength, A, rowA, alpha, B, rowB, beta, C, rowC, offset + 1, end);
        }
        /**
         * Scales the elements in the specified row starting at element colStart by 'val'.<br>
         * W = val*Y
         *
         * Takes in account zeros and leading one automatically.
         *
         * @param zeroOffset How far off the diagonal is the first element in the vector.
         */
        public static void scale_row(int blockLength,
                                     FSubmatrixD1 Y,
                                     FSubmatrixD1 W,
                                     int row,
                                     int zeroOffset,
                                     float val)
        {
            int offset = row + zeroOffset;

            if (offset >= W.col1 - W.col0)
            {
                return;
            }

            // handle the one
            W.set(row, offset, val);

            // scale rest of the vector
            VectorOps_FDRB.scale_row(blockLength, Y, row, val, W, row, offset + 1, Y.col1 - Y.col0);
        }