WeaselMutator.java
01 package org.jenetics.ext;
02 
03 import java.util.stream.IntStream;
04 
05 import org.jenetics.internal.util.IntRef;
06 
07 import org.jenetics.Chromosome;
08 import org.jenetics.Gene;
09 import org.jenetics.Genotype;
10 import org.jenetics.Mutator;
11 import org.jenetics.Phenotype;
12 import org.jenetics.Population;
13 import org.jenetics.util.MSeq;
14 
15 /**
16  * Mutator implementation which is part of the
17  * <a href="https://en.wikipedia.org/wiki/Weasel_program">Weasel program</a>
18  * algorithm. The <i>Weasel program</i> is an thought experiment by Richard
19  * Dawkins to illustrate the functioning of the evolution: random <i>mutation</i>
20  * combined with non-random cumulative <i>selection</i>.
21  <p>
22  * The mutator mutates the genes of <i>every</i> chromosome of <i>every</i>
23  * genotype in the population with the given mutation probability.
24  </p>
25  {@link org.jenetics.engine.Engine} setup for the <i>Weasel program:</i>
26  <pre>{@code
27  * final Engine<CharacterGene, Integer> engine = Engine
28  *     .builder(fitness, gtf)
29  *      // Set the 'WeaselSelector'.
30  *     .selector(new WeaselSelector<>())
31  *      // Disable survivors selector.
32  *     .offspringFraction(1)
33  *      // Set the 'WeaselMutator'.
34  *     .alterers(new WeaselMutator<>(0.05))
35  *     .build();
36  * }</pre>
37  *
38  @see <a href="https://en.wikipedia.org/wiki/Weasel_program">Weasel program</a>
39  @see WeaselSelector
40  *
41  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
42  @since 3.5
43  @version 3.5
44  */
45 public class WeaselMutator<
46     extends Gene<?, G>,
47     extends Comparable<? super C>
48 >
49     extends Mutator<G, C>
50 {
51 
52     public WeaselMutator(final double probability) {
53         super(probability);
54     }
55 
56     public WeaselMutator() {
57         this(0.05);
58     }
59 
60     @Override
61     public int alter(final Population<G, C> population, final long generation) {
62         final IntRef alterations = new IntRef(0);
63 
64         for (int i = 0; i < population.size(); ++i) {
65             final Phenotype<G, C> pt = population.get(i);
66 
67             final Genotype<G> gt = pt.getGenotype();
68             final Genotype<G> mgt = mutate(gt, alterations);
69             final Phenotype<G, C> mpt = pt.newInstance(mgt, generation);
70             population.set(i, mpt);
71         }
72 
73         return alterations.value;
74     }
75 
76     private Genotype<G> mutate(
77         final Genotype<G> genotype,
78         final IntRef alterations
79     ) {
80         final MSeq<Chromosome<G>> chromosomes = genotype.toSeq().copy();
81 
82         alterations.value += IntStream.range(0, chromosomes.size())
83             .map(i -> mutate(chromosomes, i, _probability))
84             .sum();
85 
86         return Genotype.of(chromosomes);
87     }
88 
89 }