Author: tn
Date: Thu Apr 5 22:08:45 2012
New Revision: 1310103
URL: http://svn.apache.org/viewvc?rev=1310103&view=rev
Log:
[MATH-775] Cleanup ListPopulation class after suggestion from Reid Hochstedler,
added more sanity checks/exceptions in ctor and setters, unit tests, hide and
protect internal representation.
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/ElitisticListPopulation.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/ListPopulation.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/Population.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/TournamentSelection.java
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/genetics/ListPopulationTest.java
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/ElitisticListPopulation.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/ElitisticListPopulation.java?rev=1310103&r1=1310102&r2=1310103&view=diff
==============================================================================
---
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/ElitisticListPopulation.java
(original)
+++
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/ElitisticListPopulation.java
Thu Apr 5 22:08:45 2012
@@ -74,14 +74,14 @@ public class ElitisticListPopulation ext
public Population nextGeneration() {
// initialize a new generation with the same parameters
ElitisticListPopulation nextGeneration =
- new ElitisticListPopulation(this.getPopulationLimit(),
this.getElitismRate());
+ new ElitisticListPopulation(getPopulationLimit(),
getElitismRate());
- List<Chromosome> oldChromosomes = this.getChromosomes();
+ final List<Chromosome> oldChromosomes = getChromosomeList();
Collections.sort(oldChromosomes);
// index of the last "not good enough" chromosome
- int boundIndex = (int) FastMath.ceil((1.0 - this.getElitismRate()) *
oldChromosomes.size());
- for (int i=boundIndex; i<oldChromosomes.size(); i++) {
+ int boundIndex = (int) FastMath.ceil((1.0 - getElitismRate()) *
oldChromosomes.size());
+ for (int i = boundIndex; i < oldChromosomes.size(); i++) {
nextGeneration.addChromosome(oldChromosomes.get(i));
}
return nextGeneration;
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/ListPopulation.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/ListPopulation.java?rev=1310103&r1=1310102&r2=1310103&view=diff
==============================================================================
---
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/ListPopulation.java
(original)
+++
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/ListPopulation.java
Thu Apr 5 22:08:45 2012
@@ -17,12 +17,16 @@
package org.apache.commons.math3.genetics;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.math3.exception.util.LocalizedFormats;
import org.apache.commons.math3.exception.NotPositiveException;
+import org.apache.commons.math3.exception.NullArgumentException;
import org.apache.commons.math3.exception.NumberIsTooLargeException;
+import org.apache.commons.math3.exception.NumberIsTooSmallException;
/**
* Population of chromosomes represented by a {@link List}.
@@ -38,63 +42,103 @@ public abstract class ListPopulation imp
/** maximal size of the population */
private int populationLimit;
-
/**
- * Creates a new ListPopulation instance.
+ * Creates a new ListPopulation instance and initializes its inner
chromosome list.
*
- * @param chromosomes list of chromosomes in the population
* @param populationLimit maximal size of the population
- * @throws NumberIsTooLargeException if the list of chromosomes exceeds
the population limit
* @throws NotPositiveException if the population limit is not a positive
number (< 1)
*/
- public ListPopulation(final List<Chromosome> chromosomes, final int
populationLimit) {
- if (chromosomes.size() > populationLimit) {
- throw new
NumberIsTooLargeException(LocalizedFormats.LIST_OF_CHROMOSOMES_BIGGER_THAN_POPULATION_SIZE,
- chromosomes.size(),
populationLimit, false);
- }
- if (populationLimit <= 0) {
- throw new
NotPositiveException(LocalizedFormats.POPULATION_LIMIT_NOT_POSITIVE,
populationLimit);
- }
-
- this.chromosomes = chromosomes;
- this.populationLimit = populationLimit;
+ public ListPopulation(final int populationLimit) {
+ this(Collections.<Chromosome> emptyList(), populationLimit);
}
/**
- * Creates a new ListPopulation instance and initializes its inner
chromosome list.
- *
+ * Creates a new ListPopulation instance.
+ * <p>Note: the chromosomes of the specified list are added to the
population.</p>
+ * @param chromosomes list of chromosomes to be added to the population
* @param populationLimit maximal size of the population
+ * @throws NullArgumentException if the list of chromosomes is {@code null}
* @throws NotPositiveException if the population limit is not a positive
number (< 1)
+ * @throws NumberIsTooLargeException if the list of chromosomes exceeds
the population limit
*/
- public ListPopulation(final int populationLimit) {
+ public ListPopulation(final List<Chromosome> chromosomes, final int
populationLimit) {
+ if (chromosomes == null) {
+ throw new NullArgumentException();
+ }
if (populationLimit <= 0) {
throw new
NotPositiveException(LocalizedFormats.POPULATION_LIMIT_NOT_POSITIVE,
populationLimit);
}
+ if (chromosomes.size() > populationLimit) {
+ throw new
NumberIsTooLargeException(LocalizedFormats.LIST_OF_CHROMOSOMES_BIGGER_THAN_POPULATION_SIZE,
+ chromosomes.size(),
populationLimit, false);
+ }
this.populationLimit = populationLimit;
this.chromosomes = new ArrayList<Chromosome>(populationLimit);
+ this.chromosomes.addAll(chromosomes);
}
/**
* Sets the list of chromosomes.
+ * <p>Note: this method removed all existing chromosomes in the population
and adds all chromosomes
+ * of the specified list to the population.</p>
* @param chromosomes the list of chromosomes
+ * @throws NullArgumentException if the list of chromosomes is {@code null}
+ * @throws NumberIsTooLargeException if the list of chromosomes exceeds
the population limit
+ * @deprecated use {@link #addChromosomes(Collection)} instead
*/
public void setChromosomes(final List<Chromosome> chromosomes) {
- this.chromosomes = chromosomes;
+ if (chromosomes == null) {
+ throw new NullArgumentException();
+ }
+ if (chromosomes.size() > populationLimit) {
+ throw new
NumberIsTooLargeException(LocalizedFormats.LIST_OF_CHROMOSOMES_BIGGER_THAN_POPULATION_SIZE,
+ chromosomes.size(),
populationLimit, false);
+ }
+ this.chromosomes.clear();
+ this.chromosomes.addAll(chromosomes);
}
/**
- * Access the list of chromosomes.
+ * Add a {@link Collection} of chromosomes to this {@link Population}.
+ * @param chromosomeColl a {@link Collection} of chromosomes
+ * @throws NumberIsTooLargeException if the population would exceed the
population limit when
+ * adding this chromosome
+ */
+ public void addChromosomes(final Collection<Chromosome> chromosomeColl) {
+ if (chromosomes.size() + chromosomeColl.size() > populationLimit) {
+ throw new
NumberIsTooLargeException(LocalizedFormats.LIST_OF_CHROMOSOMES_BIGGER_THAN_POPULATION_SIZE,
+ chromosomes.size(),
populationLimit, false);
+ }
+ this.chromosomes.addAll(chromosomeColl);
+ }
+
+ /**
+ * Returns an unmodifiable list of the chromosomes in this population.
* @return the list of chromosomes
*/
public List<Chromosome> getChromosomes() {
+ return Collections.unmodifiableList(chromosomes);
+ }
+
+ /**
+ * Access the list of chromosomes.
+ * @return the list of chromosomes
+ */
+ protected List<Chromosome> getChromosomeList() {
return chromosomes;
}
/**
* Add the given chromosome to the population.
* @param chromosome the chromosome to add.
+ * @throws NumberIsTooLargeException if the population would exceed the
{@code populationLimit} after
+ * adding this chromosome
*/
public void addChromosome(final Chromosome chromosome) {
+ if (chromosomes.size() >= populationLimit) {
+ throw new
NumberIsTooLargeException(LocalizedFormats.LIST_OF_CHROMOSOMES_BIGGER_THAN_POPULATION_SIZE,
+ chromosomes.size(),
populationLimit, false);
+ }
this.chromosomes.add(chromosome);
}
@@ -125,8 +169,17 @@ public abstract class ListPopulation imp
/**
* Sets the maximal population size.
* @param populationLimit maximal population size.
+ * @throws NotPositiveException if the population limit is not a positive
number (< 1)
+ * @throws NumberIsTooSmallException if the new population size is smaller
than the current number
+ * of chromosomes in the population
*/
public void setPopulationLimit(final int populationLimit) {
+ if (populationLimit <= 0) {
+ throw new
NotPositiveException(LocalizedFormats.POPULATION_LIMIT_NOT_POSITIVE,
populationLimit);
+ }
+ if (populationLimit < chromosomes.size()) {
+ throw new NumberIsTooSmallException(populationLimit,
chromosomes.size(), true);
+ }
this.populationLimit = populationLimit;
}
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/Population.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/Population.java?rev=1310103&r1=1310102&r2=1310103&view=diff
==============================================================================
---
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/Population.java
(original)
+++
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/Population.java
Thu Apr 5 22:08:45 2012
@@ -16,6 +16,7 @@
*/
package org.apache.commons.math3.genetics;
+
/**
* A collection of chromosomes that facilitates generational evolution.
*
@@ -44,6 +45,8 @@ public interface Population extends Iter
/**
* Add the given chromosome to the population.
* @param chromosome the chromosome to add.
+ * @throws org.apache.commons.math3.exception.NumberIsTooLargeException if
the population would exceed
+ * the population limit when adding this chromosome
*/
void addChromosome(Chromosome chromosome);
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/TournamentSelection.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/TournamentSelection.java?rev=1310103&r1=1310102&r2=1310103&view=diff
==============================================================================
---
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/TournamentSelection.java
(original)
+++
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/genetics/TournamentSelection.java
Thu Apr 5 22:08:45 2012
@@ -51,12 +51,12 @@ public class TournamentSelection impleme
* drawing {@link #arity} random chromosomes without replacement from the
* population, and then selecting the fittest chromosome among them.
*
- * @param population the population from which the chromosomes are choosen.
+ * @param population the population from which the chromosomes are chosen.
* @return the selected chromosomes.
*/
public ChromosomePair select(final Population population) {
return new ChromosomePair(tournament((ListPopulation) population),
- tournament((ListPopulation)population));
+ tournament((ListPopulation) population));
}
/**
Modified:
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/genetics/ListPopulationTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/genetics/ListPopulationTest.java?rev=1310103&r1=1310102&r2=1310103&view=diff
==============================================================================
---
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/genetics/ListPopulationTest.java
(original)
+++
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/genetics/ListPopulationTest.java
Thu Apr 5 22:08:45 2012
@@ -19,6 +19,9 @@ package org.apache.commons.math3.genetic
import java.util.ArrayList;
+import org.apache.commons.math3.exception.NotPositiveException;
+import org.apache.commons.math3.exception.NumberIsTooLargeException;
+import org.apache.commons.math3.exception.NumberIsTooSmallException;
import org.junit.Assert;
import org.junit.Test;
@@ -47,8 +50,7 @@ public class ListPopulationTest {
chromosomes.add(c2);
chromosomes.add(c3);
- ListPopulation population = new ListPopulation(chromosomes,10) {
-
+ ListPopulation population = new ListPopulation(chromosomes, 10) {
public Population nextGeneration() {
// not important
return null;
@@ -57,5 +59,125 @@ public class ListPopulationTest {
Assert.assertEquals(c3, population.getFittestChromosome());
}
+
+ @Test
+ public void testChromosomes() {
+ final ArrayList<Chromosome> chromosomes = new ArrayList<Chromosome> ();
+ chromosomes.add(new
DummyBinaryChromosome(BinaryChromosome.randomBinaryRepresentation(3)));
+ chromosomes.add(new
DummyBinaryChromosome(BinaryChromosome.randomBinaryRepresentation(3)));
+ chromosomes.add(new
DummyBinaryChromosome(BinaryChromosome.randomBinaryRepresentation(3)));
+
+ final ListPopulation population = new ListPopulation(10) {
+ public Population nextGeneration() {
+ // not important
+ return null;
+ }
+ };
+
+ population.addChromosomes(chromosomes);
+
+ Assert.assertEquals(chromosomes, population.getChromosomes());
+ Assert.assertEquals(chromosomes.toString(), population.toString());
+
+ population.setPopulationLimit(50);
+ Assert.assertEquals(50, population.getPopulationLimit());
+ }
+
+ @Test(expected = NotPositiveException.class)
+ public void testSetPopulationLimit() {
+ final ListPopulation population = new ListPopulation(10) {
+ public Population nextGeneration() {
+ // not important
+ return null;
+ }
+ };
+
+ population.setPopulationLimit(-50);
+ }
+
+ @Test(expected = NotPositiveException.class)
+ public void testConstructorPopulationLimitNotPositive() {
+ new ListPopulation(-10) {
+ public Population nextGeneration() {
+ // not important
+ return null;
+ }
+ };
+ }
+
+ @Test(expected = NotPositiveException.class)
+ public void testChromosomeListConstructorPopulationLimitNotPositive() {
+ final ArrayList<Chromosome> chromosomes = new ArrayList<Chromosome> ();
+ chromosomes.add(new
DummyBinaryChromosome(BinaryChromosome.randomBinaryRepresentation(3)));
+ new ListPopulation(chromosomes, -10) {
+ public Population nextGeneration() {
+ // not important
+ return null;
+ }
+ };
+ }
+ @Test(expected = NumberIsTooLargeException.class)
+ public void testConstructorListOfChromosomesBiggerThanPopulationSize() {
+ final ArrayList<Chromosome> chromosomes = new ArrayList<Chromosome> ();
+ chromosomes.add(new
DummyBinaryChromosome(BinaryChromosome.randomBinaryRepresentation(3)));
+ chromosomes.add(new
DummyBinaryChromosome(BinaryChromosome.randomBinaryRepresentation(3)));
+ chromosomes.add(new
DummyBinaryChromosome(BinaryChromosome.randomBinaryRepresentation(3)));
+ new ListPopulation(chromosomes, 1) {
+ public Population nextGeneration() {
+ // not important
+ return null;
+ }
+ };
+ }
+
+ @Test(expected=NumberIsTooLargeException.class)
+ public void testAddTooManyChromosomes() {
+ final ArrayList<Chromosome> chromosomes = new ArrayList<Chromosome> ();
+ chromosomes.add(new
DummyBinaryChromosome(BinaryChromosome.randomBinaryRepresentation(3)));
+ chromosomes.add(new
DummyBinaryChromosome(BinaryChromosome.randomBinaryRepresentation(3)));
+ chromosomes.add(new
DummyBinaryChromosome(BinaryChromosome.randomBinaryRepresentation(3)));
+
+ final ListPopulation population = new ListPopulation(2) {
+ public Population nextGeneration() {
+ // not important
+ return null;
+ }
+ };
+
+ population.addChromosomes(chromosomes);
+ }
+
+ @Test(expected=NumberIsTooLargeException.class)
+ public void testAddTooManyChromosomesSingleCall() {
+
+ final ListPopulation population = new ListPopulation(2) {
+ public Population nextGeneration() {
+ // not important
+ return null;
+ }
+ };
+
+ for (int i = 0; i <= population.getPopulationLimit(); i++) {
+ population.addChromosome(new
DummyBinaryChromosome(BinaryChromosome.randomBinaryRepresentation(3)));
+ }
+ }
+
+ @Test(expected=NumberIsTooSmallException.class)
+ public void testSetPopulationLimitTooSmall() {
+ final ArrayList<Chromosome> chromosomes = new ArrayList<Chromosome> ();
+ chromosomes.add(new
DummyBinaryChromosome(BinaryChromosome.randomBinaryRepresentation(3)));
+ chromosomes.add(new
DummyBinaryChromosome(BinaryChromosome.randomBinaryRepresentation(3)));
+ chromosomes.add(new
DummyBinaryChromosome(BinaryChromosome.randomBinaryRepresentation(3)));
+
+ final ListPopulation population = new ListPopulation(chromosomes, 3) {
+ public Population nextGeneration() {
+ // not important
+ return null;
+ }
+ };
+
+ population.setPopulationLimit(2);
+ }
+
}