/**
   * An evaluator that performs coevolutionary evaluation. Like SimpleEvaluator, it applies
   * evolution pipelines, one per thread, to various subchunks of a new population.
   */
  public void evaluatePopulation(final EvolutionState state) {
    int numinds[] = new int[state.evalthreads];
    int from[] = new int[state.evalthreads];
    boolean[] assessFitness = new boolean[state.population.subpops.length];
    for (int i = 0; i < assessFitness.length; i++)
      assessFitness[i] = true; // update everyone's fitness in preprocess and postprocess

    for (int y = 0; y < state.evalthreads; y++) {
      // figure numinds
      if (y < state.evalthreads - 1) // not last one
      numinds[y] = state.population.subpops[0].individuals.length / state.evalthreads;
      else
        numinds[y] =
            state.population.subpops[0].individuals.length / state.evalthreads
                + (state.population.subpops[0].individuals.length
                    - (state.population.subpops[0].individuals.length / state.evalthreads)
                        * state.evalthreads);
      // figure from
      from[y] = (state.population.subpops[0].individuals.length / state.evalthreads) * y;
    }

    randomizeOrder(state, state.population.subpops[0].individuals);

    GroupedProblemForm prob = (GroupedProblemForm) (p_problem.clone());

    prob.preprocessPopulation(
        state, state.population, assessFitness, style == STYLE_SINGLE_ELIMINATION);

    switch (style) {
      case STYLE_SINGLE_ELIMINATION:
        evalSingleElimination(state, state.population.subpops[0].individuals, 0, prob);
        break;
      case STYLE_ROUND_ROBIN:
        evalRoundRobin(state, from, numinds, state.population.subpops[0].individuals, 0, prob);
        break;
      case STYLE_N_RANDOM_COMPETITORS_ONEWAY:
        evalNRandomOneWay(state, from, numinds, state.population.subpops[0].individuals, 0, prob);
        break;
      case STYLE_N_RANDOM_COMPETITORS_TWOWAY:
        evalNRandomTwoWay(state, from, numinds, state.population.subpops[0].individuals, 0, prob);
        break;
      default:
        state.output.fatal(
            "Invalid competition style in CompetitiveEvaluator.evaluatePopulation()");
    }

    prob.postprocessPopulation(
        state, state.population, assessFitness, style == STYLE_SINGLE_ELIMINATION);
  }