/* * This file is part of JGAP. * * JGAP offers a dual license model containing the LGPL as well as the MPL. * * For licensing information please see the file license.txt included with JGAP * or have a look at the top of class org.jgap.Chromosome which representatively * includes the JGAP license policy applicable for any file delivered with JGAP. */ package org.jgap.impl; import java.util.*; import org.jgap.*; import org.jgap.util.*; /** * Implementation of a NaturalSelector that is suited for being processed after * genetic operators have been executed. It takes all chromosomes with no * fitness value computed to the next generation. Then it takes the top n * chromosomes from the remaining input into the next generation. * Which chromosomes are the best is decided by evaluating their fitness value. * * @author Klaus Meffert * @since 3.2 */ public class StandardPostSelector extends NaturalSelector implements ICloneable { /** String containing the CVS revision. Read out via reflection!*/ private final static String CVS_REVISION = "$Revision: 1.4 $"; /** * Stores the chromosomes to be taken into account for selection */ private Population m_chromosomes; /** * Indicated whether the list of added chromosomes needs sorting */ private boolean m_needsSorting; /** * Comparator that is only concerned about fitness values */ private FitnessValueComparator m_fitnessValueComparator; /** * Default constructor.<p> * Attention: The configuration used is the one set with the static method * Genotype.setConfiguration. * * @throws InvalidConfigurationException * * @author Klaus Meffert * @since 3.2 */ public StandardPostSelector() throws InvalidConfigurationException { this(Genotype.getStaticConfiguration()); } /** * Constructor. * * @param a_config the configuration to use * @throws InvalidConfigurationException * * @author Klaus Meffert * @since 3.2 */ public StandardPostSelector(final Configuration a_config) throws InvalidConfigurationException { super(a_config); m_chromosomes = new Population(a_config); m_needsSorting = false; m_fitnessValueComparator = new FitnessValueComparator(); } /** * Add a Chromosome instance to this selector's working pool of Chromosomes. * * @param a_chromosomeToAdd the specimen to add to the pool * * @author Klaus Meffert * @since 3.2 */ protected void add(final IChromosome a_chromosomeToAdd) { // New chromosome, insert it into the sorted collection of chromosomes. // -------------------------------------------------------------------- a_chromosomeToAdd.setIsSelectedForNextGeneration(false); m_chromosomes.addChromosome(a_chromosomeToAdd); // Indicate that the list of chromosomes to add needs sorting. // ----------------------------------------------------------- m_needsSorting = true; } /** * Selects a given number of Chromosomes from the pool that will move on * to the next generation population. This selection will be guided by the * fitness values. The chromosomes with the best fitness value win. * * @param a_from_pop the population the Chromosomes will be selected from * @param a_to_pop the population the Chromosomes will be added to * @param a_howManyToSelect the number of Chromosomes to select * * @author Klaus Meffert * @since 1.1 */ public void select(final int a_howManyToSelect, final Population a_from_pop, final Population a_to_pop) { if (a_from_pop != null) { int popSize = a_from_pop.size(); if (popSize < 1) { throw new IllegalStateException("Population size must be greater 0"); } for (int i = 0; i < popSize; i++) { add(a_from_pop.getChromosome(i)); } } int canBeSelected; int chromsSize = m_chromosomes.size(); if (chromsSize < 1) { throw new IllegalStateException( "Number of chromosomes must be greater 0"); } if (a_howManyToSelect > chromsSize) { canBeSelected = chromsSize; } else { canBeSelected = a_howManyToSelect; } int neededSize = a_howManyToSelect; // First select all chromosomes with no fitness value computed. // ------------------------------------------------------------ Iterator it = m_chromosomes.iterator(); while (it.hasNext()) { IChromosome c = (IChromosome)it.next(); if (Math.abs(c.getFitnessValueDirectly() - FitnessFunction.NO_FITNESS_VALUE) < FitnessFunction.DELTA) { a_to_pop.addChromosome(c); it.remove(); canBeSelected--; if (canBeSelected < 1) { break; } } } // Sort the collection of chromosomes previously added for evaluation. // Only do this if necessary. // ------------------------------------------------------------------- if (m_needsSorting && canBeSelected > 0) { Collections.sort(m_chromosomes.getChromosomes(), m_fitnessValueComparator); m_needsSorting = false; } // To select a chromosome, we just go thru the sorted list. // -------------------------------------------------------- IChromosome selectedChromosome; for (int i = 0; i < canBeSelected; i++) { selectedChromosome = m_chromosomes.getChromosome(i); selectedChromosome.setIsSelectedForNextGeneration(true); a_to_pop.addChromosome(selectedChromosome); } int toAdd; toAdd = neededSize - a_to_pop.size(); // Add existing chromosomes to fill up the return // result to contain the desired number of chromosomes. // ---------------------------------------------------- for (int i = 0; i < toAdd; i++) { selectedChromosome = m_chromosomes.getChromosome(i % chromsSize); selectedChromosome.setIsSelectedForNextGeneration(true); a_to_pop.addChromosome(selectedChromosome); } } /** * Empties out the working pool of chromosomes. * * @author Klaus Meffert * @since 3.2 */ public void empty() { // Clear the list of chromosomes. // ------------------------------ m_chromosomes.getChromosomes().clear(); m_needsSorting = false; } /** * @return always true as no chromosome can be returnd multiple times * * @author Klaus Meffert * @since 3.2 */ public boolean returnsUniqueChromosomes() { return true; } public boolean equals(Object a_o) { if (a_o == null) { return false; } StandardPostSelector other = (StandardPostSelector) a_o; if (!m_fitnessValueComparator.getClass().getName().equals( other.m_fitnessValueComparator.getClass().getName())) { return false; } if (!m_chromosomes.equals(other.m_chromosomes)) { return false; } return true; } public Object clone() { try { StandardPostSelector sel = new StandardPostSelector(getConfiguration()); sel.m_needsSorting = m_needsSorting; return sel; } catch (Throwable t) { throw new CloneException(t); } } }