Evolutionary operators are the components that perform the actual evolution of a population. Cross-over is an evolutionary operator, as is mutation.
In the Watchmaker Framework, evolutionary operators are defined in terms of the
EvolutionaryOperator
interface. This interface
declares a single method that takes a list of selected individuals and returns a
list of evolved individuals. Some operators (i.e. mutation) will process one
individual at a time, whereas others will process individuals in groups
(cross-over processes two individuals at a time).
As with candidate factories, evolutionary operators have associated types that
must be compatible with the type of the evolution engine that they are used with.
And, as with candidate factories, the framework provides several ready-made operators
for common types. These can be found in the
org.uncommons.watchmaker.framework.operators package. The
cross-over and mutation operators that we need for our "Hello World" program are
provided by the StringCrossover
and
StringMutation
classes.
Alert readers will have noticed that the evolution engine constructor only accepts
a single evolutionary operator. So how can we use both cross-over and mutation?
The answer is provided by the EvolutionPipeline
operator.
This is a compound evolutionary operator that chains together multiple operators of
the same type.
List<EvolutionaryOperator<String>> operators
= new LinkedList<EvolutionaryOperator<String>>();
operators.add(new StringCrossover());
operators.add(new StringMutation(chars, new Probability(0.02)));
EvolutionaryOperator<String> pipeline
= new EvolutionPipeline<String>(operators);
The evolution pipeline is just one of many useful operators included in the org.uncommons.watchmaker.framework.operators package. Elaborate evolution schemes can be constructed from combinations of these operators. Users of the Watchmaker Framework should take a few minutes to browse the API documentation and familiarise themselves with the available classes.