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.SelectionPolicy; 17 import net.bmahe.genetics4j.core.spec.selection.Tournament; 18 19 public class TournamentSelector<T extends Comparable<T>> implements Selector<T> { 20 public static final Logger logger = LogManager.getLogger(TournamentSelector.class); 21 22 private final SelectionPolicy selectionPolicy; 23 private final RandomGenerator randomGenerator; 24 25 public TournamentSelector(final SelectionPolicy _selectionPolicy, final RandomGenerator _randomGenerator) { 26 Objects.requireNonNull(_selectionPolicy); 27 Validate.isInstanceOf(Tournament.class, _selectionPolicy); 28 Objects.requireNonNull(_randomGenerator); 29 30 this.selectionPolicy = _selectionPolicy; 31 this.randomGenerator = _randomGenerator; 32 } 33 34 @Override 35 public Population<T> select(final AbstractEAConfiguration<T> eaConfiguration, final long generation, 36 final int numIndividuals, final List<Genotype> population, final List<T> fitnessScore) { 37 Objects.requireNonNull(eaConfiguration); 38 Objects.requireNonNull(population); 39 Objects.requireNonNull(fitnessScore); 40 Validate.isTrue(generation >= 0); 41 Validate.isTrue(numIndividuals > 0); 42 Validate.isTrue(population.size() == fitnessScore.size()); 43 44 @SuppressWarnings("unchecked") 45 final Tournament<T> tournamentSelection = (Tournament<T>) selectionPolicy; 46 47 final Comparator<Individual<T>> baseComparator = tournamentSelection.comparator(); 48 final Comparator<Individual<T>> comparator = switch (eaConfiguration.optimization()) { 49 case MAXIMIZE -> baseComparator; 50 case MINIMIZE -> baseComparator.reversed(); 51 }; 52 53 logger.debug("Selecting {} individuals", numIndividuals); 54 55 final Population<T> selectedIndividuals = new Population<>(); 56 while (selectedIndividuals.size() < numIndividuals) { 57 58 Individual<T> bestIndividual = null; 59 60 for (int i = 0; i < tournamentSelection.numCandidates(); i++) { 61 final int candidateIndex = randomGenerator.nextInt(fitnessScore.size()); 62 final Individual<T> candidate = Individual.of(population.get(candidateIndex), 63 fitnessScore.get(candidateIndex)); 64 65 if (bestIndividual == null || comparator.compare(bestIndividual, candidate) < 0) { 66 bestIndividual = candidate; 67 } 68 } 69 70 selectedIndividuals.add(bestIndividual); 71 } 72 73 return selectedIndividuals; 74 } 75 }