NeatSelectionPolicyHandler.java
package net.bmahe.genetics4j.neat.selection;
import java.util.random.RandomGenerator;
import org.apache.commons.lang3.Validate;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.bmahe.genetics4j.core.selection.SelectionPolicyHandler;
import net.bmahe.genetics4j.core.selection.SelectionPolicyHandlerResolver;
import net.bmahe.genetics4j.core.selection.Selector;
import net.bmahe.genetics4j.core.spec.AbstractEAConfiguration;
import net.bmahe.genetics4j.core.spec.AbstractEAExecutionContext;
import net.bmahe.genetics4j.core.spec.selection.SelectionPolicy;
import net.bmahe.genetics4j.neat.SpeciesIdGenerator;
import net.bmahe.genetics4j.neat.spec.selection.NeatSelection;
/**
* Selection policy handler for NEAT (NeuroEvolution of Augmenting Topologies) species-based selection.
*
* <p>NeatSelectionPolicyHandler implements the species-based selection mechanism that is fundamental to
* the NEAT algorithm. It organizes the population into species based on genetic compatibility, applies
* fitness sharing within species, and manages reproduction allocation across species to maintain
* population diversity and protect innovative topologies.
*
* <p>Key responsibilities:
* <ul>
* <li><strong>Species formation</strong>: Groups genetically similar individuals into species</li>
* <li><strong>Fitness sharing</strong>: Adjusts individual fitness based on species membership</li>
* <li><strong>Reproduction allocation</strong>: Distributes offspring across species based on average fitness</li>
* <li><strong>Diversity preservation</strong>: Protects innovative topologies from elimination by established forms</li>
* </ul>
*
* <p>NEAT species-based selection process:
* <ol>
* <li><strong>Compatibility calculation</strong>: Measure genetic distance between individuals</li>
* <li><strong>Species assignment</strong>: Assign individuals to species based on compatibility thresholds</li>
* <li><strong>Fitness adjustment</strong>: Apply fitness sharing within each species</li>
* <li><strong>Species evaluation</strong>: Calculate average fitness for each species</li>
* <li><strong>Reproduction allocation</strong>: Determine offspring count for each species</li>
* <li><strong>Within-species selection</strong>: Select parents within each species for reproduction</li>
* </ol>
*
* <p>Species management features:
* <ul>
* <li><strong>Dynamic speciation</strong>: Species boundaries adjust as population evolves</li>
* <li><strong>Species extinction</strong>: Poor-performing species are eliminated</li>
* <li><strong>Representative tracking</strong>: Maintains species representatives for compatibility testing</li>
* <li><strong>Population diversity</strong>: Prevents single topology from dominating</li>
* </ul>
*
* <p>Common usage patterns:
* <pre>{@code
* // Create NEAT selection policy handler
* RandomGenerator randomGen = RandomGenerator.getDefault();
* SpeciesIdGenerator speciesIdGen = new SpeciesIdGenerator();
*
* NeatSelectionPolicyHandler<Double> handler = new NeatSelectionPolicyHandler<>(
* randomGen, speciesIdGen
* );
*
* // Configure NEAT selection policy
* NeatSelection<Double> neatSelection = NeatSelection.<Double>builder()
* .compatibilityThreshold(3.0)
* .speciesSelection(new TournamentSelection(3)) // Within-species selection
* .build();
*
* // Resolve selector for EA execution
* Selector<Double> selector = handler.resolve(
* executionContext, configuration, resolverRegistry, neatSelection
* );
* }</pre>
*
* <p>Integration with genetic operators:
* <ul>
* <li><strong>Crossover compatibility</strong>: Species ensure genetic compatibility for meaningful recombination</li>
* <li><strong>Mutation guidance</strong>: Species composition influences structural mutation rates</li>
* <li><strong>Innovation protection</strong>: New topologies get time to optimize within their species</li>
* <li><strong>Diversity maintenance</strong>: Multiple species explore different regions of topology space</li>
* </ul>
*
* <p>Performance considerations:
* <ul>
* <li><strong>Compatibility caching</strong>: Genetic distances cached for efficiency</li>
* <li><strong>Species reuse</strong>: Species structures maintained across generations</li>
* <li><strong>Parallel processing</strong>: Species-based selection enables concurrent evaluation</li>
* <li><strong>Memory management</strong>: Efficient species membership tracking</li>
* </ul>
*
* <p>Selection policy delegation:
* <ul>
* <li><strong>Within-species selection</strong>: Delegates to standard selection policies (tournament, roulette, etc.)</li>
* <li><strong>Composable policies</strong>: Can combine with any standard selection mechanism</li>
* <li><strong>Flexible configuration</strong>: Different species can use different selection strategies</li>
* <li><strong>Performance optimization</strong>: Leverages existing high-performance selectors</li>
* </ul>
*
* @param <T> the fitness value type (typically Double)
* @see NeatSelection
* @see NeatSelectorImpl
* @see Species
* @see SpeciesIdGenerator
* @see SelectionPolicyHandler
*/
public class NeatSelectionPolicyHandler<T extends Number & Comparable<T>> implements SelectionPolicyHandler<T> {
public static final Logger logger = LogManager.getLogger(NeatSelectionPolicyHandler.class);
private final RandomGenerator randomGenerator;
private final SpeciesIdGenerator speciesIdGenerator;
/**
* Constructs a new NEAT selection policy handler with the specified components.
*
* <p>The random generator is used for stochastic operations during species formation
* and selection. The species ID generator provides unique identifiers for newly
* created species throughout the evolutionary process.
*
* @param _randomGenerator random number generator for stochastic operations
* @param _speciesIdGenerator generator for unique species identifiers
* @throws IllegalArgumentException if randomGenerator or speciesIdGenerator is null
*/
public NeatSelectionPolicyHandler(final RandomGenerator _randomGenerator,
final SpeciesIdGenerator _speciesIdGenerator) {
Validate.notNull(_randomGenerator);
Validate.notNull(_speciesIdGenerator);
this.randomGenerator = _randomGenerator;
this.speciesIdGenerator = _speciesIdGenerator;
}
/**
* Determines whether this handler can process the given selection policy.
*
* <p>This handler specifically processes NeatSelection policies, which configure
* species-based selection with compatibility thresholds and within-species
* selection strategies.
*
* @param selectionPolicy the selection policy to check
* @return true if the policy is a NeatSelection instance, false otherwise
* @throws IllegalArgumentException if selectionPolicy is null
*/
@Override
public boolean canHandle(final SelectionPolicy selectionPolicy) {
Validate.notNull(selectionPolicy);
return selectionPolicy instanceof NeatSelection;
}
/**
* Resolves a NEAT selection policy into a concrete selector implementation.
*
* <p>This method creates a NeatSelectorImpl that implements the species-based selection
* mechanism. It resolves the within-species selection policy using the provided
* resolver and configures the selector with the necessary NEAT components.
*
* <p>Resolution process:
* <ol>
* <li>Extract the within-species selection policy from the NEAT selection configuration</li>
* <li>Resolve the within-species selection policy to a concrete selector</li>
* <li>Create a NeatSelectorImpl with all necessary components</li>
* <li>Return the configured selector ready for use in evolution</li>
* </ol>
*
* @param eaExecutionContext the execution context for the evolutionary algorithm
* @param eaConfiguration the configuration for the evolutionary algorithm
* @param selectionPolicyHandlerResolver resolver for nested selection policies
* @param selectionPolicy the NEAT selection policy to resolve
* @return a configured selector implementing NEAT species-based selection
* @throws IllegalArgumentException if selectionPolicy is null or not a NeatSelection
*/
@Override
public Selector<T> resolve(final AbstractEAExecutionContext<T> eaExecutionContext,
final AbstractEAConfiguration<T> eaConfiguration,
final SelectionPolicyHandlerResolver<T> selectionPolicyHandlerResolver,
final SelectionPolicy selectionPolicy) {
Validate.notNull(selectionPolicy);
Validate.isInstanceOf(NeatSelection.class, selectionPolicy);
final NeatSelection<T> neatSelection = (NeatSelection<T>) selectionPolicy;
final SelectionPolicy speciesSelection = neatSelection.speciesSelection();
final SelectionPolicyHandler<T> speciesSelectionPolicyHandler = selectionPolicyHandlerResolver
.resolve(speciesSelection);
final Selector<T> speciesSelector = speciesSelectionPolicyHandler
.resolve(eaExecutionContext, eaConfiguration, selectionPolicyHandlerResolver, speciesSelection);
return new NeatSelectorImpl<>(randomGenerator, neatSelection, speciesIdGenerator, speciesSelector);
}
}