View Javadoc
1   package net.bmahe.genetics4j.neat.mutation;
2   
3   import java.util.Objects;
4   import java.util.random.RandomGenerator;
5   
6   import net.bmahe.genetics4j.core.chromosomes.Chromosome;
7   import net.bmahe.genetics4j.core.mutation.GenericMutatorImpl;
8   import net.bmahe.genetics4j.core.mutation.MutationPolicyHandler;
9   import net.bmahe.genetics4j.core.mutation.MutationPolicyHandlerResolver;
10  import net.bmahe.genetics4j.core.mutation.Mutator;
11  import net.bmahe.genetics4j.core.mutation.chromosome.ChromosomeMutationHandler;
12  import net.bmahe.genetics4j.core.spec.AbstractEAConfiguration;
13  import net.bmahe.genetics4j.core.spec.AbstractEAExecutionContext;
14  import net.bmahe.genetics4j.core.spec.mutation.MutationPolicy;
15  import net.bmahe.genetics4j.core.util.ChromosomeResolverUtils;
16  import net.bmahe.genetics4j.neat.spec.mutation.NeatConnectionWeight;
17  
18  /**
19   * Mutation policy handler for NEAT (NeuroEvolution of Augmenting Topologies) connection weight mutations.
20   * 
21   * <p>NeatConnectionWeightPolicyHandler manages weight mutations for NEAT neural network connections, which are
22   * essential for fine-tuning network behavior and optimizing performance. Weight mutations are typically the most
23   * frequent type of mutation in NEAT evolution, applied to existing connections to improve network functionality.
24   * 
25   * <p>Weight mutation strategies:
26   * <ul>
27   * <li><strong>Gaussian perturbation</strong>: Add small random values to existing weights</li>
28   * <li><strong>Random replacement</strong>: Replace weights with new random values</li>
29   * <li><strong>Creep mutation</strong>: Small incremental changes to weights</li>
30   * <li><strong>Uniform perturbation</strong>: Add uniform random noise to weights</li>
31   * </ul>
32   * 
33   * <p>Key characteristics:
34   * <ul>
35   * <li><strong>Behavioral optimization</strong>: Fine-tunes network behavior without changing topology</li>
36   * <li><strong>High frequency</strong>: Applied more often than structural mutations</li>
37   * <li><strong>Bounded values</strong>: Respects chromosome weight bounds during mutation</li>
38   * <li><strong>Continuous evolution</strong>: Enables continuous improvement of network performance</li>
39   * </ul>
40   * 
41   * <p>Integration with NEAT algorithm:
42   * <ul>
43   * <li><strong>Chromosome mutation</strong>: Delegates to NEAT chromosome weight mutation handlers</li>
44   * <li><strong>Population evolution</strong>: Applied based on configured mutation probability</li>
45   * <li><strong>Performance optimization</strong>: Primary mechanism for network performance tuning</li>
46   * <li><strong>Genetic diversity</strong>: Maintains behavioral diversity in the population</li>
47   * </ul>
48   * 
49   * <p>Common usage patterns:
50   * 
51   * <pre>{@code
52   * // Create weight mutation policy
53   * NeatConnectionWeight weightPolicy = NeatConnectionWeight.builder()
54   * 		.populationMutationProbability(0.8) // 80% of population
55   * 		.chromosomeMutationProbability(0.9) // 90% of connections per chromosome
56   * 		.mutationStandardDeviation(0.1) // Standard deviation for Gaussian perturbation
57   * 		.build();
58   * 
59   * // Create policy handler
60   * RandomGenerator randomGen = RandomGenerator.getDefault();
61   * NeatConnectionWeightPolicyHandler<Double> handler = new NeatConnectionWeightPolicyHandler<>(randomGen);
62   * 
63   * // Check if handler can process the policy
64   * boolean canHandle = handler.canHandle(resolver, weightPolicy);
65   * 
66   * // Create mutator for the policy
67   * Mutator mutator = handler.createMutator(executionContext, configuration, resolver, weightPolicy);
68   * }</pre>
69   * 
70   * <p>Weight mutation effects:
71   * <ul>
72   * <li><strong>Performance tuning</strong>: Optimizes network output for better fitness</li>
73   * <li><strong>Exploration vs exploitation</strong>: Balances exploration of weight space with convergence</li>
74   * <li><strong>Gradient-like behavior</strong>: Can simulate gradient-based optimization</li>
75   * <li><strong>Population diversity</strong>: Maintains diverse behavioral patterns</li>
76   * </ul>
77   * 
78   * <p>Mutation policy configuration:
79   * <ul>
80   * <li><strong>Population probability</strong>: Fraction of population to apply mutations to</li>
81   * <li><strong>Chromosome probability</strong>: Fraction of connections to mutate per chromosome</li>
82   * <li><strong>Mutation magnitude</strong>: Size of weight perturbations</li>
83   * <li><strong>Mutation type</strong>: Strategy for weight modification (Gaussian, uniform, etc.)</li>
84   * </ul>
85   * 
86   * <p>Performance considerations:
87   * <ul>
88   * <li><strong>High frequency application</strong>: Efficient implementation for frequent use</li>
89   * <li><strong>Memory efficiency</strong>: Minimal allocation during weight modification</li>
90   * <li><strong>Numerical stability</strong>: Maintains weight values within valid ranges</li>
91   * <li><strong>Concurrent safety</strong>: Thread-safe for parallel mutation application</li>
92   * </ul>
93   * 
94   * @param <T> the fitness value type (typically Double)
95   * @see NeatConnectionWeight
96   * @see net.bmahe.genetics4j.neat.mutation.chromosome.NeatChromosomeConnectionWeightMutationHandler
97   * @see MutationPolicyHandler
98   */
99  public class NeatConnectionWeightPolicyHandler<T extends Comparable<T>> implements MutationPolicyHandler<T> {
100 
101 	private final RandomGenerator randomGenerator;
102 
103 	/**
104 	 * Constructs a new connection weight policy handler with the specified random generator.
105 	 * 
106 	 * <p>The random generator is used for stochastic decisions during mutation application, including selection of
107 	 * individuals to mutate and generation of weight perturbations.
108 	 * 
109 	 * @param _randomGenerator random number generator for stochastic mutation operations
110 	 * @throws IllegalArgumentException if randomGenerator is null
111 	 */
112 	public NeatConnectionWeightPolicyHandler(final RandomGenerator _randomGenerator) {
113 		Objects.requireNonNull(_randomGenerator);
114 
115 		this.randomGenerator = _randomGenerator;
116 	}
117 
118 	/**
119 	 * Determines whether this handler can process the given mutation policy.
120 	 * 
121 	 * <p>This handler specifically processes NeatConnectionWeight mutation policies, which configure the parameters for
122 	 * mutating connection weights in NEAT neural networks.
123 	 * 
124 	 * @param mutationPolicyHandlerResolver resolver for nested mutation policies
125 	 * @param mutationPolicy                the mutation policy to check
126 	 * @return true if the policy is a NeatConnectionWeight instance, false otherwise
127 	 * @throws IllegalArgumentException if any parameter is null
128 	 */
129 	@Override
130 	public boolean canHandle(final MutationPolicyHandlerResolver<T> mutationPolicyHandlerResolver,
131 			final MutationPolicy mutationPolicy) {
132 		Objects.requireNonNull(mutationPolicyHandlerResolver);
133 		Objects.requireNonNull(mutationPolicy);
134 
135 		return mutationPolicy instanceof NeatConnectionWeight;
136 	}
137 
138 	/**
139 	 * Creates a concrete mutator for connection weight mutations.
140 	 * 
141 	 * <p>This method resolves the appropriate chromosome mutation handlers for NEAT chromosomes and creates a generic
142 	 * mutator that applies weight mutations according to the specified policy parameters.
143 	 * 
144 	 * <p>Mutator creation process:
145 	 * <ol>
146 	 * <li>Extract population mutation probability from the policy</li>
147 	 * <li>Resolve chromosome-specific mutation handlers</li>
148 	 * <li>Create generic mutator with resolved components</li>
149 	 * <li>Return configured mutator ready for population application</li>
150 	 * </ol>
151 	 * 
152 	 * @param eaExecutionContext            execution context containing NEAT-specific components
153 	 * @param eaConfiguration               evolutionary algorithm configuration
154 	 * @param mutationPolicyHandlerResolver resolver for chromosome mutation handlers
155 	 * @param mutationPolicy                the connection weight mutation policy
156 	 * @return a configured mutator for applying weight mutations
157 	 * @throws IllegalArgumentException if any parameter is null
158 	 */
159 	@Override
160 	public Mutator createMutator(final AbstractEAExecutionContext<T> eaExecutionContext,
161 			final AbstractEAConfiguration<T> eaConfiguration,
162 			final MutationPolicyHandlerResolver<T> mutationPolicyHandlerResolver, MutationPolicy mutationPolicy) {
163 		Objects.requireNonNull(eaExecutionContext);
164 		Objects.requireNonNull(eaConfiguration);
165 		Objects.requireNonNull(mutationPolicy);
166 		Objects.requireNonNull(mutationPolicyHandlerResolver);
167 
168 		final NeatConnectionWeight neatConnectionWeightMutationPolicy = (NeatConnectionWeight) mutationPolicy;
169 		final double populationMutationProbability = neatConnectionWeightMutationPolicy.populationMutationProbability();
170 
171 		final ChromosomeMutationHandler<? extends Chromosome>[] chromosomeMutationHandlers = ChromosomeResolverUtils
172 				.resolveChromosomeMutationHandlers(eaExecutionContext, eaConfiguration, mutationPolicy);
173 
174 		return new GenericMutatorImpl(randomGenerator,
175 				chromosomeMutationHandlers,
176 				mutationPolicy,
177 				populationMutationProbability);
178 	}
179 }