/*
* Copyright 2007-2013
* Licensed under GNU Lesser General Public License
*
* This file is part of EpochX: genetic programming software for research
*
* EpochX is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EpochX is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with EpochX. If not, see <http://www.gnu.org/licenses/>.
*
* The latest version is available from: http://www.epochx.org
*/
package org.epochx.fitness;
import java.util.HashMap;
import java.util.Map;
import org.epochx.AbstractFitnessFunction;
import org.epochx.Fitness;
import org.epochx.Individual;
/**
* A fitness function which caches fitness scores and delegates fitness calculations to a
* delegate fitness function. For the caching to work correctly the fitness cases must not
* be changed, or the cache must be cleared when they are changed. Caching is based on
* hash code so it is important that Individuals have a suitable hashCode implementation.
*
* @since 2.0
*/
public class CachedFitnessFunction extends AbstractFitnessFunction {
// The cache of fitness scores
private Map<Object, Fitness> cache;
// The fitness function to delegate to when not in cache
private AbstractFitnessFunction delegate;
/**
* Constructs a <code>CachedFitnessFunction</code> fitness function. Fitness calculations
* are performed by the given delegate, unless the individual's fitness has been
* cached.
*
* @param delegate the fitness function the fitness calculations should be delegated to
*/
public CachedFitnessFunction(AbstractFitnessFunction delegate) {
this.delegate = delegate;
cache = new HashMap<Object, Fitness>();
}
/**
* Returns the fitness of the given individual. If the cache contains a fitness score
* for the given individual then the fitness value from the cache is returned.
* Otherwise the fitness is calculated using the delegate fitness function and then
* cached for future evaluations.
*
* The caching of individuals is based on hash codes. If two individuals return the
* same hash code then its assumed they have equal fitness scores.
*
* @param individual the program to evaluate
* @return the fitness of the given individual
*/
@Override
public Fitness evaluate(Individual individual) {
Object key = individual.hashCode();
//TODO Use source generator if one is set
Fitness fitness = cache.get(key);
if (fitness == null) {
fitness = delegate.evaluate(individual);
cache.put(key, fitness);
}
return fitness;
}
/**
* Clears the cache.
*/
public void clear() {
cache.clear();
}
}