001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.math.genetics;
018    
019    import java.util.Collections;
020    import java.util.List;
021    
022    /**
023     * Population of chromosomes which uses elitism (certain percentace of the best
024     * chromosomes is directly copied to the next generation).
025     * 
026     * @version $Revision: 799857 $ $Date: 2009-08-01 09:07:12 -0400 (Sat, 01 Aug 2009) $
027     * @since 2.0
028     */
029    public class ElitisticListPopulation extends ListPopulation {
030        
031        /** percentage of chromosomes copied to the next generation */
032        private double elitismRate = 0.9;
033    
034        /**
035         * Creates a new ElitisticListPopulation instance.
036         * 
037         * @param chromosomes
038         *            list of chromosomes in the population
039         * @param populationLimit
040         *            maximal size of the population
041         * @param elitismRate
042         *            how many best chromosomes will be directly transferred to the
043         *            next generation [in %]
044         */
045        public ElitisticListPopulation(List<Chromosome> chromosomes, int populationLimit, double elitismRate) {
046            super(chromosomes, populationLimit);
047            this.elitismRate = elitismRate;
048        }
049    
050        /**
051         * Creates a new ListPopulation instance and initializes its inner
052         * chromosome list.
053         * 
054         * @param populationLimit maximal size of the population
055         * @param elitismRate
056         *            how many best chromosomes will be directly transferred to the
057         *            next generation [in %] 
058         */
059        public ElitisticListPopulation(int populationLimit, double elitismRate) {
060            super(populationLimit);
061            this.elitismRate = elitismRate;
062        }
063    
064        /**
065         * Start the population for the next generation. The
066         * <code>{@link #elitismRate}<code> percents of the best 
067         * chromosomes are directly copied to the next generation.
068         * 
069         * @return the beginnings of the next generation.
070         */
071        public Population nextGeneration() {
072            // initialize a new generation with the same parameters
073            ElitisticListPopulation nextGeneration = new ElitisticListPopulation(this.getPopulationLimit(), this.getElitismRate());
074            
075            List<Chromosome> oldChromosomes = this.getChromosomes();
076            Collections.sort(oldChromosomes);
077            
078            // index of the last "not good enough" chromosome 
079            int boundIndex = (int) Math.ceil((1.0 - this.getElitismRate()) * oldChromosomes.size());
080            for (int i=boundIndex; i<oldChromosomes.size(); i++) {
081                nextGeneration.addChromosome(oldChromosomes.get(i));
082            }
083            return nextGeneration;
084        }
085    
086        /**
087         * Sets the elitism rate, i.e. how many best chromosomes will be directly
088         * transferred to the next generation [in %].
089         * 
090         * @param elitismRate
091         *            how many best chromosomes will be directly transferred to the
092         *            next generation [in %]
093         */
094        public void setElitismRate(double elitismRate) {
095            if (elitismRate < 0 || elitismRate > 1)
096                throw new IllegalArgumentException("Elitism rate has to be in [0,1]");
097            this.elitismRate = elitismRate;
098        }
099    
100        /**
101         * Access the elitism rate.
102         * @return the elitism rate
103         */
104        public double getElitismRate() {
105            return this.elitismRate;
106        }
107    
108    }