/** * 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); }
/** * A private helper function for evalutatePopulation which evaluates a chunk of individuals in a * subpopulation for a given thread. * * <p>Although this method is declared public (for the benefit of a private helper class in this * file), you should not call it. * * @param state * @param numinds * @param from * @param threadnum * @param prob */ public void evalRoundRobinPopChunk( final EvolutionState state, int from, int numinds, int threadnum, final Individual[] individuals, int subpop, final GroupedProblemForm prob) { Individual[] competition = new Individual[2]; int[] subpops = new int[] {subpop, subpop}; boolean[] updates = new boolean[2]; updates[0] = updates[1] = true; int upperBound = from + numinds; // evaluate chunk of population against entire population // since an individual x will be evaluated against all // other individuals <x in other threads, only evaluate it against // individuals >x in this thread. for (int x = from; x < upperBound; x++) for (int y = x + 1; y < individuals.length; y++) { competition[0] = individuals[x]; competition[1] = individuals[y]; prob.evaluate(state, competition, updates, false, subpops, 0); } }
public void evalSingleElimination( final EvolutionState state, final Individual[] individuals, final int subpop, final GroupedProblemForm prob) { // for a single-elimination tournament, the subpop[0] size must be 2^n for // some value n. We don't check that here! Check it in setup. // create the tournament array Individual[] tourn = new Individual[individuals.length]; System.arraycopy(individuals, 0, tourn, 0, individuals.length); int len = tourn.length; Individual[] competition = new Individual[2]; int[] subpops = new int[] {subpop, subpop}; boolean[] updates = new boolean[2]; updates[0] = updates[1] = true; // the "top half" of our array will be losers. // the bottom half will be winners. Then we cut our array in half and repeat. while (len > 1) { for (int x = 0; x < len / 2; x++) { competition[0] = tourn[x]; competition[1] = tourn[len - x - 1]; prob.evaluate(state, competition, updates, true, subpops, 0); } for (int x = 0; x < len / 2; x++) { // if the second individual is better, or coin flip if equal, than we switch them around if (tourn[len - x - 1].fitness.betterThan(tourn[x].fitness) || (tourn[len - x - 1].fitness.equivalentTo(tourn[x].fitness) && state.random[0].nextBoolean())) { Individual temp = tourn[x]; tourn[x] = tourn[len - x - 1]; tourn[len - x - 1] = temp; } } // last part of the tournament: deal with odd values of len! if (len % 2 != 0) len = 1 + len / 2; else len /= 2; } }
public void evalNRandomOneWayPopChunk( final EvolutionState state, int from, int numinds, int threadnum, final Individual[] individuals, final int subpop, final GroupedProblemForm prob) { Individual[] queue = new Individual[individuals.length]; int len = queue.length; System.arraycopy(individuals, 0, queue, 0, len); Individual[] competition = new Individual[2]; int subpops[] = new int[] {subpop, subpop}; boolean[] updates = new boolean[2]; updates[0] = true; updates[1] = false; int upperBound = from + numinds; for (int x = from; x < upperBound; x++) { competition[0] = individuals[x]; // fill up our tournament for (int y = 0; y < groupSize; ) { // swap to end and remove int index = state.random[0].nextInt(len - y); competition[1] = queue[index]; queue[index] = queue[len - y - 1]; queue[len - y - 1] = competition[1]; // if the opponent is not the actual individual, we can // have a competition if (competition[1] != individuals[x]) { prob.evaluate(state, competition, updates, false, subpops, 0); y++; } } } }
public void evalNRandomTwoWayPopChunk( final EvolutionState state, int from, int numinds, int threadnum, final Individual[] individuals, final int subpop, final GroupedProblemForm prob) { // the number of games played for each player EncapsulatedIndividual[] individualsOrdered = new EncapsulatedIndividual[individuals.length]; EncapsulatedIndividual[] queue = new EncapsulatedIndividual[individuals.length]; for (int i = 0; i < individuals.length; i++) individualsOrdered[i] = new EncapsulatedIndividual(individuals[i], 0); Individual[] competition = new Individual[2]; int[] subpops = new int[] {subpop, subpop}; boolean[] updates = new boolean[2]; updates[0] = true; int upperBound = from + numinds; for (int x = from; x < upperBound; x++) { System.arraycopy(individualsOrdered, 0, queue, 0, queue.length); competition[0] = queue[x].ind; // if the rest of individuals is not enough to fill // all games remaining for the current individual // (meaning that the current individual has left a // lot of games to play versus players with index // greater than his own), then it should play with // all. In the end, we should check that he finished // all the games he needs. If he did, everything is // ok, otherwise he should play with some other players // with index smaller than his own, but all these games // will count only for his fitness evaluation, and // not for the opponents' (unless allowOverEvaluations is set to true) // if true, it means that he has to play against all opponents with greater index if (individuals.length - x - 1 <= groupSize - queue[x].nOpponentsMet) { for (int y = x + 1; y < queue.length; y++) { competition[1] = queue[y].ind; updates[1] = (queue[y].nOpponentsMet < groupSize) || allowOverEvaluation; prob.evaluate(state, competition, updates, false, subpops, 0); queue[x].nOpponentsMet++; if (updates[1]) queue[y].nOpponentsMet++; } } else // here he has to play against a selection of the opponents with greater index { // we can use the queue structure because we'll just rearrange the indexes // but we should make sure we also rearrange the other vectors referring to the individuals for (int y = 0; groupSize > queue[x].nOpponentsMet; y++) { // swap to the end and remove from list int index = state.random[0].nextInt(queue.length - x - 1 - y) + x + 1; competition[1] = queue[index].ind; updates[1] = (queue[index].nOpponentsMet < groupSize) || allowOverEvaluation; prob.evaluate(state, competition, updates, false, subpops, 0); queue[x].nOpponentsMet++; if (updates[1]) queue[index].nOpponentsMet++; // swap the players (such that a player will not be considered twice) EncapsulatedIndividual temp = queue[index]; queue[index] = queue[queue.length - y - 1]; queue[queue.length - y - 1] = temp; } } // if true, it means that the current player needs to play some games with other players with // lower indexes. // this is an unfortunate situation, since all those players have already had their groupSize // games for the evaluation if (queue[x].nOpponentsMet < groupSize) { for (int y = queue[x].nOpponentsMet; y < groupSize; y++) { // select a random opponent with smaller index (don't even care for duplicates) int index; if (x > 0) // if x is 0, then there are no players with smaller index, therefore pick a // random one index = state.random[0].nextInt(x); else index = state.random[0].nextInt(queue.length - 1) + 1; // use the opponent for the evaluation competition[1] = queue[index].ind; updates[1] = (queue[index].nOpponentsMet < groupSize) || allowOverEvaluation; prob.evaluate(state, competition, updates, false, subpops, 0); queue[x].nOpponentsMet++; if (updates[1]) queue[index].nOpponentsMet++; } } } }