Beispiel #1
0
        /**
         * <p>
         * Computes a metric which measures the the quality of an eigen value decomposition.  If a
         * value is returned that is close to or smaller than 1e-15 then it is within machine precision.
         * </p>
         * <p>
         * EVD quality is defined as:<br>
         * <br>
         * Quality = ||A*V - V*D|| / ||A*V||.
         *  </p>
         *
         * @param orig The original matrix. Not modified.
         * @param eig EVD of the original matrix. Not modified.
         * @return The quality of the decomposition.
         */
        public static double quality(DMatrixRMaj orig, EigenDecomposition_F64 <DMatrixRMaj> eig)
        {
            DMatrixRMaj A = orig;
            DMatrixRMaj V = EigenOps_DDRM.createMatrixV(eig);
            DMatrixRMaj D = EigenOps_DDRM.createMatrixD(eig);

            // L = A*V
            DMatrixRMaj L = new DMatrixRMaj(A.numRows, V.numCols);

            CommonOps_DDRM.mult(A, V, L);
            // R = V*D
            DMatrixRMaj R = new DMatrixRMaj(V.numRows, D.numCols);

            CommonOps_DDRM.mult(V, D, R);

            DMatrixRMaj diff = new DMatrixRMaj(L.numRows, L.numCols);

            CommonOps_DDRM.subtract(L, R, diff);

            double top    = NormOps_DDRM.normF(diff);
            double bottom = NormOps_DDRM.normF(L);

            double error = top / bottom;

            return(error);
        }
Beispiel #2
0
        /**
         * Computes the QR decomposition of the provided matrix.
         *
         * @param A Matrix which is to be decomposed.  Not modified.
         */
        public void decompose(DMatrixRMaj A)
        {
            Equation.Equation eq = new Equation.Equation();

            this.QR = (DMatrixRMaj)A.copy();

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

            gammas = new double[A.numCols];

            for (int i = 0; i < N; i++)
            {
                // update temporary variables
                eq.alias(QR.numRows - i, "Ni", QR, "QR", i, "i");

                // Place the column that should be zeroed into v
                eq.process("v=QR(i:,i)");
                eq.process("maxV=max(abs(v))");

                // Note that v is lazily created above.  Need direct access to it, which is done below.
                DMatrixRMaj v = eq.lookupMatrix("v");

                double maxV = eq.lookupDouble("maxV");
                if (maxV > 0 && v.getNumElements() > 1)
                {
                    // normalize to reduce overflow issues
                    eq.process("v=v/maxV");

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

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

                    eq.alias(tau, "tau");
                    eq.process("u_0 = v(0,0)+tau");
                    eq.process("gamma = u_0/tau");
                    eq.process("v=v/u_0");
                    eq.process("v(0,0)=1");
                    eq.process("QR(i:,i:) = (eye(Ni) - gamma*v*v')*QR(i:,i:)");
                    eq.process("QR(i:,i) = v");
                    eq.process("QR(i,i) = -1*tau*maxV");

                    // save gamma for recomputing Q later on
                    gammas[i] = eq.lookupDouble("gamma");
                }
            }
        }
        /**
         * Computes the dot product of each basis vector against the sample.  Can be used as a measure
         * for membership in the training sample set.  High values correspond to a better fit.
         *
         * @param sample Sample of original data.
         * @return Higher value indicates it is more likely to be a member of input dataset.
         */
        public double response(double[] sample)
        {
            if (sample.Length != A.numCols)
            {
                throw new ArgumentException("Expected input vector to be in sample space");
            }

            DMatrixRMaj dots = new DMatrixRMaj(numComponents, 1);
            DMatrixRMaj s    = DMatrixRMaj.wrap(A.numCols, 1, sample);

            CommonOps_DDRM.mult(V_t, s, dots);

            return(NormOps_DDRM.normF(dots));
        }
Beispiel #4
0
        public static double quality(DMatrixRMaj orig, DMatrixRMaj U, DMatrixRMaj W, DMatrixRMaj Vt)
        {
            // foundA = U*W*Vt
            DMatrixRMaj UW = new DMatrixRMaj(U.numRows, W.numCols);

            CommonOps_DDRM.mult(U, W, UW);
            DMatrixRMaj foundA = new DMatrixRMaj(UW.numRows, Vt.numCols);

            CommonOps_DDRM.mult(UW, Vt, foundA);

            double normA = NormOps_DDRM.normF(foundA);

            return(SpecializedOps_DDRM.diffNormF(orig, foundA) / normA);
        }
        /**
         * This method computes the eigen vector with the largest eigen value by using the
         * direct power method. This technique is the easiest to implement, but the slowest to converge.
         * Works only if all the eigenvalues are real.
         *
         * @param A The matrix. Not modified.
         * @return If it converged or not.
         */
        public bool computeDirect(DMatrixRMaj A)
        {
            initPower(A);

            bool converged = false;

            for (int i = 0; i < maxIterations && !converged; i++)
            {
//            q0.print();

                CommonOps_DDRM.mult(A, q0, q1);
                double s = NormOps_DDRM.normPInf(q1);
                CommonOps_DDRM.divide(q1, s, q2);

                converged = checkConverged(A);
            }

            return(converged);
        }
        private void solveEigenvectorDuplicateEigenvalue(double real, int first, bool isTriangle)
        {
            double scale = Math.Abs(real);

            if (scale == 0)
            {
                scale = 1;
            }

            eigenvectorTemp.reshape(N, 1, false);
            eigenvectorTemp.zero();

            if (first > 0)
            {
                if (isTriangle)
                {
                    solveUsingTriangle(real, first, eigenvectorTemp);
                }
                else
                {
                    solveWithLU(real, first, eigenvectorTemp);
                }
            }

            eigenvectorTemp.reshape(N, 1, false);

            for (int i = first; i < N; i++)
            {
                Complex_F64 c = _implicit.eigenvalues[N - i - 1];

                if (c.isReal() && Math.Abs(c.real - real) / scale < 100.0 * UtilEjml.EPS)
                {
                    eigenvectorTemp.data[i] = 1;

                    DMatrixRMaj v = new DMatrixRMaj(N, 1);
                    CommonOps_DDRM.multTransA(Q, eigenvectorTemp, v);
                    eigenvectors[N - i - 1] = v;
                    NormOps_DDRM.normalizeF(v);

                    eigenvectorTemp.data[i] = 0;
                }
            }
        }
        /**
         * Computes the most dominant eigen vector of A using an inverted shifted matrix.
         * The inverted shifted matrix is defined as <b>B = (A - &alpha;I)<sup>-1</sup></b> and
         * can converge faster if &alpha; is chosen wisely.
         *
         * @param A An invertible square matrix matrix.
         * @param alpha Shifting factor.
         * @return If it converged or not.
         */
        public bool computeShiftInvert(DMatrixRMaj A, double alpha)
        {
            initPower(A);

            LinearSolverDense <DMatrixRMaj> solver = LinearSolverFactory_DDRM.linear(A.numCols);

            SpecializedOps_DDRM.addIdentity(A, B, -alpha);
            solver.setA(B);

            bool converged = false;

            for (int i = 0; i < maxIterations && !converged; i++)
            {
                solver.solve(q0, q1);
                double s = NormOps_DDRM.normPInf(q1);
                CommonOps_DDRM.divide(q1, s, q2);

                converged = checkConverged(A);
            }

            return(converged);
        }
 public virtual double conditionP2(DMatrixRMaj A)
 {
     return(NormOps_DDRM.conditionP2(A));
 }
 public virtual double normF(DMatrixRMaj A)
 {
     return(NormOps_DDRM.normF(A));
 }
        public static void main(String[] args)
        {
            IMersenneTwister rand = new MersenneTwisterFast(234);

            // easy to work with sparse format, but hard to do computations with
            DMatrixSparseTriplet work = new DMatrixSparseTriplet(5, 4, 5);

            work.addItem(0, 1, 1.2);
            work.addItem(3, 0, 3);
            work.addItem(1, 1, 22.21234);
            work.addItem(2, 3, 6);

            // convert into a format that's easier to perform math with
            DMatrixSparseCSC Z = ConvertDMatrixStruct.convert(work, (DMatrixSparseCSC)null);

            // print the matrix to standard out in two different formats
            Z.print();
            Console.WriteLine();
            Z.printNonZero();
            Console.WriteLine();

            // Create a large matrix that is 5% filled
            DMatrixSparseCSC A = RandomMatrices_DSCC.rectangle(ROWS, COLS, (int)(ROWS * COLS * 0.05), rand);
            //          large vector that is 70% filled
            DMatrixSparseCSC x = RandomMatrices_DSCC.rectangle(COLS, XCOLS, (int)(XCOLS * COLS * 0.7), rand);

            Console.WriteLine("Done generating random matrices");
            // storage for the initial solution
            DMatrixSparseCSC y = new DMatrixSparseCSC(ROWS, XCOLS, 0);
            DMatrixSparseCSC z = new DMatrixSparseCSC(ROWS, XCOLS, 0);

            // To demonstration how to perform sparse math let's multiply:
            //                  y=A*x
            // Optional storage is set to null so that it will declare it internally
            long       before = DateTimeHelper.CurrentTimeMilliseconds;
            IGrowArray workA  = new IGrowArray(A.numRows);
            DGrowArray workB  = new DGrowArray(A.numRows);

            for (int i = 0; i < 100; i++)
            {
                CommonOps_DSCC.mult(A, x, y, workA, workB);
                CommonOps_DSCC.add(1.5, y, 0.75, y, z, workA, workB);
            }
            long after = DateTimeHelper.CurrentTimeMilliseconds;

            Console.WriteLine("norm = " + NormOps_DSCC.fastNormF(y) + "  sparse time = " + (after - before) + " ms");

            DMatrixRMaj Ad = ConvertDMatrixStruct.convert(A, (DMatrixRMaj)null);
            DMatrixRMaj xd = ConvertDMatrixStruct.convert(x, (DMatrixRMaj)null);
            DMatrixRMaj yd = new DMatrixRMaj(y.numRows, y.numCols);
            DMatrixRMaj zd = new DMatrixRMaj(y.numRows, y.numCols);

            before = DateTimeHelper.CurrentTimeMilliseconds;
            for (int i = 0; i < 100; i++)
            {
                CommonOps_DDRM.mult(Ad, xd, yd);
                CommonOps_DDRM.add(1.5, yd, 0.75, yd, zd);
            }
            after = DateTimeHelper.CurrentTimeMilliseconds;
            Console.WriteLine("norm = " + NormOps_DDRM.fastNormF(yd) + "  dense time  = " + (after - before) + " ms");
        }
Beispiel #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;
                }
            }
        }