/**
         * Computes a basis (the principal components) from the most dominant eigenvectors.
         *
         * @param numComponents Number of vectors it will use to describe the data.  Typically much
         * smaller than the number of elements in the input vector.
         */
        public void computeBasis(int numComponents)
        {
            if (numComponents > A.getNumCols())
            {
                throw new ArgumentException("More components requested that the data's length.");
            }
            if (sampleIndex != A.getNumRows())
            {
                throw new ArgumentException("Not all the data has been added");
            }
            if (numComponents > sampleIndex)
            {
                throw new ArgumentException("More data needed to compute the desired number of components");
            }

            this.numComponents = numComponents;

            // compute the mean of all the samples
            for (int i = 0; i < A.getNumRows(); i++)
            {
                for (int j = 0; j < mean.Length; j++)
                {
                    mean[j] += A.get(i, j);
                }
            }
            for (int j = 0; j < mean.Length; j++)
            {
                mean[j] /= A.getNumRows();
            }

            // subtract the mean from the original data
            for (int i = 0; i < A.getNumRows(); i++)
            {
                for (int j = 0; j < mean.Length; j++)
                {
                    A.set(i, j, A.get(i, j) - mean[j]);
                }
            }

            // Compute SVD and save time by not computing U
            SingularValueDecomposition <DMatrixRMaj> svd =
                DecompositionFactory_DDRM.svd(A.numRows, A.numCols, false, true, false);

            if (!svd.decompose(A))
            {
                throw new InvalidOperationException("SVD failed");
            }

            V_t = svd.getV(null, true);
            DMatrixRMaj W = svd.getW(null);

            // Singular values are in an arbitrary order initially
            SingularOps_DDRM.descendingOrder(null, false, W, V_t, true);

            // strip off unneeded components and find the basis
            V_t.reshape(numComponents, mean.Length, true);
        }
Ejemplo n.º 2
0
        public static DMatrixRMaj createQ(double T, double var)
        {
            DMatrixRMaj Q = new DMatrixRMaj(9, 9);

            double a00 = (1.0 / 4.0) * T * T * T * T * var;
            double a01 = (1.0 / 2.0) * T * T * T * var;
            double a02 = (1.0 / 2.0) * T * T * var;
            double a11 = T * T * var;
            double a12 = T * var;
            double a22 = var;

            for (int i = 0; i < 3; i++)
            {
                Q.set(i, i, a00);
                Q.set(i, 3 + i, a01);
                Q.set(i, 6 + i, a02);
                Q.set(3 + i, 3 + i, a11);
                Q.set(3 + i, 6 + i, a12);
                Q.set(6 + i, 6 + i, a22);
            }

            for (int y = 1; y < 9; y++)
            {
                for (int x = 0; x < y; x++)
                {
                    Q.set(y, x, Q.get(x, y));
                }
            }

            return(Q);
        }
Ejemplo n.º 3
0
        /**
         * <p>
         * Puts all the real eigenvectors into the columns of a matrix.  If an eigenvalue is imaginary
         * then the corresponding eigenvector will have zeros in its column.
         * </p>
         *
         * @param eig An eigenvalue decomposition which has already decomposed a matrix.
         * @return An m by m matrix containing eigenvectors in its columns.
         */
        public static DMatrixRMaj createMatrixV(EigenDecomposition_F64 <DMatrixRMaj> eig)
        {
            int N = eig.getNumberOfEigenvalues();

            DMatrixRMaj V = new DMatrixRMaj(N, N);

            for (int i = 0; i < N; i++)
            {
                Complex_F64 c = eig.getEigenvalue(i);

                if (c.isReal())
                {
                    DMatrixRMaj v = eig.getEigenVector(i);

                    if (v != null)
                    {
                        for (int j = 0; j < N; j++)
                        {
                            V.set(j, i, v.get(j, 0));
                        }
                    }
                }
            }

            return(V);
        }
        private void replaceZeros(DSubmatrixD1 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));
                }
            }
        }
Ejemplo n.º 5
0
        /**
         * A = H + lambda*I <br>
         * <br>
         * where I is an identity matrix.
         */
        private void computeA(DMatrixRMaj A, DMatrixRMaj H, double lambda)
        {
            int numParam = param.getNumElements();

            A.set(H);
            for (int i = 0; i < numParam; i++)
            {
                A.set(i, i, A.get(i, i) + lambda);
            }
        }
        /**
         * Extracts the tridiagonal matrix found in the decomposition.
         *
         * @param T If not null then the results will be stored here.  Otherwise a new matrix will be created.
         * @return The extracted T matrix.
         */
        public DMatrixRMaj getT(DMatrixRMaj T)
        {
            T = UtilDecompositons_DDRM.checkZeros(T, N, N);

            T.data[0] = QT.data[0];
            T.data[1] = QT.data[1];


            for (int i = 1; i < N - 1; i++)
            {
                T.set(i, i, QT.get(i, i));
                T.set(i, i + 1, QT.get(i, i + 1));
                T.set(i, i - 1, QT.get(i - 1, i));
            }

            T.data[(N - 1) * N + N - 1] = QT.data[(N - 1) * N + N - 1];
            T.data[(N - 1) * N + N - 2] = QT.data[(N - 2) * N + N - 1];

            return(T);
        }
        public override void solve(DMatrixRMaj B, DMatrixRMaj X)
        {
            if (X.numRows != numCols)
            {
                throw new ArgumentException("Unexpected dimensions for X");
            }
            else if (B.numRows != numRows || B.numCols != X.numCols)
            {
                throw new ArgumentException("Unexpected dimensions for B");
            }

            int BnumCols = B.numCols;

            // get the pivots and transpose them
            int[] pivots = decomposition.getColPivots();

            // solve each column one by one
            for (int colB = 0; colB < BnumCols; colB++)
            {
                x_basic.reshape(numRows, 1);
                Y.reshape(numRows, 1);

                // make a copy of this column in the vector
                for (int i = 0; i < numRows; i++)
                {
                    Y.data[i] = B.get(i, colB);
                }

                // Solve Q*a=b => a = Q'*b
                CommonOps_DDRM.multTransA(Q, Y, x_basic);

                // solve for Rx = b using the standard upper triangular solver
                TriangularSolver_DDRM.solveU(R11.data, x_basic.data, rank);

                // finish the basic solution by filling in zeros
                x_basic.reshape(numCols, 1, true);
                for (int i = rank; i < numCols; i++)
                {
                    x_basic.data[i] = 0;
                }

                if (norm2Solution && rank < numCols)
                {
                    upgradeSolution(x_basic);
                }

                // save the results
                for (int i = 0; i < numCols; i++)
                {
                    X.set(pivots[i], colB, x_basic.data[i]);
                }
            }
        }
Ejemplo n.º 8
0
        /**
         * Multiplied a transpose orthogonal matrix Q by the specified rotator.  This is used
         * to update the U and V matrices.  Updating the transpose of the matrix is faster
         * since it only modifies the rows.
         *
         *
         * @param Q Orthogonal matrix
         * @param m Coordinate of rotator.
         * @param n Coordinate of rotator.
         * @param c cosine of rotator.
         * @param s sine of rotator.
         */
        protected void updateRotator(DMatrixRMaj Q, int m, int n, double c, double s)
        {
            int rowA = m * Q.numCols;
            int rowB = n * Q.numCols;

//        for( int i = 0; i < Q.numCols; i++ ) {
//            double a = Q.get(rowA+i);
//            double b = Q.get(rowB+i);
//            Q.set( rowA+i, c*a + s*b);
//            Q.set( rowB+i, -s*a + c*b);
//        }
//        Console.WriteLine("------ AFter Update Rotator "+m+" "+n);
//        Q.print();
//        Console.WriteLine();
            int endA = rowA + Q.numCols;

            for (; rowA != endA; rowA++, rowB++)
            {
                double a = Q.get(rowA);
                double b = Q.get(rowB);
                Q.set(rowA, c * a + s * b);
                Q.set(rowB, -s * a + c * b);
            }
        }
Ejemplo n.º 9
0
        /**
         * <p>
         * Generates a bound for the largest eigen value of the provided matrix using Perron-Frobenius
         * theorem.   This function only applies to non-negative real matrices.
         * </p>
         *
         * <p>
         * For "stochastic" matrices (Markov process) this should return one for the upper and lower bound.
         * </p>
         *
         * @param A Square matrix with positive elements.  Not modified.
         * @param bound Where the results are stored.  If null then a matrix will be declared. Modified.
         * @return Lower and upper bound in the first and second elements respectively.
         */
        public static double[] boundLargestEigenValue(DMatrixRMaj A, double[] bound)
        {
            if (A.numRows != A.numCols)
            {
                throw new ArgumentException("A must be a square matrix.");
            }

            double min = double.MaxValue;
            double max = 0;

            int n = A.numRows;

            for (int i = 0; i < n; i++)
            {
                double total = 0;
                for (int j = 0; j < n; j++)
                {
                    double v = A.get(i, j);
                    if (v < 0)
                    {
                        throw new ArgumentException("Matrix must be positive");
                    }

                    total += v;
                }

                if (total < min)
                {
                    min = total;
                }

                if (total > max)
                {
                    max = total;
                }
            }

            if (bound == null)
            {
                bound = new double[2];
            }

            bound[0] = min;
            bound[1] = max;

            return(bound);
        }
Ejemplo n.º 10
0
        public override /**/ double quality()
        {
            return(SpecializedOps_DDRM.qualityTriangular(R));
        }

        /**
         * Solves for X using the QR decomposition.
         *
         * @param B A matrix that is n by m.  Not modified.
         * @param X An n by m matrix where the solution is written to.  Modified.
         */
        public override void solve(DMatrixRMaj B, DMatrixRMaj X)
        {
            if (X.numRows != numCols)
            {
                throw new ArgumentException("Unexpected dimensions for X");
            }
            else if (B.numRows != numRows || B.numCols != X.numCols)
            {
                throw new ArgumentException("Unexpected dimensions for B");
            }

            int BnumCols = B.numCols;

            Y.reshape(numRows, 1, false);
            Z.reshape(numRows, 1, false);

            // solve each column one by one
            for (int colB = 0; colB < BnumCols; colB++)
            {
                // make a copy of this column in the vector
                for (int i = 0; i < numRows; i++)
                {
                    Y.data[i] = B.get(i, colB);
                }

                // Solve Qa=b
                // a = Q'b
                CommonOps_DDRM.multTransA(Q, Y, Z);

                // solve for Rx = b using the standard upper triangular solver
                TriangularSolver_DDRM.solveU(R.data, Z.data, numCols);

                // save the results
                for (int i = 0; i < numCols; i++)
                {
                    X.set(i, colB, Z.data[i]);
                }
            }
        }
Ejemplo n.º 11
0
        /**
         * Computes the QR decomposition of the provided matrix.
         *
         * @param A Matrix which is to be decomposed.  Not modified.
         */
        public void decompose(DMatrixRMaj A)
        {
            this.QR = (DMatrixRMaj)A.copy();

            int N = Math.Min(A.numCols, A.numRows);

            gammas = new double[A.numCols];

            DMatrixRMaj A_small = new DMatrixRMaj(A.numRows, A.numCols);
            DMatrixRMaj A_mod   = new DMatrixRMaj(A.numRows, A.numCols);
            DMatrixRMaj v       = new DMatrixRMaj(A.numRows, 1);
            DMatrixRMaj Q_k     = new DMatrixRMaj(A.numRows, A.numRows);

            for (int i = 0; i < N; i++)
            {
                // reshape temporary variables
                A_small.reshape(QR.numRows - i, QR.numCols - i, false);
                A_mod.reshape(A_small.numRows, A_small.numCols, false);
                v.reshape(A_small.numRows, 1, false);
                Q_k.reshape(v.getNumElements(), v.getNumElements(), false);

                // use extract matrix to get the column that is to be zeroed
                CommonOps_DDRM.extract(QR, i, QR.numRows, i, i + 1, v, 0, 0);

                double max = CommonOps_DDRM.elementMaxAbs(v);

                if (max > 0 && v.getNumElements() > 1)
                {
                    // normalize to reduce overflow issues
                    CommonOps_DDRM.divide(v, max);

                    // compute the magnitude of the vector
                    double tau = NormOps_DDRM.normF(v);

                    if (v.get(0) < 0)
                    {
                        tau *= -1.0;
                    }

                    double u_0   = v.get(0) + tau;
                    double gamma = u_0 / tau;

                    CommonOps_DDRM.divide(v, u_0);
                    v.set(0, 1.0);

                    // extract the submatrix of A which is being operated on
                    CommonOps_DDRM.extract(QR, i, QR.numRows, i, QR.numCols, A_small, 0, 0);

                    // A = (I - &gamma;*u*u<sup>T</sup>)A
                    CommonOps_DDRM.setIdentity(Q_k);
                    CommonOps_DDRM.multAddTransB(-gamma, v, v, Q_k);
                    CommonOps_DDRM.mult(Q_k, A_small, A_mod);

                    // save the results
                    CommonOps_DDRM.insert(A_mod, QR, i, i);
                    CommonOps_DDRM.insert(v, QR, i, i);
                    QR.unsafe_set(i, i, -tau * max);

                    // save gamma for recomputing Q later on
                    gammas[i] = gamma;
                }
            }
        }
        public override void solve(DMatrixRMaj B, DMatrixRMaj X)
        {
            if (X.numRows != numCols)
            {
                throw new ArgumentException("Unexpected dimensions for X");
            }
            else if (B.numRows != numRows || B.numCols != X.numCols)
            {
                throw new ArgumentException("Unexpected dimensions for B");
            }

            int BnumCols = B.numCols;

            // get the pivots and transpose them
            int[] pivots = decomposition.getColPivots();

            double[][] qr     = decomposition.getQR();
            double[]   gammas = decomposition.getGammas();

            // solve each column one by one
            for (int colB = 0; colB < BnumCols; colB++)
            {
                x_basic.reshape(numRows, 1);
                Y.reshape(numRows, 1);

                // make a copy of this column in the vector
                for (int i = 0; i < numRows; i++)
                {
                    x_basic.data[i] = B.get(i, colB);
                }

                // Solve Q*x=b => x = Q'*b
                // Q_n*b = (I-gamma*u*u^T)*b = b - u*(gamma*U^T*b)
                for (int i = 0; i < rank; i++)
                {
                    double[] u = qr[i];

                    double vv = u[i];
                    u[i] = 1;
                    QrHelperFunctions_DDRM.rank1UpdateMultR(x_basic, u, gammas[i], 0, i, numRows, Y.data);
                    u[i] = vv;
                }

                // solve for Rx = b using the standard upper triangular solver
                TriangularSolver_DDRM.solveU(R11.data, x_basic.data, rank);

                // finish the basic solution by filling in zeros
                x_basic.reshape(numCols, 1, true);
                for (int i = rank; i < numCols; i++)
                {
                    x_basic.data[i] = 0;
                }

                if (norm2Solution && rank < numCols)
                {
                    upgradeSolution(x_basic);
                }

                // save the results
                for (int i = 0; i < numCols; i++)
                {
                    X.set(pivots[i], colB, x_basic.data[i]);
                }
            }
        }
Ejemplo n.º 13
0
        public bool isZero(int x1, int x2)
        {
            // this provides a relative threshold for when dealing with very large/small numbers
            double target = Math.Abs(A.get(x1, x2));

            double above = Math.Abs(A.get(x1 - 1, x2));

            // according to Matrix Computations page 352 this is what is done in Eispack
            double right = Math.Abs(A.get(x1, x2 + 1));

            return(target <= 0.5 * UtilEjml.EPS * (above + right));
        }