| 1 | package net.bmahe.genetics4j.neat.mutation; | |
| 2 | ||
| 3 | import java.util.random.RandomGenerator; | |
| 4 | ||
| 5 | import org.apache.commons.lang3.Validate; | |
| 6 | ||
| 7 | import net.bmahe.genetics4j.core.chromosomes.Chromosome; | |
| 8 | import net.bmahe.genetics4j.core.mutation.GenericMutatorImpl; | |
| 9 | import net.bmahe.genetics4j.core.mutation.MutationPolicyHandler; | |
| 10 | import net.bmahe.genetics4j.core.mutation.MutationPolicyHandlerResolver; | |
| 11 | import net.bmahe.genetics4j.core.mutation.Mutator; | |
| 12 | import net.bmahe.genetics4j.core.mutation.chromosome.ChromosomeMutationHandler; | |
| 13 | import net.bmahe.genetics4j.core.spec.AbstractEAConfiguration; | |
| 14 | import net.bmahe.genetics4j.core.spec.AbstractEAExecutionContext; | |
| 15 | import net.bmahe.genetics4j.core.spec.mutation.MutationPolicy; | |
| 16 | import net.bmahe.genetics4j.core.util.ChromosomeResolverUtils; | |
| 17 | import net.bmahe.genetics4j.neat.spec.mutation.AddConnection; | |
| 18 | ||
| 19 | /** | |
| 20 | * Mutation policy handler for NEAT (NeuroEvolution of Augmenting Topologies) add-connection mutations. | |
| 21 | * | |
| 22 | * <p>AddConnectionPolicyHandler manages the structural mutation that adds new connections between existing nodes in | |
| 23 | * NEAT neural networks. This is one of the fundamental structural mutations that enables NEAT to explore different | |
| 24 | * network topologies by increasing connectivity complexity. | |
| 25 | * | |
| 26 | * <p>Add-connection mutation process: | |
| 27 | * <ol> | |
| 28 | * <li><strong>Node selection</strong>: Choose source and target nodes for the new connection</li> | |
| 29 | * <li><strong>Validity checking</strong>: Ensure connection doesn't already exist and doesn't create cycles</li> | |
| 30 | * <li><strong>Innovation assignment</strong>: Assign unique innovation number to the new connection</li> | |
| 31 | * <li><strong>Weight initialization</strong>: Set initial weight for the new connection</li> | |
| 32 | * <li><strong>Connection creation</strong>: Add enabled connection to the chromosome</li> | |
| 33 | * </ol> | |
| 34 | * | |
| 35 | * <p>Key characteristics: | |
| 36 | * <ul> | |
| 37 | * <li><strong>Structural evolution</strong>: Increases network connectivity without adding nodes</li> | |
| 38 | * <li><strong>Innovation tracking</strong>: New connections receive unique innovation numbers</li> | |
| 39 | * <li><strong>Topology exploration</strong>: Enables discovery of useful connection patterns</li> | |
| 40 | * <li><strong>Gradual complexity</strong>: Incrementally increases network complexity</li> | |
| 41 | * </ul> | |
| 42 | * | |
| 43 | * <p>Integration with NEAT algorithm: | |
| 44 | * <ul> | |
| 45 | * <li><strong>Innovation management</strong>: Coordinates with InnovationManager for tracking</li> | |
| 46 | * <li><strong>Chromosome mutation</strong>: Delegates to NeatChromosomeAddConnection handler</li> | |
| 47 | * <li><strong>Population evolution</strong>: Applied based on configured mutation probability</li> | |
| 48 | * <li><strong>Genetic diversity</strong>: Maintains structural diversity in the population</li> | |
| 49 | * </ul> | |
| 50 | * | |
| 51 | * <p>Common usage patterns: | |
| 52 | * | |
| 53 | * <pre>{@code | |
| 54 | * // Create add-connection mutation policy | |
| 55 | * AddConnection addConnectionPolicy = AddConnection.of(0.1); // 10% mutation rate | |
| 56 | * | |
| 57 | * // Create policy handler | |
| 58 | * RandomGenerator randomGen = RandomGenerator.getDefault(); | |
| 59 | * AddConnectionPolicyHandler<Double> handler = new AddConnectionPolicyHandler<>(randomGen); | |
| 60 | * | |
| 61 | * // Check if handler can process the policy | |
| 62 | * boolean canHandle = handler.canHandle(resolver, addConnectionPolicy); | |
| 63 | * | |
| 64 | * // Create mutator for the policy | |
| 65 | * Mutator mutator = handler.createMutator(executionContext, configuration, resolver, addConnectionPolicy); | |
| 66 | * | |
| 67 | * // Apply mutation to population | |
| 68 | * List<Individual<Double>> mutatedPopulation = mutator.mutate(configuration, population); | |
| 69 | * }</pre> | |
| 70 | * | |
| 71 | * <p>Mutation policy configuration: | |
| 72 | * <ul> | |
| 73 | * <li><strong>Population probability</strong>: Fraction of population to apply mutation to</li> | |
| 74 | * <li><strong>Individual probability</strong>: Probability of mutating each selected individual</li> | |
| 75 | * <li><strong>Connection constraints</strong>: Rules governing valid connection additions</li> | |
| 76 | * <li><strong>Weight initialization</strong>: Strategy for setting initial connection weights</li> | |
| 77 | * </ul> | |
| 78 | * | |
| 79 | * <p>Structural constraints: | |
| 80 | * <ul> | |
| 81 | * <li><strong>Duplicate prevention</strong>: Avoids creating connections that already exist</li> | |
| 82 | * <li><strong>Cycle detection</strong>: Prevents creation of cycles in feed-forward networks</li> | |
| 83 | * <li><strong>Node validity</strong>: Ensures source and target nodes exist in the network</li> | |
| 84 | * <li><strong>Self-connection handling</strong>: May prevent or allow self-connections based on policy</li> | |
| 85 | * </ul> | |
| 86 | * | |
| 87 | * <p>Performance considerations: | |
| 88 | * <ul> | |
| 89 | * <li><strong>Innovation caching</strong>: Leverages InnovationManager for efficient number assignment</li> | |
| 90 | * <li><strong>Connection checking</strong>: Efficient algorithms for duplicate and cycle detection</li> | |
| 91 | * <li><strong>Memory efficiency</strong>: Minimal allocation during mutation operations</li> | |
| 92 | * <li><strong>Concurrent safety</strong>: Thread-safe for parallel mutation application</li> | |
| 93 | * </ul> | |
| 94 | * | |
| 95 | * @param <T> the fitness value type (typically Double) | |
| 96 | * @see AddConnection | |
| 97 | * @see net.bmahe.genetics4j.neat.mutation.chromosome.NeatChromosomeAddConnection | |
| 98 | * @see MutationPolicyHandler | |
| 99 | * @see InnovationManager | |
| 100 | */ | |
| 101 | public class AddConnectionPolicyHandler<T extends Comparable<T>> implements MutationPolicyHandler<T> { | |
| 102 | ||
| 103 | private final RandomGenerator randomGenerator; | |
| 104 | ||
| 105 | /** | |
| 106 | * Constructs a new add-connection policy handler with the specified random generator. | |
| 107 | * | |
| 108 | * <p>The random generator is used for stochastic decisions during mutation application, including selection of | |
| 109 | * individuals to mutate and choices within the mutation process. | |
| 110 | * | |
| 111 | * @param _randomGenerator random number generator for stochastic mutation operations | |
| 112 | * @throws IllegalArgumentException if randomGenerator is null | |
| 113 | */ | |
| 114 | public AddConnectionPolicyHandler(final RandomGenerator _randomGenerator) { | |
| 115 | Validate.notNull(_randomGenerator); | |
| 116 | ||
| 117 |
1
1. <init> : Removed assignment to member variable randomGenerator → KILLED |
this.randomGenerator = _randomGenerator; |
| 118 | } | |
| 119 | ||
| 120 | /** | |
| 121 | * Determines whether this handler can process the given mutation policy. | |
| 122 | * | |
| 123 | * <p>This handler specifically processes AddConnection mutation policies, which configure the parameters for adding | |
| 124 | * new connections to NEAT neural networks. | |
| 125 | * | |
| 126 | * @param mutationPolicyHandlerResolver resolver for nested mutation policies | |
| 127 | * @param mutationPolicy the mutation policy to check | |
| 128 | * @return true if the policy is an AddConnection instance, false otherwise | |
| 129 | * @throws IllegalArgumentException if any parameter is null | |
| 130 | */ | |
| 131 | @Override | |
| 132 | public boolean canHandle(final MutationPolicyHandlerResolver<T> mutationPolicyHandlerResolver, | |
| 133 | final MutationPolicy mutationPolicy) { | |
| 134 | Validate.notNull(mutationPolicyHandlerResolver); | |
| 135 | Validate.notNull(mutationPolicy); | |
| 136 | ||
| 137 |
2
1. canHandle : replaced boolean return with false for net/bmahe/genetics4j/neat/mutation/AddConnectionPolicyHandler::canHandle → KILLED 2. canHandle : replaced boolean return with true for net/bmahe/genetics4j/neat/mutation/AddConnectionPolicyHandler::canHandle → KILLED |
return mutationPolicy instanceof AddConnection; |
| 138 | } | |
| 139 | ||
| 140 | /** | |
| 141 | * Creates a concrete mutator for add-connection mutations. | |
| 142 | * | |
| 143 | * <p>This method resolves the appropriate chromosome mutation handlers for NEAT chromosomes and creates a generic | |
| 144 | * mutator that applies add-connection mutations according to the specified policy parameters. | |
| 145 | * | |
| 146 | * <p>Mutator creation process: | |
| 147 | * <ol> | |
| 148 | * <li>Extract population mutation probability from the policy</li> | |
| 149 | * <li>Resolve chromosome-specific mutation handlers</li> | |
| 150 | * <li>Create generic mutator with resolved components</li> | |
| 151 | * <li>Return configured mutator ready for population application</li> | |
| 152 | * </ol> | |
| 153 | * | |
| 154 | * @param eaExecutionContext execution context containing NEAT-specific components | |
| 155 | * @param eaConfiguration evolutionary algorithm configuration | |
| 156 | * @param mutationPolicyHandlerResolver resolver for chromosome mutation handlers | |
| 157 | * @param mutationPolicy the add-connection mutation policy | |
| 158 | * @return a configured mutator for applying add-connection mutations | |
| 159 | * @throws IllegalArgumentException if any parameter is null | |
| 160 | */ | |
| 161 | @Override | |
| 162 | public Mutator createMutator(final AbstractEAExecutionContext<T> eaExecutionContext, | |
| 163 | final AbstractEAConfiguration<T> eaConfiguration, | |
| 164 | final MutationPolicyHandlerResolver<T> mutationPolicyHandlerResolver, MutationPolicy mutationPolicy) { | |
| 165 | Validate.notNull(eaExecutionContext); | |
| 166 | Validate.notNull(eaConfiguration); | |
| 167 | Validate.notNull(mutationPolicy); | |
| 168 | Validate.notNull(mutationPolicyHandlerResolver); | |
| 169 | ||
| 170 | final AddConnection addConnectionMutationPolicy = (AddConnection) mutationPolicy; | |
| 171 |
1
1. createMutator : removed call to net/bmahe/genetics4j/neat/spec/mutation/AddConnection::populationMutationProbability → SURVIVED |
final double populationMutationProbability = addConnectionMutationPolicy.populationMutationProbability(); |
| 172 | ||
| 173 | final ChromosomeMutationHandler<? extends Chromosome>[] chromosomeMutationHandlers = ChromosomeResolverUtils | |
| 174 |
1
1. createMutator : removed call to net/bmahe/genetics4j/core/util/ChromosomeResolverUtils::resolveChromosomeMutationHandlers → KILLED |
.resolveChromosomeMutationHandlers(eaExecutionContext, eaConfiguration, mutationPolicy); |
| 175 | ||
| 176 |
2
1. createMutator : removed call to net/bmahe/genetics4j/core/mutation/GenericMutatorImpl::<init> → KILLED 2. createMutator : replaced return value with null for net/bmahe/genetics4j/neat/mutation/AddConnectionPolicyHandler::createMutator → KILLED |
return new GenericMutatorImpl(randomGenerator, |
| 177 | chromosomeMutationHandlers, | |
| 178 | mutationPolicy, | |
| 179 | populationMutationProbability); | |
| 180 | } | |
| 181 | } | |
Mutations | ||
| 117 |
1.1 |
|
| 137 |
1.1 2.2 |
|
| 171 |
1.1 |
|
| 174 |
1.1 |
|
| 176 |
1.1 2.2 |