/* 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