Martin Waßmann
unread,May 27, 2011, 10:04:33 AM5/27/11Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to Watchmaker Framework for Evolutionary Computation
When implementing evolutionary operators, especially several mutation,
I found myself doing the same thing over and over again, and therefore
introduced a basic platform to realise mutations. As I think it'd be a
good addition to the framework (the idea, not the code), I'm sharing
it with you. (See code below!)
As the EvolutionaryOperator is defined on the whole population, each
mutation operator starts with creating a new empty population, then
iterating over the candidates and mutating them according to a
probability. Therefore I separated the common behaviour (of all
mutations) from the mutation specific, resulting in a class
MutationOperator, implementing the EvoOp interface, and an Interface
MutationStrategy. In order to implement a new mutation operator, one
would just have to implement the MutationStrategy Interface and
instantiate the MutationOperator Class with the new MutationStrategy
implementation.
The main advantage of this approach is, that the framework provides a
platform to easily realise mutations, rather than everyone inventing
something similar on its own, and that the framework would have full
control of the program flow. It'd be quite easy (as mutations a
generally independent from each other) to exploit parallelism in the
MutationOperators apply-Method. The same could of course be done for
the other large group of operators, the recombinations.
Another advantage of the MutationStrategy Interface is, that it'd be
quite easy to introduce combinators, aggregating several mutations,
e.g. randomly selecting a mutation from a set of available mutations.
(These combinators could be general purpose (and so part of the
framework), when realised as generics.)
It's just a thought.
Regards,
Martin
public interface MutationStrategy<T> {
public T mutate( T individual, Random rng );
}
public class MutationOperator<T> implements EvolutionaryOperator<T> {
protected final double probability;
protected final MutationStrategy<T> strategy;
public MutationOperator( MutationStrategy<T> strategy, double
probability ) {
this.probability = probability;
this.strategy = strategy;
}
@Override
public List<T> apply( List<T> selectedCandidates, Random rng) {
final List<T> mutatedIndividuals = new LinkedList<T>();
for( T candidate : selectedCandidates ) {
if( rng.nextDouble() < this.probability ) {
mutatedIndividuals.add(this.strategy.mutate(candidate, rng));
}
else {
mutatedIndividuals.add(candidate);
}
}
return mutatedIndividuals;
}
}
public class RandomMutationSelector<T> implements MutationStrategy<T>
{
protected final List<MutationStrategy<T>> strategies;
public RandomMutationSelector( Collection<MutationStrategy<T>>
strategies ) {
this.strategies = new ArrayList<MutationStrategy<T>>(strategies);
}
@Override
public T mutate(T individual, Random rng) {
return
this.strategies.get(rng.nextInt(this.strategies.size())).mutate(individual,
rng);
};
}