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 G extends Gene<?, G>,
047 C 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 }
|