示例#1
0
        public virtual DMatrixRMaj getU(DMatrixRMaj U, bool transpose, bool compact)
        {
            U = BidiagonalDecompositionRow_DDRM.handleU(U, false, compact, m, n, min);

            if (compact)
            {
                // U = Q*U1
                DMatrixRMaj Q1 = decompQRP.getQ(null, true);
                DMatrixRMaj U1 = decompBi.getU(null, false, true);
                CommonOps_DDRM.mult(Q1, U1, U);
            }
            else
            {
                // U = [Q1*U1 Q2]
                DMatrixRMaj Q   = decompQRP.getQ(U, false);
                DMatrixRMaj U1  = decompBi.getU(null, false, true);
                DMatrixRMaj Q1  = CommonOps_DDRM.extract(Q, 0, Q.numRows, 0, min);
                DMatrixRMaj tmp = new DMatrixRMaj(Q1.numRows, U1.numCols);
                CommonOps_DDRM.mult(Q1, U1, tmp);
                CommonOps_DDRM.insert(tmp, Q, 0, 0);
            }

            if (transpose)
            {
                CommonOps_DDRM.transpose(U);
            }

            return(U);
        }
示例#2
0
        /**
         * Returns the Q matrix.
         */
        public DMatrixRMaj getQ()
        {
            DMatrixRMaj Q   = CommonOps_DDRM.identity(QR.numRows);
            DMatrixRMaj Q_k = new DMatrixRMaj(QR.numRows, QR.numRows);
            DMatrixRMaj u   = new DMatrixRMaj(QR.numRows, 1);

            DMatrixRMaj temp = new DMatrixRMaj(QR.numRows, QR.numRows);

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

            // compute Q by first extracting the householder vectors from the columns of QR and then applying it to Q
            for (int j = N - 1; j >= 0; j--)
            {
                CommonOps_DDRM.extract(QR, j, QR.numRows, j, j + 1, u, j, 0);
                u.set(j, 1.0);

                // A = (I - &gamma;*u*u<sup>T</sup>)*A<br>
                CommonOps_DDRM.setIdentity(Q_k);
                CommonOps_DDRM.multAddTransB(-gammas[j], u, u, Q_k);
                CommonOps_DDRM.mult(Q_k, Q, temp);
                Q.set(temp);
            }

            return(Q);
        }
示例#3
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);
        }
        //@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);
        }
        public virtual bool setA(DMatrixRMaj A)
        {
            pinv.reshape(A.numCols, A.numRows, false);

            if (!svd.decompose(A))
            {
                return(false);
            }

            svd.getU(U_t, true);
            svd.getV(V, false);
            double[] S = svd.getSingularValues();
            int      N = Math.Min(A.numRows, A.numCols);

            // compute the threshold for singular values which are to be zeroed
            double maxSingular = 0;

            for (int i = 0; i < N; i++)
            {
                if (S[i] > maxSingular)
                {
                    maxSingular = S[i];
                }
            }

            double tau = threshold * Math.Max(A.numCols, A.numRows) * maxSingular;

            // computer the pseudo inverse of A
            if (maxSingular != 0.0)
            {
                for (int i = 0; i < N; i++)
                {
                    double s = S[i];
                    if (s < tau)
                    {
                        S[i] = 0;
                    }
                    else
                    {
                        S[i] = 1.0 / S[i];
                    }
                }
            }

            // V*W
            for (int i = 0; i < V.numRows; i++)
            {
                int index = i * V.numCols;
                for (int j = 0; j < V.numCols; j++)
                {
                    V.data[index++] *= S[j];
                }
            }

            // V*W*U^T
            CommonOps_DDRM.mult(V, U_t, pinv);

            return(true);
        }
        //@Override
        public void predict()
        {
            // x = F x
            CommonOps_DDRM.mult(F, x, a);
            x.set(a);

            // P = F P F' + Q
            CommonOps_DDRM.mult(F, P, b);
            CommonOps_DDRM.multTransB(b, F, P);
            CommonOps_DDRM.addEquals(P, Q);
        }
示例#7
0
        /**
         * Compute the A matrix from the Q and R matrices.
         *
         * @return The A matrix.
         */
        public override DMatrixRMaj getA()
        {
            if (A.data.Length < numRows * numCols)
            {
                A = new DMatrixRMaj(numRows, numCols);
            }
            A.reshape(numRows, numCols, false);
            CommonOps_DDRM.mult(Q, R, A);

            return(A);
        }
示例#8
0
        /**
         * Creates a newJava.Util.Random symmetric matrix that will have the specified real eigenvalues.
         *
         * @param num Dimension of the resulting matrix.
         * @param randJava.Util.Random number generator.
         * @param eigenvalues Set of real eigenvalues that the matrix will have.
         * @return AJava.Util.Random matrix with the specified eigenvalues.
         */
        public static DMatrixRMaj symmetricWithEigenvalues(int num, Java.Util.Random rand, double[] eigenvalues)
        {
            DMatrixRMaj V = RandomMatrices_DDRM.orthogonal(num, num, rand);
            DMatrixRMaj D = CommonOps_DDRM.diag(eigenvalues);

            DMatrixRMaj temp = new DMatrixRMaj(num, num);

            CommonOps_DDRM.mult(V, D, temp);
            CommonOps_DDRM.multTransB(temp, V, D);

            return(D);
        }
        /**
         * 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));
        }
        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);
        }
示例#11
0
        private void checkMatrix(int numRows, int numCols)
        {
            DMatrixRMaj A = RandomMatrices_DDRM.rectangle(numRows, numCols, -1, 1, rand);

            QRExampleOperations alg = new QRExampleOperations();

            alg.decompose(A);

            DMatrixRMaj Q = alg.getQ();
            DMatrixRMaj R = alg.getR();

            DMatrixRMaj A_found = new DMatrixRMaj(numRows, numCols);

            CommonOps_DDRM.mult(Q, R, A_found);

            Assert.IsTrue(MatrixFeatures_DDRM.isIdentical(A, A_found, UtilEjml.TEST_F64));
        }
        /**
         * Converts a vector from sample space into eigen space.
         *
         * @param sampleData Sample space data.
         * @return Eigen space projection.
         */
        public double[] sampleToEigenSpace(double[] sampleData)
        {
            if (sampleData.Length != A.getNumCols())
            {
                throw new ArgumentException("Unexpected sample length");
            }
            DMatrixRMaj mean = DMatrixRMaj.wrap(A.getNumCols(), 1, this.mean);

            DMatrixRMaj s = new DMatrixRMaj(A.getNumCols(), 1, true, sampleData);
            DMatrixRMaj r = new DMatrixRMaj(numComponents, 1);

            CommonOps_DDRM.subtract(s, mean, s);

            CommonOps_DDRM.mult(V_t, s, r);

            return(r.data);
        }
示例#13
0
        /**
         * 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);
        }
        public bool extractVectors(DMatrixRMaj Q_h)
        {
            Array.Clear(eigenvectorTemp.data, 0, eigenvectorTemp.data.Length);
            // extract eigenvectors from the shur matrix
            // start at the top left corner of the matrix
            bool triangular = true;

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

                if (triangular && !c.isReal())
                {
                    triangular = false;
                }

                if (c.isReal() && eigenvectors[N - i - 1] == null)
                {
                    solveEigenvectorDuplicateEigenvalue(c.real, i, triangular);
                }
            }

            // translate the eigenvectors into the frame of the original matrix
            if (Q_h != null)
            {
                DMatrixRMaj temp = new DMatrixRMaj(N, 1);
                for (int i = 0; i < N; i++)
                {
                    DMatrixRMaj v = eigenvectors[i];

                    if (v != null)
                    {
                        CommonOps_DDRM.mult(Q_h, v, temp);
                        eigenvectors[i] = temp;
                        temp            = v;
                    }
                }
            }

            return(true);
        }
示例#15
0
        private List <DMatrixRMaj> createSimulatedMeas(DMatrixRMaj x)
        {
            List <DMatrixRMaj> ret = new List <DMatrixRMaj>();

            DMatrixRMaj F = createF(T);
            DMatrixRMaj H = createH();

//        UtilEjml.print(F);
//        UtilEjml.print(H);

            DMatrixRMaj x_next = new DMatrixRMaj(x);
            DMatrixRMaj z      = new DMatrixRMaj(H.numRows, 1);

            for (int i = 0; i < MAX_STEPS; i++)
            {
                CommonOps_DDRM.mult(F, x, x_next);
                CommonOps_DDRM.mult(H, x_next, z);
                ret.Add((DMatrixRMaj)z.copy());
                x.set(x_next);
            }

            return(ret);
        }
示例#16
0
        /**
         * <p>
         * Creates a random matrix which will have the provided singular values.  The length of sv
         * is assumed to be the rank of the matrix.  This can be useful for testing purposes when one
         * needs to ensure that a matrix is not singular but randomly generated.
         * </p>
         *
         * @param numRows Number of rows in generated matrix.
         * @param numCols NUmber of columns in generated matrix.
         * @param rand Random number generator.
         * @param sv Singular values of the matrix.
         * @return A new matrix with the specified singular values.
         */
        public static DMatrixRMaj singleValues(int numRows, int numCols,
                                               IMersenneTwister rand, double[] sv)
        {
            DMatrixRMaj U = RandomMatrices_DDRM.orthogonal(numRows, numRows, rand);
            DMatrixRMaj V = RandomMatrices_DDRM.orthogonal(numCols, numCols, rand);

            DMatrixRMaj S = new DMatrixRMaj(numRows, numCols);

            int min = Math.Min(numRows, numCols);

            min = Math.Min(min, sv.Length);

            for (int i = 0; i < min; i++)
            {
                S.set(i, i, sv[i]);
            }

            DMatrixRMaj tmp = new DMatrixRMaj(numRows, numCols);

            CommonOps_DDRM.mult(U, S, tmp);
            CommonOps_DDRM.multTransB(tmp, V, S);

            return(S);
        }
示例#17
0
        /**
         * <p>
         * Creates aJava.Util.Random matrix which will have the provided singular values.  The Count() of sv
         * is assumed to be the rank of the matrix.  This can be useful for testing purposes when one
         * needs to ensure that a matrix is not singular but randomly generated.
         * </p>
         *
         * @param numRows Number of rows in generated matrix.
         * @param numCols NUmber of columns in generated matrix.
         * @param randJava.Util.Random number generator.
         * @param sv Singular values of the matrix.
         * @return A new matrix with the specified singular values.
         */
        public static DMatrixRMaj singular(int numRows, int numCols,
                                           Java.Util.Random rand, double[] sv)
        {
            DMatrixRMaj U, V, S;

            // speed it up in compact format
            if (numRows > numCols)
            {
                U = RandomMatrices_DDRM.orthogonal(numRows, numCols, rand);
                V = RandomMatrices_DDRM.orthogonal(numCols, numCols, rand);
                S = new DMatrixRMaj(numCols, numCols);
            }
            else
            {
                U = RandomMatrices_DDRM.orthogonal(numRows, numRows, rand);
                V = RandomMatrices_DDRM.orthogonal(numCols, numCols, rand);
                S = new DMatrixRMaj(numRows, numCols);
            }

            int min = Math.Min(numRows, numCols);

            min = Math.Min(min, sv.Count());

            for (int i = 0; i < min; i++)
            {
                S.set(i, i, sv[i]);
            }

            DMatrixRMaj tmp = new DMatrixRMaj(numRows, numCols);

            CommonOps_DDRM.mult(U, S, tmp);
            S.reshape(numRows, numCols);
            CommonOps_DDRM.multTransB(tmp, V, S);

            return(S);
        }
示例#18
0
        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");
        }
示例#19
0
        /** Revises the CMA-ES distribution to reflect the current fitness results in the provided subpopulation. */
        public void UpdateDistribution(IEvolutionState state, Subpopulation subpop)
        {
            // % Sort by fitness and compute weighted mean into xmean
            // [arfitness, arindex] = sort(arfitness); % minimization
            // xmean = arx(:,arindex(1:mu))*weights;   % recombination            % Eq.39
            // counteval += lambda;

            // only need partial sort?
            ((List <Individual>)subpop.Individuals).Sort();

            SimpleMatrixD artmp = new SimpleMatrixD(GenomeSize, mu);
            SimpleMatrixD xold  = xmean;

            xmean = new SimpleMatrixD(GenomeSize, 1);

            for (int i = 0; i < mu; i++)
            {
                DoubleVectorIndividual dvind = (DoubleVectorIndividual)subpop.Individuals[i];

                // won't modify the genome
                SimpleMatrixD arz = new SimpleMatrixD(GenomeSize, 1, true, dvind.genome);
                arz = (arz.minus(xold).divide(sigma));

                for (int j = 0; j < GenomeSize; j++)
                {
                    xmean.set(j, 0, xmean.get(j, 0) + weights[i] * dvind.genome[j]);
                    artmp.set(j, i, arz.get(j, 0));
                }
            }

            // % Cumulation: Update evolution paths

            SimpleMatrixD y         = xmean.minus(xold).divide(sigma);
            SimpleMatrixD bz        = invsqrtC.mult(y);
            SimpleMatrixD bz_scaled = bz.scale(Math.Sqrt(cs * (2.0 - cs) * mueff));

            ps = ps.scale(1.0 - cs).plus(bz_scaled);

            double h_sigma_value =
                ((ps.dot(ps) / (1.0 - Math.Pow(1.0 - cs, 2.0 * (state.Generation + 1)))) / GenomeSize);
            int hsig = (h_sigma_value < (2.0 + (4.0 / (GenomeSize + 1)))) ? 1 : 0;

            SimpleMatrixD y_scaled = y.scale(hsig * Math.Sqrt(cc * (2.0 - cc) * mueff));

            pc = pc.scale(1.0 - cc).plus(y_scaled);

            // % Adapt covariance matrix C
            c = c.scale(1.0 - c1 - cmu);
            c = c.plus(pc.mult(pc.transpose()).plus(c.scale((1.0 - hsig) * cc * (2.0 - cc))).scale(c1));
            c = c.plus((artmp.mult(SimpleMatrixD.diag(weights).mult(artmp.transpose()))).scale(cmu));

            // % Adapt step-size sigma
            sigma = sigma * Math.Exp((cs / damps) * (ps.normF() / chiN - 1.0));

            // % Update B and D from C
            if ((state.Generation - lastEigenDecompositionGeneration) > 1.0 / ((c1 + cmu) * GenomeSize * 10.0))
            {
                lastEigenDecompositionGeneration = state.Generation;

                // make sure the matrix is symmetric (it should be already)
                // not sure if this is necessary
                for (int i = 0; i < GenomeSize; i++)
                {
                    for (int j = 0; j < i; j++)
                    {
                        c.set(j, i, c.get(i, j));
                    }
                }

                // this copy gets modified by the decomposition
                DMatrixRMaj copy = c.copy().getMatrix();
                EigenDecomposition <DMatrixRMaj> eig = DecompositionFactory_DDRM.eig(GenomeSize, true, true);
                if (eig.decompose(copy))
                {
                    SimpleMatrixD dinv = new SimpleMatrixD(GenomeSize, GenomeSize);
                    for (int i = 0; i < GenomeSize; i++)
                    {
                        double eigrt = Math.Sqrt(eig.getEigenValue(i).real);
                        d.set(i, i, eigrt);
                        dinv.set(i, i, 1 / eigrt);
                        CommonOps_DDRM.insert(eig.getEigenVector(i), b.getMatrix(), 0, i);
                    }

                    invsqrtC = b.mult(dinv.mult(b.transpose()));
                    CommonOps_DDRM.mult(b.getMatrix(), d.getMatrix(), bd);
                }
                else
                {
                    state.Output.Fatal("CMA-ES eigendecomposition failed. ");
                }
            }

            CommonOps_DDRM.scale(sigma, bd, sbd);

            // % Break, if fitness is good enough or condition exceeds 1e14, better termination methods are advisable
            // if arfitness(1) <= stopfitness || max(D) > 1e7 * min(D)
            //   break;
            // end
            if (useAltTermination && CommonOps_DDRM.elementMax(d.diag().getMatrix()) >
                1e7 * CommonOps_DDRM.elementMin(d.diag().getMatrix()))
            {
                state.Evaluator.SetRunCompleted("CMAESSpecies: Stopped because matrix condition exceeded limit.");
            }
        }
示例#20
0
 public virtual void mult(DMatrixRMaj A, DMatrixRMaj B, DMatrixRMaj output)
 {
     CommonOps_DDRM.mult(A, B, output);
 }
示例#21
0
        public override Individual NewIndividual(IEvolutionState state, int thread)
        {
            Individual       newind = base.NewIndividual(state, thread);
            IMersenneTwister random = state.Random[thread];

            if (!(newind is DoubleVectorIndividual)) // uh oh
            {
                state.Output.Fatal(
                    "To use CMAESSpecies, the species must be initialized with a DoubleVectorIndividual.  But it contains a " +
                    newind);
            }

            DoubleVectorIndividual dvind = (DoubleVectorIndividual)(newind);

            DMatrixRMaj genome = DMatrixRMaj.wrap(GenomeSize, 1, dvind.genome);
            DMatrixRMaj temp   = new DMatrixRMaj(GenomeSize, 1);

            // arz(:,k) = randn(N,1); % standard normally distributed vector
            // arx(:,k) = xmean + sigma*(B*D*arz(:,k));
            int tries = 0;

            while (true)
            {
                for (int i = 0; i < GenomeSize; i++)
                {
                    dvind.genome[i] = random.NextGaussian();
                }

                CommonOps_DDRM.mult(sbd, genome, temp);              // temp = sigma*b*d*genome;
                CommonOps_DDRM.add(temp, xmean.getMatrix(), genome); // genome = temp + xmean;

                bool invalid_value = false;
                for (int i = 0; i < GenomeSize; i++)
                {
                    if (dvind.genome[i] < MinGenes[i] || dvind.genome[i] > MaxGenes[i])
                    {
                        if (useAltGenerator && tries > altGeneratorTries)
                        {
                            // instead of just failing, we're going to select uniformly from
                            // possible values for this particular gene.
                            dvind.genome[i] = state.Random[thread].NextDouble() * (MaxGenes[i] - MinGenes[i]) +
                                              MinGenes[i];
                        }
                        else
                        {
                            invalid_value = true;
                            break;
                        }
                    }
                }

                if (invalid_value)
                {
                    if (++tries > MAX_TRIES_BEFORE_WARNING)
                    {
                        state.Output.WarnOnce(
                            "CMA-ES may be slow because many individuals are being generated which\n" +
                            "are outside the min/max gene bounds.  If an individual violates a single\n" +
                            "gene bounds, it is rejected, so as the number of genes grows, the\n" +
                            "probability of this happens increases exponentially.  You can deal\n" +
                            "with this by decreasing sigma.  Alternatively you can use set\n" +
                            "pop.subpop.0.alternative-generation=true (see the manual).\n" +
                            "Finally, if this is happening during initialization, you might also\n" +
                            "change pop.subpop.0.species.covariance=scaled.\n");
                    }
                    continue;
                }

                return(newind);
            }
        }
示例#22
0
        public override void Setup(IEvolutionState state, IParameter paramBase)
        {
            base.Setup(state, paramBase);
            IMersenneTwister random = state.Random[0];

            IParameter def = DefaultBase;

            IParameter subpopBase        = paramBase.Pop();
            IParameter subpopDefaultBase = ECDefaults.ParamBase.Push(Subpopulation.P_SUBPOPULATION);

            if (!state.Parameters.ParameterExists(paramBase.Push(P_SIGMA), def.Push(P_SIGMA)))
            {
                state.Output.Message("CMA-ES sigma was not provided, defaulting to 1.0");
                sigma = 1.0;
            }
            else
            {
                sigma = state.Parameters.GetDouble(paramBase.Push(P_SIGMA), def.Push(P_SIGMA), 0.0);
                if (sigma <= 0)
                {
                    state.Output.Fatal("If CMA-ES sigma is provided, it must be > 0.0", paramBase.Push(P_SIGMA),
                                       def.Push(P_SIGMA));
                }
            }

            double[] cvals = new double[GenomeSize];
            string   covarianceInitialization =
                state.Parameters.GetStringWithDefault(paramBase.Push(P_COVARIANCE), def.Push(P_COVARIANCE), V_IDENTITY);
            string covs = "Initial Covariance: <";

            for (int i = 0; i < GenomeSize; i++)
            {
                if (i > 0)
                {
                    covs += ", ";
                }
                if (covarianceInitialization.Equals(V_SCALED))
                {
                    cvals[i] = (MaxGenes[i] - MinGenes[i]);
                }
                else if (covarianceInitialization.Equals(V_IDENTITY))
                {
                    cvals[i] = 1.0;
                }
                else
                {
                    state.Output.Fatal("Invalid covariance initialization type " + covarianceInitialization,
                                       paramBase.Push(P_COVARIANCE), def.Push(P_COVARIANCE));
                }

                // cvals is standard deviations, so we change them to variances now
                cvals[i] *= cvals[i];
                covs     += cvals[i];
            }
            state.Output.Message(covs + ">");

            // set myself up and define my initial distribution here
            int n = GenomeSize;

            b = SimpleMatrixD.identity(n);
            c = new SimpleMatrixD(CommonOps_DDRM.diag(cvals));

            d        = SimpleMatrixD.identity(n);
            bd       = CommonOps_DDRM.identity(n, n);
            sbd      = CommonOps_DDRM.identity(n, n);
            invsqrtC = SimpleMatrixD.identity(n);


            // Here we do one FIRST round of eigendecomposition, because newIndividual needs
            // a valid version of sbd.  If c is initially the identity matrix (and sigma = 1),
            // then sbd is too, and we're done.  But if c is scaled in any way, we need to compute
            // the proper value of sbd.  Along the way we'll wind up computing b, d, bd, and invsqrtC

            EigenDecomposition <DMatrixRMaj> eig = DecompositionFactory_DDRM.eig(GenomeSize, true, true);

            if (eig.decompose(c.copy().getMatrix()))
            {
                SimpleMatrixD dinv = new SimpleMatrixD(GenomeSize, GenomeSize);
                for (int i = 0; i < GenomeSize; i++)
                {
                    double eigrt = Math.Sqrt(eig.getEigenValue(i).real);
                    d.set(i, i, eigrt);
                    dinv.set(i, i, 1 / eigrt);
                    CommonOps_DDRM.insert(eig.getEigenVector(i), b.getMatrix(), 0, i);
                }

                invsqrtC = b.mult(dinv.mult(b.transpose()));
                CommonOps_DDRM.mult(b.getMatrix(), d.getMatrix(), bd);
            }
            else
            {
                state.Output.Fatal("CMA-ES eigendecomposition failed. ");
            }
            CommonOps_DDRM.scale(sigma, bd, sbd);

            // End FIRST round of eigendecomposition



            // Initialize dynamic (internal) strategy parameters and constants
            pc   = new SimpleMatrixD(n, 1);
            ps   = new SimpleMatrixD(n, 1);                        // evolution paths for C and sigma
            chiN = Math.Sqrt(n) *
                   (1.0 - 1.0 / (4.0 * n) + 1.0 / (21.0 * n * n)); // expectation of ||N(0,I)|| == norm(randn(N,1))

            xmean = new SimpleMatrixD(GenomeSize, 1);

            bool   meanSpecified = false;
            string val           = state.Parameters.GetString(paramBase.Push(P_MEAN), def.Push(P_MEAN));

            if (val != null)
            {
                meanSpecified = true;
                if (val.Equals(V_CENTER))
                {
                    for (int i = 0; i < GenomeSize; i++)
                    {
                        xmean.set(i, 0, (MaxGenes[i] + MinGenes[i]) / 2.0);
                    }
                }
                else if (val.Equals(V_ZERO))
                {
                    for (int i = 0; i < GenomeSize; i++)
                    {
                        xmean.set(i, 0, 0); // it is this anyway
                    }
                }
                else if (val.Equals(V_RANDOM))
                {
                    for (int i = 0; i < GenomeSize; i++)
                    {
                        xmean.set(i, 0,
                                  state.Random[0].NextDouble(true, true) * (MaxGenes[i] - MinGenes[i]) + MinGenes[i]);
                    }
                }
                else
                {
                    state.Output.Fatal("Unknown mean value specified: " + val, paramBase.Push(P_MEAN), def.Push(P_MEAN));
                }
            }
            else
            {
                state.Output.Fatal("No default mean value specified.  Loading full mean from parameters.",
                                   paramBase.Push(P_MEAN), def.Push(P_MEAN));
            }

            bool nonDefaultMeanSpecified = false;

            for (int i = 0; i < GenomeSize; i++)
            {
                double m_i = 0;
                try
                {
                    m_i = state.Parameters.GetDouble(paramBase.Push(P_MEAN).Push("" + i), def.Push(P_MEAN).Push("" + i));
                    xmean.set(i, 0, m_i);
                    nonDefaultMeanSpecified = true;
                }
                catch (FormatException e)
                {
                    if (!meanSpecified)
                    {
                        state.Output.Error(
                            "No default mean value was specified, but CMA-ES mean index " + i +
                            " is missing or not a number.", paramBase.Push(P_MEAN).Push("" + i),
                            def.Push(P_MEAN).Push("" + i));
                    }
                }
            }

            state.Output.ExitIfErrors();
            if (nonDefaultMeanSpecified && meanSpecified)
            {
                state.Output.Warning("A default mean value was specified, but certain mean values were overridden.");
            }

            string mes = "Initial Mean: <";

            for (int i = 0; i < GenomeSize - 1; i++)
            {
                mes = mes + xmean.get(i, 0) + ", ";
            }
            mes = mes + xmean.get(GenomeSize - 1, 0) + ">";
            state.Output.Message(mes);

            if (!state.Parameters.ParameterExists(paramBase.Push(P_LAMBDA), def.Push(P_LAMBDA)))
            {
                lambda = 4 + (int)Math.Floor(3 * Math.Log(n));
            }
            else
            {
                lambda = state.Parameters.GetInt(paramBase.Push(P_LAMBDA), def.Push(P_LAMBDA), 1);
                if (lambda <= 0)
                {
                    state.Output.Fatal("If the CMA-ES lambda parameter is provided, it must be a valid integer > 0",
                                       paramBase.Push(P_LAMBDA), def.Push(P_LAMBDA));
                }
            }

            if (!state.Parameters.ParameterExists(paramBase.Push(P_MU), def.Push(P_MU)))
            {
                mu = (int)(Math.Floor(lambda / 2.0));
            }
            else
            {
                mu = state.Parameters.GetInt(paramBase.Push(P_MU), def.Push(P_MU), 1);
                if (mu <= 0)
                {
                    state.Output.Fatal("If the CMA-ES mu parameter is provided, it must be a valid integer > 0",
                                       paramBase.Push(P_MU), def.Push(P_MU));
                }
            }

            if (mu > lambda) // uh oh
            {
                state.Output.Fatal("CMA-ES mu must be <= lambda.  Presently mu=" + mu + " and lambda=" + lambda);
            }

            weights = new double[mu];
            bool weightsSpecified = false;

            for (int i = 0; i < mu; i++)
            {
                if (state.Parameters.ParameterExists(paramBase.Push(P_WEIGHTS).Push("" + i), def.Push(P_WEIGHTS).Push("" + i)))
                {
                    state.Output.Message("CMA-ES weight index " + i +
                                         " specified.  Loading all weights from parameters.");
                    weightsSpecified = true;
                    break;
                }
            }

            if (weightsSpecified)
            {
                for (int i = 0; i < mu; i++)
                {
                    double m_i = 0;
                    try
                    {
                        weights[i] = state.Parameters.GetDouble(paramBase.Push(P_WEIGHTS).Push("" + i),
                                                                def.Push(P_WEIGHTS).Push("" + i));
                    }
                    catch (FormatException e)
                    {
                        state.Output.Error("CMA-ES weight index " + i + " missing or not a number.",
                                           paramBase.Push(P_WEIGHTS).Push("" + i), def.Push(P_WEIGHTS).Push("" + i));
                    }
                }
                state.Output.ExitIfErrors();
            }
            else
            {
                for (int i = 0; i < mu; i++)
                {
                    weights[i] = Math.Log((lambda + 1.0) / (2.0 * (i + 1)));
                }
            }

            // normalize
            double sum = 0.0;

            for (int i = 0; i < mu; i++)
            {
                sum += weights[i];
            }
            for (int i = 0; i < mu; i++)
            {
                weights[i] /= sum;
            }

            // compute mueff
            double sumSqr = 0.0;

            for (int i = 0; i < mu; i++)
            {
                sumSqr += weights[i] * weights[i];
            }
            mueff = 1.0 / sumSqr;

            mes = "Weights: <";
            for (int i = 0; i < weights.Length - 1; i++)
            {
                mes = mes + weights[i] + ", ";
            }
            mes = mes + (weights.Length - 1) + ">";
            state.Output.Message(mes);

            useAltTermination = state.Parameters.GetBoolean(paramBase.Push(P_ALTERNATIVE_TERMINATION),
                                                            def.Push(P_ALTERNATIVE_TERMINATION), false);
            useAltGenerator = state.Parameters.GetBoolean(paramBase.Push(P_ALTERNATIVE_GENERATOR),
                                                          def.Push(P_ALTERNATIVE_GENERATOR), false);
            altGeneratorTries = state.Parameters.GetIntWithDefault(paramBase.Push(P_ALTERNATIVE_GENERATOR_TRIES),
                                                                   def.Push(P_ALTERNATIVE_GENERATOR_TRIES), DEFAULT_ALT_GENERATOR_TRIES);
            if (altGeneratorTries < 1)
            {
                state.Output.Fatal(
                    "If specified (the default is " + DEFAULT_ALT_GENERATOR_TRIES +
                    "), alt-generation-tries must be >= 1",
                    paramBase.Push(P_ALTERNATIVE_GENERATOR_TRIES), def.Push(P_ALTERNATIVE_GENERATOR_TRIES));
            }

            if (!state.Parameters.ParameterExists(paramBase.Push(P_CC), def.Push(P_CC)))
            {
                cc = (4.0 + mueff / n) / (n + 4.0 + 2.0 * mueff / n); // time constant for cumulation for C
            }
            else
            {
                cc = state.Parameters.GetDoubleWithMax(paramBase.Push(P_CC), def.Push(P_CC), 0.0, 1.0);
                if (cc < 0.0)
                {
                    state.Output.Fatal(
                        "If the CMA-ES cc parameter is provided, it must be a valid number in the range [0,1]",
                        paramBase.Push(P_CC), def.Push(P_CC));
                }
            }

            if (!state.Parameters.ParameterExists(paramBase.Push(P_CS), def.Push(P_CS)))
            {
                cs = (mueff + 2.0) / (n + mueff + 5.0); // t-const for cumulation for sigma control
            }
            else
            {
                cs = state.Parameters.GetDoubleWithMax(paramBase.Push(P_CS), def.Push(P_CS), 0.0, 1.0);
                if (cs < 0.0)
                {
                    state.Output.Fatal(
                        "If the CMA-ES cs parameter is provided, it must be a valid number in the range [0,1]",
                        paramBase.Push(P_CS), def.Push(P_CS));
                }
            }

            if (!state.Parameters.ParameterExists(paramBase.Push(P_C1), def.Push(P_C1)))
            {
                c1 = 2.0 / ((n + 1.3) * (n + 1.3) + mueff); // learning rate for rank-one update of C
            }
            else
            {
                c1 = state.Parameters.GetDouble(paramBase.Push(P_C1), def.Push(P_C1), 0.0);
                if (c1 < 0)
                {
                    state.Output.Fatal("If the CMA-ES c1 parameter is provided, it must be a valid number >= 0.0",
                                       paramBase.Push(P_C1), def.Push(P_C1));
                }
            }

            if (!state.Parameters.ParameterExists(paramBase.Push(P_CMU), def.Push(P_CMU)))
            {
                cmu = Math.Min(1.0 - c1, 2.0 * (mueff - 2.0 + 1.0 / mueff) / ((n + 2.0) * (n + 2.0) + mueff));
            }
            else
            {
                cmu = state.Parameters.GetDouble(paramBase.Push(P_CMU), def.Push(P_CMU), 0.0);
                if (cmu < 0)
                {
                    state.Output.Fatal("If the CMA-ES cmu parameter is provided, it must be a valid number >= 0.0",
                                       paramBase.Push(P_CMU), def.Push(P_CMU));
                }
            }

            if (c1 > (1 - cmu)) // uh oh
            {
                state.Output.Fatal("CMA-ES c1 must be <= 1 - cmu.  You are using c1=" + c1 + " and cmu=" + cmu);
            }
            if (cmu > (1 - c1)) // uh oh
            {
                state.Output.Fatal("CMA-ES cmu must be <= 1 - c1.  You are using cmu=" + cmu + " and c1=" + c1);
            }

            if (!state.Parameters.ParameterExists(paramBase.Push(P_DAMPS), def.Push(P_DAMPS)))
            {
                damps = 1.0 + 2.0 * Math.Max(0.0, Math.Sqrt((mueff - 1.0) / (n + 1.0)) - 1.0) + cs; // damping for sigma
            }
            else
            {
                damps = state.Parameters.GetDouble(paramBase.Push(P_DAMPS), def.Push(P_DAMPS), 0.0);
                if (damps <= 0)
                {
                    state.Output.Fatal("If the CMA-ES damps parameter is provided, it must be a valid number > 0.0",
                                       paramBase.Push(P_DAMPS), def.Push(P_DAMPS));
                }
            }

            double damps_min = 0.5;
            double damps_max = 2.0;

            if (damps > damps_max || damps < damps_min)
            {
                state.Output.Warning("CMA-ES damps ought to be close to 1.  You are using damps = " + damps);
            }

            state.Output.Message("lambda: " + lambda);
            state.Output.Message("mu:     " + mu);
            state.Output.Message("mueff:  " + mueff);
            state.Output.Message("cmu:    " + cmu);
            state.Output.Message("c1:     " + c1);
            state.Output.Message("cc:     " + cc);
            state.Output.Message("cs:     " + cs);
            state.Output.Message("damps:  " + damps);
        }
示例#23
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 DEigenpair computeEigenVector(DMatrixRMaj A, double eigenvalue)
        {
            if (A.numRows != A.numCols)
            {
                throw new ArgumentException("Must be a square matrix.");
            }

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

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

            CommonOps_DDRM.fill(b, 1);

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

            double origEigenvalue = eigenvalue;

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

            double threshold = NormOps_DDRM.normPInf(A) * UtilEjml.EPS;

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

            LinearSolverDense <DMatrixRMaj> solver = LinearSolverFactory_DDRM.linear(M.numRows);

            double perp = 0.0001;

            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_DDRM.hasUncountable(x))
                {
                    failed = true;
                }

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

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

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

                    // compute the residual
                    CommonOps_DDRM.mult(M, b, x);
                    double error = NormOps_DDRM.normPInf(x);

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

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

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

            return(null);
        }
示例#24
0
 public void mult(Matrix A, Matrix B, Matrix output)
 {
     CommonOps_DDRM.mult((DMatrixRMaj)A, (DMatrixRMaj)B, (DMatrixRMaj)output);
 }
示例#25
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;
                }
            }
        }