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.math4.legacy.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.math4.legacy.exception.NotPositiveException; 026import org.apache.commons.math4.legacy.exception.NullArgumentException; 027import org.apache.commons.math4.legacy.exception.NumberIsTooLargeException; 028import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException; 029import org.apache.commons.math4.legacy.exception.util.LocalizedFormats; 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 final 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<>(populationLimit); 080 this.chromosomes.addAll(chromosomes); 081 } 082 083 /** 084 * Add a {@link Collection} of chromosomes to this {@link Population}. 085 * @param chromosomeColl a {@link Collection} of chromosomes 086 * @throws NumberIsTooLargeException if the population would exceed the population limit when 087 * adding this chromosome 088 * @since 3.1 089 */ 090 public void addChromosomes(final Collection<Chromosome> chromosomeColl) throws NumberIsTooLargeException { 091 if (chromosomes.size() + chromosomeColl.size() > populationLimit) { 092 throw new NumberIsTooLargeException(LocalizedFormats.LIST_OF_CHROMOSOMES_BIGGER_THAN_POPULATION_SIZE, 093 chromosomes.size(), populationLimit, false); 094 } 095 this.chromosomes.addAll(chromosomeColl); 096 } 097 098 /** 099 * 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}