View Javadoc
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 (&lt; 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 (&lt; 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 (&lt; 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 }