@Override
  protected Individual select(EvolutionaryAlgorithm algorithm, List<Individual> individuals) {

    double random;
    double acum;
    int n = individuals.size();
    double min = 2 - this.max;
    double range = this.max - min;
    Individual individual;
    int i;

    // Se ordena la lista de individuos segĂșn el comparador en orden inverso:
    Collections.sort(individuals, algorithm.getComparator());
    Collections.reverse(individuals);

    // Ahora la posicion en la lista de cada individuo indica su rank:
    random = EAFRandom.nextDouble();

    acum = 0.0;

    i = 0;
    do {

      i++;
      acum += (1.0 / n) * (this.max - range * ((double) (i - 1.0) / (double) (n - 1.0)));

    } while (acum < random);

    individual = individuals.get(--i);

    return (Individual) individual.clone();
  }
  @Override
  public List<Individual> operate(EvolutionaryAlgorithm algorithm, List<Individual> individuals)
      throws OperatorException {
    MacroevolutionaryAlgorithm alg = (MacroevolutionaryAlgorithm) algorithm;
    FitnessComparator<Individual> comparator = algorithm.getComparator();
    Wxy wxy;
    MaIndividual indA, indB;
    double weight;
    int survivors = 0;

    if (comparator instanceof MaximizingFitnessComparator) {
      wxy = new WxyMaximizing();
    } else {
      if (comparator instanceof MinimizingFitnessComparator) {
        wxy = new WxyMinimizing();
      } else {
        throw new OperatorException("Wrong comparator for Inherit Extintion operator");
      }
    }
    for (int i = 0; i < individuals.size(); i++) {
      indA = (MaIndividual) individuals.get(i);
      if (indA.getBestFitness() != indA.getFitness()) {
        indA.setSurvivor(false);
      } else {
        for (int j = i + 1; j < individuals.size(); j++) {
          indB = (MaIndividual) individuals.get(j);
          if (!indA.isSurvivor() || !indB.isSurvivor()) {
            alg.setWxy(i, j, wxy.get(indA, indB));
          }
        }
        weight = 0;
        for (int j = 0; j < i; j++) {
          weight -= alg.getWxy(j, i);
        }
        for (int j = i + 1; j < individuals.size(); j++) {
          weight += alg.getWxy(i, j);
        }
        if (weight > 0) {
          indA.setSurvivor(true);
          survivors++;
        } else {
          if (weight < 0) {
            indA.setSurvivor(false);
          } else {
            if (EAFRandom.nextDouble() < 0.5) {
              indA.setSurvivor(true);
              survivors++;
            } else {
              indA.setSurvivor(false);
            }
          }
        }
      }
    }

    // We always need at least one survivor
    if (survivors == 0) {
      BestIndividual chooser = new BestIndividual();
      ((MaIndividual) chooser.get(algorithm, individuals, null)).setSurvivor(true);
    }

    return individuals;
  }
  @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;
  }