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 }