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.ArrayList;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.Iterator;
23 import java.util.List;
24
25 import org.apache.commons.math4.legacy.exception.NotPositiveException;
26 import org.apache.commons.math4.legacy.exception.NullArgumentException;
27 import org.apache.commons.math4.legacy.exception.NumberIsTooLargeException;
28 import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
29 import org.apache.commons.math4.legacy.exception.util.LocalizedFormats;
30
31 /**
32 * Population of chromosomes represented by a {@link List}.
33 *
34 * @since 2.0
35 */
36 public abstract class ListPopulation implements Population {
37
38 /** List of chromosomes. */
39 private final List<Chromosome> chromosomes;
40
41 /** maximal size of the population. */
42 private int populationLimit;
43
44 /**
45 * Creates a new ListPopulation instance and initializes its inner chromosome list.
46 *
47 * @param populationLimit maximal size of the population
48 * @throws NotPositiveException if the population limit is not a positive number (< 1)
49 */
50 public ListPopulation(final int populationLimit) throws NotPositiveException {
51 this(Collections.<Chromosome>emptyList(), populationLimit);
52 }
53
54 /**
55 * Creates a new ListPopulation instance.
56 * <p>
57 * Note: the chromosomes of the specified list are added to the population.
58 *
59 * @param chromosomes list of chromosomes to be added to the population
60 * @param populationLimit maximal size of the population
61 * @throws NullArgumentException if the list of chromosomes is {@code null}
62 * @throws NotPositiveException if the population limit is not a positive number (< 1)
63 * @throws NumberIsTooLargeException if the list of chromosomes exceeds the population limit
64 */
65 public ListPopulation(final List<Chromosome> chromosomes, final int populationLimit)
66 throws NullArgumentException, NotPositiveException, NumberIsTooLargeException {
67
68 if (chromosomes == null) {
69 throw new NullArgumentException();
70 }
71 if (populationLimit <= 0) {
72 throw new NotPositiveException(LocalizedFormats.POPULATION_LIMIT_NOT_POSITIVE, populationLimit);
73 }
74 if (chromosomes.size() > populationLimit) {
75 throw new NumberIsTooLargeException(LocalizedFormats.LIST_OF_CHROMOSOMES_BIGGER_THAN_POPULATION_SIZE,
76 chromosomes.size(), populationLimit, false);
77 }
78 this.populationLimit = populationLimit;
79 this.chromosomes = new ArrayList<>(populationLimit);
80 this.chromosomes.addAll(chromosomes);
81 }
82
83 /**
84 * Add a {@link Collection} of chromosomes to this {@link Population}.
85 * @param chromosomeColl a {@link Collection} of chromosomes
86 * @throws NumberIsTooLargeException if the population would exceed the population limit when
87 * adding this chromosome
88 * @since 3.1
89 */
90 public void addChromosomes(final Collection<Chromosome> chromosomeColl) throws NumberIsTooLargeException {
91 if (chromosomes.size() + chromosomeColl.size() > populationLimit) {
92 throw new NumberIsTooLargeException(LocalizedFormats.LIST_OF_CHROMOSOMES_BIGGER_THAN_POPULATION_SIZE,
93 chromosomes.size(), populationLimit, false);
94 }
95 this.chromosomes.addAll(chromosomeColl);
96 }
97
98 /**
99 * Returns an unmodifiable list of the chromosomes in this population.
100 * @return the unmodifiable list of chromosomes
101 */
102 public List<Chromosome> getChromosomes() {
103 return Collections.unmodifiableList(chromosomes);
104 }
105
106 /**
107 * Access the list of chromosomes.
108 * @return the list of chromosomes
109 * @since 3.1
110 */
111 protected List<Chromosome> getChromosomeList() {
112 return chromosomes;
113 }
114
115 /**
116 * Add the given chromosome to the population.
117 *
118 * @param chromosome the chromosome to add.
119 * @throws NumberIsTooLargeException if the population would exceed the {@code populationLimit} after
120 * adding this chromosome
121 */
122 @Override
123 public void addChromosome(final Chromosome chromosome) throws NumberIsTooLargeException {
124 if (chromosomes.size() >= populationLimit) {
125 throw new NumberIsTooLargeException(LocalizedFormats.LIST_OF_CHROMOSOMES_BIGGER_THAN_POPULATION_SIZE,
126 chromosomes.size(), populationLimit, false);
127 }
128 this.chromosomes.add(chromosome);
129 }
130
131 /**
132 * Access the fittest chromosome in this population.
133 * @return the fittest chromosome.
134 */
135 @Override
136 public Chromosome getFittestChromosome() {
137 // best so far
138 Chromosome bestChromosome = this.chromosomes.get(0);
139 for (Chromosome chromosome : this.chromosomes) {
140 if (chromosome.compareTo(bestChromosome) > 0) {
141 // better chromosome found
142 bestChromosome = chromosome;
143 }
144 }
145 return bestChromosome;
146 }
147
148 /**
149 * Access the maximum population size.
150 * @return the maximum population size.
151 */
152 @Override
153 public int getPopulationLimit() {
154 return this.populationLimit;
155 }
156
157 /**
158 * Sets the maximal population size.
159 * @param populationLimit maximal population size.
160 * @throws NotPositiveException if the population limit is not a positive number (< 1)
161 * @throws NumberIsTooSmallException if the new population size is smaller than the current number
162 * of chromosomes in the population
163 */
164 public void setPopulationLimit(final int populationLimit) throws NotPositiveException, NumberIsTooSmallException {
165 if (populationLimit <= 0) {
166 throw new NotPositiveException(LocalizedFormats.POPULATION_LIMIT_NOT_POSITIVE, populationLimit);
167 }
168 if (populationLimit < chromosomes.size()) {
169 throw new NumberIsTooSmallException(populationLimit, chromosomes.size(), true);
170 }
171 this.populationLimit = populationLimit;
172 }
173
174 /**
175 * Access the current population size.
176 * @return the current population size.
177 */
178 @Override
179 public int getPopulationSize() {
180 return this.chromosomes.size();
181 }
182
183 /**
184 * {@inheritDoc}
185 */
186 @Override
187 public String toString() {
188 return this.chromosomes.toString();
189 }
190
191 /**
192 * Returns an iterator over the unmodifiable list of chromosomes.
193 * <p>Any call to {@link Iterator#remove()} will result in a {@link UnsupportedOperationException}.</p>
194 *
195 * @return chromosome iterator
196 */
197 @Override
198 public Iterator<Chromosome> iterator() {
199 return getChromosomes().iterator();
200 }
201 }