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    import org.apache.commons.math.util.FastMath;
023    
024    /**
025     * Population of chromosomes which uses elitism (certain percentace of the best
026     * chromosomes is directly copied to the next generation).
027     *
028     * @version $Revision: 990655 $ $Date: 2010-08-29 23:49:40 +0200 (dim. 29 ao??t 2010) $
029     * @since 2.0
030     */
031    public class ElitisticListPopulation extends ListPopulation {
032    
033        /** percentage of chromosomes copied to the next generation */
034        private double elitismRate = 0.9;
035    
036        /**
037         * Creates a new ElitisticListPopulation instance.
038         *
039         * @param chromosomes
040         *            list of chromosomes in the population
041         * @param populationLimit
042         *            maximal size of the population
043         * @param elitismRate
044         *            how many best chromosomes will be directly transferred to the
045         *            next generation [in %]
046         */
047        public ElitisticListPopulation(List<Chromosome> chromosomes, int populationLimit, double elitismRate) {
048            super(chromosomes, populationLimit);
049            this.elitismRate = elitismRate;
050        }
051    
052        /**
053         * Creates a new ListPopulation instance and initializes its inner
054         * chromosome list.
055         *
056         * @param populationLimit maximal size of the population
057         * @param elitismRate
058         *            how many best chromosomes will be directly transferred to the
059         *            next generation [in %]
060         */
061        public ElitisticListPopulation(int populationLimit, double elitismRate) {
062            super(populationLimit);
063            this.elitismRate = elitismRate;
064        }
065    
066        /**
067         * Start the population for the next generation. The
068         * <code>{@link #elitismRate}<code> percents of the best
069         * chromosomes are directly copied to the next generation.
070         *
071         * @return the beginnings of the next generation.
072         */
073        public Population nextGeneration() {
074            // initialize a new generation with the same parameters
075            ElitisticListPopulation nextGeneration = new ElitisticListPopulation(this.getPopulationLimit(), this.getElitismRate());
076    
077            List<Chromosome> oldChromosomes = this.getChromosomes();
078            Collections.sort(oldChromosomes);
079    
080            // index of the last "not good enough" chromosome
081            int boundIndex = (int) FastMath.ceil((1.0 - this.getElitismRate()) * oldChromosomes.size());
082            for (int i=boundIndex; i<oldChromosomes.size(); i++) {
083                nextGeneration.addChromosome(oldChromosomes.get(i));
084            }
085            return nextGeneration;
086        }
087    
088        /**
089         * Sets the elitism rate, i.e. how many best chromosomes will be directly
090         * transferred to the next generation [in %].
091         *
092         * @param elitismRate
093         *            how many best chromosomes will be directly transferred to the
094         *            next generation [in %]
095         */
096        public void setElitismRate(double elitismRate) {
097            if (elitismRate < 0 || elitismRate > 1)
098                throw new IllegalArgumentException("Elitism rate has to be in [0,1]");
099            this.elitismRate = elitismRate;
100        }
101    
102        /**
103         * Access the elitism rate.
104         * @return the elitism rate
105         */
106        public double getElitismRate() {
107            return this.elitismRate;
108        }
109    
110    }