org.uncommons.watchmaker.framework.EvolutionUtils Maven / Gradle / Ivy
The newest version!
//=============================================================================
// Copyright 2006-2010 Daniel W. Dyer
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//=============================================================================
package org.uncommons.watchmaker.framework;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.uncommons.maths.statistics.DataSet;
/**
* Utility methods used by different evolution implementations. This class exists to
* avoid duplication of this logic among multiple evolution implementations.
* @author Daniel Dyer
*/
public final class EvolutionUtils
{
private EvolutionUtils()
{
// Prevents instantiation of utility class.
}
/**
* Given data about the current population and a set of termination conditions, determines
* whether or not the evolution should continue.
* @param data The current state of the population.
* @param conditions One or more termination conditions. The evolution should not continue if
* any of these is satisfied.
* @param The type of entity that is being evolved.
* @return A list of satisfied termination conditions if the evolution has reached some
* pre-specified state, an empty list if the evolution should stop because of a thread
* interruption, or null if the evolution should continue.
*/
public static List shouldContinue(PopulationData data,
TerminationCondition... conditions)
{
// If the thread has been interrupted, we should abort and return whatever
// result we currently have.
if (Thread.currentThread().isInterrupted())
{
return Collections.emptyList();
}
// Otherwise check the termination conditions for the evolution.
List satisfiedConditions = new LinkedList();
for (TerminationCondition condition : conditions)
{
if (condition.shouldTerminate(data))
{
satisfiedConditions.add(condition);
}
}
return satisfiedConditions.isEmpty() ? null : satisfiedConditions;
}
/**
* Sorts an evaluated population in descending order of fitness
* (descending order of fitness score for natural scores, ascending
* order of scores for non-natural scores).
*
* @param evaluatedPopulation The population to be sorted (in-place).
* @param naturalFitness True if higher fitness scores mean fitter individuals, false otherwise.
* @param The type of entity that is being evolved.
*/
public static void sortEvaluatedPopulation(List> evaluatedPopulation,
boolean naturalFitness)
{
// Sort candidates in descending order according to fitness.
if (naturalFitness) // Descending values for natural fitness.
{
Collections.sort(evaluatedPopulation, Collections.reverseOrder());
}
else // Ascending values for non-natural fitness.
{
Collections.sort(evaluatedPopulation);
}
}
/**
* Gets data about the current population, including the fittest candidate
* and statistics about the population as a whole.
*
* @param evaluatedPopulation Population of candidate solutions with their
* associated fitness scores.
* @param naturalFitness True if higher fitness scores mean fitter individuals, false otherwise.
* @param eliteCount The number of candidates preserved via elitism.
* @param iterationNumber The zero-based index of the current generation/epoch.
* @param startTime The time at which the evolution began, expressed as a number of milliseconds since
* 00:00 on 1st January 1970.
* @param The type of entity that is being evolved.
* @return Statistics about the current generation of evolved individuals.
*/
public static PopulationData getPopulationData(List> evaluatedPopulation,
boolean naturalFitness,
int eliteCount,
int iterationNumber,
long startTime)
{
DataSet stats = new DataSet(evaluatedPopulation.size());
for (EvaluatedCandidate candidate : evaluatedPopulation)
{
stats.addValue(candidate.getFitness());
}
return new PopulationData(evaluatedPopulation.get(0).getCandidate(),
evaluatedPopulation.get(0).getFitness(),
stats.getArithmeticMean(),
stats.getStandardDeviation(),
naturalFitness,
stats.getSize(),
eliteCount,
iterationNumber,
System.currentTimeMillis() - startTime);
}
}