1 package net.bmahe.genetics4j.core.selection;
2
3 import java.util.Comparator;
4 import java.util.List;
5 import java.util.Objects;
6 import java.util.random.RandomGenerator;
7
8 import org.apache.commons.lang3.Validate;
9 import org.apache.logging.log4j.LogManager;
10 import org.apache.logging.log4j.Logger;
11
12 import net.bmahe.genetics4j.core.Genotype;
13 import net.bmahe.genetics4j.core.Individual;
14 import net.bmahe.genetics4j.core.Population;
15 import net.bmahe.genetics4j.core.spec.AbstractEAConfiguration;
16 import net.bmahe.genetics4j.core.spec.selection.ProportionalTournament;
17 import net.bmahe.genetics4j.core.spec.selection.SelectionPolicy;
18
19 public class ProportionalTournamentSelector<T extends Comparable<T>> implements Selector<T> {
20 final static public Logger logger = LogManager.getLogger(ProportionalTournamentSelector.class);
21
22 private final SelectionPolicy selectionPolicy;
23 private final RandomGenerator randomGenerator;
24
25 public ProportionalTournamentSelector(final SelectionPolicy _selectionPolicy,
26 final RandomGenerator _randomGenerator) {
27 Objects.requireNonNull(_selectionPolicy);
28 Validate.isInstanceOf(ProportionalTournament.class, _selectionPolicy);
29 Objects.requireNonNull(_randomGenerator);
30
31 this.selectionPolicy = _selectionPolicy;
32 this.randomGenerator = _randomGenerator;
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> fitnessScore) {
38 Objects.requireNonNull(eaConfiguration);
39 Objects.requireNonNull(population);
40 Objects.requireNonNull(fitnessScore);
41 Validate.isTrue(generation >= 0);
42 Validate.isTrue(numIndividuals > 0);
43 Validate.isTrue(population.size() == fitnessScore.size());
44
45 @SuppressWarnings("unchecked")
46 final ProportionalTournament<T> proportionalTournament = (ProportionalTournament<T>) selectionPolicy;
47 final Comparator<Individual<T>> firstComparator = proportionalTournament.firstComparator();
48 final Comparator<Individual<T>> secondComparator = proportionalTournament.secondComparator();
49 final int numCandidates = proportionalTournament.numCandidates();
50 final double proportionFirst = proportionalTournament.proportionFirst();
51
52 final Comparator<Individual<T>> firstComparatorOptimize = switch (eaConfiguration.optimization()) {
53 case MAXIMIZE -> firstComparator;
54 case MINIMIZE -> firstComparator.reversed();
55 };
56
57 final Comparator<Individual<T>> secondComparatorOptimize = switch (eaConfiguration.optimization()) {
58 case MAXIMIZE -> secondComparator;
59 case MINIMIZE -> secondComparator.reversed();
60 };
61
62 logger.debug("Selecting {} individuals", numIndividuals);
63
64 final Population<T> selectedIndividuals = new Population<>();
65
66 while (selectedIndividuals.size() < numIndividuals) {
67
68 final Comparator<Individual<T>> comparator = randomGenerator.nextDouble() < proportionFirst
69 ? firstComparatorOptimize
70 : secondComparatorOptimize;
71
72 final Individual<T> selected = randomGenerator.ints(numCandidates, 0, population.size())
73 .boxed()
74 .map((i) -> Individual.of(population.get(i), fitnessScore.get(i)))
75 .max(comparator)
76 .get();
77
78 selectedIndividuals.add(selected.genotype(), selected.fitness());
79 }
80
81 return selectedIndividuals;
82 }
83 }