So far we've been able to build our evolutionary program by simply combining instances of classes provided by the framework. There is one part of the program that we will always have to write for ourselves though and that is the fitness function, which is necessarily different for every program.
In the Watchmaker Framework, a fitness function is written by implementing the
FitnessEvaluator
interface. The
getFitness
method of this interface takes a candidate solution
and returns its fitness score as a Java double. The method actually takes two
arguments, but we can ignore the second for now.
The listing below is a fitness evaluator for the "Hello World" program. It simply assigns one point for each character in the candidate string that matches the corresponding position in the target string.
public class StringEvaluator implements FitnessEvaluator<String> { private final String targetString = "HELLO WORLD"; /** * Assigns one "fitness point" for every character in the * candidate String that matches the corresponding position in * the target string. */ public double getFitness(String candidate, List<? extends String> population) { int matches = 0; for (int i = 0; i < candidate.length(); i++) { if (candidate.charAt(i) == targetString.charAt(i)) { ++matches; } } return matches; } public boolean isNatural() { return true; } }
By some fitness measures, a higher value indicates a fitter solution. In other
cases a lower value is better. The isNatural
method
of a fitness evaluator simply specifies which scenario applies. In Watchmaker
Framework terminology, a natural fitness function is one that
returns higher values for fitter individuals.