예제 #1
0
        public bool setA(T A)
        {
            if (alg.modifiesA())
            {
                this.A    = (T)UtilEjml.reshapeOrDeclare(this.A, A);
                this.A.To = A;
                return(alg.setA(this.A));
            }

            return(alg.setA(A));
        }
        public bool setA(DMatrixRMaj A)
        {
            blockA.reshape(A.numRows, A.numCols, false);
            MatrixOps_DDRB.convert(A, blockA);

            return(alg.setA(blockA));
        }
예제 #3
0
        //@Override
        public void update(DMatrixRMaj z, DMatrixRMaj R)
        {
            // y = z - H x
            CommonOps_DDRM.mult(H, x, y);
            CommonOps_DDRM.subtract(z, y, y);

            // S = H P H' + R
            CommonOps_DDRM.mult(H, P, c);
            CommonOps_DDRM.multTransB(c, H, S);
            CommonOps_DDRM.addEquals(S, R);

            // K = PH'S^(-1)
            if (!solver.setA(S))
            {
                throw new InvalidOperationException("Invert failed");
            }
            solver.invert(S_inv);
            CommonOps_DDRM.multTransA(H, S_inv, d);
            CommonOps_DDRM.mult(P, d, K);

            // x = x + Ky
            CommonOps_DDRM.mult(K, y, a);
            CommonOps_DDRM.addEquals(x, a);

            // P = (I-kH)P = P - (KH)P = P-K(HP)
            CommonOps_DDRM.mult(H, P, c);
            CommonOps_DDRM.mult(K, c, b);
            CommonOps_DDRM.subtractEquals(P, b);
        }
예제 #4
0
        public virtual bool setA(T A)
        {
            if (alg.modifiesA())
            {
                if (this.A == null)
                {
                    this.A = (T)A.copy();
                }
                else
                {
                    if (this.A.getNumRows() != A.getNumRows() || this.A.getNumCols() != A.getNumCols())
                    {
                        this.A.reshape(A.getNumRows(), A.getNumCols());
                    }
                    this.A.set(A);
                }
                return(alg.setA(this.A));
            }

            return(alg.setA(A));
        }
예제 #5
0
        /**
         * <p>
         * Performs a matrix inversion operation on the specified matrix and stores the results
         * in the same matrix.<br>
         * <br>
         * a = a<sup>-1</sup>
         * </p>
         *
         * <p>
         * If the algorithm could not invert the matrix then false is returned.  If it returns true
         * that just means the algorithm finished.  The results could still be bad
         * because the matrix is singular or nearly singular.
         * </p>
         *
         * @param A The matrix that is to be inverted.  Results are stored here.  Modified.
         * @return true if it could invert the matrix false if it could not.
         */
        public static bool invert(CMatrixRMaj A)
        {
            LinearSolverDense <CMatrixRMaj> solver = LinearSolverFactory_CDRM.lu(A.numRows);

            if (solver.setA(A))
            {
                solver.invert(A);
            }
            else
            {
                return(false);
            }
            return(true);
        }
예제 #6
0
        /**
         * <p>
         * Performs a matrix inversion operation that does not modify the original
         * and stores the results in another matrix.  The two matrices must have the
         * same dimension.<br>
         * <br>
         * b = a<sup>-1</sup>
         * </p>
         *
         * <p>
         * If the algorithm could not invert the matrix then false is returned.  If it returns true
         * that just means the algorithm finished.  The results could still be bad
         * because the matrix is singular or nearly singular.
         * </p>
         *
         * <p>
         * For medium to large matrices there might be a slight performance boost to using
         * {@link LinearSolverFactory_CDRM} instead.
         * </p>
         *
         * @param input The matrix that is to be inverted. Not modified.
         * @param output Where the inverse matrix is stored.  Modified.
         * @return true if it could invert the matrix false if it could not.
         */
        public static bool invert(CMatrixRMaj input, CMatrixRMaj output)
        {
            LinearSolverDense <CMatrixRMaj> solver = LinearSolverFactory_CDRM.lu(input.numRows);

            if (solver.modifiesA())
            {
                input = (CMatrixRMaj)input.copy();
            }

            if (!solver.setA(input))
            {
                return(false);
            }
            solver.invert(output);
            return(true);
        }
예제 #7
0
        public override /**/ double quality()
        {
            return(SpecializedOps_FDRM.qualityTriangular(R));
        }

        /**
         * <p>
         * Upgrades the basic solution to the optimal 2-norm solution.
         * </p>
         *
         * <pre>
         * First solves for 'z'
         *
         *       || x_b - P*[ R_11^-1 * R_12 ] * z ||2
         * min z ||         [ - I_{n-r}      ]     ||
         *
         * </pre>
         *
         * @param X basic solution, also output solution
         */
        protected void upgradeSolution(FMatrixRMaj X)
        {
            FMatrixRMaj z = Y; // recycle Y

            // compute the z which will minimize the 2-norm of X
            // because of the identity matrix tacked onto the end 'A' should never be singular
            if (!internalSolver.setA(W))
            {
                throw new InvalidOperationException("This should never happen.  Is input NaN?");
            }
            z.reshape(numCols - rank, 1);
            internalSolver.solve(X, z);

            // compute X by tweaking the original
            CommonOps_FDRM.multAdd(-1, W, z, X);
        }
예제 #8
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(FMatrixRMaj A, float alpha)
        {
            initPower(A);

            LinearSolverDense <FMatrixRMaj> solver = LinearSolverFactory_FDRM.linear(A.numCols);

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

            bool converged = false;

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

                converged = checkConverged(A);
            }

            return(converged);
        }
        private void solveWithLU(float real, int index, FMatrixRMaj r)
        {
            FMatrixRMaj A = new FMatrixRMaj(index, index);

            CommonOps_FDRM.extract(_implicit.A, 0, index, 0, index, A, 0, 0);

            for (int i = 0; i < index; i++)
            {
                A.add(i, i, -real);
            }

            r.reshape(index, 1, false);

            SpecializedOps_FDRM.subvector(_implicit.A, 0, index, index, false, 0, r);
            CommonOps_FDRM.changeSign(r);

            // TODO this must be very inefficient
            if (!solver.setA(A))
            {
                throw new InvalidOperationException("Solve failed");
            }
            solver.solve(r, r);
        }
예제 #10
0
        /**
         * <p>
         * Given an eigenvalue it computes an eigenvector using inverse iteration:
         * <br>
         * for i=1:MAX {<br>
         *   (A - &mu;I)z<sup>(i)</sup> = q<sup>(i-1)</sup><br>
         *   q<sup>(i)</sup> = z<sup>(i)</sup> / ||z<sup>(i)</sup>||<br>
         * &lambda;<sup>(i)</sup> =  q<sup>(i)</sup><sup>T</sup> A  q<sup>(i)</sup><br>
         * }<br>
         * </p>
         * <p>
         * NOTE: If there is another eigenvalue that is very similar to the provided one then there
         * is a chance of it converging towards that one instead.  The larger a matrix is the more
         * likely this is to happen.
         * </p>
         * @param A Matrix whose eigenvector is being computed.  Not modified.
         * @param eigenvalue The eigenvalue in the eigen pair.
         * @return The eigenvector or null if none could be found.
         */
        public static FEigenpair computeEigenVector(FMatrixRMaj A, float eigenvalue)
        {
            if (A.numRows != A.numCols)
            {
                throw new ArgumentException("Must be a square matrix.");
            }

            FMatrixRMaj M = new FMatrixRMaj(A.numRows, A.numCols);

            FMatrixRMaj x = new FMatrixRMaj(A.numRows, 1);
            FMatrixRMaj b = new FMatrixRMaj(A.numRows, 1);

            CommonOps_FDRM.fill(b, 1);

            // perturb the eigenvalue slightly so that its not an exact solution the first time
//        eigenvalue -= eigenvalue*UtilEjml.F_EPS*10;

            float origEigenvalue = eigenvalue;

            SpecializedOps_FDRM.addIdentity(A, M, -eigenvalue);

            float threshold = NormOps_FDRM.normPInf(A) * UtilEjml.F_EPS;

            float prevError = float.MaxValue;
            bool  hasWorked = false;

            LinearSolverDense <FMatrixRMaj> solver = LinearSolverFactory_FDRM.linear(M.numRows);

            float perp = 0.0001f;

            for (int i = 0; i < 200; i++)
            {
                bool failed = false;
                // if the matrix is singular then the eigenvalue is within machine precision
                // of the true value, meaning that x must also be.
                if (!solver.setA(M))
                {
                    failed = true;
                }
                else
                {
                    solver.solve(b, x);
                }

                // see if solve silently failed
                if (MatrixFeatures_FDRM.hasUncountable(x))
                {
                    failed = true;
                }

                if (failed)
                {
                    if (!hasWorked)
                    {
                        // if it failed on the first trial try perturbing it some more
                        float val = i % 2 == 0 ? 1.0f - perp : 1.0f + perp;
                        // maybe this should be turn into a parameter allowing the user
                        // to configure the wise of each step

                        eigenvalue = origEigenvalue * (float)Math.Pow(val, i / 2 + 1);
                        SpecializedOps_FDRM.addIdentity(A, M, -eigenvalue);
                    }
                    else
                    {
                        // otherwise assume that it was so accurate that the matrix was singular
                        // and return that result
                        return(new FEigenpair(eigenvalue, b));
                    }
                }
                else
                {
                    hasWorked = true;

                    b.set(x);
                    NormOps_FDRM.normalizeF(b);

                    // compute the residual
                    CommonOps_FDRM.mult(M, b, x);
                    float error = NormOps_FDRM.normPInf(x);

                    if (error - prevError > UtilEjml.F_EPS * 10)
                    {
                        // if the error increased it is probably converging towards a different
                        // eigenvalue
//                    CommonOps.set(b,1);
                        prevError = float.MaxValue;
                        hasWorked = false;
                        float val = i % 2 == 0 ? 1.0f - perp : 1.0f + perp;
                        eigenvalue = origEigenvalue * (float)Math.Pow(val, 1);
                    }
                    else
                    {
                        // see if it has converged
                        if (error <= threshold || Math.Abs(prevError - error) <= UtilEjml.F_EPS)
                        {
                            return(new FEigenpair(eigenvalue, b));
                        }

                        // update everything
                        prevError  = error;
                        eigenvalue = VectorVectorMult_FDRM.innerProdA(b, A, b);
                    }

                    SpecializedOps_FDRM.addIdentity(A, M, -eigenvalue);
                }
            }

            return(null);
        }