WeaselMutator.java
001 package org.jenetix;
002 
003 import java.util.stream.IntStream;
004 
005 import org.jenetics.internal.util.IntRef;
006 
007 import org.jenetics.Chromosome;
008 import org.jenetics.Gene;
009 import org.jenetics.Genotype;
010 import org.jenetics.Mutator;
011 import org.jenetics.Phenotype;
012 import org.jenetics.Population;
013 import org.jenetics.util.MSeq;
014 
015 /**
016  * Mutator implementation which is part of the
017  * <a href="https://en.wikipedia.org/wiki/Weasel_program">Weasel program</a>
018  * algorithm. The <i>Weasel program</i> is an thought experiment by Richard
019  * Dawkins to illustrate the functioning of the evolution: random <i>mutation</i>
020  * combined with non-random cumulative <i>selection</i>.
021  <p>
022  * The mutator mutates the genes of <i>every</i> chromosome of <i>every</i>
023  * genotype in the population with the given mutation probability.
024  </p>
025  {@link org.jenetics.engine.Engine} setup for the <i>Weasel program:</i>
026  <pre>{@code
027  * final Engine<CharacterGene, Integer> engine = Engine
028  *     .builder(fitness, gtf)
029  *      // Set the 'WeaselSelector'.
030  *     .selector(new WeaselSelector<>())
031  *      // Disable survivors selector.
032  *     .offspringFraction(1)
033  *      // Set the 'WeaselMutator'.
034  *     .alterers(new WeaselMutator<>(0.05))
035  *     .build();
036  * }</pre>
037  *
038  @see <a href="https://en.wikipedia.org/wiki/Weasel_program">Weasel program</a>
039  @see WeaselSelector
040  *
041  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
042  @since 3.5
043  @version 3.5
044  */
045 public class WeaselMutator<
046     extends Gene<?, G>,
047     extends Comparable<? super C>
048 >
049     extends Mutator<G, C>
050 {
051 
052     public WeaselMutator(final double probability) {
053         super(probability);
054     }
055 
056     public WeaselMutator() {
057         this(0.05);
058     }
059 
060     @Override
061     public int alter(final Population<G, C> population, final long generation) {
062         final IntRef alterations = new IntRef(0);
063 
064         for (int i = 0; i < population.size(); ++i) {
065             final Phenotype<G, C> pt = population.get(i);
066 
067             final Genotype<G> gt = pt.getGenotype();
068             final Genotype<G> mgt = mutate(gt, alterations);
069             final Phenotype<G, C> mpt = pt.newInstance(mgt, generation);
070             population.set(i, mpt);
071         }
072 
073         return alterations.value;
074     }
075 
076     private Genotype<G> mutate(
077         final Genotype<G> genotype,
078         final IntRef alterations
079     ) {
080         final MSeq<Chromosome<G>> chromosomes = genotype.toSeq().copy();
081 
082         alterations.value += IntStream.range(0, chromosomes.size())
083             .map(i -> mutate(chromosomes, i))
084             .sum();
085 
086         return Genotype.of(chromosomes);
087     }
088 
089     private int mutate(final MSeq<Chromosome<G>> c, final int index) {
090         final Chromosome<G> chromosome = c.get(index);
091         final MSeq<G> genes = chromosome.toSeq().copy();
092 
093         final int mutations = mutate(genes, _probability);
094         if (mutations > 0) {
095             c.set(index, chromosome.newInstance(genes.toISeq()));
096         }
097         return mutations;
098     }
099 
100 }