1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.math4.legacy.genetics;
18
19 import java.util.Collections;
20 import java.util.List;
21
22 import org.apache.commons.math4.legacy.exception.NotPositiveException;
23 import org.apache.commons.math4.legacy.exception.NullArgumentException;
24 import org.apache.commons.math4.legacy.exception.NumberIsTooLargeException;
25 import org.apache.commons.math4.legacy.exception.OutOfRangeException;
26 import org.apache.commons.math4.legacy.exception.util.LocalizedFormats;
27 import org.apache.commons.math4.core.jdkmath.JdkMath;
28
29 /**
30 * Population of chromosomes which uses elitism (certain percentage of the best
31 * chromosomes is directly copied to the next generation).
32 *
33 * @since 2.0
34 */
35 public class ElitisticListPopulation extends ListPopulation {
36
37 /** percentage of chromosomes copied to the next generation. */
38 private double elitismRate = 0.9;
39
40 /**
41 * Creates a new {@link ElitisticListPopulation} instance.
42 *
43 * @param chromosomes list of chromosomes in the population
44 * @param populationLimit maximal size of the population
45 * @param elitismRate how many best chromosomes will be directly transferred to the next generation [in %]
46 * @throws NullArgumentException if the list of chromosomes is {@code null}
47 * @throws NotPositiveException if the population limit is not a positive number (< 1)
48 * @throws NumberIsTooLargeException if the list of chromosomes exceeds the population limit
49 * @throws OutOfRangeException if the elitism rate is outside the [0, 1] range
50 */
51 public ElitisticListPopulation(final List<Chromosome> chromosomes, final int populationLimit,
52 final double elitismRate)
53 throws NullArgumentException, NotPositiveException, NumberIsTooLargeException, OutOfRangeException {
54
55 super(chromosomes, populationLimit);
56 setElitismRate(elitismRate);
57 }
58
59 /**
60 * Creates a new {@link ElitisticListPopulation} instance and initializes its inner chromosome list.
61 *
62 * @param populationLimit maximal size of the population
63 * @param elitismRate how many best chromosomes will be directly transferred to the next generation [in %]
64 * @throws NotPositiveException if the population limit is not a positive number (< 1)
65 * @throws OutOfRangeException if the elitism rate is outside the [0, 1] range
66 */
67 public ElitisticListPopulation(final int populationLimit, final double elitismRate)
68 throws NotPositiveException, OutOfRangeException {
69
70 super(populationLimit);
71 setElitismRate(elitismRate);
72 }
73
74 /**
75 * Start the population for the next generation. The <code>{@link #elitismRate}</code>
76 * percents of the best chromosomes are directly copied to the next generation.
77 *
78 * @return the beginnings of the next generation.
79 */
80 @Override
81 public Population nextGeneration() {
82 // initialize a new generation with the same parameters
83 ElitisticListPopulation nextGeneration =
84 new ElitisticListPopulation(getPopulationLimit(), getElitismRate());
85
86 final List<Chromosome> oldChromosomes = getChromosomeList();
87 Collections.sort(oldChromosomes);
88
89 // index of the last "not good enough" chromosome
90 int boundIndex = (int) JdkMath.ceil((1.0 - getElitismRate()) * oldChromosomes.size());
91 for (int i = boundIndex; i < oldChromosomes.size(); i++) {
92 nextGeneration.addChromosome(oldChromosomes.get(i));
93 }
94 return nextGeneration;
95 }
96
97 /**
98 * Sets the elitism rate, i.e. how many best chromosomes will be directly transferred to the next generation [in %].
99 *
100 * @param elitismRate how many best chromosomes will be directly transferred to the next generation [in %]
101 * @throws OutOfRangeException if the elitism rate is outside the [0, 1] range
102 */
103 public void setElitismRate(final double elitismRate) throws OutOfRangeException {
104 if (elitismRate < 0 || elitismRate > 1) {
105 throw new OutOfRangeException(LocalizedFormats.ELITISM_RATE, elitismRate, 0, 1);
106 }
107 this.elitismRate = elitismRate;
108 }
109
110 /**
111 * Access the elitism rate.
112 * @return the elitism rate
113 */
114 public double getElitismRate() {
115 return this.elitismRate;
116 }
117 }