Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>org.uncommons.watchmaker</groupId>
<artifactId>watchmaker</artifactId>
<version>0.7.2</version>
<version>0.7.2-qumul</version>
</parent>
<artifactId>watchmaker-examples</artifactId>

Expand Down
4 changes: 2 additions & 2 deletions framework/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@
<parent>
<groupId>org.uncommons.watchmaker</groupId>
<artifactId>watchmaker</artifactId>
<version>0.7.2</version>
<version>0.7.2-qumul</version>
</parent>
<artifactId>watchmaker-framework</artifactId>

<dependencies>
<dependency>
<groupId>org.uncommons.maths</groupId>
<artifactId>uncommons-maths</artifactId>
<version>1.2.2</version>
<version>1.2.2a</version>
</dependency>
<dependency>
<groupId>com.google.collections</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,8 @@ public static <T> PopulationData<T> getPopulationData(List<EvaluatedCandidate<T>
int iterationNumber,
long startTime)
{
DataSet stats = new DataSet(evaluatedPopulation.size());
for (EvaluatedCandidate<T> candidate : evaluatedPopulation)
{
stats.addValue(candidate.getFitness());
}
return new PopulationData<T>(evaluatedPopulation.get(0).getCandidate(),
evaluatedPopulation.get(0).getFitness(),
stats.getArithmeticMean(),
stats.getStandardDeviation(),
return new PopulationData<T>(evaluatedPopulation,
naturalFitness,
stats.getSize(),
eliteCount,
iterationNumber,
System.currentTimeMillis() - startTime);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
//=============================================================================
package org.uncommons.watchmaker.framework;

import org.uncommons.maths.statistics.DataSet;

import java.util.List;

/**
* Immutable data object containing statistics about the state of
* an evolved population and a reference to the fittest candidate
Expand All @@ -26,6 +30,7 @@
*/
public final class PopulationData<T>
{
private final List<EvaluatedCandidate<T>> evaluatedPopulation;
private final T bestCandidate;
private final double bestCandidateFitness;
private final double meanFitness;
Expand All @@ -37,6 +42,8 @@ public final class PopulationData<T>
private final long elapsedTime;

/**
* Constructor only
* @param evaluatedPopulation List of all candidates
* @param bestCandidate The fittest candidate present in the population.
* @param bestCandidateFitness The fitness score for the fittest candidate
* in the population.
Expand All @@ -45,23 +52,25 @@ public final class PopulationData<T>
* @param fitnessStandardDeviation A measure of the variation in fitness
* scores.
* @param naturalFitness True if higher fitness scores are better, false
* otherwise.
* otherwise.
* @param populationSize The number of individuals in the population.
* @param eliteCount The number of candidates preserved via elitism.
* @param generationNumber The (zero-based) number of the last generation
* that was processed.
* @param elapsedTime The number of milliseconds since the start of the
*/
public PopulationData(T bestCandidate,
double bestCandidateFitness,
double meanFitness,
double fitnessStandardDeviation,
boolean naturalFitness,
int populationSize,
int eliteCount,
int generationNumber,
long elapsedTime)
public PopulationData(
List<EvaluatedCandidate<T>> evaluatedPopulation, T bestCandidate,
double bestCandidateFitness,
double meanFitness,
double fitnessStandardDeviation,
boolean naturalFitness,
int populationSize,
int eliteCount,
int generationNumber,
long elapsedTime)
{
this.evaluatedPopulation = evaluatedPopulation;
this.bestCandidate = bestCandidate;
this.bestCandidateFitness = bestCandidateFitness;
this.meanFitness = meanFitness;
Expand All @@ -72,7 +81,48 @@ public PopulationData(T bestCandidate,
this.generationNumber = generationNumber;
this.elapsedTime = elapsedTime;
}
/**
* @param evaluatedPopulation List of all candidates, the list should be
* ordered by fitness for the the best candidate to be meaningfull.
* Otherwise consider making your own statistics and use the other
* constructor
* @param naturalFitness True if higher fitness scores are better, false otherwise.
* @param eliteCount The number of candidates preserved via elitism.
* @param generationNumber The (zero-based) number of the last generation that was processed.
* @param elapsedTime The number of milliseconds since the start of the
*/
public PopulationData(List<EvaluatedCandidate<T>> evaluatedPopulation,
boolean naturalFitness,
int eliteCount,
int generationNumber,
long elapsedTime)
{
DataSet stats = new DataSet(evaluatedPopulation.size());
for (EvaluatedCandidate<T> candidate : evaluatedPopulation)
{
stats.addValue(candidate.getFitness());
}

this.bestCandidate = evaluatedPopulation.get(0).getCandidate();
this.bestCandidateFitness = evaluatedPopulation.get(0).getFitness();
this.meanFitness = stats.getArithmeticMean();
this.fitnessStandardDeviation = stats.getStandardDeviation();
this.naturalFitness = naturalFitness;
this.populationSize = stats.getSize();
this.eliteCount = eliteCount;
this.generationNumber = generationNumber;
this.elapsedTime = elapsedTime;
this.evaluatedPopulation = evaluatedPopulation;
}

/**
* @return The list of all candidates in the population at this stage,
* be carefull in the references you hold of this and don't assume this
* list to remain unchanged over generations.
*/
public List<EvaluatedCandidate<T>> getEvaluatedPopulation() {
return evaluatedPopulation;
}

/**
* @return The fittest candidate present in the population.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import org.uncommons.watchmaker.framework.PopulationData;
import org.uncommons.watchmaker.framework.TerminationCondition;

import java.util.ArrayList;

/**
* Unit test for termination condition that checks the time taken so far by the
* evolutionary algorithm.
Expand All @@ -30,9 +32,9 @@ public class ElapsedTimeTest
public void testElapsedTimes()
{
TerminationCondition condition = new ElapsedTime(1000);
PopulationData<Object> data = new PopulationData<Object>(new Object(), 0, 0, 0, true, 2, 0, 0, 100);
PopulationData<Object> data = new PopulationData<Object>(new ArrayList(), new Object(), 0, 0, 0, true, 2, 0, 0, 100);
assert !condition.shouldTerminate(data) : "Should not terminate before timeout.";
data = new PopulationData<Object>(new Object(), 0, 0, 0, true, 2, 0, 0, 1000);
data = new PopulationData<Object>(new ArrayList(), new Object(), 0, 0, 0, true, 2, 0, 0, 1000);
assert condition.shouldTerminate(data) : "Should terminate after timeout.";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import org.uncommons.watchmaker.framework.PopulationData;
import org.uncommons.watchmaker.framework.TerminationCondition;

import java.util.ArrayList;

/**
* Unit test for termination condition that checks the number of evolved generations.
* @author Daniel Dyer
Expand All @@ -29,10 +31,10 @@ public class GenerationCountTest
public void testGenerationCounts()
{
TerminationCondition condition = new GenerationCount(5);
PopulationData<Object> data = new PopulationData<Object>(new Object(), 0, 0, 0, true, 2, 0, 3, 100);
PopulationData<Object> data = new PopulationData<Object>(new ArrayList(), new Object(), 0, 0, 0, true, 2, 0, 3, 100);
// Generation number 3 is the 4th generation (generation numbers are zero-based).
assert !condition.shouldTerminate(data) : "Should not terminate after 4th generation.";
data = new PopulationData<Object>(new Object(), 0, 0, 0, true, 2, 0, 4, 100);
data = new PopulationData<Object>(new ArrayList(), new Object(), 0, 0, 0, true, 2, 0, 4, 100);
// Generation number 4 is the 5th generation (generation numbers are zero-based).
assert condition.shouldTerminate(data) : "Should terminate after 5th generation.";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import org.uncommons.watchmaker.framework.PopulationData;
import org.uncommons.watchmaker.framework.TerminationCondition;

import java.util.ArrayList;

/**
* Unit test for the {@link Stagnation} termination condition.
* @author Daniel Dyer
Expand All @@ -29,27 +31,27 @@ public class StagnationTest
public void testFittestCandidateStagnation()
{
TerminationCondition stagnation = new Stagnation(2, true);
PopulationData<Object> data = new PopulationData<Object>(new Object(), 2, 1, 0.1, true, 10, 0, 0, 1);
PopulationData<Object> data = new PopulationData<Object>(new ArrayList(), new Object(), 2, 1, 0.1, true, 10, 0, 0, 1);
assert !stagnation.shouldTerminate(data) : "Stagnation should not be triggered for at least 2 more generations.";
// Best doesn't improve even though mean does.
data = new PopulationData<Object>(new Object(), 1.8, 1.2, 0.1, true, 10, 0, 1, 2);
data = new PopulationData<Object>(new ArrayList(), new Object(), 1.8, 1.2, 0.1, true, 10, 0, 1, 2);
assert !stagnation.shouldTerminate(data) : "Stagnation should not be triggered for at least 1 more generation.";
// Best doesn't improve even though mean does.
data = new PopulationData<Object>(new Object(), 2, 1.5, 0.1, true, 10, 0, 2, 3);
data = new PopulationData<Object>(new ArrayList(), new Object(), 2, 1.5, 0.1, true, 10, 0, 2, 3);
assert stagnation.shouldTerminate(data) : "Stagnation should be triggered after 2 generations without improvement.";
}

@Test
public void testFittestCandidateStagnationNonNatural()
{
TerminationCondition stagnation = new Stagnation(2, false);
PopulationData<Object> data = new PopulationData<Object>(new Object(), 2, 1.5, 0.1, true, 10, 0, 0, 1);
PopulationData<Object> data = new PopulationData<Object>(new ArrayList(), new Object(), 2, 1.5, 0.1, true, 10, 0, 0, 1);
assert !stagnation.shouldTerminate(data) : "Stagnation should not be triggered for at least 2 more generations.";
// Best doesn't improve even though mean does.
data = new PopulationData<Object>(new Object(), 2.2, 1.2, 0.1, true, 10, 0, 1, 2);
data = new PopulationData<Object>(new ArrayList(), new Object(), 2.2, 1.2, 0.1, true, 10, 0, 1, 2);
assert !stagnation.shouldTerminate(data) : "Stagnation should not be triggered for at least 1 more generation.";
// Best doesn't improve even though mean does.
data = new PopulationData<Object>(new Object(), 2, 1, 0.1, true, 10, 0, 2, 3);
data = new PopulationData<Object>(new ArrayList(), new Object(), 2, 1, 0.1, true, 10, 0, 2, 3);
assert stagnation.shouldTerminate(data) : "Stagnation should be triggered after 2 generations without improvement.";
}

Expand All @@ -58,19 +60,19 @@ public void testFittestCandidateStagnationNonNatural()
public void testPopulationMeanStagnation()
{
TerminationCondition stagnation = new Stagnation(2, true, true);
PopulationData<Object> data = new PopulationData<Object>(new Object(), 2, 1, 0.1, true, 10, 0, 0, 1);
PopulationData<Object> data = new PopulationData<Object>(new ArrayList(), new Object(), 2, 1, 0.1, true, 10, 0, 0, 1);
assert !stagnation.shouldTerminate(data) : "Stagnation should not be triggered for at least 2 more generations.";
// Best doesn't improve but mean does.
data = new PopulationData<Object>(new Object(), 2, 1.2, 0.1, true, 10, 0, 1, 2);
data = new PopulationData<Object>(new ArrayList(), new Object(), 2, 1.2, 0.1, true, 10, 0, 1, 2);
assert !stagnation.shouldTerminate(data) : "Stagnation should not be triggered for at least 2 more generations.";
// Best doesn't improve but mean does.
data = new PopulationData<Object>(new Object(), 2, 1.5, 0.1, true, 10, 0, 2, 3);
data = new PopulationData<Object>(new ArrayList(), new Object(), 2, 1.5, 0.1, true, 10, 0, 2, 3);
// Best has stagnated but mean hasn't so shouldn't terminate.
assert !stagnation.shouldTerminate(data) : "Stagnation should not be triggered for at least 2 more generations.";
// Now we let the mean stagnate...and let the best candidate get fitter...
data = new PopulationData<Object>(new Object(), 2.1, 1.5, 0.1, true, 10, 0, 3, 4);
data = new PopulationData<Object>(new ArrayList(), new Object(), 2.1, 1.5, 0.1, true, 10, 0, 3, 4);
assert !stagnation.shouldTerminate(data) : "Stagnation should not be triggered for at least 1 more generation.";
data = new PopulationData<Object>(new Object(), 2.2, 1.5, 0.1, true, 10, 0, 4, 4);
data = new PopulationData<Object>(new ArrayList(), new Object(), 2.2, 1.5, 0.1, true, 10, 0, 4, 4);
assert stagnation.shouldTerminate(data) : "Stagnation should be triggered after 2 generations without improvement.";
}

Expand All @@ -79,19 +81,19 @@ public void testPopulationMeanStagnation()
public void testPopulationMeanStagnationNonNatural()
{
TerminationCondition stagnation = new Stagnation(2, false, true);
PopulationData<Object> data = new PopulationData<Object>(new Object(), 2, 1.5, 0.1, true, 10, 0, 0, 1);
PopulationData<Object> data = new PopulationData<Object>(new ArrayList(), new Object(), 2, 1.5, 0.1, true, 10, 0, 0, 1);
assert !stagnation.shouldTerminate(data) : "Stagnation should not be triggered for at least 2 more generations.";
// Best doesn't improve but mean does.
data = new PopulationData<Object>(new Object(), 2, 1.2, 0.1, true, 10, 0, 1, 2);
data = new PopulationData<Object>(new ArrayList(), new Object(), 2, 1.2, 0.1, true, 10, 0, 1, 2);
assert !stagnation.shouldTerminate(data) : "Stagnation should not be triggered for at least 2 more generations.";
// Best doesn't improve but mean does.
data = new PopulationData<Object>(new Object(), 2, 1, 0.1, true, 10, 0, 2, 3);
data = new PopulationData<Object>(new ArrayList(), new Object(), 2, 1, 0.1, true, 10, 0, 2, 3);
// Best has stagnated but mean hasn't so shouldn't terminate.
assert !stagnation.shouldTerminate(data) : "Stagnation should not be triggered for at least 2 more generations.";
// Now we let the mean stagnate...and let the best candidate get fitter...
data = new PopulationData<Object>(new Object(), 2.1, 1.6, 0.1, true, 10, 0, 3, 4);
data = new PopulationData<Object>(new ArrayList(), new Object(), 2.1, 1.6, 0.1, true, 10, 0, 3, 4);
assert !stagnation.shouldTerminate(data) : "Stagnation should not be triggered for at least 1 more generation.";
data = new PopulationData<Object>(new Object(), 2.2, 1.5, 0.1, true, 10, 0, 4, 4);
data = new PopulationData<Object>(new ArrayList(), new Object(), 2.2, 1.5, 0.1, true, 10, 0, 4, 4);
assert stagnation.shouldTerminate(data) : "Stagnation should be triggered after 2 generations without improvement.";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import org.uncommons.watchmaker.framework.PopulationData;
import org.uncommons.watchmaker.framework.TerminationCondition;

import java.util.ArrayList;

/**
* Unit test for termination condition that checks the best fitness attained so far
* against a pre-determined target.
Expand All @@ -30,9 +32,9 @@ public class TargetFitnessTest
public void testNaturalFitness()
{
TerminationCondition condition = new TargetFitness(10.0d, true);
PopulationData<Object> data = new PopulationData<Object>(new Object(), 5.0d, 4.0d, 0, true, 2, 0, 0, 100);
PopulationData<Object> data = new PopulationData<Object>(new ArrayList(), new Object(), 5.0d, 4.0d, 0, true, 2, 0, 0, 100);
assert !condition.shouldTerminate(data) : "Should not terminate before target fitness is reached.";
data = new PopulationData<Object>(new Object(), 10.0d, 8.0d, 0, true, 2, 0, 0, 100);
data = new PopulationData<Object>(new ArrayList(), new Object(), 10.0d, 8.0d, 0, true, 2, 0, 0, 100);
assert condition.shouldTerminate(data) : "Should terminate once target fitness is reached.";
}

Expand All @@ -41,9 +43,9 @@ public void testNaturalFitness()
public void testNonNaturalFitness()
{
TerminationCondition condition = new TargetFitness(1.0d, false);
PopulationData<Object> data = new PopulationData<Object>(new Object(), 5.0d, 4.0d, 0, true, 2, 0, 0, 100);
PopulationData<Object> data = new PopulationData<Object>(new ArrayList(), new Object(), 5.0d, 4.0d, 0, true, 2, 0, 0, 100);
assert !condition.shouldTerminate(data) : "Should not terminate before target fitness is reached.";
data = new PopulationData<Object>(new Object(), 1.0d, 3.1d, 0, true, 2, 0, 0, 100);
data = new PopulationData<Object>(new ArrayList(), new Object(), 1.0d, 3.1d, 0, true, 2, 0, 0, 100);
assert condition.shouldTerminate(data) : "Should terminate once target fitness is reached.";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import org.testng.annotations.Test;
import org.uncommons.watchmaker.framework.PopulationData;

import java.util.ArrayList;

/**
* Unit test for termination condition that checks an abort flag set by the user.
* @author Daniel Dyer
Expand All @@ -29,7 +31,7 @@ public void testAbort()
{
UserAbort condition = new UserAbort();
// This population data should be irrelevant.
PopulationData<Object> data = new PopulationData<Object>(new Object(), 0, 0, 0, true, 2, 0, 0, 100);
PopulationData<Object> data = new PopulationData<Object>(new ArrayList(), new Object(), 0, 0, 0, true, 2, 0, 0, 100);
assert !condition.shouldTerminate(data) : "Should not terminate without user abort.";
assert !condition.isAborted() : "Should not be aborted without user intervention.";
condition.abort();
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</parent>
<groupId>org.uncommons.watchmaker</groupId>
<artifactId>watchmaker</artifactId>
<version>0.7.2</version>
<version>0.7.2-qumul</version>
<packaging>pom</packaging>
<name>watchmaker</name>
<description>Watchmaker Framework - Root Project</description>
Expand Down
2 changes: 1 addition & 1 deletion swing/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>org.uncommons.watchmaker</groupId>
<artifactId>watchmaker</artifactId>
<version>0.7.2</version>
<version>0.7.2-qumul</version>
</parent>
<artifactId>watchmaker-swing</artifactId>

Expand Down
Loading