View Javadoc
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 }