package org.jenetix; import java.util.stream.IntStream; import org.jenetics.internal.util.IntRef; import org.jenetics.Chromosome; import org.jenetics.Gene; import org.jenetics.Genotype; import org.jenetics.Mutator; import org.jenetics.Phenotype; import org.jenetics.Population; import org.jenetics.util.MSeq; /** * Mutator implementation which is part of the * <a href="https://en.wikipedia.org/wiki/Weasel_program">Weasel program</a> * algorithm. The <i>Weasel program</i> is an thought experiment by Richard * Dawkins to illustrate the functioning of the evolution: random <i>mutation</i> * combined with non-random cumulative <i>selection</i>. * <p> * The mutator mutates the genes of <i>every</i> chromosome of <i>every</i> * genotype in the population with the given mutation probability. * </p> * {@link org.jenetics.engine.Engine} setup for the <i>Weasel program:</i> * <pre>{@code * final Engine<CharacterGene, Integer> engine = Engine * .builder(fitness, gtf) * // Set the 'WeaselSelector'. * .selector(new WeaselSelector<>()) * // Disable survivors selector. * .offspringFraction(1) * // Set the 'WeaselMutator'. * .alterers(new WeaselMutator<>(0.05)) * .build(); * }</pre> * * @see <a href="https://en.wikipedia.org/wiki/Weasel_program">Weasel program</a> * @see WeaselSelector * * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a> * @since 3.5 * @version 3.5 */ public class WeaselMutator< G extends Gene<?, G>, C extends Comparable<? super C> > extends Mutator<G, C> { public WeaselMutator(final double probability) { super(probability); } public WeaselMutator() { this(0.05); } @Override public int alter(final Population<G, C> population, final long generation) { final IntRef alterations = new IntRef(0); for (int i = 0; i < population.size(); ++i) { final Phenotype<G, C> pt = population.get(i); final Genotype<G> gt = pt.getGenotype(); final Genotype<G> mgt = mutate(gt, alterations); final Phenotype<G, C> mpt = pt.newInstance(mgt, generation); population.set(i, mpt); } return alterations.value; } private Genotype<G> mutate( final Genotype<G> genotype, final IntRef alterations ) { final MSeq<Chromosome<G>> chromosomes = genotype.toSeq().copy(); alterations.value += IntStream.range(0, chromosomes.size()) .map(i -> mutate(chromosomes, i)) .sum(); return Genotype.of(chromosomes); } private int mutate(final MSeq<Chromosome<G>> c, final int index) { final Chromosome<G> chromosome = c.get(index); final MSeq<G> genes = chromosome.toSeq().copy(); final int mutations = mutate(genes, _probability); if (mutations > 0) { c.set(index, chromosome.newInstance(genes.toISeq())); } return mutations; } }