CMAESOptimizer.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. package org.apache.commons.math3.optim.nonlinear.scalar.noderiv;

  18. import java.util.ArrayList;
  19. import java.util.Arrays;
  20. import java.util.List;

  21. import org.apache.commons.math3.exception.DimensionMismatchException;
  22. import org.apache.commons.math3.exception.NotPositiveException;
  23. import org.apache.commons.math3.exception.NotStrictlyPositiveException;
  24. import org.apache.commons.math3.exception.OutOfRangeException;
  25. import org.apache.commons.math3.exception.TooManyEvaluationsException;
  26. import org.apache.commons.math3.linear.Array2DRowRealMatrix;
  27. import org.apache.commons.math3.linear.EigenDecomposition;
  28. import org.apache.commons.math3.linear.MatrixUtils;
  29. import org.apache.commons.math3.linear.RealMatrix;
  30. import org.apache.commons.math3.optim.ConvergenceChecker;
  31. import org.apache.commons.math3.optim.OptimizationData;
  32. import org.apache.commons.math3.optim.nonlinear.scalar.GoalType;
  33. import org.apache.commons.math3.optim.PointValuePair;
  34. import org.apache.commons.math3.optim.nonlinear.scalar.MultivariateOptimizer;
  35. import org.apache.commons.math3.random.RandomGenerator;
  36. import org.apache.commons.math3.util.FastMath;
  37. import org.apache.commons.math3.util.MathArrays;

  38. /**
  39.  * An implementation of the active Covariance Matrix Adaptation Evolution Strategy (CMA-ES)
  40.  * for non-linear, non-convex, non-smooth, global function minimization.
  41.  * <p>
  42.  * The CMA-Evolution Strategy (CMA-ES) is a reliable stochastic optimization method
  43.  * which should be applied if derivative-based methods, e.g. quasi-Newton BFGS or
  44.  * conjugate gradient, fail due to a rugged search landscape (e.g. noise, local
  45.  * optima, outlier, etc.) of the objective function. Like a
  46.  * quasi-Newton method, the CMA-ES learns and applies a variable metric
  47.  * on the underlying search space. Unlike a quasi-Newton method, the
  48.  * CMA-ES neither estimates nor uses gradients, making it considerably more
  49.  * reliable in terms of finding a good, or even close to optimal, solution.
  50.  * <p>
  51.  * In general, on smooth objective functions the CMA-ES is roughly ten times
  52.  * slower than BFGS (counting objective function evaluations, no gradients provided).
  53.  * For up to <math>N=10</math> variables also the derivative-free simplex
  54.  * direct search method (Nelder and Mead) can be faster, but it is
  55.  * far less reliable than CMA-ES.
  56.  * <p>
  57.  * The CMA-ES is particularly well suited for non-separable
  58.  * and/or badly conditioned problems. To observe the advantage of CMA compared
  59.  * to a conventional evolution strategy, it will usually take about
  60.  * <math>30 N</math> function evaluations. On difficult problems the complete
  61.  * optimization (a single run) is expected to take <em>roughly</em> between
  62.  * <math>30 N</math> and <math>300 N<sup>2</sup></math>
  63.  * function evaluations.
  64.  * <p>
  65.  * This implementation is translated and adapted from the Matlab version
  66.  * of the CMA-ES algorithm as implemented in module {@code cmaes.m} version 3.51.
  67.  * <p>
  68.  * For more information, please refer to the following links:
  69.  * <ul>
  70.  *  <li><a href="http://www.lri.fr/~hansen/cmaes.m">Matlab code</a></li>
  71.  *  <li><a href="http://www.lri.fr/~hansen/cmaesintro.html">Introduction to CMA-ES</a></li>
  72.  *  <li><a href="http://en.wikipedia.org/wiki/CMA-ES">Wikipedia</a></li>
  73.  * </ul>
  74.  *
  75.  * @since 3.0
  76.  */
  77. public class CMAESOptimizer
  78.     extends MultivariateOptimizer {
  79.     // global search parameters
  80.     /**
  81.      * Population size, offspring number. The primary strategy parameter to play
  82.      * with, which can be increased from its default value. Increasing the
  83.      * population size improves global search properties in exchange to speed.
  84.      * Speed decreases, as a rule, at most linearly with increasing population
  85.      * size. It is advisable to begin with the default small population size.
  86.      */
  87.     private int lambda; // population size
  88.     /**
  89.      * Covariance update mechanism, default is active CMA. isActiveCMA = true
  90.      * turns on "active CMA" with a negative update of the covariance matrix and
  91.      * checks for positive definiteness. OPTS.CMA.active = 2 does not check for
  92.      * pos. def. and is numerically faster. Active CMA usually speeds up the
  93.      * adaptation.
  94.      */
  95.     private final boolean isActiveCMA;
  96.     /**
  97.      * Determines how often a new random offspring is generated in case it is
  98.      * not feasible / beyond the defined limits, default is 0.
  99.      */
  100.     private final int checkFeasableCount;
  101.     /**
  102.      * @see Sigma
  103.      */
  104.     private double[] inputSigma;
  105.     /** Number of objective variables/problem dimension */
  106.     private int dimension;
  107.     /**
  108.      * Defines the number of initial iterations, where the covariance matrix
  109.      * remains diagonal and the algorithm has internally linear time complexity.
  110.      * diagonalOnly = 1 means keeping the covariance matrix always diagonal and
  111.      * this setting also exhibits linear space complexity. This can be
  112.      * particularly useful for dimension > 100.
  113.      * @see <a href="http://hal.archives-ouvertes.fr/inria-00287367/en">A Simple Modification in CMA-ES</a>
  114.      */
  115.     private int diagonalOnly;
  116.     /** Number of objective variables/problem dimension */
  117.     private boolean isMinimize = true;
  118.     /** Indicates whether statistic data is collected. */
  119.     private final boolean generateStatistics;

  120.     // termination criteria
  121.     /** Maximal number of iterations allowed. */
  122.     private final int maxIterations;
  123.     /** Limit for fitness value. */
  124.     private final double stopFitness;
  125.     /** Stop if x-changes larger stopTolUpX. */
  126.     private double stopTolUpX;
  127.     /** Stop if x-change smaller stopTolX. */
  128.     private double stopTolX;
  129.     /** Stop if fun-changes smaller stopTolFun. */
  130.     private double stopTolFun;
  131.     /** Stop if back fun-changes smaller stopTolHistFun. */
  132.     private double stopTolHistFun;

  133.     // selection strategy parameters
  134.     /** Number of parents/points for recombination. */
  135.     private int mu; //
  136.     /** log(mu + 0.5), stored for efficiency. */
  137.     private double logMu2;
  138.     /** Array for weighted recombination. */
  139.     private RealMatrix weights;
  140.     /** Variance-effectiveness of sum w_i x_i. */
  141.     private double mueff; //

  142.     // dynamic strategy parameters and constants
  143.     /** Overall standard deviation - search volume. */
  144.     private double sigma;
  145.     /** Cumulation constant. */
  146.     private double cc;
  147.     /** Cumulation constant for step-size. */
  148.     private double cs;
  149.     /** Damping for step-size. */
  150.     private double damps;
  151.     /** Learning rate for rank-one update. */
  152.     private double ccov1;
  153.     /** Learning rate for rank-mu update' */
  154.     private double ccovmu;
  155.     /** Expectation of ||N(0,I)|| == norm(randn(N,1)). */
  156.     private double chiN;
  157.     /** Learning rate for rank-one update - diagonalOnly */
  158.     private double ccov1Sep;
  159.     /** Learning rate for rank-mu update - diagonalOnly */
  160.     private double ccovmuSep;

  161.     // CMA internal values - updated each generation
  162.     /** Objective variables. */
  163.     private RealMatrix xmean;
  164.     /** Evolution path. */
  165.     private RealMatrix pc;
  166.     /** Evolution path for sigma. */
  167.     private RealMatrix ps;
  168.     /** Norm of ps, stored for efficiency. */
  169.     private double normps;
  170.     /** Coordinate system. */
  171.     private RealMatrix B;
  172.     /** Scaling. */
  173.     private RealMatrix D;
  174.     /** B*D, stored for efficiency. */
  175.     private RealMatrix BD;
  176.     /** Diagonal of sqrt(D), stored for efficiency. */
  177.     private RealMatrix diagD;
  178.     /** Covariance matrix. */
  179.     private RealMatrix C;
  180.     /** Diagonal of C, used for diagonalOnly. */
  181.     private RealMatrix diagC;
  182.     /** Number of iterations already performed. */
  183.     private int iterations;

  184.     /** History queue of best values. */
  185.     private double[] fitnessHistory;
  186.     /** Size of history queue of best values. */
  187.     private int historySize;

  188.     /** Random generator. */
  189.     private final RandomGenerator random;

  190.     /** History of sigma values. */
  191.     private final List<Double> statisticsSigmaHistory = new ArrayList<Double>();
  192.     /** History of mean matrix. */
  193.     private final List<RealMatrix> statisticsMeanHistory = new ArrayList<RealMatrix>();
  194.     /** History of fitness values. */
  195.     private final List<Double> statisticsFitnessHistory = new ArrayList<Double>();
  196.     /** History of D matrix. */
  197.     private final List<RealMatrix> statisticsDHistory = new ArrayList<RealMatrix>();

  198.     /**
  199.      * @param maxIterations Maximal number of iterations.
  200.      * @param stopFitness Whether to stop if objective function value is smaller than
  201.      * {@code stopFitness}.
  202.      * @param isActiveCMA Chooses the covariance matrix update method.
  203.      * @param diagonalOnly Number of initial iterations, where the covariance matrix
  204.      * remains diagonal.
  205.      * @param checkFeasableCount Determines how often new random objective variables are
  206.      * generated in case they are out of bounds.
  207.      * @param random Random generator.
  208.      * @param generateStatistics Whether statistic data is collected.
  209.      * @param checker Convergence checker.
  210.      *
  211.      * @since 3.1
  212.      */
  213.     public CMAESOptimizer(int maxIterations,
  214.                           double stopFitness,
  215.                           boolean isActiveCMA,
  216.                           int diagonalOnly,
  217.                           int checkFeasableCount,
  218.                           RandomGenerator random,
  219.                           boolean generateStatistics,
  220.                           ConvergenceChecker<PointValuePair> checker) {
  221.         super(checker);
  222.         this.maxIterations = maxIterations;
  223.         this.stopFitness = stopFitness;
  224.         this.isActiveCMA = isActiveCMA;
  225.         this.diagonalOnly = diagonalOnly;
  226.         this.checkFeasableCount = checkFeasableCount;
  227.         this.random = random;
  228.         this.generateStatistics = generateStatistics;
  229.     }

  230.     /**
  231.      * @return History of sigma values.
  232.      */
  233.     public List<Double> getStatisticsSigmaHistory() {
  234.         return statisticsSigmaHistory;
  235.     }

  236.     /**
  237.      * @return History of mean matrix.
  238.      */
  239.     public List<RealMatrix> getStatisticsMeanHistory() {
  240.         return statisticsMeanHistory;
  241.     }

  242.     /**
  243.      * @return History of fitness values.
  244.      */
  245.     public List<Double> getStatisticsFitnessHistory() {
  246.         return statisticsFitnessHistory;
  247.     }

  248.     /**
  249.      * @return History of D matrix.
  250.      */
  251.     public List<RealMatrix> getStatisticsDHistory() {
  252.         return statisticsDHistory;
  253.     }

  254.     /**
  255.      * Input sigma values.
  256.      * They define the initial coordinate-wise standard deviations for
  257.      * sampling new search points around the initial guess.
  258.      * It is suggested to set them to the estimated distance from the
  259.      * initial to the desired optimum.
  260.      * Small values induce the search to be more local (and very small
  261.      * values are more likely to find a local optimum close to the initial
  262.      * guess).
  263.      * Too small values might however lead to early termination.
  264.      */
  265.     public static class Sigma implements OptimizationData {
  266.         /** Sigma values. */
  267.         private final double[] sigma;

  268.         /**
  269.          * @param s Sigma values.
  270.          * @throws NotPositiveException if any of the array entries is smaller
  271.          * than zero.
  272.          */
  273.         public Sigma(double[] s)
  274.             throws NotPositiveException {
  275.             for (int i = 0; i < s.length; i++) {
  276.                 if (s[i] < 0) {
  277.                     throw new NotPositiveException(s[i]);
  278.                 }
  279.             }

  280.             sigma = s.clone();
  281.         }

  282.         /**
  283.          * @return the sigma values.
  284.          */
  285.         public double[] getSigma() {
  286.             return sigma.clone();
  287.         }
  288.     }

  289.     /**
  290.      * Population size.
  291.      * The number of offspring is the primary strategy parameter.
  292.      * In the absence of better clues, a good default could be an
  293.      * integer close to {@code 4 + 3 ln(n)}, where {@code n} is the
  294.      * number of optimized parameters.
  295.      * Increasing the population size improves global search properties
  296.      * at the expense of speed (which in general decreases at most
  297.      * linearly with increasing population size).
  298.      */
  299.     public static class PopulationSize implements OptimizationData {
  300.         /** Population size. */
  301.         private final int lambda;

  302.         /**
  303.          * @param size Population size.
  304.          * @throws NotStrictlyPositiveException if {@code size <= 0}.
  305.          */
  306.         public PopulationSize(int size)
  307.             throws NotStrictlyPositiveException {
  308.             if (size <= 0) {
  309.                 throw new NotStrictlyPositiveException(size);
  310.             }
  311.             lambda = size;
  312.         }

  313.         /**
  314.          * @return the population size.
  315.          */
  316.         public int getPopulationSize() {
  317.             return lambda;
  318.         }
  319.     }

  320.     /**
  321.      * {@inheritDoc}
  322.      *
  323.      * @param optData Optimization data. In addition to those documented in
  324.      * {@link MultivariateOptimizer#parseOptimizationData(OptimizationData[])
  325.      * MultivariateOptimizer}, this method will register the following data:
  326.      * <ul>
  327.      *  <li>{@link Sigma}</li>
  328.      *  <li>{@link PopulationSize}</li>
  329.      * </ul>
  330.      * @return {@inheritDoc}
  331.      * @throws TooManyEvaluationsException if the maximal number of
  332.      * evaluations is exceeded.
  333.      * @throws DimensionMismatchException if the initial guess, target, and weight
  334.      * arguments have inconsistent dimensions.
  335.      */
  336.     @Override
  337.     public PointValuePair optimize(OptimizationData... optData)
  338.         throws TooManyEvaluationsException,
  339.                DimensionMismatchException {
  340.         // Set up base class and perform computation.
  341.         return super.optimize(optData);
  342.     }

  343.     /** {@inheritDoc} */
  344.     @Override
  345.     protected PointValuePair doOptimize() {
  346.          // -------------------- Initialization --------------------------------
  347.         isMinimize = getGoalType().equals(GoalType.MINIMIZE);
  348.         final FitnessFunction fitfun = new FitnessFunction();
  349.         final double[] guess = getStartPoint();
  350.         // number of objective variables/problem dimension
  351.         dimension = guess.length;
  352.         initializeCMA(guess);
  353.         iterations = 0;
  354.         ValuePenaltyPair valuePenalty = fitfun.value(guess);
  355.         double bestValue = valuePenalty.value+valuePenalty.penalty;
  356.         push(fitnessHistory, bestValue);
  357.         PointValuePair optimum
  358.             = new PointValuePair(getStartPoint(),
  359.                                  isMinimize ? bestValue : -bestValue);
  360.         PointValuePair lastResult = null;

  361.         // -------------------- Generation Loop --------------------------------

  362.         generationLoop:
  363.         for (iterations = 1; iterations <= maxIterations; iterations++) {
  364.             incrementIterationCount();

  365.             // Generate and evaluate lambda offspring
  366.             final RealMatrix arz = randn1(dimension, lambda);
  367.             final RealMatrix arx = zeros(dimension, lambda);
  368.             final double[] fitness = new double[lambda];
  369.             final ValuePenaltyPair[] valuePenaltyPairs = new ValuePenaltyPair[lambda];
  370.             // generate random offspring
  371.             for (int k = 0; k < lambda; k++) {
  372.                 RealMatrix arxk = null;
  373.                 for (int i = 0; i < checkFeasableCount + 1; i++) {
  374.                     if (diagonalOnly <= 0) {
  375.                         arxk = xmean.add(BD.multiply(arz.getColumnMatrix(k))
  376.                                          .scalarMultiply(sigma)); // m + sig * Normal(0,C)
  377.                     } else {
  378.                         arxk = xmean.add(times(diagD,arz.getColumnMatrix(k))
  379.                                          .scalarMultiply(sigma));
  380.                     }
  381.                     if (i >= checkFeasableCount ||
  382.                         fitfun.isFeasible(arxk.getColumn(0))) {
  383.                         break;
  384.                     }
  385.                     // regenerate random arguments for row
  386.                     arz.setColumn(k, randn(dimension));
  387.                 }
  388.                 copyColumn(arxk, 0, arx, k);
  389.                 try {
  390.                     valuePenaltyPairs[k] = fitfun.value(arx.getColumn(k)); // compute fitness
  391.                 } catch (TooManyEvaluationsException e) {
  392.                     break generationLoop;
  393.                 }
  394.             }

  395.             // Compute fitnesses by adding value and penalty after scaling by value range.
  396.             double valueRange = valueRange(valuePenaltyPairs);
  397.             for (int iValue=0;iValue<valuePenaltyPairs.length;iValue++) {
  398.                  fitness[iValue] = valuePenaltyPairs[iValue].value + valuePenaltyPairs[iValue].penalty*valueRange;
  399.             }

  400.             // Sort by fitness and compute weighted mean into xmean
  401.             final int[] arindex = sortedIndices(fitness);
  402.             // Calculate new xmean, this is selection and recombination
  403.             final RealMatrix xold = xmean; // for speed up of Eq. (2) and (3)
  404.             final RealMatrix bestArx = selectColumns(arx, MathArrays.copyOf(arindex, mu));
  405.             xmean = bestArx.multiply(weights);
  406.             final RealMatrix bestArz = selectColumns(arz, MathArrays.copyOf(arindex, mu));
  407.             final RealMatrix zmean = bestArz.multiply(weights);
  408.             final boolean hsig = updateEvolutionPaths(zmean, xold);
  409.             if (diagonalOnly <= 0) {
  410.                 updateCovariance(hsig, bestArx, arz, arindex, xold);
  411.             } else {
  412.                 updateCovarianceDiagonalOnly(hsig, bestArz);
  413.             }
  414.             // Adapt step size sigma - Eq. (5)
  415.             sigma *= FastMath.exp(FastMath.min(1, (normps/chiN - 1) * cs / damps));
  416.             final double bestFitness = fitness[arindex[0]];
  417.             final double worstFitness = fitness[arindex[arindex.length - 1]];
  418.             if (bestValue > bestFitness) {
  419.                 bestValue = bestFitness;
  420.                 lastResult = optimum;
  421.                 optimum = new PointValuePair(fitfun.repair(bestArx.getColumn(0)),
  422.                                              isMinimize ? bestFitness : -bestFitness);
  423.                 if (getConvergenceChecker() != null && lastResult != null &&
  424.                     getConvergenceChecker().converged(iterations, optimum, lastResult)) {
  425.                     break generationLoop;
  426.                 }
  427.             }
  428.             // handle termination criteria
  429.             // Break, if fitness is good enough
  430.             if (stopFitness != 0 && bestFitness < (isMinimize ? stopFitness : -stopFitness)) {
  431.                 break generationLoop;
  432.             }
  433.             final double[] sqrtDiagC = sqrt(diagC).getColumn(0);
  434.             final double[] pcCol = pc.getColumn(0);
  435.             for (int i = 0; i < dimension; i++) {
  436.                 if (sigma * FastMath.max(FastMath.abs(pcCol[i]), sqrtDiagC[i]) > stopTolX) {
  437.                     break;
  438.                 }
  439.                 if (i >= dimension - 1) {
  440.                     break generationLoop;
  441.                 }
  442.             }
  443.             for (int i = 0; i < dimension; i++) {
  444.                 if (sigma * sqrtDiagC[i] > stopTolUpX) {
  445.                     break generationLoop;
  446.                 }
  447.             }
  448.             final double historyBest = min(fitnessHistory);
  449.             final double historyWorst = max(fitnessHistory);
  450.             if (iterations > 2 &&
  451.                 FastMath.max(historyWorst, worstFitness) -
  452.                 FastMath.min(historyBest, bestFitness) < stopTolFun) {
  453.                 break generationLoop;
  454.             }
  455.             if (iterations > fitnessHistory.length &&
  456.                 historyWorst - historyBest < stopTolHistFun) {
  457.                 break generationLoop;
  458.             }
  459.             // condition number of the covariance matrix exceeds 1e14
  460.             if (max(diagD) / min(diagD) > 1e7) {
  461.                 break generationLoop;
  462.             }
  463.             // user defined termination
  464.             if (getConvergenceChecker() != null) {
  465.                 final PointValuePair current
  466.                     = new PointValuePair(bestArx.getColumn(0),
  467.                                          isMinimize ? bestFitness : -bestFitness);
  468.                 if (lastResult != null &&
  469.                     getConvergenceChecker().converged(iterations, current, lastResult)) {
  470.                     break generationLoop;
  471.                     }
  472.                 lastResult = current;
  473.             }
  474.             // Adjust step size in case of equal function values (flat fitness)
  475.             if (bestValue == fitness[arindex[(int)(0.1+lambda/4.)]]) {
  476.                 sigma *= FastMath.exp(0.2 + cs / damps);
  477.             }
  478.             if (iterations > 2 && FastMath.max(historyWorst, bestFitness) -
  479.                 FastMath.min(historyBest, bestFitness) == 0) {
  480.                 sigma *= FastMath.exp(0.2 + cs / damps);
  481.             }
  482.             // store best in history
  483.             push(fitnessHistory,bestFitness);
  484.             if (generateStatistics) {
  485.                 statisticsSigmaHistory.add(sigma);
  486.                 statisticsFitnessHistory.add(bestFitness);
  487.                 statisticsMeanHistory.add(xmean.transpose());
  488.                 statisticsDHistory.add(diagD.transpose().scalarMultiply(1E5));
  489.             }
  490.         }
  491.         return optimum;
  492.     }

  493.     /**
  494.      * Scans the list of (required and optional) optimization data that
  495.      * characterize the problem.
  496.      *
  497.      * @param optData Optimization data. The following data will be looked for:
  498.      * <ul>
  499.      *  <li>{@link Sigma}</li>
  500.      *  <li>{@link PopulationSize}</li>
  501.      * </ul>
  502.      */
  503.     @Override
  504.     protected void parseOptimizationData(OptimizationData... optData) {
  505.         // Allow base class to register its own data.
  506.         super.parseOptimizationData(optData);

  507.         // The existing values (as set by the previous call) are reused if
  508.         // not provided in the argument list.
  509.         for (OptimizationData data : optData) {
  510.             if (data instanceof Sigma) {
  511.                 inputSigma = ((Sigma) data).getSigma();
  512.                 continue;
  513.             }
  514.             if (data instanceof PopulationSize) {
  515.                 lambda = ((PopulationSize) data).getPopulationSize();
  516.                 continue;
  517.             }
  518.         }

  519.         checkParameters();
  520.     }

  521.     /**
  522.      * Checks dimensions and values of boundaries and inputSigma if defined.
  523.      */
  524.     private void checkParameters() {
  525.         final double[] init = getStartPoint();
  526.         final double[] lB = getLowerBound();
  527.         final double[] uB = getUpperBound();

  528.         if (inputSigma != null) {
  529.             if (inputSigma.length != init.length) {
  530.                 throw new DimensionMismatchException(inputSigma.length, init.length);
  531.             }
  532.             for (int i = 0; i < init.length; i++) {
  533.                 if (inputSigma[i] > uB[i] - lB[i]) {
  534.                     throw new OutOfRangeException(inputSigma[i], 0, uB[i] - lB[i]);
  535.                 }
  536.             }
  537.         }
  538.     }

  539.     /**
  540.      * Initialization of the dynamic search parameters
  541.      *
  542.      * @param guess Initial guess for the arguments of the fitness function.
  543.      */
  544.     private void initializeCMA(double[] guess) {
  545.         if (lambda <= 0) {
  546.             throw new NotStrictlyPositiveException(lambda);
  547.         }
  548.         // initialize sigma
  549.         final double[][] sigmaArray = new double[guess.length][1];
  550.         for (int i = 0; i < guess.length; i++) {
  551.             sigmaArray[i][0] = inputSigma[i];
  552.         }
  553.         final RealMatrix insigma = new Array2DRowRealMatrix(sigmaArray, false);
  554.         sigma = max(insigma); // overall standard deviation

  555.         // initialize termination criteria
  556.         stopTolUpX = 1e3 * max(insigma);
  557.         stopTolX = 1e-11 * max(insigma);
  558.         stopTolFun = 1e-12;
  559.         stopTolHistFun = 1e-13;

  560.         // initialize selection strategy parameters
  561.         mu = lambda / 2; // number of parents/points for recombination
  562.         logMu2 = FastMath.log(mu + 0.5);
  563.         weights = log(sequence(1, mu, 1)).scalarMultiply(-1).scalarAdd(logMu2);
  564.         double sumw = 0;
  565.         double sumwq = 0;
  566.         for (int i = 0; i < mu; i++) {
  567.             double w = weights.getEntry(i, 0);
  568.             sumw += w;
  569.             sumwq += w * w;
  570.         }
  571.         weights = weights.scalarMultiply(1 / sumw);
  572.         mueff = sumw * sumw / sumwq; // variance-effectiveness of sum w_i x_i

  573.         // initialize dynamic strategy parameters and constants
  574.         cc = (4 + mueff / dimension) /
  575.                 (dimension + 4 + 2 * mueff / dimension);
  576.         cs = (mueff + 2) / (dimension + mueff + 3.);
  577.         damps = (1 + 2 * FastMath.max(0, FastMath.sqrt((mueff - 1) /
  578.                                                        (dimension + 1)) - 1)) *
  579.             FastMath.max(0.3,
  580.                          1 - dimension / (1e-6 + maxIterations)) + cs; // minor increment
  581.         ccov1 = 2 / ((dimension + 1.3) * (dimension + 1.3) + mueff);
  582.         ccovmu = FastMath.min(1 - ccov1, 2 * (mueff - 2 + 1 / mueff) /
  583.                               ((dimension + 2) * (dimension + 2) + mueff));
  584.         ccov1Sep = FastMath.min(1, ccov1 * (dimension + 1.5) / 3);
  585.         ccovmuSep = FastMath.min(1 - ccov1, ccovmu * (dimension + 1.5) / 3);
  586.         chiN = FastMath.sqrt(dimension) *
  587.                 (1 - 1 / ((double) 4 * dimension) + 1 / ((double) 21 * dimension * dimension));
  588.         // intialize CMA internal values - updated each generation
  589.         xmean = MatrixUtils.createColumnRealMatrix(guess); // objective variables
  590.         diagD = insigma.scalarMultiply(1 / sigma);
  591.         diagC = square(diagD);
  592.         pc = zeros(dimension, 1); // evolution paths for C and sigma
  593.         ps = zeros(dimension, 1); // B defines the coordinate system
  594.         normps = ps.getFrobeniusNorm();

  595.         B = eye(dimension, dimension);
  596.         D = ones(dimension, 1); // diagonal D defines the scaling
  597.         BD = times(B, repmat(diagD.transpose(), dimension, 1));
  598.         C = B.multiply(diag(square(D)).multiply(B.transpose())); // covariance
  599.         historySize = 10 + (int) (3 * 10 * dimension / (double) lambda);
  600.         fitnessHistory = new double[historySize]; // history of fitness values
  601.         for (int i = 0; i < historySize; i++) {
  602.             fitnessHistory[i] = Double.MAX_VALUE;
  603.         }
  604.     }

  605.     /**
  606.      * Update of the evolution paths ps and pc.
  607.      *
  608.      * @param zmean Weighted row matrix of the gaussian random numbers generating
  609.      * the current offspring.
  610.      * @param xold xmean matrix of the previous generation.
  611.      * @return hsig flag indicating a small correction.
  612.      */
  613.     private boolean updateEvolutionPaths(RealMatrix zmean, RealMatrix xold) {
  614.         ps = ps.scalarMultiply(1 - cs).add(
  615.                 B.multiply(zmean).scalarMultiply(
  616.                         FastMath.sqrt(cs * (2 - cs) * mueff)));
  617.         normps = ps.getFrobeniusNorm();
  618.         final boolean hsig = normps /
  619.             FastMath.sqrt(1 - FastMath.pow(1 - cs, 2 * iterations)) /
  620.             chiN < 1.4 + 2 / ((double) dimension + 1);
  621.         pc = pc.scalarMultiply(1 - cc);
  622.         if (hsig) {
  623.             pc = pc.add(xmean.subtract(xold).scalarMultiply(FastMath.sqrt(cc * (2 - cc) * mueff) / sigma));
  624.         }
  625.         return hsig;
  626.     }

  627.     /**
  628.      * Update of the covariance matrix C for diagonalOnly > 0
  629.      *
  630.      * @param hsig Flag indicating a small correction.
  631.      * @param bestArz Fitness-sorted matrix of the gaussian random values of the
  632.      * current offspring.
  633.      */
  634.     private void updateCovarianceDiagonalOnly(boolean hsig,
  635.                                               final RealMatrix bestArz) {
  636.         // minor correction if hsig==false
  637.         double oldFac = hsig ? 0 : ccov1Sep * cc * (2 - cc);
  638.         oldFac += 1 - ccov1Sep - ccovmuSep;
  639.         diagC = diagC.scalarMultiply(oldFac) // regard old matrix
  640.             .add(square(pc).scalarMultiply(ccov1Sep)) // plus rank one update
  641.             .add((times(diagC, square(bestArz).multiply(weights))) // plus rank mu update
  642.                  .scalarMultiply(ccovmuSep));
  643.         diagD = sqrt(diagC); // replaces eig(C)
  644.         if (diagonalOnly > 1 &&
  645.             iterations > diagonalOnly) {
  646.             // full covariance matrix from now on
  647.             diagonalOnly = 0;
  648.             B = eye(dimension, dimension);
  649.             BD = diag(diagD);
  650.             C = diag(diagC);
  651.         }
  652.     }

  653.     /**
  654.      * Update of the covariance matrix C.
  655.      *
  656.      * @param hsig Flag indicating a small correction.
  657.      * @param bestArx Fitness-sorted matrix of the argument vectors producing the
  658.      * current offspring.
  659.      * @param arz Unsorted matrix containing the gaussian random values of the
  660.      * current offspring.
  661.      * @param arindex Indices indicating the fitness-order of the current offspring.
  662.      * @param xold xmean matrix of the previous generation.
  663.      */
  664.     private void updateCovariance(boolean hsig, final RealMatrix bestArx,
  665.                                   final RealMatrix arz, final int[] arindex,
  666.                                   final RealMatrix xold) {
  667.         double negccov = 0;
  668.         if (ccov1 + ccovmu > 0) {
  669.             final RealMatrix arpos = bestArx.subtract(repmat(xold, 1, mu))
  670.                 .scalarMultiply(1 / sigma); // mu difference vectors
  671.             final RealMatrix roneu = pc.multiply(pc.transpose())
  672.                 .scalarMultiply(ccov1); // rank one update
  673.             // minor correction if hsig==false
  674.             double oldFac = hsig ? 0 : ccov1 * cc * (2 - cc);
  675.             oldFac += 1 - ccov1 - ccovmu;
  676.             if (isActiveCMA) {
  677.                 // Adapt covariance matrix C active CMA
  678.                 negccov = (1 - ccovmu) * 0.25 * mueff /
  679.                     (FastMath.pow(dimension + 2, 1.5) + 2 * mueff);
  680.                 // keep at least 0.66 in all directions, small popsize are most
  681.                 // critical
  682.                 final double negminresidualvariance = 0.66;
  683.                 // where to make up for the variance loss
  684.                 final double negalphaold = 0.5;
  685.                 // prepare vectors, compute negative updating matrix Cneg
  686.                 final int[] arReverseIndex = reverse(arindex);
  687.                 RealMatrix arzneg = selectColumns(arz, MathArrays.copyOf(arReverseIndex, mu));
  688.                 RealMatrix arnorms = sqrt(sumRows(square(arzneg)));
  689.                 final int[] idxnorms = sortedIndices(arnorms.getRow(0));
  690.                 final RealMatrix arnormsSorted = selectColumns(arnorms, idxnorms);
  691.                 final int[] idxReverse = reverse(idxnorms);
  692.                 final RealMatrix arnormsReverse = selectColumns(arnorms, idxReverse);
  693.                 arnorms = divide(arnormsReverse, arnormsSorted);
  694.                 final int[] idxInv = inverse(idxnorms);
  695.                 final RealMatrix arnormsInv = selectColumns(arnorms, idxInv);
  696.                 // check and set learning rate negccov
  697.                 final double negcovMax = (1 - negminresidualvariance) /
  698.                     square(arnormsInv).multiply(weights).getEntry(0, 0);
  699.                 if (negccov > negcovMax) {
  700.                     negccov = negcovMax;
  701.                 }
  702.                 arzneg = times(arzneg, repmat(arnormsInv, dimension, 1));
  703.                 final RealMatrix artmp = BD.multiply(arzneg);
  704.                 final RealMatrix Cneg = artmp.multiply(diag(weights)).multiply(artmp.transpose());
  705.                 oldFac += negalphaold * negccov;
  706.                 C = C.scalarMultiply(oldFac)
  707.                     .add(roneu) // regard old matrix
  708.                     .add(arpos.scalarMultiply( // plus rank one update
  709.                                               ccovmu + (1 - negalphaold) * negccov) // plus rank mu update
  710.                          .multiply(times(repmat(weights, 1, dimension),
  711.                                          arpos.transpose())))
  712.                     .subtract(Cneg.scalarMultiply(negccov));
  713.             } else {
  714.                 // Adapt covariance matrix C - nonactive
  715.                 C = C.scalarMultiply(oldFac) // regard old matrix
  716.                     .add(roneu) // plus rank one update
  717.                     .add(arpos.scalarMultiply(ccovmu) // plus rank mu update
  718.                          .multiply(times(repmat(weights, 1, dimension),
  719.                                          arpos.transpose())));
  720.             }
  721.         }
  722.         updateBD(negccov);
  723.     }

  724.     /**
  725.      * Update B and D from C.
  726.      *
  727.      * @param negccov Negative covariance factor.
  728.      */
  729.     private void updateBD(double negccov) {
  730.         if (ccov1 + ccovmu + negccov > 0 &&
  731.             (iterations % 1. / (ccov1 + ccovmu + negccov) / dimension / 10.) < 1) {
  732.             // to achieve O(N^2)
  733.             C = triu(C, 0).add(triu(C, 1).transpose());
  734.             // enforce symmetry to prevent complex numbers
  735.             final EigenDecomposition eig = new EigenDecomposition(C);
  736.             B = eig.getV(); // eigen decomposition, B==normalized eigenvectors
  737.             D = eig.getD();
  738.             diagD = diag(D);
  739.             if (min(diagD) <= 0) {
  740.                 for (int i = 0; i < dimension; i++) {
  741.                     if (diagD.getEntry(i, 0) < 0) {
  742.                         diagD.setEntry(i, 0, 0);
  743.                     }
  744.                 }
  745.                 final double tfac = max(diagD) / 1e14;
  746.                 C = C.add(eye(dimension, dimension).scalarMultiply(tfac));
  747.                 diagD = diagD.add(ones(dimension, 1).scalarMultiply(tfac));
  748.             }
  749.             if (max(diagD) > 1e14 * min(diagD)) {
  750.                 final double tfac = max(diagD) / 1e14 - min(diagD);
  751.                 C = C.add(eye(dimension, dimension).scalarMultiply(tfac));
  752.                 diagD = diagD.add(ones(dimension, 1).scalarMultiply(tfac));
  753.             }
  754.             diagC = diag(C);
  755.             diagD = sqrt(diagD); // D contains standard deviations now
  756.             BD = times(B, repmat(diagD.transpose(), dimension, 1)); // O(n^2)
  757.         }
  758.     }

  759.     /**
  760.      * Pushes the current best fitness value in a history queue.
  761.      *
  762.      * @param vals History queue.
  763.      * @param val Current best fitness value.
  764.      */
  765.     private static void push(double[] vals, double val) {
  766.         for (int i = vals.length-1; i > 0; i--) {
  767.             vals[i] = vals[i-1];
  768.         }
  769.         vals[0] = val;
  770.     }

  771.     /**
  772.      * Sorts fitness values.
  773.      *
  774.      * @param doubles Array of values to be sorted.
  775.      * @return a sorted array of indices pointing into doubles.
  776.      */
  777.     private int[] sortedIndices(final double[] doubles) {
  778.         final DoubleIndex[] dis = new DoubleIndex[doubles.length];
  779.         for (int i = 0; i < doubles.length; i++) {
  780.             dis[i] = new DoubleIndex(doubles[i], i);
  781.         }
  782.         Arrays.sort(dis);
  783.         final int[] indices = new int[doubles.length];
  784.         for (int i = 0; i < doubles.length; i++) {
  785.             indices[i] = dis[i].index;
  786.         }
  787.         return indices;
  788.     }
  789.    /**
  790.      * Get range of values.
  791.      *
  792.      * @param vpPairs Array of valuePenaltyPairs to get range from.
  793.      * @return a double equal to maximum value minus minimum value.
  794.      */
  795.     private double valueRange(final ValuePenaltyPair[] vpPairs) {
  796.         double max = Double.NEGATIVE_INFINITY;
  797.         double min = Double.MAX_VALUE;
  798.         for (ValuePenaltyPair vpPair:vpPairs) {
  799.             if (vpPair.value > max) {
  800.                 max = vpPair.value;
  801.             }
  802.             if (vpPair.value < min) {
  803.                 min = vpPair.value;
  804.             }
  805.         }
  806.         return max-min;
  807.     }

  808.     /**
  809.      * Used to sort fitness values. Sorting is always in lower value first
  810.      * order.
  811.      */
  812.     private static class DoubleIndex implements Comparable<DoubleIndex> {
  813.         /** Value to compare. */
  814.         private final double value;
  815.         /** Index into sorted array. */
  816.         private final int index;

  817.         /**
  818.          * @param value Value to compare.
  819.          * @param index Index into sorted array.
  820.          */
  821.         DoubleIndex(double value, int index) {
  822.             this.value = value;
  823.             this.index = index;
  824.         }

  825.         /** {@inheritDoc} */
  826.         public int compareTo(DoubleIndex o) {
  827.             return Double.compare(value, o.value);
  828.         }

  829.         /** {@inheritDoc} */
  830.         @Override
  831.         public boolean equals(Object other) {

  832.             if (this == other) {
  833.                 return true;
  834.             }

  835.             if (other instanceof DoubleIndex) {
  836.                 return Double.compare(value, ((DoubleIndex) other).value) == 0;
  837.             }

  838.             return false;
  839.         }

  840.         /** {@inheritDoc} */
  841.         @Override
  842.         public int hashCode() {
  843.             long bits = Double.doubleToLongBits(value);
  844.             return (int) ((1438542 ^ (bits >>> 32) ^ bits) & 0xffffffff);
  845.         }
  846.     }
  847.     /**
  848.      * Stores the value and penalty (for repair of out of bounds point).
  849.      */
  850.     private static class ValuePenaltyPair {
  851.         /** Objective function value. */
  852.         private double value;
  853.         /** Penalty value for repair of out out of bounds points. */
  854.         private double penalty;

  855.         /**
  856.          * @param value Function value.
  857.          * @param penalty Out-of-bounds penalty.
  858.         */
  859.         public ValuePenaltyPair(final double value, final double penalty) {
  860.             this.value   = value;
  861.             this.penalty = penalty;
  862.         }
  863.     }


  864.     /**
  865.      * Normalizes fitness values to the range [0,1]. Adds a penalty to the
  866.      * fitness value if out of range.
  867.      */
  868.     private class FitnessFunction {
  869.         /**
  870.          * Flag indicating whether the objective variables are forced into their
  871.          * bounds if defined
  872.          */
  873.         private final boolean isRepairMode;

  874.         /** Simple constructor.
  875.          */
  876.         public FitnessFunction() {
  877.             isRepairMode = true;
  878.         }

  879.         /**
  880.          * @param point Normalized objective variables.
  881.          * @return the objective value + penalty for violated bounds.
  882.          */
  883.         public ValuePenaltyPair value(final double[] point) {
  884.             double value;
  885.             double penalty=0.0;
  886.             if (isRepairMode) {
  887.                 double[] repaired = repair(point);
  888.                 value = CMAESOptimizer.this.computeObjectiveValue(repaired);
  889.                 penalty =  penalty(point, repaired);
  890.             } else {
  891.                 value = CMAESOptimizer.this.computeObjectiveValue(point);
  892.             }
  893.             value = isMinimize ? value : -value;
  894.             penalty = isMinimize ? penalty : -penalty;
  895.             return new ValuePenaltyPair(value,penalty);
  896.         }

  897.         /**
  898.          * @param x Normalized objective variables.
  899.          * @return {@code true} if in bounds.
  900.          */
  901.         public boolean isFeasible(final double[] x) {
  902.             final double[] lB = CMAESOptimizer.this.getLowerBound();
  903.             final double[] uB = CMAESOptimizer.this.getUpperBound();

  904.             for (int i = 0; i < x.length; i++) {
  905.                 if (x[i] < lB[i]) {
  906.                     return false;
  907.                 }
  908.                 if (x[i] > uB[i]) {
  909.                     return false;
  910.                 }
  911.             }
  912.             return true;
  913.         }

  914.         /**
  915.          * @param x Normalized objective variables.
  916.          * @return the repaired (i.e. all in bounds) objective variables.
  917.          */
  918.         private double[] repair(final double[] x) {
  919.             final double[] lB = CMAESOptimizer.this.getLowerBound();
  920.             final double[] uB = CMAESOptimizer.this.getUpperBound();

  921.             final double[] repaired = new double[x.length];
  922.             for (int i = 0; i < x.length; i++) {
  923.                 if (x[i] < lB[i]) {
  924.                     repaired[i] = lB[i];
  925.                 } else if (x[i] > uB[i]) {
  926.                     repaired[i] = uB[i];
  927.                 } else {
  928.                     repaired[i] = x[i];
  929.                 }
  930.             }
  931.             return repaired;
  932.         }

  933.         /**
  934.          * @param x Normalized objective variables.
  935.          * @param repaired Repaired objective variables.
  936.          * @return Penalty value according to the violation of the bounds.
  937.          */
  938.         private double penalty(final double[] x, final double[] repaired) {
  939.             double penalty = 0;
  940.             for (int i = 0; i < x.length; i++) {
  941.                 double diff = FastMath.abs(x[i] - repaired[i]);
  942.                 penalty += diff;
  943.             }
  944.             return isMinimize ? penalty : -penalty;
  945.         }
  946.     }

  947.     // -----Matrix utility functions similar to the Matlab build in functions------

  948.     /**
  949.      * @param m Input matrix
  950.      * @return Matrix representing the element-wise logarithm of m.
  951.      */
  952.     private static RealMatrix log(final RealMatrix m) {
  953.         final double[][] d = new double[m.getRowDimension()][m.getColumnDimension()];
  954.         for (int r = 0; r < m.getRowDimension(); r++) {
  955.             for (int c = 0; c < m.getColumnDimension(); c++) {
  956.                 d[r][c] = FastMath.log(m.getEntry(r, c));
  957.             }
  958.         }
  959.         return new Array2DRowRealMatrix(d, false);
  960.     }

  961.     /**
  962.      * @param m Input matrix.
  963.      * @return Matrix representing the element-wise square root of m.
  964.      */
  965.     private static RealMatrix sqrt(final RealMatrix m) {
  966.         final double[][] d = new double[m.getRowDimension()][m.getColumnDimension()];
  967.         for (int r = 0; r < m.getRowDimension(); r++) {
  968.             for (int c = 0; c < m.getColumnDimension(); c++) {
  969.                 d[r][c] = FastMath.sqrt(m.getEntry(r, c));
  970.             }
  971.         }
  972.         return new Array2DRowRealMatrix(d, false);
  973.     }

  974.     /**
  975.      * @param m Input matrix.
  976.      * @return Matrix representing the element-wise square of m.
  977.      */
  978.     private static RealMatrix square(final RealMatrix m) {
  979.         final double[][] d = new double[m.getRowDimension()][m.getColumnDimension()];
  980.         for (int r = 0; r < m.getRowDimension(); r++) {
  981.             for (int c = 0; c < m.getColumnDimension(); c++) {
  982.                 double e = m.getEntry(r, c);
  983.                 d[r][c] = e * e;
  984.             }
  985.         }
  986.         return new Array2DRowRealMatrix(d, false);
  987.     }

  988.     /**
  989.      * @param m Input matrix 1.
  990.      * @param n Input matrix 2.
  991.      * @return the matrix where the elements of m and n are element-wise multiplied.
  992.      */
  993.     private static RealMatrix times(final RealMatrix m, final RealMatrix n) {
  994.         final double[][] d = new double[m.getRowDimension()][m.getColumnDimension()];
  995.         for (int r = 0; r < m.getRowDimension(); r++) {
  996.             for (int c = 0; c < m.getColumnDimension(); c++) {
  997.                 d[r][c] = m.getEntry(r, c) * n.getEntry(r, c);
  998.             }
  999.         }
  1000.         return new Array2DRowRealMatrix(d, false);
  1001.     }

  1002.     /**
  1003.      * @param m Input matrix 1.
  1004.      * @param n Input matrix 2.
  1005.      * @return Matrix where the elements of m and n are element-wise divided.
  1006.      */
  1007.     private static RealMatrix divide(final RealMatrix m, final RealMatrix n) {
  1008.         final double[][] d = new double[m.getRowDimension()][m.getColumnDimension()];
  1009.         for (int r = 0; r < m.getRowDimension(); r++) {
  1010.             for (int c = 0; c < m.getColumnDimension(); c++) {
  1011.                 d[r][c] = m.getEntry(r, c) / n.getEntry(r, c);
  1012.             }
  1013.         }
  1014.         return new Array2DRowRealMatrix(d, false);
  1015.     }

  1016.     /**
  1017.      * @param m Input matrix.
  1018.      * @param cols Columns to select.
  1019.      * @return Matrix representing the selected columns.
  1020.      */
  1021.     private static RealMatrix selectColumns(final RealMatrix m, final int[] cols) {
  1022.         final double[][] d = new double[m.getRowDimension()][cols.length];
  1023.         for (int r = 0; r < m.getRowDimension(); r++) {
  1024.             for (int c = 0; c < cols.length; c++) {
  1025.                 d[r][c] = m.getEntry(r, cols[c]);
  1026.             }
  1027.         }
  1028.         return new Array2DRowRealMatrix(d, false);
  1029.     }

  1030.     /**
  1031.      * @param m Input matrix.
  1032.      * @param k Diagonal position.
  1033.      * @return Upper triangular part of matrix.
  1034.      */
  1035.     private static RealMatrix triu(final RealMatrix m, int k) {
  1036.         final double[][] d = new double[m.getRowDimension()][m.getColumnDimension()];
  1037.         for (int r = 0; r < m.getRowDimension(); r++) {
  1038.             for (int c = 0; c < m.getColumnDimension(); c++) {
  1039.                 d[r][c] = r <= c - k ? m.getEntry(r, c) : 0;
  1040.             }
  1041.         }
  1042.         return new Array2DRowRealMatrix(d, false);
  1043.     }

  1044.     /**
  1045.      * @param m Input matrix.
  1046.      * @return Row matrix representing the sums of the rows.
  1047.      */
  1048.     private static RealMatrix sumRows(final RealMatrix m) {
  1049.         final double[][] d = new double[1][m.getColumnDimension()];
  1050.         for (int c = 0; c < m.getColumnDimension(); c++) {
  1051.             double sum = 0;
  1052.             for (int r = 0; r < m.getRowDimension(); r++) {
  1053.                 sum += m.getEntry(r, c);
  1054.             }
  1055.             d[0][c] = sum;
  1056.         }
  1057.         return new Array2DRowRealMatrix(d, false);
  1058.     }

  1059.     /**
  1060.      * @param m Input matrix.
  1061.      * @return the diagonal n-by-n matrix if m is a column matrix or the column
  1062.      * matrix representing the diagonal if m is a n-by-n matrix.
  1063.      */
  1064.     private static RealMatrix diag(final RealMatrix m) {
  1065.         if (m.getColumnDimension() == 1) {
  1066.             final double[][] d = new double[m.getRowDimension()][m.getRowDimension()];
  1067.             for (int i = 0; i < m.getRowDimension(); i++) {
  1068.                 d[i][i] = m.getEntry(i, 0);
  1069.             }
  1070.             return new Array2DRowRealMatrix(d, false);
  1071.         } else {
  1072.             final double[][] d = new double[m.getRowDimension()][1];
  1073.             for (int i = 0; i < m.getColumnDimension(); i++) {
  1074.                 d[i][0] = m.getEntry(i, i);
  1075.             }
  1076.             return new Array2DRowRealMatrix(d, false);
  1077.         }
  1078.     }

  1079.     /**
  1080.      * Copies a column from m1 to m2.
  1081.      *
  1082.      * @param m1 Source matrix.
  1083.      * @param col1 Source column.
  1084.      * @param m2 Target matrix.
  1085.      * @param col2 Target column.
  1086.      */
  1087.     private static void copyColumn(final RealMatrix m1, int col1,
  1088.                                    RealMatrix m2, int col2) {
  1089.         for (int i = 0; i < m1.getRowDimension(); i++) {
  1090.             m2.setEntry(i, col2, m1.getEntry(i, col1));
  1091.         }
  1092.     }

  1093.     /**
  1094.      * @param n Number of rows.
  1095.      * @param m Number of columns.
  1096.      * @return n-by-m matrix filled with 1.
  1097.      */
  1098.     private static RealMatrix ones(int n, int m) {
  1099.         final double[][] d = new double[n][m];
  1100.         for (int r = 0; r < n; r++) {
  1101.             Arrays.fill(d[r], 1);
  1102.         }
  1103.         return new Array2DRowRealMatrix(d, false);
  1104.     }

  1105.     /**
  1106.      * @param n Number of rows.
  1107.      * @param m Number of columns.
  1108.      * @return n-by-m matrix of 0 values out of diagonal, and 1 values on
  1109.      * the diagonal.
  1110.      */
  1111.     private static RealMatrix eye(int n, int m) {
  1112.         final double[][] d = new double[n][m];
  1113.         for (int r = 0; r < n; r++) {
  1114.             if (r < m) {
  1115.                 d[r][r] = 1;
  1116.             }
  1117.         }
  1118.         return new Array2DRowRealMatrix(d, false);
  1119.     }

  1120.     /**
  1121.      * @param n Number of rows.
  1122.      * @param m Number of columns.
  1123.      * @return n-by-m matrix of zero values.
  1124.      */
  1125.     private static RealMatrix zeros(int n, int m) {
  1126.         return new Array2DRowRealMatrix(n, m);
  1127.     }

  1128.     /**
  1129.      * @param mat Input matrix.
  1130.      * @param n Number of row replicates.
  1131.      * @param m Number of column replicates.
  1132.      * @return a matrix which replicates the input matrix in both directions.
  1133.      */
  1134.     private static RealMatrix repmat(final RealMatrix mat, int n, int m) {
  1135.         final int rd = mat.getRowDimension();
  1136.         final int cd = mat.getColumnDimension();
  1137.         final double[][] d = new double[n * rd][m * cd];
  1138.         for (int r = 0; r < n * rd; r++) {
  1139.             for (int c = 0; c < m * cd; c++) {
  1140.                 d[r][c] = mat.getEntry(r % rd, c % cd);
  1141.             }
  1142.         }
  1143.         return new Array2DRowRealMatrix(d, false);
  1144.     }

  1145.     /**
  1146.      * @param start Start value.
  1147.      * @param end End value.
  1148.      * @param step Step size.
  1149.      * @return a sequence as column matrix.
  1150.      */
  1151.     private static RealMatrix sequence(double start, double end, double step) {
  1152.         final int size = (int) ((end - start) / step + 1);
  1153.         final double[][] d = new double[size][1];
  1154.         double value = start;
  1155.         for (int r = 0; r < size; r++) {
  1156.             d[r][0] = value;
  1157.             value += step;
  1158.         }
  1159.         return new Array2DRowRealMatrix(d, false);
  1160.     }

  1161.     /**
  1162.      * @param m Input matrix.
  1163.      * @return the maximum of the matrix element values.
  1164.      */
  1165.     private static double max(final RealMatrix m) {
  1166.         double max = -Double.MAX_VALUE;
  1167.         for (int r = 0; r < m.getRowDimension(); r++) {
  1168.             for (int c = 0; c < m.getColumnDimension(); c++) {
  1169.                 double e = m.getEntry(r, c);
  1170.                 if (max < e) {
  1171.                     max = e;
  1172.                 }
  1173.             }
  1174.         }
  1175.         return max;
  1176.     }

  1177.     /**
  1178.      * @param m Input matrix.
  1179.      * @return the minimum of the matrix element values.
  1180.      */
  1181.     private static double min(final RealMatrix m) {
  1182.         double min = Double.MAX_VALUE;
  1183.         for (int r = 0; r < m.getRowDimension(); r++) {
  1184.             for (int c = 0; c < m.getColumnDimension(); c++) {
  1185.                 double e = m.getEntry(r, c);
  1186.                 if (min > e) {
  1187.                     min = e;
  1188.                 }
  1189.             }
  1190.         }
  1191.         return min;
  1192.     }

  1193.     /**
  1194.      * @param m Input array.
  1195.      * @return the maximum of the array values.
  1196.      */
  1197.     private static double max(final double[] m) {
  1198.         double max = -Double.MAX_VALUE;
  1199.         for (int r = 0; r < m.length; r++) {
  1200.             if (max < m[r]) {
  1201.                 max = m[r];
  1202.             }
  1203.         }
  1204.         return max;
  1205.     }

  1206.     /**
  1207.      * @param m Input array.
  1208.      * @return the minimum of the array values.
  1209.      */
  1210.     private static double min(final double[] m) {
  1211.         double min = Double.MAX_VALUE;
  1212.         for (int r = 0; r < m.length; r++) {
  1213.             if (min > m[r]) {
  1214.                 min = m[r];
  1215.             }
  1216.         }
  1217.         return min;
  1218.     }

  1219.     /**
  1220.      * @param indices Input index array.
  1221.      * @return the inverse of the mapping defined by indices.
  1222.      */
  1223.     private static int[] inverse(final int[] indices) {
  1224.         final int[] inverse = new int[indices.length];
  1225.         for (int i = 0; i < indices.length; i++) {
  1226.             inverse[indices[i]] = i;
  1227.         }
  1228.         return inverse;
  1229.     }

  1230.     /**
  1231.      * @param indices Input index array.
  1232.      * @return the indices in inverse order (last is first).
  1233.      */
  1234.     private static int[] reverse(final int[] indices) {
  1235.         final int[] reverse = new int[indices.length];
  1236.         for (int i = 0; i < indices.length; i++) {
  1237.             reverse[i] = indices[indices.length - i - 1];
  1238.         }
  1239.         return reverse;
  1240.     }

  1241.     /**
  1242.      * @param size Length of random array.
  1243.      * @return an array of Gaussian random numbers.
  1244.      */
  1245.     private double[] randn(int size) {
  1246.         final double[] randn = new double[size];
  1247.         for (int i = 0; i < size; i++) {
  1248.             randn[i] = random.nextGaussian();
  1249.         }
  1250.         return randn;
  1251.     }

  1252.     /**
  1253.      * @param size Number of rows.
  1254.      * @param popSize Population size.
  1255.      * @return a 2-dimensional matrix of Gaussian random numbers.
  1256.      */
  1257.     private RealMatrix randn1(int size, int popSize) {
  1258.         final double[][] d = new double[size][popSize];
  1259.         for (int r = 0; r < size; r++) {
  1260.             for (int c = 0; c < popSize; c++) {
  1261.                 d[r][c] = random.nextGaussian();
  1262.             }
  1263.         }
  1264.         return new Array2DRowRealMatrix(d, false);
  1265.     }
  1266. }