package org.biojavax.ga.functions;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Random;
import org.biojava.bio.BioError;
import org.biojava.utils.ChangeVetoException;
import org.biojavax.ga.GeneticAlgorithm;
import org.biojavax.ga.Organism;
import org.biojavax.ga.Population;
import org.biojavax.ga.exception.IllegalOrganismException;
import org.biojavax.ga.functions.SelectionFunction;
import org.biojavax.ga.impl.SimplePopulation;
/**
* Tournament Selection chooses the best organisms from n random subsets of a
* given population. Currently it assumes a maximization problem. Perhaps this
* could be selected depending on the Genetic Algorithm utilized.
*
* @author Susanne Merz
*/
public class TournamentSelection implements SelectionFunction {
private int selpressure;
/**
* Default constructor: sets the selection pressure to the value of 10.
*/
public TournamentSelection() {
this.setSelectionPressure(10);
};
/**
* sets the parameter controlling selection pressure
*
* @param numberOfIndividuals
* the number of Individuals the best is selected from, ranges from 1
* (random selection) to the size of the population (elitism)
*/
public void setSelectionPressure(int numberOfIndividuals) {
selpressure = numberOfIndividuals;
}
/**
* Standard call to select organisms, will select a number of Organisms
* corresponding to 75 % of the population.
*
* @see org.biojavax.ga.functions.SelectionFunction#select(org.biojavax.ga.Population, org.biojavax.ga.GeneticAlgorithm)
*/
public Population select(Population pop, GeneticAlgorithm genAlg)
throws ChangeVetoException {
return selectNIndividuals(pop, genAlg, pop.size());
}
/**
* This method selects n Organism from the population it is given, using the
* tournament selection method
*
* @param pop
* the population to select from
* @param ga
* the GeneticAlgorithm
this selection belongs to
* @param n
* number of individuals to be selected.
* @return nextgen a Population
containing the selected
* Organisms
*/
public Population selectNIndividuals(Population pop, GeneticAlgorithm ga,
int n) {
SimplePopulation nextgen = new SimplePopulation();
if (selpressure <= 0) {
System.out.println("Sorry can't select with a selection pressure <= 0");
return null;
}
int q = selpressure;
Random r = new Random();
// choose n individuals
for (int i = 0; i < n; i++) {
// need to check that the size of the set we want
// to choose from does not exceed the populations size
if (q > pop.size()) {
q = pop.size();
}
// Maximization Problem
double bestvalue = Double.MIN_VALUE;
Organism best = null;
// create a List of Organisms, simulating a subpopulation of size q
LinkedList subpopulation = new LinkedList();
while (subpopulation.size() < q) {
Iterator it = pop.organisms();
int pos = r.nextInt(pop.size());
Organism current = it.next();
while (pos > 0) {
current = it.next();
pos--;
}
// if the subpopulation already contains the choosen
// element, we pick the next that isn't contained
while (subpopulation.contains(current)) {
// run in circles ;)
if (!it.hasNext()) {
it = pop.organisms();
}
current = it.next();
}
// while we already have a handle on the organism
// we want save which one is the best so far in the
// subpopulation
double value[] = current.getFitness();
if ((value[0] >= bestvalue)) {
best = current;
bestvalue = value[0];
}
subpopulation.add(current);
}
// finished creating subpopulation, add best organism
// from the subpopulation to the next generation
try {
if (best != null) {
String namesprefix = best.getName().split(":")[0];
Organism o = best.replicate(namesprefix + ":" + i);
nextgen.addOrganism(o);
// pop.removeOrganism(best);
}
} catch (IllegalOrganismException e) {
e.printStackTrace();
}
}
pop.removeAllOrganisms();
for (Iterator it = nextgen.organisms(); it.hasNext();) {
try {
pop.addOrganism((Organism) it.next());
} catch (ChangeVetoException e) {
e.printStackTrace();
} catch (IllegalOrganismException ex) {
throw new BioError("A previously legal organism is now illegal??", ex);
}
}
pop = nextgen;
return nextgen;
}
}