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