package jcgp.backend.modules.es; import jcgp.backend.modules.mutator.Mutator; import jcgp.backend.population.Population; import jcgp.backend.resources.Resources; import jcgp.backend.resources.parameters.BooleanParameter; import jcgp.backend.resources.parameters.IntegerParameter; import jcgp.backend.resources.parameters.Parameter; import jcgp.backend.resources.parameters.ParameterStatus; /** * (μ + λ)-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 implements 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) { mu = new IntegerParameter(1, "Parents (μ)") { @Override public void validate(Number newValue) { if (newValue.intValue() + lambda.get() != resources.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() != resources.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") { @Override public void validate(Boolean newValue) { // nothing } }; } @Override public Parameter[] getLocalParameters() { return new Parameter[] {mu, lambda, report}; } @Override public void evolve(Population population, Mutator mutator, Resources resources) { /* Population is sorted in ascending order of fitness, so leave the last * mu chromosomes intact */ for (int i = 0; i < resources.populationSize() - mu.get(); i++) { // select a random parent out of the lambda offspring individuals int randomParent = resources.populationSize() - 1 - resources.getRandomInt(mu.get()); if (report.get()) resources.reportln("[ES] Copying Chr " + randomParent + " to population position " + i); population.copyChromosome(randomParent, i); // mutate selected chromosome if (report.get()) resources.reportln("[ES] Mutating copied chromosome"); mutator.mutate(population.getChromosome(i), resources); } if (report.get()) resources.reportln("[ES] Generation is complete"); } @Override public String toString() { return "(μ + λ)"; } }