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.ArrayList;
020 import java.util.Collection;
021 import java.util.Collections;
022 import java.util.Iterator;
023 import java.util.List;
024
025 import org.apache.commons.math3.exception.util.LocalizedFormats;
026 import org.apache.commons.math3.exception.NotPositiveException;
027 import org.apache.commons.math3.exception.NullArgumentException;
028 import org.apache.commons.math3.exception.NumberIsTooLargeException;
029 import org.apache.commons.math3.exception.NumberIsTooSmallException;
030
031 /**
032 * Population of chromosomes represented by a {@link List}.
033 *
034 * @since 2.0
035 * @version $Id: ListPopulation.java 1422195 2012-12-15 06:45:18Z psteitz $
036 */
037 public abstract class ListPopulation implements Population {
038
039 /** List of chromosomes */
040 private List<Chromosome> chromosomes;
041
042 /** maximal size of the population */
043 private int populationLimit;
044
045 /**
046 * Creates a new ListPopulation instance and initializes its inner chromosome list.
047 *
048 * @param populationLimit maximal size of the population
049 * @throws NotPositiveException if the population limit is not a positive number (< 1)
050 */
051 public ListPopulation(final int populationLimit) throws NotPositiveException {
052 this(Collections.<Chromosome> emptyList(), populationLimit);
053 }
054
055 /**
056 * Creates a new ListPopulation instance.
057 * <p>
058 * Note: the chromosomes of the specified list are added to the population.
059 *
060 * @param chromosomes list of chromosomes to be added to the population
061 * @param populationLimit maximal size of the population
062 * @throws NullArgumentException if the list of chromosomes is {@code null}
063 * @throws NotPositiveException if the population limit is not a positive number (< 1)
064 * @throws NumberIsTooLargeException if the list of chromosomes exceeds the population limit
065 */
066 public ListPopulation(final List<Chromosome> chromosomes, final int populationLimit)
067 throws NullArgumentException, NotPositiveException, NumberIsTooLargeException {
068
069 if (chromosomes == null) {
070 throw new NullArgumentException();
071 }
072 if (populationLimit <= 0) {
073 throw new NotPositiveException(LocalizedFormats.POPULATION_LIMIT_NOT_POSITIVE, populationLimit);
074 }
075 if (chromosomes.size() > populationLimit) {
076 throw new NumberIsTooLargeException(LocalizedFormats.LIST_OF_CHROMOSOMES_BIGGER_THAN_POPULATION_SIZE,
077 chromosomes.size(), populationLimit, false);
078 }
079 this.populationLimit = populationLimit;
080 this.chromosomes = new ArrayList<Chromosome>(populationLimit);
081 this.chromosomes.addAll(chromosomes);
082 }
083
084 /**
085 * Sets the list of chromosomes.
086 * <p>
087 * Note: this method removed all existing chromosomes in the population and adds all chromosomes
088 * of the specified list to the population.
089 *
090 * @param chromosomes the list of chromosomes
091 * @throws NullArgumentException if the list of chromosomes is {@code null}
092 * @throws NumberIsTooLargeException if the list of chromosomes exceeds the population limit
093 * @deprecated use {@link #addChromosomes(Collection)} instead
094 */
095 @Deprecated
096 public void setChromosomes(final List<Chromosome> chromosomes)
097 throws NullArgumentException, NumberIsTooLargeException {
098
099 if (chromosomes == null) {
100 throw new NullArgumentException();
101 }
102 if (chromosomes.size() > populationLimit) {
103 throw new NumberIsTooLargeException(LocalizedFormats.LIST_OF_CHROMOSOMES_BIGGER_THAN_POPULATION_SIZE,
104 chromosomes.size(), populationLimit, false);
105 }
106 this.chromosomes.clear();
107 this.chromosomes.addAll(chromosomes);
108 }
109
110 /**
111 * Add a {@link Collection} of chromosomes to this {@link Population}.
112 * @param chromosomeColl a {@link Collection} of chromosomes
113 * @throws NumberIsTooLargeException if the population would exceed the population limit when
114 * adding this chromosome
115 * @since 3.1
116 */
117 public void addChromosomes(final Collection<Chromosome> chromosomeColl) throws NumberIsTooLargeException {
118 if (chromosomes.size() + chromosomeColl.size() > populationLimit) {
119 throw new NumberIsTooLargeException(LocalizedFormats.LIST_OF_CHROMOSOMES_BIGGER_THAN_POPULATION_SIZE,
120 chromosomes.size(), populationLimit, false);
121 }
122 this.chromosomes.addAll(chromosomeColl);
123 }
124
125 /**
126 * Returns an unmodifiable list of the chromosomes in this population.
127 * @return the unmodifiable list of chromosomes
128 */
129 public List<Chromosome> getChromosomes() {
130 return Collections.unmodifiableList(chromosomes);
131 }
132
133 /**
134 * Access the list of chromosomes.
135 * @return the list of chromosomes
136 * @since 3.1
137 */
138 protected List<Chromosome> getChromosomeList() {
139 return chromosomes;
140 }
141
142 /**
143 * Add the given chromosome to the population.
144 *
145 * @param chromosome the chromosome to add.
146 * @throws NumberIsTooLargeException if the population would exceed the {@code populationLimit} after
147 * adding this chromosome
148 */
149 public void addChromosome(final Chromosome chromosome) throws NumberIsTooLargeException {
150 if (chromosomes.size() >= populationLimit) {
151 throw new NumberIsTooLargeException(LocalizedFormats.LIST_OF_CHROMOSOMES_BIGGER_THAN_POPULATION_SIZE,
152 chromosomes.size(), populationLimit, false);
153 }
154 this.chromosomes.add(chromosome);
155 }
156
157 /**
158 * Access the fittest chromosome in this population.
159 * @return the fittest chromosome.
160 */
161 public Chromosome getFittestChromosome() {
162 // best so far
163 Chromosome bestChromosome = this.chromosomes.get(0);
164 for (Chromosome chromosome : this.chromosomes) {
165 if (chromosome.compareTo(bestChromosome) > 0) {
166 // better chromosome found
167 bestChromosome = chromosome;
168 }
169 }
170 return bestChromosome;
171 }
172
173 /**
174 * Access the maximum population size.
175 * @return the maximum population size.
176 */
177 public int getPopulationLimit() {
178 return this.populationLimit;
179 }
180
181 /**
182 * Sets the maximal population size.
183 * @param populationLimit maximal population size.
184 * @throws NotPositiveException if the population limit is not a positive number (< 1)
185 * @throws NumberIsTooSmallException if the new population size is smaller than the current number
186 * of chromosomes in the population
187 */
188 public void setPopulationLimit(final int populationLimit) throws NotPositiveException, NumberIsTooSmallException {
189 if (populationLimit <= 0) {
190 throw new NotPositiveException(LocalizedFormats.POPULATION_LIMIT_NOT_POSITIVE, populationLimit);
191 }
192 if (populationLimit < chromosomes.size()) {
193 throw new NumberIsTooSmallException(populationLimit, chromosomes.size(), true);
194 }
195 this.populationLimit = populationLimit;
196 }
197
198 /**
199 * Access the current population size.
200 * @return the current population size.
201 */
202 public int getPopulationSize() {
203 return this.chromosomes.size();
204 }
205
206 /**
207 * {@inheritDoc}
208 */
209 @Override
210 public String toString() {
211 return this.chromosomes.toString();
212 }
213
214 /**
215 * Returns an iterator over the unmodifiable list of chromosomes.
216 * <p>Any call to {@link Iterator#remove()} will result in a {@link UnsupportedOperationException}.</p>
217 *
218 * @return chromosome iterator
219 */
220 public Iterator<Chromosome> iterator() {
221 return getChromosomes().iterator();
222 }
223 }