@Override
  public List<Individual> operate(EvolutionaryAlgorithm algorithm, List<Individual> individuals)
      throws OperatorException {

    List<Individual> new_population = new ArrayList<Individual>(individuals.size());
    CMAEvolutionaryAlgorithm alg = (CMAEvolutionaryAlgorithm) algorithm;
    debug = algorithm.isDebug();

    double[] chromosome;

    int N = individuals.get(0).getDimension();

    countCUpdatesSinceEigenupdate = alg.getCountCupdatesSinceEigenupdate();
    // latest possibility to generate B and diagD:
    eidgendecomposition(alg, N, 0);

    // ensure minimal and maximal standard deviation:
    double minsqrtdiagC = Math.sqrt(StatUtils.min(alg.diag(alg.getC())));
    double maxsqrtdiagC = Math.sqrt(StatUtils.max(alg.diag(alg.getC())));

    /*
     * TODO: test if it is necessary *
     */
    for (int i = 0; i < individuals.size(); i++) {
      new_population.add((Individual) individuals.get(i).clone());
    }

    if (lowerStandardDeviation != null && lowerStandardDeviation.length > 0) {

      for (int i = 0; i < N; i++) {

        double d = lowerStandardDeviation[Math.min(i, lowerStandardDeviation.length - 1)];

        if (d > alg.getSigma() * minsqrtdiagC) {
          alg.setSigma(d / minsqrtdiagC);
        }
      }
    }

    if (upperStandardDeviation != null && upperStandardDeviation.length > 0) {

      for (int i = 0; i < N; i++) {

        double d = upperStandardDeviation[Math.min(i, upperStandardDeviation.length - 1)];

        if (d < alg.getSigma() * maxsqrtdiagC) {
          alg.setSigma(d / maxsqrtdiagC);
        }
      }
    }

    testAndCorrectNumerics(alg, N, new_population);

    double[] artmp = new double[N];

    /*
     * Sample the distribution
     */
    for (int iNk = 0; iNk < alg.getLambda(); iNk++) {

      chromosome = new_population.get(iNk).getChromosomeAt(0);

      if (alg.getFlgDiag()) {

        for (int i = 0; i < N; i++) {

          chromosome[i] =
              this.checkBounds(
                  alg,
                  alg.getxMean()[i] + alg.getSigma() * alg.getDiag()[i] * EAFRandom.nextGaussian());
        }

      } else {

        for (int i = 0; i < N; i++) {

          artmp[i] = alg.getDiag()[i] * EAFRandom.nextGaussian();
        }

        /*
         * add mutation (sigma * B * (D*z))
         */
        for (int i = 0; i < N; i++) {

          double sum = 0.0;
          for (int j = 0; j < N; j++) {

            sum += alg.getB()[i][j] * artmp[j];
          }

          chromosome[i] = this.checkBounds(alg, alg.getxMean()[i] + alg.getSigma() * sum);
        }
      }

      new_population.get(iNk).setChromosomeAt(0, chromosome);
    }

    return new_population;
  }