1 package net.bmahe.genetics4j.core.selection; 2 3 import java.util.ArrayList; 4 import java.util.Comparator; 5 import java.util.List; 6 import java.util.random.RandomGenerator; 7 import java.util.stream.Collectors; 8 9 import org.apache.commons.lang3.Validate; 10 import org.apache.logging.log4j.LogManager; 11 import org.apache.logging.log4j.Logger; 12 13 import net.bmahe.genetics4j.core.Genotype; 14 import net.bmahe.genetics4j.core.Individual; 15 import net.bmahe.genetics4j.core.Population; 16 import net.bmahe.genetics4j.core.spec.AbstractEAConfiguration; 17 import net.bmahe.genetics4j.core.spec.AbstractEAExecutionContext; 18 import net.bmahe.genetics4j.core.spec.selection.MultiTournaments; 19 import net.bmahe.genetics4j.core.spec.selection.SelectionPolicy; 20 import net.bmahe.genetics4j.core.spec.selection.Tournament; 21 22 public class MultiTournamentsSelectionPolicyHandler<T extends Comparable<T>> implements SelectionPolicyHandler<T> { 23 final static public Logger logger = LogManager.getLogger(MultiTournamentsSelectionPolicyHandler.class); 24 25 private final RandomGenerator randomGenerator; 26 27 private List<Individual<T>> pickRandomCandidates(final RandomGenerator randomGenerator, 28 final List<Genotype> population, final List<T> fitnessScore, final int numCandidates) { 29 Validate.notNull(randomGenerator); 30 Validate.notNull(population); 31 Validate.notNull(fitnessScore); 32 Validate.isTrue(fitnessScore.size() > 0); 33 Validate.isTrue(numCandidates > 0); 34 35 return randomGenerator.ints(0, fitnessScore.size()) 36 .boxed() 37 .limit(numCandidates) 38 .map(i -> Individual.of(population.get(i), fitnessScore.get(i))) 39 .collect(Collectors.toList()); 40 } 41 42 private Individual<T> runTournament(final Tournament<T> tournament, final List<Genotype> population, 43 final List<T> fitnessScore, final List<Individual<T>> candidates) { 44 Validate.notNull(tournament); 45 46 final Comparator<Individual<T>> comparator = tournament.comparator(); 47 48 return candidates.stream() 49 .max(comparator) 50 .get(); 51 } 52 53 private Individual<T> runTournament(final RandomGenerator randomGenerator, final List<Tournament<T>> tournaments, 54 final List<Genotype> population, final List<T> fitnessScore, final int tournamentIndex) { 55 Validate.notNull(tournaments); 56 Validate.notNull(population); 57 Validate.notNull(fitnessScore); 58 Validate.isTrue(tournamentIndex < tournaments.size()); 59 Validate.isTrue(tournamentIndex >= 0); 60 61 final Tournament<T> tournament = tournaments.get(tournamentIndex); 62 final int numCandidates = tournament.numCandidates(); 63 64 List<Individual<T>> candidates; 65 if (tournamentIndex == 0) { 66 candidates = pickRandomCandidates(randomGenerator, population, fitnessScore, numCandidates); 67 } else { 68 candidates = new ArrayList<>(); 69 70 for (int i = 0; i < numCandidates; i++) { 71 final Individual<T> candidate = runTournament(randomGenerator, 72 tournaments, 73 population, 74 fitnessScore, 75 tournamentIndex - 1); 76 candidates.add(candidate); 77 } 78 } 79 80 return runTournament(tournament, population, fitnessScore, candidates); 81 82 } 83 84 public MultiTournamentsSelectionPolicyHandler(final RandomGenerator _randomGenerator) { 85 Validate.notNull(_randomGenerator); 86 87 this.randomGenerator = _randomGenerator; 88 } 89 90 @Override 91 public boolean canHandle(final SelectionPolicy selectionPolicy) { 92 Validate.notNull(selectionPolicy); 93 return selectionPolicy instanceof MultiTournaments; 94 } 95 96 @Override 97 public Selector<T> resolve(final AbstractEAExecutionContext<T> eaExecutionContext, 98 final AbstractEAConfiguration<T> eaConfiguration, 99 final SelectionPolicyHandlerResolver<T> selectionPolicyHandlerResolver, 100 final SelectionPolicy selectionPolicy) { 101 Validate.notNull(selectionPolicy); 102 Validate.isInstanceOf(MultiTournaments.class, selectionPolicy); 103 104 return new Selector<T>() { 105 106 @Override 107 public Population<T> select(final AbstractEAConfiguration<T> eaConfiguration, final int numIndividuals, 108 final List<Genotype> population, final List<T> fitnessScore) { 109 Validate.notNull(eaConfiguration); 110 Validate.notNull(population); 111 Validate.notNull(fitnessScore); 112 Validate.isTrue(numIndividuals > 0); 113 Validate.isTrue(population.size() == fitnessScore.size()); 114 115 @SuppressWarnings("unchecked") 116 final MultiTournaments<T> multiTournaments = (MultiTournaments<T>) selectionPolicy; 117 final List<Tournament<T>> tournaments = multiTournaments.tournaments(); 118 119 logger.debug("Selecting {} individuals", numIndividuals); 120 final Population<T> selectedIndividuals = new Population<>(); 121 while (selectedIndividuals.size() < numIndividuals) { 122 final Individual<T> selectedIndividual = runTournament(randomGenerator, 123 tournaments, 124 population, 125 fitnessScore, 126 tournaments.size() - 1); 127 selectedIndividuals.add(selectedIndividual); 128 } 129 130 return selectedIndividuals; 131 } 132 }; 133 } 134 }