1 package net.bmahe.genetics4j.neat.selection;
2
3 import java.util.Objects;
4 import java.util.random.RandomGenerator;
5
6 import org.apache.commons.lang3.Validate;
7 import org.apache.logging.log4j.LogManager;
8 import org.apache.logging.log4j.Logger;
9
10 import net.bmahe.genetics4j.core.selection.SelectionPolicyHandler;
11 import net.bmahe.genetics4j.core.selection.SelectionPolicyHandlerResolver;
12 import net.bmahe.genetics4j.core.selection.Selector;
13 import net.bmahe.genetics4j.core.spec.AbstractEAConfiguration;
14 import net.bmahe.genetics4j.core.spec.AbstractEAExecutionContext;
15 import net.bmahe.genetics4j.core.spec.selection.SelectionPolicy;
16 import net.bmahe.genetics4j.neat.SpeciesIdGenerator;
17 import net.bmahe.genetics4j.neat.spec.selection.NeatSelection;
18
19 /**
20 * Selection policy handler for NEAT (NeuroEvolution of Augmenting Topologies) species-based selection.
21 *
22 * <p>NeatSelectionPolicyHandler implements the species-based selection mechanism that is fundamental to the NEAT
23 * algorithm. It organizes the population into species based on genetic compatibility, applies fitness sharing within
24 * species, and manages reproduction allocation across species to maintain population diversity and protect innovative
25 * topologies.
26 *
27 * <p>Key responsibilities:
28 * <ul>
29 * <li><strong>Species formation</strong>: Groups genetically similar individuals into species</li>
30 * <li><strong>Fitness sharing</strong>: Adjusts individual fitness based on species membership</li>
31 * <li><strong>Reproduction allocation</strong>: Distributes offspring across species based on average fitness</li>
32 * <li><strong>Diversity preservation</strong>: Protects innovative topologies from elimination by established
33 * forms</li>
34 * </ul>
35 *
36 * <p>NEAT species-based selection process:
37 * <ol>
38 * <li><strong>Compatibility calculation</strong>: Measure genetic distance between individuals</li>
39 * <li><strong>Species assignment</strong>: Assign individuals to species based on compatibility thresholds</li>
40 * <li><strong>Fitness adjustment</strong>: Apply fitness sharing within each species</li>
41 * <li><strong>Species evaluation</strong>: Calculate average fitness for each species</li>
42 * <li><strong>Reproduction allocation</strong>: Determine offspring count for each species</li>
43 * <li><strong>Within-species selection</strong>: Select parents within each species for reproduction</li>
44 * </ol>
45 *
46 * <p>Species management features:
47 * <ul>
48 * <li><strong>Dynamic speciation</strong>: Species boundaries adjust as population evolves</li>
49 * <li><strong>Species extinction</strong>: Poor-performing species are eliminated</li>
50 * <li><strong>Representative tracking</strong>: Maintains species representatives for compatibility testing</li>
51 * <li><strong>Population diversity</strong>: Prevents single topology from dominating</li>
52 * </ul>
53 *
54 * <p>Common usage patterns:
55 *
56 * <pre>{@code
57 * // Create NEAT selection policy handler
58 * RandomGenerator randomGen = RandomGenerator.getDefault();
59 * SpeciesIdGenerator speciesIdGen = new SpeciesIdGenerator();
60 *
61 * NeatSelectionPolicyHandler<Double> handler = new NeatSelectionPolicyHandler<>(randomGen, speciesIdGen);
62 *
63 * // Configure NEAT selection policy
64 * NeatSelection<Double> neatSelection = NeatSelection.<Double>builder()
65 * .compatibilityThreshold(3.0)
66 * .speciesSelection(new TournamentSelection(3)) // Within-species selection
67 * .build();
68 *
69 * // Resolve selector for EA execution
70 * Selector<Double> selector = handler.resolve(executionContext, configuration, resolverRegistry, neatSelection);
71 * }</pre>
72 *
73 * <p>Integration with genetic operators:
74 * <ul>
75 * <li><strong>Crossover compatibility</strong>: Species ensure genetic compatibility for meaningful recombination</li>
76 * <li><strong>Mutation guidance</strong>: Species composition influences structural mutation rates</li>
77 * <li><strong>Innovation protection</strong>: New topologies get time to optimize within their species</li>
78 * <li><strong>Diversity maintenance</strong>: Multiple species explore different regions of topology space</li>
79 * </ul>
80 *
81 * <p>Performance considerations:
82 * <ul>
83 * <li><strong>Compatibility caching</strong>: Genetic distances cached for efficiency</li>
84 * <li><strong>Species reuse</strong>: Species structures maintained across generations</li>
85 * <li><strong>Parallel processing</strong>: Species-based selection enables concurrent evaluation</li>
86 * <li><strong>Memory management</strong>: Efficient species membership tracking</li>
87 * </ul>
88 *
89 * <p>Selection policy delegation:
90 * <ul>
91 * <li><strong>Within-species selection</strong>: Delegates to standard selection policies (tournament, roulette,
92 * etc.)</li>
93 * <li><strong>Composable policies</strong>: Can combine with any standard selection mechanism</li>
94 * <li><strong>Flexible configuration</strong>: Different species can use different selection strategies</li>
95 * <li><strong>Performance optimization</strong>: Leverages existing high-performance selectors</li>
96 * </ul>
97 *
98 * @param <T> the fitness value type (typically Double)
99 * @see NeatSelection
100 * @see NeatSelectorImpl
101 * @see Species
102 * @see SpeciesIdGenerator
103 * @see SelectionPolicyHandler
104 */
105 public class NeatSelectionPolicyHandler<T extends Number & Comparable<T>> implements SelectionPolicyHandler<T> {
106 public static final Logger logger = LogManager.getLogger(NeatSelectionPolicyHandler.class);
107
108 private final RandomGenerator randomGenerator;
109 private final SpeciesIdGenerator speciesIdGenerator;
110
111 /**
112 * Constructs a new NEAT selection policy handler with the specified components.
113 *
114 * <p>The random generator is used for stochastic operations during species formation and selection. The species ID
115 * generator provides unique identifiers for newly created species throughout the evolutionary process.
116 *
117 * @param _randomGenerator random number generator for stochastic operations
118 * @param _speciesIdGenerator generator for unique species identifiers
119 * @throws IllegalArgumentException if randomGenerator or speciesIdGenerator is null
120 */
121 public NeatSelectionPolicyHandler(final RandomGenerator _randomGenerator,
122 final SpeciesIdGenerator _speciesIdGenerator) {
123 Objects.requireNonNull(_randomGenerator);
124 Objects.requireNonNull(_speciesIdGenerator);
125
126 this.randomGenerator = _randomGenerator;
127 this.speciesIdGenerator = _speciesIdGenerator;
128 }
129
130 /**
131 * Determines whether this handler can process the given selection policy.
132 *
133 * <p>This handler specifically processes NeatSelection policies, which configure species-based selection with
134 * compatibility thresholds and within-species selection strategies.
135 *
136 * @param selectionPolicy the selection policy to check
137 * @return true if the policy is a NeatSelection instance, false otherwise
138 * @throws IllegalArgumentException if selectionPolicy is null
139 */
140 @Override
141 public boolean canHandle(final SelectionPolicy selectionPolicy) {
142 Objects.requireNonNull(selectionPolicy);
143
144 return selectionPolicy instanceof NeatSelection;
145 }
146
147 /**
148 * Resolves a NEAT selection policy into a concrete selector implementation.
149 *
150 * <p>This method creates a NeatSelectorImpl that implements the species-based selection mechanism. It resolves the
151 * within-species selection policy using the provided resolver and configures the selector with the necessary NEAT
152 * components.
153 *
154 * <p>Resolution process:
155 * <ol>
156 * <li>Extract the within-species selection policy from the NEAT selection configuration</li>
157 * <li>Resolve the within-species selection policy to a concrete selector</li>
158 * <li>Create a NeatSelectorImpl with all necessary components</li>
159 * <li>Return the configured selector ready for use in evolution</li>
160 * </ol>
161 *
162 * @param eaExecutionContext the execution context for the evolutionary algorithm
163 * @param eaConfiguration the configuration for the evolutionary algorithm
164 * @param selectionPolicyHandlerResolver resolver for nested selection policies
165 * @param selectionPolicy the NEAT selection policy to resolve
166 * @return a configured selector implementing NEAT species-based selection
167 * @throws IllegalArgumentException if selectionPolicy is null or not a NeatSelection
168 */
169 @Override
170 public Selector<T> resolve(final AbstractEAExecutionContext<T> eaExecutionContext,
171 final AbstractEAConfiguration<T> eaConfiguration,
172 final SelectionPolicyHandlerResolver<T> selectionPolicyHandlerResolver,
173 final SelectionPolicy selectionPolicy) {
174 Objects.requireNonNull(selectionPolicy);
175 Validate.isInstanceOf(NeatSelection.class, selectionPolicy);
176
177 final NeatSelection<T> neatSelection = (NeatSelection<T>) selectionPolicy;
178
179 final SelectionPolicy speciesSelection = neatSelection.speciesSelection();
180 final SelectionPolicyHandler<T> speciesSelectionPolicyHandler = selectionPolicyHandlerResolver
181 .resolve(speciesSelection);
182 final Selector<T> speciesSelector = speciesSelectionPolicyHandler
183 .resolve(eaExecutionContext, eaConfiguration, selectionPolicyHandlerResolver, speciesSelection);
184
185 return new NeatSelectorImpl<>(randomGenerator, neatSelection, speciesIdGenerator, speciesSelector);
186 }
187 }