public static double getBICValue(Array2DRowRealMatrix mat)
        {
            double             num = (double)0f;
            EigenDecomposition eigenDecomposition = new EigenDecomposition(new Covariance(mat).getCovarianceMatrix());

            double[] realEigenvalues = eigenDecomposition.getRealEigenvalues();
            for (int i = 0; i < realEigenvalues.Length; i++)
            {
                num += java.lang.Math.log(realEigenvalues[i]);
            }
            return(num * (double)(mat.getRowDimension() / 2));
        }
        /**
         * @param mat
         *            A matrix with feature vectors as rows.
         * @return Returns the BICValue of the Gaussian model that approximates the
         *         the feature vectors data samples
         */
        public static double GetBICValue(Array2DRowRealMatrix mat)
        {
            double             ret = 0;
            EigenDecomposition ed  = new EigenDecomposition(new Covariance(mat).getCovarianceMatrix());

            double[] re = ed.getRealEigenvalues();
            for (int i = 0; i < re.Length; i++)
            {
                ret += Math.Log(re[i]);
            }
            return(ret * (mat.getRowDimension() / 2));
        }
Example #3
0
        public SimpleEVD(T mat)
        {
            this.mat  = mat;
            this.is64 = mat is DMatrixRMaj;

            if (is64)
            {
                eig = (EigenDecomposition <T>)DecompositionFactory_DDRM.eig(mat.getNumCols(), true);
            }
            else
            {
                eig = (EigenDecomposition <T>)DecompositionFactory_FDRM.eig(mat.getNumCols(), true);
            }
            if (!eig.decompose((T)mat))
            {
                throw new InvalidOperationException("Eigenvalue Decomposition failed");
            }
        }
Example #4
0
        public void ProcessData()
        {
            int N = dataSet.GetLength(0);

            int[,] indices            = new int[N, numberOfKNN];
            double[,] sortedDistances = new double[N, numberOfKNN];
            for (var i = 0; i < N; i++)
            {
                double[] dataPoint  = Enumerable.Range(0, dataSet.GetLength(1)).Select(x => dataSet[i, x]).ToArray();
                int[]    ind        = NearestNeighborSearch.KnnSearch(dataSet, dataPoint, numberOfKNN).Item1;
                double[] sortedDist = NearestNeighborSearch.KnnSearch(dataSet, dataPoint, numberOfKNN).Item2;
                for (var j = 0; j < numberOfKNN; j++)
                {
                    indices[i, j]         = ind[j];
                    sortedDistances[i, j] = sortedDist[j];
                }
            }

            // build ad hoc bandwidth function by autotuning epsilon for each point
            double[] epss = new double[401];
            for (var i = 0; i < 401; i++)
            {
                epss[i] = Math.Pow(2, -30 + i * 0.1);               // Will store both distance and index in here
            }
            double[] rho0 = evaluateRho0(sortedDistances, NNofKDE);
            // pre-kernel used with ad hoc bandwidth only for estimating dimension and sampling density
            double[,] dt = evaluateDt(sortedDistances, rho0, indices, numberOfKNN);
            // tune epsilon on the pre-kernel
            double[] dpreGlobal = evaluateDpreGlobal(epss, dt, numberOfKNN, N);
            (double maxval, int maxind) = findMaxvalMaxind(dpreGlobal, epss);
            double dim = 2 * maxval;

            // use ad hoc bandwidth function, rho0, to estimate the density
            for (var i = 0; i < dt.GetLength(0); i++)
            {
                for (var j = 0; j < dt.GetLength(1); j++)
                {
                    dt[i, j] = Math.Exp(-dt[i, j] / (2 * epss[maxind])) / Math.Pow(2 * Math.PI * epss[maxind], (dim / 2));
                }
            }

            // the matrix created here might be large, must change it to sparse format
            double[,] reshapedDt  = reshapeDt(dt, indices, N, numberOfKNN);
            double[,] symmetricDt = new double[reshapedDt.GetLength(0), reshapedDt.GetLength(1)];
            for (var i = 0; i < reshapedDt.GetLength(0); i++)
            {
                for (var j = 0; j < reshapedDt.GetLength(1); j++)
                {
                    symmetricDt[i, j] = (reshapedDt[i, j] + reshapedDt[j, i]) / 2;
                }
            }

            // sampling density estimate for bandwidth function
            double[] qest = new double[symmetricDt.GetLength(0)];
            for (var i = 0; i < symmetricDt.GetLength(0); i++)
            {
                double sum = 0;
                for (var j = 0; j < symmetricDt.GetLength(1); j++)
                {
                    sum += reshapedDt[i, j];
                }
                qest[i] = sum / (N * Math.Pow(rho0[i], dim));
            }

            if (differentialOperator == 1)
            {
                beta  = -0.5;
                alpha = -dim / 4 + 0.5;
            }
            else if (differentialOperator == 2)
            {
                beta  = -0.5;
                alpha = -dim / 4;
            }

            double c1 = 2 - (2 * alpha) + (dim * beta) + (2 * beta);
            double c2 = 0.5 - (2 * alpha) + (2 * dim * alpha) + (dim * beta / 2) + beta;

            for (var i = 0; i < sortedDistances.GetLength(0); i++)
            {
                for (int j = 0; j < sortedDistances.GetLength(1); j++)
                {
                    sortedDistances[i, j] = Math.Pow(sortedDistances[i, j], 2);
                }
            }

            // construct bandwidth function rho(x) from the sampling density estimate
            double[] rho    = new double[qest.Length];
            double   sumRho = 0;

            for (var i = 0; i < qest.Length; i++)
            {
                rho[i]  = Math.Pow(qest[i], beta);
                sumRho += rho[i];
            }
            for (var i = 1; i < qest.Length; i++)
            {
                rho[i] = rho[i] / sumRho * rho.Length;
            }

            // construct the exponent of K^S_epsilon
            for (var i = 0; i < sortedDistances.GetLength(0); i++)
            {
                for (var j = 0; j < sortedDistances.GetLength(1); j++)
                {
                    sortedDistances[i, j] = sortedDistances[i, j] / rho[i];
                }
            }
            for (var i = 0; i < sortedDistances.GetLength(0); i++)
            {
                for (var j = 0; j < sortedDistances.GetLength(1); j++)
                {
                    sortedDistances[i, j] = sortedDistances[i, j] / rho[indices[i, j]];
                }
            }

            // tune epsilon for the final kernel
            double epsilon = evaluateFinalEpsilon(epss, sortedDistances, N, numberOfKNN);

            // K^S_epsilon with final choice of epsilon
            for (var i = 0; i < sortedDistances.GetLength(0); i++)
            {
                for (var j = 0; j < sortedDistances.GetLength(1); j++)
                {
                    sortedDistances[i, j] = Math.Exp(-sortedDistances[i, j] / (4 * epsilon));
                }
            }

            // the matrix created here might be large, must change it to sparse format
            double[,] reshapedSortedDistances  = reshapeDt(sortedDistances, indices, N, numberOfKNN);
            double[,] symmetricSortedDistances = new double[reshapedSortedDistances.GetLength(0), reshapedSortedDistances.GetLength(1)];
            for (var i = 0; i < reshapedSortedDistances.GetLength(0); i++)
            {
                for (var j = 0; j < reshapedSortedDistances.GetLength(1); j++)
                {
                    symmetricSortedDistances[i, j] = (reshapedSortedDistances[i, j] + reshapedSortedDistances[j, i]) / 2;
                }
            }

            double temp;

            // q^S_epsilon (this is the sampling density estimate q(x) obtained from the VB kernel)
            for (var i = 0; i < symmetricSortedDistances.GetLength(0); i++)
            {
                temp = 0;
                for (var j = 0; j < symmetricSortedDistances.GetLength(1); j++)
                {
                    temp += symmetricSortedDistances[i, j];
                }
                qest[i] = temp / Math.Pow(rho[i], dim);
            }

            double[,] Dinv1 = new double[N, N];
            for (var i = 0; i < N; i++)
            {
                Dinv1[i, i] = Math.Pow(qest[i], -alpha);
            }

            double[,] DtimesDinv = new double[N, N];
            DtimesDinv           = Accord.Math.Matrix.Dot(symmetricSortedDistances, Dinv1);
            double[,] newD       = new double[N, N];
            newD = Accord.Math.Matrix.Dot(Dinv1, DtimesDinv);

            double[,] Sinv = new double[N, N];
            double temp2;

            for (var i = 0; i < N; i++)
            {
                temp2 = 0;
                for (var j = 0; j < N; j++)
                {
                    temp2 += newD[i, j];
                }
                Sinv[i, i] = Math.Pow(Math.Pow(rho[i], 2) * temp2, -0.5);
            }

            double[,] newDtimesSinv = new double[N, N];
            newDtimesSinv           = Accord.Math.Matrix.Dot(newD, Sinv);
            double[,] finalD        = new double[N, N];
            finalD = Accord.Math.Matrix.Dot(Sinv, newDtimesSinv);
            for (var i = 0; i < N; i++)
            {
                finalD[i, i] = finalD[i, i] - Math.Pow(rho[i], -2) + 1;
            }

            double[] DMAPEigVals;
            double[,] DMAPEigVecs;
            bool sort    = true;
            bool inPlace = false;
            bool scaled  = true;

            (DMAPEigVals, DMAPEigVecs) = EigenDecomposition.FindEigenValuesAndEigenvectorsSymmetricOnly(finalD, numberOfEigenvectors, inPlace, sort, scaled);
            for (var i = 0; i < numberOfEigenvectors; i++)
            {
                DMAPEigVals[i] = Math.Log(DMAPEigVals[i]) / epsilon;
            }
            DMAPEigVecs = Accord.Math.Matrix.Dot(Sinv, DMAPEigVecs);


            // normalize qest into a density
            for (var i = 0; i < N; i++)
            {
                qest[i] = qest[i] / (N * Math.Pow(4 * Math.PI * epsilon, dim / 2));
            }

            // constuct the invariant measure of the system
            double[] peq = new double[N];
            for (var i = 0; i < N; i++)
            {
                peq[i] = qest[i] * Math.Pow(Sinv[i, i], -2);
            }

            double normalizationFactor = 0;

            for (var i = 0; i < N; i++)
            {
                normalizationFactor += peq[i] / qest[i] / N;
            }

            // normalize the invariant measure
            for (var i = 0; i < N; i++)
            {
                peq[i] = peq[i] / normalizationFactor;
            }

            //normalize eigenfunctions such that: \sum_i psi(x_i)^2 p(x_i)/q(x_i) = 1
            double[] EigVec_i       = new double[N];
            double[] tempVector     = new double[N];
            double   meanTempVector = 0;

            for (var i = 0; i < numberOfEigenvectors; i++)
            {
                EigVec_i = Enumerable.Range(0, DMAPEigVecs.GetLength(0)).Select(x => DMAPEigVecs[x, i]).ToArray();
                for (var j = 0; j < N; j++)
                {
                    tempVector[j] = Math.Pow(EigVec_i[j], 2) * (peq[j] / qest[j]);
                }
                meanTempVector = FindMeanOfVector(tempVector);
                for (var j = 0; j < N; j++)
                {
                    DMAPEigVecs[j, i] = DMAPEigVecs[j, i] / Math.Sqrt(meanTempVector);
                }
            }

            DMAPeigenvalues  = DMAPEigVals;
            DMAPeigenvectors = DMAPEigVecs;
        }
Example #5
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.");
            }
        }
Example #6
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);
        }