1 package net.bmahe.genetics4j.core.replacement;
2
3 import java.util.List;
4 import java.util.Objects;
5
6 import org.apache.commons.lang3.Validate;
7 import org.apache.logging.log4j.LogManager;
8 import org.apache.logging.log4j.Logger;
9
10 import net.bmahe.genetics4j.core.Genotype;
11 import net.bmahe.genetics4j.core.Population;
12 import net.bmahe.genetics4j.core.selection.Selector;
13 import net.bmahe.genetics4j.core.spec.AbstractEAConfiguration;
14 import net.bmahe.genetics4j.core.spec.replacement.Elitism;
15
16 public class ElitismImpl<T extends Comparable<T>> implements ReplacementStrategyImplementor<T> {
17 final static public Logger logger = LogManager.getLogger(ElitismImpl.class);
18
19 private final Elitism elitismSpec;
20 private final Selector<T> offspringSelector;
21 private final Selector<T> survivorSelector;
22
23 public ElitismImpl(final Elitism _elistismSpec,
24 final Selector<T> _offspringSelector,
25 final Selector<T> _survivorSelector) {
26 Objects.requireNonNull(_elistismSpec);
27 Objects.requireNonNull(_offspringSelector);
28 Objects.requireNonNull(_survivorSelector);
29
30 this.elitismSpec = _elistismSpec;
31 this.offspringSelector = _offspringSelector;
32 this.survivorSelector = _survivorSelector;
33 }
34
35 @Override
36 public Population<T> select(final AbstractEAConfiguration<T> eaConfiguration, final long generation,
37 final int numIndividuals, final List<Genotype> population, final List<T> populationScores,
38 final List<Genotype> offsprings, final List<T> offspringScores) {
39 Objects.requireNonNull(eaConfiguration);
40 Validate.isTrue(generation >= 0);
41 Validate.isTrue(numIndividuals > 0);
42 Objects.requireNonNull(population);
43 Objects.requireNonNull(populationScores);
44 Validate.isTrue(population.size() == populationScores.size());
45 Objects.requireNonNull(offsprings);
46 Objects.requireNonNull(offspringScores);
47 Validate.isTrue(offsprings.size() == offspringScores.size());
48 Validate.isTrue(elitismSpec.atLeastNumOffsprings() + elitismSpec.atLeastNumSurvivors() <= numIndividuals);
49
50 final int scaledOffspring = (int) (elitismSpec.offspringRatio() * numIndividuals);
51 final int offspringNeeded = Math.max(scaledOffspring, elitismSpec.atLeastNumOffsprings());
52 final int survivorNeeded = numIndividuals - offspringNeeded;
53
54 final int adjustedOffspringNeeded;
55 final int adjustedSurvivorNeeded;
56 if (survivorNeeded < elitismSpec.atLeastNumSurvivors()) {
57
58 adjustedOffspringNeeded = offspringNeeded - (elitismSpec.atLeastNumSurvivors() - survivorNeeded);
59 adjustedSurvivorNeeded = elitismSpec.atLeastNumSurvivors();
60 } else {
61 adjustedOffspringNeeded = offspringNeeded;
62 adjustedSurvivorNeeded = survivorNeeded;
63 }
64
65 logger.debug(
66 "We have {} individuals requested and an offspring ratio of {}. Survivors:{}, Offsprings:{}",
67 numIndividuals,
68 elitismSpec.offspringRatio(),
69 adjustedSurvivorNeeded,
70 adjustedOffspringNeeded);
71
72 final Population<T> selected = new Population<>();
73
74 logger.info("Selecting {} offsprings", adjustedOffspringNeeded);
75 final Population<T> selectedOffspring = offspringSelector
76 .select(eaConfiguration, generation, adjustedOffspringNeeded, offsprings, offspringScores);
77 selected.addAll(selectedOffspring);
78
79 logger.info("Selecting {} survivors", adjustedSurvivorNeeded);
80 final Population<T> selectedSurvivors = survivorSelector
81 .select(eaConfiguration, generation, adjustedSurvivorNeeded, population, populationScores);
82 selected.addAll(selectedSurvivors);
83
84 return selected;
85 }
86 }