/* Copyright 2006 by Sean Luke Licensed under the Academic Free License version 3.0 See the file "LICENSE" for more information */ package ec.select; import ec.*; import ec.util.*; import ec.steadystate.*; /* * TournamentSelection.java * * Created: Mon Aug 30 19:27:15 1999 * By: Sean Luke */ /** * Does a simple tournament selection, limited to the subpopulation it's * working in at the time. * *

Tournament selection works like this: first, size individuals * are chosen at random from the population. Then of those individuals, * the one with the best fitness is selected. * *

size can also be a floating-point value between 1.0 and 2.0, * exclusive of them. In this situation, two individuals are chosen at random, and * the better one is selected with a probability of size/2 * *

Common sizes for size include: 2, popular in Genetic Algorithms * circles, and 7, popularized in Genetic Programming by John Koza. * If the size is 1, then individuals are picked entirely at random. * *

Tournament selection is so simple that it doesn't need to maintain * a cache of any form, so many of the SelectionMethod methods just * don't do anything at all. *

Typical Number of Individuals Produced Per produce(...) call
Always 1.

Parameters
base.size
float >= 1
(the tournament size)
base.pick-worst
bool = true or false (default)
(should we pick the worst individual in the tournament instead of the best?)

Default Base
select.tournament * * @author Sean Luke * @version 1.0 */ public class TournamentSelection extends SelectionMethod implements SteadyStateBSourceForm { /** default base */ public static final String P_TOURNAMENT = "tournament"; public static final String P_PICKWORST = "pick-worst"; /** size parameter */ public static final String P_SIZE = "size"; /* Default size */ public static final int DEFAULT_SIZE = 7; /** Base size of the tournament; this may change. */ int size; /** Probablity of picking the size plus one */ public double probabilityOfPickingSizePlusOne; /** Do we pick the worst instead of the best? */ public boolean pickWorst; public Parameter defaultBase() { return SelectDefaults.base().push(P_TOURNAMENT); } public void setup(final EvolutionState state, final Parameter base) { super.setup(state,base); Parameter def = defaultBase(); double val = state.parameters.getDouble(base.push(P_SIZE),def.push(P_SIZE),1.0); if (val < 1.0) state.output.fatal("Tournament size must be >= 1.",base.push(P_SIZE),def.push(P_SIZE)); else if (val == (int) val) // easy, it's just an integer { size = (int) val; probabilityOfPickingSizePlusOne = 0.0; } else { size = (int) Math.floor(val); probabilityOfPickingSizePlusOne = val - size; // for example, if we have 5.4, then the probability of picking *6* is 0.4 } pickWorst = state.parameters.getBoolean(base.push(P_PICKWORST),def.push(P_PICKWORST),false); } /** Returns a tournament size to use, at random, based on base size and probability of picking the size plus one. */ public int getTournamentSizeToUse(MersenneTwisterFast random) { double p = probabilityOfPickingSizePlusOne; // pulls us to under 35 bytes if (p == 0.0) return size; return size + (random.nextBoolean(p) ? 1 : 0); } /** Produces the index of a (typically uniformly distributed) randomly chosen individual to fill the tournament. number is the position of the individual in the tournament. */ public int getRandomIndividual(int number, int subpopulation, EvolutionState state, int thread) { Individual[] oldinds = state.population.subpops[subpopulation].individuals; return state.random[thread].nextInt(oldinds.length); } /** Returns true if *first* is a better (fitter, whatever) individual than *second*. */ public boolean betterThan(Individual first, Individual second, int subpopulation, EvolutionState state, int thread) { return first.fitness.betterThan(second.fitness); } public int produce(final int subpopulation, final EvolutionState state, final int thread) { // pick size random individuals, then pick the best. Individual[] oldinds = state.population.subpops[subpopulation].individuals; int best = getRandomIndividual(0, subpopulation, state, thread); int s = getTournamentSizeToUse(state.random[thread]); if (pickWorst) for (int x=1;x