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