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