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.math3.genetics;
018
019 import java.util.Collections;
020 import java.util.List;
021
022 import org.apache.commons.math3.exception.NotPositiveException;
023 import org.apache.commons.math3.exception.NullArgumentException;
024 import org.apache.commons.math3.exception.NumberIsTooLargeException;
025 import org.apache.commons.math3.exception.OutOfRangeException;
026 import org.apache.commons.math3.exception.util.LocalizedFormats;
027 import org.apache.commons.math3.util.FastMath;
028
029 /**
030 * Population of chromosomes which uses elitism (certain percentage of the best
031 * chromosomes is directly copied to the next generation).
032 *
033 * @version $Id: ElitisticListPopulation.java 1416643 2012-12-03 19:37:14Z tn $
034 * @since 2.0
035 */
036 public class ElitisticListPopulation extends ListPopulation {
037
038 /** percentage of chromosomes copied to the next generation */
039 private double elitismRate = 0.9;
040
041 /**
042 * Creates a new {@link ElitisticListPopulation} instance.
043 *
044 * @param chromosomes list of chromosomes in the population
045 * @param populationLimit maximal size of the population
046 * @param elitismRate how many best chromosomes will be directly transferred to the next generation [in %]
047 * @throws NullArgumentException if the list of chromosomes is {@code null}
048 * @throws NotPositiveException if the population limit is not a positive number (< 1)
049 * @throws NumberIsTooLargeException if the list of chromosomes exceeds the population limit
050 * @throws OutOfRangeException if the elitism rate is outside the [0, 1] range
051 */
052 public ElitisticListPopulation(final List<Chromosome> chromosomes, final int populationLimit,
053 final double elitismRate)
054 throws NullArgumentException, NotPositiveException, NumberIsTooLargeException, OutOfRangeException {
055
056 super(chromosomes, populationLimit);
057 setElitismRate(elitismRate);
058
059 }
060
061 /**
062 * Creates a new {@link ElitisticListPopulation} instance and initializes its inner chromosome list.
063 *
064 * @param populationLimit maximal size of the population
065 * @param elitismRate how many best chromosomes will be directly transferred to the next generation [in %]
066 * @throws NotPositiveException if the population limit is not a positive number (< 1)
067 * @throws OutOfRangeException if the elitism rate is outside the [0, 1] range
068 */
069 public ElitisticListPopulation(final int populationLimit, final double elitismRate)
070 throws NotPositiveException, OutOfRangeException {
071
072 super(populationLimit);
073 setElitismRate(elitismRate);
074
075 }
076
077 /**
078 * Start the population for the next generation. The <code>{@link #elitismRate}</code>
079 * percents of the best chromosomes are directly copied to the next generation.
080 *
081 * @return the beginnings of the next generation.
082 */
083 public Population nextGeneration() {
084 // initialize a new generation with the same parameters
085 ElitisticListPopulation nextGeneration =
086 new ElitisticListPopulation(getPopulationLimit(), getElitismRate());
087
088 final List<Chromosome> oldChromosomes = getChromosomeList();
089 Collections.sort(oldChromosomes);
090
091 // index of the last "not good enough" chromosome
092 int boundIndex = (int) FastMath.ceil((1.0 - getElitismRate()) * oldChromosomes.size());
093 for (int i = boundIndex; i < oldChromosomes.size(); i++) {
094 nextGeneration.addChromosome(oldChromosomes.get(i));
095 }
096 return nextGeneration;
097 }
098
099 /**
100 * Sets the elitism rate, i.e. how many best chromosomes will be directly transferred to the next generation [in %].
101 *
102 * @param elitismRate how many best chromosomes will be directly transferred to the next generation [in %]
103 * @throws OutOfRangeException if the elitism rate is outside the [0, 1] range
104 */
105 public void setElitismRate(final double elitismRate) throws OutOfRangeException {
106 if (elitismRate < 0 || elitismRate > 1) {
107 throw new OutOfRangeException(LocalizedFormats.ELITISM_RATE, elitismRate, 0, 1);
108 }
109 this.elitismRate = elitismRate;
110 }
111
112 /**
113 * Access the elitism rate.
114 * @return the elitism rate
115 */
116 public double getElitismRate() {
117 return this.elitismRate;
118 }
119
120 }