Пример #1
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_DSCC} instead.
         * </p>
         *
         * @param A (Input) The matrix that is to be inverted. Not modified.
         * @param inverse (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(DMatrixSparseCSC A, DMatrixRMaj inverse)
        {
            if (A.numRows != A.numCols)
            {
                throw new ArgumentException("A must be a square matrix");
            }
            if (A.numRows != inverse.numRows || A.numCols != inverse.numCols)
            {
                throw new ArgumentException("A and inverse must have the same shape.");
            }

            LinearSolverSparse <DMatrixSparseCSC, DMatrixRMaj> solver;

            solver = LinearSolverFactory_DSCC.lu(FillReducing.NONE);

            // Ensure that the input isn't modified
            if (solver.modifiesA())
            {
                A = (DMatrixSparseCSC)A.copy();
            }

            DMatrixRMaj I = CommonOps_DDRM.identity(A.numRows);

            // decompose then solve the matrix
            if (!solver.setA(A))
            {
                return(false);
            }

            solver.solve(I, inverse);
            return(true);
        }
Пример #2
0
        public void run()
        {
            DMatrixRMaj priorX = new DMatrixRMaj(9, 1, true, 0.5, -0.2, 0, 0, 0.2, -0.9, 0, 0.2, -0.5);
            DMatrixRMaj priorP = CommonOps_DDRM.identity(9);

            DMatrixRMaj trueX = new DMatrixRMaj(9, 1, true, 0, 0, 0, 0.2, 0.2, 0.2, 0.5, 0.1, 0.6);

            List <DMatrixRMaj> meas = createSimulatedMeas(trueX);

            DMatrixRMaj F = createF(T);
            DMatrixRMaj Q = createQ(T, 0.1);
            DMatrixRMaj H = createH();

            foreach (KalmanFilter f in filters)
            {
                long timeBefore = DateTimeHelper.CurrentTimeMilliseconds;

                f.configure(F, Q, H);

                for (int trial = 0; trial < NUM_TRIALS; trial++)
                {
                    f.setState(priorX, priorP);
                    processMeas(f, meas);
                }

                long timeAfter = DateTimeHelper.CurrentTimeMilliseconds;

                Console.WriteLine("Filter = " + f.GetType().Name);
                Console.WriteLine("Elapsed time: " + (timeAfter - timeBefore));

                //System.gc();
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
        }
Пример #3
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);
        }
Пример #4
0
 public static DMatrixRMaj ensureIdentity(DMatrixRMaj A, int numRows, int numCols)
 {
     if (A == null)
     {
         return(CommonOps_DDRM.identity(numRows, numCols));
     }
     A.reshape(numRows, numCols);
     CommonOps_DDRM.setIdentity(A);
     return(A);
 }
Пример #5
0
        private void processMeas(KalmanFilter f,
                                 List <DMatrixRMaj> meas)
        {
            DMatrixRMaj R = CommonOps_DDRM.identity(measDOF);

            foreach (DMatrixRMaj z in meas)
            {
                f.predict();
                f.update(z, R);
            }
        }
        /**
         * Computes the Q matrix from the information stored in the QR matrix.  This
         * operation requires about 4(m<sup>2</sup>n-mn<sup>2</sup>+n<sup>3</sup>/3) flops.
         *
         * @param Q The orthogonal Q matrix.
         */
        //@Override
        public DMatrixRMaj getQ(DMatrixRMaj Q, bool compact)
        {
            if (compact)
            {
                if (Q == null)
                {
                    Q = CommonOps_DDRM.identity(numRows, minLength);
                }
                else
                {
                    if (Q.numRows != numRows || Q.numCols != minLength)
                    {
                        throw new ArgumentException("Unexpected matrix dimension.");
                    }
                    else
                    {
                        CommonOps_DDRM.setIdentity(Q);
                    }
                }
            }
            else
            {
                if (Q == null)
                {
                    Q = CommonOps_DDRM.identity(numRows);
                }
                else
                {
                    if (Q.numRows != numRows || Q.numCols != numRows)
                    {
                        throw new ArgumentException("Unexpected matrix dimension.");
                    }
                    else
                    {
                        CommonOps_DDRM.setIdentity(Q);
                    }
                }
            }

            // Unlike applyQ() this takes advantage of zeros in the identity matrix
            // by not multiplying across all rows.
            for (int j = minLength - 1; j >= 0; j--)
            {
                int    diagIndex = j * numRows + j;
                double before    = QR.data[diagIndex];
                QR.data[diagIndex] = 1;
                QrHelperFunctions_DDRM.rank1UpdateMultR(Q, QR.data, j * numRows, gammas[j], j, j, numRows, v);
                QR.data[diagIndex] = before;
            }

            return(Q);
        }
Пример #7
0
        /**
         * <p>
         * Creates a reflector from the provided vector and gamma.<br>
         * <br>
         * Q = I - &gamma; u u<sup>T</sup><br>
         * </p>
         *
         * <p>
         * In practice {@link VectorVectorMult_DDRM#householder(double, DMatrixD1, DMatrixD1, DMatrixD1)}  multHouseholder}
         * should be used for performance reasons since there is no need to calculate Q explicitly.
         * </p>
         *
         * @param u A vector.  Not modified.
         * @param gamma To produce a reflector gamma needs to be equal to 2/||u||.
         * @return An orthogonal reflector.
         */
        public static DMatrixRMaj createReflector(DMatrixRMaj u, double gamma)
        {
            if (!MatrixFeatures_DDRM.isVector(u))
            {
                throw new ArgumentException("u must be a vector");
            }

            DMatrixRMaj Q = CommonOps_DDRM.identity(u.getNumElements());

            CommonOps_DDRM.multAddTransB(-gamma, u, u, Q);

            return(Q);
        }
Пример #8
0
        /**
         * Computes the Q matrix from the information stored in the QR matrix.  This
         * operation requires about 4(m<sup>2</sup>n-mn<sup>2</sup>+n<sup>3</sup>/3) flops.
         *
         * @param Q The orthogonal Q matrix.
         */
        public override DMatrixRMaj getQ(DMatrixRMaj Q, bool compact)
        {
            if (compact)
            {
                if (Q == null)
                {
                    Q = CommonOps_DDRM.identity(numRows, minLength);
                }
                else
                {
                    if (Q.numRows != numRows || Q.numCols != minLength)
                    {
                        throw new ArgumentException("Unexpected matrix dimension.");
                    }
                    else
                    {
                        CommonOps_DDRM.setIdentity(Q);
                    }
                }
            }
            else
            {
                if (Q == null)
                {
                    Q = CommonOps_DDRM.identity(numRows);
                }
                else
                {
                    if (Q.numRows != numRows || Q.numCols != numRows)
                    {
                        throw new ArgumentException("Unexpected matrix dimension.");
                    }
                    else
                    {
                        CommonOps_DDRM.setIdentity(Q);
                    }
                }
            }

            for (int j = rank - 1; j >= 0; j--)
            {
                double[] u = dataQR[j];

                double vv = u[j];
                u[j] = 1;
                QrHelperFunctions_DDRM.rank1UpdateMultR(Q, u, gammas[j], j, j, numRows, v);
                u[j] = vv;
            }

            return(Q);
        }
        /**
         * Computes the Q matrix from the imformation stored in the QR matrix.  This
         * operation requires about 4(m<sup>2</sup>n-mn<sup>2</sup>+n<sup>3</sup>/3) flops.
         *
         * @param Q The orthogonal Q matrix.
         */
        public virtual DMatrixRMaj getQ(DMatrixRMaj Q, bool compact)
        {
            if (compact)
            {
                if (Q == null)
                {
                    Q = CommonOps_DDRM.identity(numRows, minLength);
                }
                else
                {
                    if (Q.numRows != numRows || Q.numCols != minLength)
                    {
                        throw new ArgumentException("Unexpected matrix dimension.");
                    }
                    else
                    {
                        CommonOps_DDRM.setIdentity(Q);
                    }
                }
            }
            else
            {
                if (Q == null)
                {
                    Q = CommonOps_DDRM.identity(numRows);
                }
                else
                {
                    if (Q.numRows != numRows || Q.numCols != numRows)
                    {
                        throw new ArgumentException("Unexpected matrix dimension.");
                    }
                    else
                    {
                        CommonOps_DDRM.setIdentity(Q);
                    }
                }
            }

            for (int j = minLength - 1; j >= 0; j--)
            {
                u[j] = 1;
                for (int i = j + 1; i < numRows; i++)
                {
                    u[i] = QR.get(i, j);
                }
                QrHelperFunctions_DDRM.rank1UpdateMultR(Q, u, gammas[j], j, j, numRows, v);
            }

            return(Q);
        }
Пример #10
0
        /**
         * <p>
         * Creates a reflector from the provided vector.<br>
         * <br>
         * Q = I - &gamma; u u<sup>T</sup><br>
         * &gamma; = 2/||u||<sup>2</sup>
         * </p>
         *
         * <p>
         * In practice {@link VectorVectorMult_DDRM#householder(double, DMatrixD1, DMatrixD1, DMatrixD1)}  multHouseholder}
         * should be used for performance reasons since there is no need to calculate Q explicitly.
         * </p>
         *
         * @param u A vector. Not modified.
         * @return An orthogonal reflector.
         */
        public static DMatrixRMaj createReflector(DMatrix1Row u)
        {
            if (!MatrixFeatures_DDRM.isVector(u))
            {
                throw new ArgumentException("u must be a vector");
            }

            double norm  = NormOps_DDRM.fastNormF(u);
            double gamma = -2.0 / (norm * norm);

            DMatrixRMaj Q = CommonOps_DDRM.identity(u.getNumElements());

            CommonOps_DDRM.multAddTransB(gamma, u, u, Q);

            return(Q);
        }
Пример #11
0
 public static DMatrixRMaj checkIdentity(DMatrixRMaj A, int numRows, int numCols)
 {
     if (A == null)
     {
         return(CommonOps_DDRM.identity(numRows, numCols));
     }
     else if (numRows != A.numRows || numCols != A.numCols)
     {
         throw new ArgumentException("Input is not " + numRows + " x " + numCols + " matrix");
     }
     else
     {
         CommonOps_DDRM.setIdentity(A);
     }
     return(A);
 }
Пример #12
0
        public void checkIdentical()
        {
            KalmanFilterSimple simple = new KalmanFilterSimple();

            List <KalmanFilter> all = new List <KalmanFilter>();

            all.Add(new KalmanFilterOperations());
            all.Add(new KalmanFilterEquation());
            all.Add(simple);

            DMatrixRMaj priorX = new DMatrixRMaj(9, 1, true, 0.5, -0.2, 0, 0, 0.2, -0.9, 0, 0.2, -0.5);
            DMatrixRMaj priorP = CommonOps_DDRM.identity(9);

            DMatrixRMaj F = BenchmarkKalmanPerformance.createF(T);
            DMatrixRMaj Q = BenchmarkKalmanPerformance.createQ(T, 0.1);
            DMatrixRMaj H = BenchmarkKalmanPerformance.createH();


            foreach (KalmanFilter f in all)
            {
                f.configure(F, Q, H);
                f.setState(priorX, priorP);
                f.predict();
            }

            foreach (KalmanFilter f in all)
            {
                compareFilters(simple, f);
            }

            DMatrixRMaj z = new DMatrixRMaj(H.numRows, 1);
            DMatrixRMaj R = CommonOps_DDRM.identity(H.numRows);

            foreach (KalmanFilter f in all)
            {
                f.update(z, R);
            }

            foreach (KalmanFilter f in all)
            {
                compareFilters(simple, f);
            }
        }
Пример #13
0
        /**
         * Computes the eigenvalue of the provided tridiagonal matrix.  Note that only the upper portion
         * needs to be tridiagonal.  The bottom diagonal is assumed to be the same as the top.
         *
         * @param sideLength Number of rows and columns in the input matrix.
         * @param diag Diagonal elements from tridiagonal matrix. Modified.
         * @param off Off diagonal elements from tridiagonal matrix. Modified.
         * @return true if it succeeds and false if it fails.
         */
        public bool process(int sideLength,
                            double[] diag,
                            double[] off,
                            double[] eigenvalues)
        {
            if (diag != null)
            {
                helper.init(diag, off, sideLength);
            }
            if (Q == null)
            {
                Q = CommonOps_DDRM.identity(helper.N);
            }
            helper.setQ(Q);

            this.followingScript = true;
            this.eigenvalues     = eigenvalues;
            this.fastEigenvalues = false;

            return(_process());
        }
Пример #14
0
        /**
         * Returns the Q matrix.
         */
        public DMatrixRMaj getQ()
        {
            Equation.Equation eq = new Equation.Equation();

            DMatrixRMaj Q = CommonOps_DDRM.identity(QR.numRows);
            DMatrixRMaj u = new DMatrixRMaj(QR.numRows, 1);

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

            eq.alias(u, "u", Q, "Q", QR, "QR", QR.numRows, "r");

            // 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--)
            {
                eq.alias(j, "j", gammas[j], "gamma");

                eq.process("u(j:,0) = [1 ; QR((j+1):,j)]");
                eq.process("Q=(eye(r)-gamma*u*u')*Q");
            }

            return(Q);
        }
Пример #15
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);
        }