package org.jenetix;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
import org.jenetics.Gene;
import org.jenetics.Optimize;
import org.jenetics.Phenotype;
import org.jenetics.Population;
import org.jenetics.Selector;
import org.jenetics.stat.MinMax;
/**
* Selector 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 selector always returns populations which only contains "{@code count}"
* instances of the <i>best</i> {@link Phenotype}.
* </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 WeaselMutator
*
* @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
* @since 3.5
* @version 3.5
*/
public class WeaselSelector<
G extends Gene<?, G>,
C extends Comparable<? super C>
>
implements Selector<G, C>
{
@Override
public Population<G, C> select(
final Population<G, C> population,
final int count,
final Optimize opt
) {
requireNonNull(population, "Population");
requireNonNull(opt, "Optimization");
if (count < 0) {
throw new IllegalArgumentException(format(
"Selection count must be greater or equal then zero, but was %s",
count
));
}
final MinMax<Phenotype<G, C>> minMax = population.stream()
.collect(MinMax.toMinMax(opt.ascending()));
return new Population<G, C>(count).fill(minMax::getMax, count);
}
}