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