NeatConnectionWeightPolicyHandler.java
package net.bmahe.genetics4j.neat.mutation;
import java.util.random.RandomGenerator;
import org.apache.commons.lang3.Validate;
import net.bmahe.genetics4j.core.chromosomes.Chromosome;
import net.bmahe.genetics4j.core.mutation.GenericMutatorImpl;
import net.bmahe.genetics4j.core.mutation.MutationPolicyHandler;
import net.bmahe.genetics4j.core.mutation.MutationPolicyHandlerResolver;
import net.bmahe.genetics4j.core.mutation.Mutator;
import net.bmahe.genetics4j.core.mutation.chromosome.ChromosomeMutationHandler;
import net.bmahe.genetics4j.core.spec.AbstractEAConfiguration;
import net.bmahe.genetics4j.core.spec.AbstractEAExecutionContext;
import net.bmahe.genetics4j.core.spec.mutation.MutationPolicy;
import net.bmahe.genetics4j.core.util.ChromosomeResolverUtils;
import net.bmahe.genetics4j.neat.spec.mutation.NeatConnectionWeight;
/**
* Mutation policy handler for NEAT (NeuroEvolution of Augmenting Topologies) connection weight mutations.
*
* <p>NeatConnectionWeightPolicyHandler manages weight mutations for NEAT neural network connections,
* which are essential for fine-tuning network behavior and optimizing performance. Weight mutations
* are typically the most frequent type of mutation in NEAT evolution, applied to existing connections
* to improve network functionality.
*
* <p>Weight mutation strategies:
* <ul>
* <li><strong>Gaussian perturbation</strong>: Add small random values to existing weights</li>
* <li><strong>Random replacement</strong>: Replace weights with new random values</li>
* <li><strong>Creep mutation</strong>: Small incremental changes to weights</li>
* <li><strong>Uniform perturbation</strong>: Add uniform random noise to weights</li>
* </ul>
*
* <p>Key characteristics:
* <ul>
* <li><strong>Behavioral optimization</strong>: Fine-tunes network behavior without changing topology</li>
* <li><strong>High frequency</strong>: Applied more often than structural mutations</li>
* <li><strong>Bounded values</strong>: Respects chromosome weight bounds during mutation</li>
* <li><strong>Continuous evolution</strong>: Enables continuous improvement of network performance</li>
* </ul>
*
* <p>Integration with NEAT algorithm:
* <ul>
* <li><strong>Chromosome mutation</strong>: Delegates to NEAT chromosome weight mutation handlers</li>
* <li><strong>Population evolution</strong>: Applied based on configured mutation probability</li>
* <li><strong>Performance optimization</strong>: Primary mechanism for network performance tuning</li>
* <li><strong>Genetic diversity</strong>: Maintains behavioral diversity in the population</li>
* </ul>
*
* <p>Common usage patterns:
* <pre>{@code
* // Create weight mutation policy
* NeatConnectionWeight weightPolicy = NeatConnectionWeight.builder()
* .populationMutationProbability(0.8) // 80% of population
* .chromosomeMutationProbability(0.9) // 90% of connections per chromosome
* .mutationStandardDeviation(0.1) // Standard deviation for Gaussian perturbation
* .build();
*
* // Create policy handler
* RandomGenerator randomGen = RandomGenerator.getDefault();
* NeatConnectionWeightPolicyHandler<Double> handler =
* new NeatConnectionWeightPolicyHandler<>(randomGen);
*
* // Check if handler can process the policy
* boolean canHandle = handler.canHandle(resolver, weightPolicy);
*
* // Create mutator for the policy
* Mutator mutator = handler.createMutator(
* executionContext, configuration, resolver, weightPolicy
* );
* }</pre>
*
* <p>Weight mutation effects:
* <ul>
* <li><strong>Performance tuning</strong>: Optimizes network output for better fitness</li>
* <li><strong>Exploration vs exploitation</strong>: Balances exploration of weight space with convergence</li>
* <li><strong>Gradient-like behavior</strong>: Can simulate gradient-based optimization</li>
* <li><strong>Population diversity</strong>: Maintains diverse behavioral patterns</li>
* </ul>
*
* <p>Mutation policy configuration:
* <ul>
* <li><strong>Population probability</strong>: Fraction of population to apply mutations to</li>
* <li><strong>Chromosome probability</strong>: Fraction of connections to mutate per chromosome</li>
* <li><strong>Mutation magnitude</strong>: Size of weight perturbations</li>
* <li><strong>Mutation type</strong>: Strategy for weight modification (Gaussian, uniform, etc.)</li>
* </ul>
*
* <p>Performance considerations:
* <ul>
* <li><strong>High frequency application</strong>: Efficient implementation for frequent use</li>
* <li><strong>Memory efficiency</strong>: Minimal allocation during weight modification</li>
* <li><strong>Numerical stability</strong>: Maintains weight values within valid ranges</li>
* <li><strong>Concurrent safety</strong>: Thread-safe for parallel mutation application</li>
* </ul>
*
* @param <T> the fitness value type (typically Double)
* @see NeatConnectionWeight
* @see net.bmahe.genetics4j.neat.mutation.chromosome.NeatChromosomeConnectionWeightMutationHandler
* @see MutationPolicyHandler
*/
public class NeatConnectionWeightPolicyHandler<T extends Comparable<T>> implements MutationPolicyHandler<T> {
private final RandomGenerator randomGenerator;
/**
* Constructs a new connection weight policy handler with the specified random generator.
*
* <p>The random generator is used for stochastic decisions during mutation application,
* including selection of individuals to mutate and generation of weight perturbations.
*
* @param _randomGenerator random number generator for stochastic mutation operations
* @throws IllegalArgumentException if randomGenerator is null
*/
public NeatConnectionWeightPolicyHandler(final RandomGenerator _randomGenerator) {
Validate.notNull(_randomGenerator);
this.randomGenerator = _randomGenerator;
}
/**
* Determines whether this handler can process the given mutation policy.
*
* <p>This handler specifically processes NeatConnectionWeight mutation policies, which
* configure the parameters for mutating connection weights in NEAT neural networks.
*
* @param mutationPolicyHandlerResolver resolver for nested mutation policies
* @param mutationPolicy the mutation policy to check
* @return true if the policy is a NeatConnectionWeight instance, false otherwise
* @throws IllegalArgumentException if any parameter is null
*/
@Override
public boolean canHandle(final MutationPolicyHandlerResolver<T> mutationPolicyHandlerResolver,
final MutationPolicy mutationPolicy) {
Validate.notNull(mutationPolicyHandlerResolver);
Validate.notNull(mutationPolicy);
return mutationPolicy instanceof NeatConnectionWeight;
}
/**
* Creates a concrete mutator for connection weight mutations.
*
* <p>This method resolves the appropriate chromosome mutation handlers for NEAT chromosomes
* and creates a generic mutator that applies weight mutations according to the
* specified policy parameters.
*
* <p>Mutator creation process:
* <ol>
* <li>Extract population mutation probability from the policy</li>
* <li>Resolve chromosome-specific mutation handlers</li>
* <li>Create generic mutator with resolved components</li>
* <li>Return configured mutator ready for population application</li>
* </ol>
*
* @param eaExecutionContext execution context containing NEAT-specific components
* @param eaConfiguration evolutionary algorithm configuration
* @param mutationPolicyHandlerResolver resolver for chromosome mutation handlers
* @param mutationPolicy the connection weight mutation policy
* @return a configured mutator for applying weight mutations
* @throws IllegalArgumentException if any parameter is null
*/
@Override
public Mutator createMutator(final AbstractEAExecutionContext<T> eaExecutionContext,
final AbstractEAConfiguration<T> eaConfiguration,
final MutationPolicyHandlerResolver<T> mutationPolicyHandlerResolver, MutationPolicy mutationPolicy) {
Validate.notNull(eaExecutionContext);
Validate.notNull(eaConfiguration);
Validate.notNull(mutationPolicy);
Validate.notNull(mutationPolicyHandlerResolver);
final NeatConnectionWeight neatConnectionWeightMutationPolicy = (NeatConnectionWeight) mutationPolicy;
final double populationMutationProbability = neatConnectionWeightMutationPolicy.populationMutationProbability();
final ChromosomeMutationHandler<? extends Chromosome>[] chromosomeMutationHandlers = ChromosomeResolverUtils
.resolveChromosomeMutationHandlers(eaExecutionContext, eaConfiguration, mutationPolicy);
return new GenericMutatorImpl(randomGenerator,
chromosomeMutationHandlers,
mutationPolicy,
populationMutationProbability);
}
}