package jcgp.backend.modules.es; import jcgp.backend.modules.mutator.Mutator; import jcgp.backend.parameters.BooleanParameter; import jcgp.backend.parameters.IntegerParameter; import jcgp.backend.parameters.ParameterStatus; import jcgp.backend.population.Population; import jcgp.backend.resources.Resources; /** * (μ + λ)-ES *

* This strategy selects the μ fittest chromosomes from the population. * The promoted individuals are copied into the new population and mutated * λ times, but also carried forward unchanged. The total population size * is μ + λ. *

* Two integer parameters are used to control this strategy: parents * and offspring. They are constrained in that they must always add up to * the population size, and must never be smaller than 1. *
* One additional parameter, report, controls whether a detailed log of the * algorithm's operation is to be printed or not. Reports respect the report * interval base parameter. * * @see EvolutionaryStrategy * @author Eduardo Pedroni * */ public class MuPlusLambda extends EvolutionaryStrategy { private IntegerParameter mu, lambda; private BooleanParameter report; /** * Creates a new instance of MuPlusLambda. * * @param resources a reference to the experiment's resources. */ public MuPlusLambda(final Resources resources) { super(resources); mu = new IntegerParameter(1, "Parents (μ)") { @Override public void validate(Number newValue) { if (newValue.intValue() + lambda.get() != getResources().populationSize()) { status = ParameterStatus.INVALID; status.setDetails("Parents + offspring must equal population size."); } else if (newValue.intValue() <= 0) { status = ParameterStatus.INVALID; status.setDetails("ES needs at least 1 parent."); } else { status = ParameterStatus.VALID; } } }; lambda = new IntegerParameter(4, "Offspring (λ)") { @Override public void validate(Number newValue) { if (newValue.intValue() + mu.get() != getResources().populationSize()) { status = ParameterStatus.INVALID; status.setDetails("Parents + offspring must equal population size."); } else if (newValue.intValue() <= 0) { status = ParameterStatus.INVALID; status.setDetails("ES needs at least 1 offspring."); } else { status = ParameterStatus.VALID; } } }; report = new BooleanParameter(false, "Report"); setName("(μ + λ)"); registerParameters(mu, lambda, report); } @Override public void evolve(Population population, Mutator mutator) { // sort the population in order of best fitness population.sort(); // population is now sorted in ascending order of fitness, the last chromosomes are the fittest for (int i = 0; i < getResources().populationSize() - mu.get(); i++) { // select a random parent out of the lambda offspring individuals int randomParent = getResources().populationSize() - 1 - getResources().getRandomInt(mu.get()); if (report.get()) getResources().reportln("[ES] Copying Chr " + randomParent + " to population position " + i); population.copyChromosome(randomParent, i); // mutate selected chromosome if (report.get()) getResources().reportln("[ES] Mutating copied chromosome"); mutator.mutate(population.get(i)); } if (report.get()) getResources().reportln("[ES] Generation is complete"); } }