001: /*
002: * This file is part of JGAP.
003: *
004: * JGAP offers a dual license model containing the LGPL as well as the MPL.
005: *
006: * For licensing information please see the file license.txt included with JGAP
007: * or have a look at the top of class org.jgap.Chromosome which representatively
008: * includes the JGAP license policy applicable for any file delivered with JGAP.
009: */
010: package org.jgap.impl;
011:
012: import java.util.*;
013: import org.jgap.*;
014: import org.jgap.distr.*;
015:
016: /**
017: * A implementation of the IPopulationMerger interface that merges two
018: * populations as specified based on the fitness function, that is, the n
019: * fittest chromosomes are returned in the new population, where n is supplied
020: * by parameter.
021: *
022: * @author Henrique Goulart
023: * @since 2.0
024: */
025: public class FittestPopulationMerger implements IPopulationMerger {
026: /** String containing the CVS revision. Read out via reflection!*/
027: private final static String CVS_REVISION = "$Revision: 1.17 $";
028:
029: public Population mergePopulations(final Population a_population1,
030: final Population a_population2,
031: final int a_new_population_size) {
032: /**@todo check if configurations of both pops are equal resp.
033: * their fitness evaluators!*/
034: try {
035: // All the chromosomes are placed in the first population for sorting.
036: a_population1.addChromosomes(a_population2);
037: // A sorting is made according to the chromosomes fitness values
038: // See the private class FitnessChromosomeComparator below to understand.
039: List allChromosomes = a_population1.getChromosomes();
040: Collections.sort(allChromosomes,
041: new FitnessChromosomeComparator(a_population1
042: .getConfiguration()));
043: //Then a new population is created and the fittest "a_new_population_size"
044: //chromosomes are added.
045: Chromosome[] chromosomes = (Chromosome[]) allChromosomes
046: .toArray(new Chromosome[0]);
047: Population mergedPopulation = new Population(a_population1
048: .getConfiguration(), a_new_population_size);
049: for (int i = 0; i < a_new_population_size
050: && i < chromosomes.length; i++) {
051: mergedPopulation.addChromosome(chromosomes[i]);
052: }
053: // Return the merged population.
054: // -----------------------------
055: return mergedPopulation;
056: } catch (InvalidConfigurationException iex) {
057: // This should never happen
058: throw new IllegalStateException(iex.getMessage());
059: }
060: }
061:
062: /**
063: * This class is used to sort the merged population chromosomes
064: * according to their fitness values. For convenience, the
065: * sorting is done in a reverse way, so this comparator
066: * returns 1 if the first chromosome has a LOWER fitness value.
067: *
068: * @author Henrique Goulart
069: * @since 2.0
070: */
071: private class FitnessChromosomeComparator implements Comparator {
072: private transient Configuration m_config;
073:
074: // Reference to the current FitnessEvaluator Object, used for comparing
075: // chromosomes.
076: private FitnessEvaluator m_fEvaluator;
077:
078: public FitnessChromosomeComparator(Configuration a_config) {
079: m_config = a_config;
080: m_fEvaluator = m_config.getFitnessEvaluator();
081: }
082:
083: /**
084: * Implements the compare method using the fitness function.
085: * The comparation is implemented in a reverse way to make the
086: * merging easier (the list of chromosomes is sorted in a
087: * descending fitness value order).
088: *
089: * @param a_o1 first IChromosome to compare
090: * @param a_o2 second IChromosome to compare
091: * @return @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
092: */
093: public int compare(final Object a_o1, final Object a_o2) {
094: // The two objects passed are always Chromosomes, so a cast must be made.
095: IChromosome chr1 = (IChromosome) a_o1;
096: IChromosome chr2 = (IChromosome) a_o2;
097: // Reverse comparison.
098: if (m_fEvaluator.isFitter(chr2.getFitnessValue(), chr1
099: .getFitnessValue())) {
100: return 1;
101: } else if (m_fEvaluator.isFitter(chr1.getFitnessValue(),
102: chr2.getFitnessValue())) {
103: return -1;
104: } else {
105: return 0;
106: }
107: }
108: }
109: }
|