View Javadoc
1   package net.bmahe.genetics4j.neat.combination;
2   
3   import java.util.Objects;
4   import java.util.Optional;
5   import java.util.random.RandomGenerator;
6   
7   import org.apache.commons.lang3.Validate;
8   
9   import net.bmahe.genetics4j.core.combination.ChromosomeCombinator;
10  import net.bmahe.genetics4j.core.combination.ChromosomeCombinatorHandler;
11  import net.bmahe.genetics4j.core.combination.ChromosomeCombinatorResolver;
12  import net.bmahe.genetics4j.core.spec.chromosome.ChromosomeSpec;
13  import net.bmahe.genetics4j.core.spec.combination.CombinationPolicy;
14  import net.bmahe.genetics4j.neat.combination.parentcompare.ParentComparisonHandler;
15  import net.bmahe.genetics4j.neat.combination.parentcompare.ParentComparisonHandlerLocator;
16  import net.bmahe.genetics4j.neat.spec.NeatChromosomeSpec;
17  import net.bmahe.genetics4j.neat.spec.combination.NeatCombination;
18  import net.bmahe.genetics4j.neat.spec.combination.parentcompare.ParentComparisonPolicy;
19  
20  /**
21   * Chromosome combinator handler for NEAT (NeuroEvolution of Augmenting Topologies) genetic crossover.
22   * 
23   * <p>NeatCombinationHandler manages the genetic recombination process for NEAT neural networks, implementing
24   * innovation-number-based gene alignment and parent comparison strategies. This handler resolves NEAT-specific
25   * combination policies into concrete chromosome combinators that understand neural network topology and can perform
26   * meaningful genetic crossover between different network structures.
27   * 
28   * <p>Key responsibilities:
29   * <ul>
30   * <li><strong>Policy resolution</strong>: Converts NeatCombination policies into executable combinators</li>
31   * <li><strong>Parent comparison</strong>: Manages strategies for determining genetic inheritance patterns</li>
32   * <li><strong>Innovation alignment</strong>: Ensures proper gene alignment using innovation numbers</li>
33   * <li><strong>Topology crossover</strong>: Handles recombination of different network topologies</li>
34   * </ul>
35   * 
36   * <p>NEAT genetic crossover features:
37   * <ul>
38   * <li><strong>Innovation-based alignment</strong>: Genes matched by innovation number for meaningful recombination</li>
39   * <li><strong>Matching genes</strong>: Genes with same innovation number can be inherited from either parent</li>
40   * <li><strong>Disjoint genes</strong>: Genes unique to one parent in middle innovation number ranges</li>
41   * <li><strong>Excess genes</strong>: Genes beyond the highest innovation number of less fit parent</li>
42   * </ul>
43   * 
44   * <p>Parent comparison strategies:
45   * <ul>
46   * <li><strong>Fitness-based inheritance</strong>: More fit parent contributes disjoint and excess genes</li>
47   * <li><strong>Equal fitness handling</strong>: Special rules when parents have equal fitness</li>
48   * <li><strong>Random inheritance</strong>: Stochastic gene inheritance for matching genes</li>
49   * <li><strong>Topology preservation</strong>: Ensures offspring have valid network topologies</li>
50   * </ul>
51   * 
52   * <p>Common usage patterns:
53   * 
54   * <pre>{@code
55   * // Create NEAT combination handler
56   * RandomGenerator randomGen = RandomGenerator.getDefault();
57   * NeatCombinationHandler<Double> handler = new NeatCombinationHandler<>(randomGen);
58   * 
59   * // Check if handler can process combination policy
60   * NeatCombination policy = NeatCombination.builder().parentComparisonPolicy(new FitnessComparison()).build();
61   * NeatChromosomeSpec spec = NeatChromosomeSpec.of(3, 2, -1.0f, 1.0f);
62   * 
63   * boolean canHandle = handler.canHandle(resolver, policy, spec);
64   * 
65   * // Resolve to concrete combinator
66   * ChromosomeCombinator<Double> combinator = handler.resolve(resolver, policy, spec);
67   * }</pre>
68   * 
69   * <p>Integration with genetic algorithm framework:
70   * <ul>
71   * <li><strong>Handler registration</strong>: Registered in EA execution context for automatic resolution</li>
72   * <li><strong>Policy-driven configuration</strong>: Behavior controlled by NeatCombination specifications</li>
73   * <li><strong>Resolver integration</strong>: Works with chromosome combinator resolver system</li>
74   * <li><strong>Type safety</strong>: Ensures compatibility between policies and chromosome specifications</li>
75   * </ul>
76   * 
77   * <p>Parent comparison handler management:
78   * <ul>
79   * <li><strong>Handler locator</strong>: Uses ParentComparisonHandlerLocator for strategy resolution</li>
80   * <li><strong>Strategy flexibility</strong>: Supports different parent comparison approaches</li>
81   * <li><strong>Extensibility</strong>: New comparison strategies can be easily added</li>
82   * <li><strong>Policy validation</strong>: Ensures configured strategies are available</li>
83   * </ul>
84   * 
85   * <p>Performance considerations:
86   * <ul>
87   * <li><strong>Handler caching</strong>: Parent comparison handlers cached for reuse</li>
88   * <li><strong>Innovation sorting</strong>: Leverages pre-sorted connection lists for efficiency</li>
89   * <li><strong>Memory efficiency</strong>: Minimal memory allocation during crossover</li>
90   * <li><strong>Parallel processing</strong>: Thread-safe operations for concurrent crossover</li>
91   * </ul>
92   * 
93   * @param <T> the fitness value type (typically Double)
94   * @see NeatCombination
95   * @see NeatChromosomeCombinator
96   * @see ParentComparisonHandler
97   * @see ChromosomeCombinatorHandler
98   */
99  public class NeatCombinationHandler<T extends Comparable<T>> implements ChromosomeCombinatorHandler<T> {
100 
101 	private final RandomGenerator randomGenerator;
102 	private final ParentComparisonHandlerLocator parentComparisonHandlerLocator;
103 
104 	/**
105 	 * Constructs a new NEAT combination handler with the specified random generator.
106 	 * 
107 	 * <p>The random generator is used for stochastic decisions during genetic crossover, such as choosing which parent
108 	 * contributes genes when multiple options are available. A parent comparison handler locator is automatically
109 	 * created to manage comparison strategies.
110 	 * 
111 	 * @param _randomGenerator random number generator for stochastic crossover operations
112 	 * @throws IllegalArgumentException if randomGenerator is null
113 	 */
114 	public NeatCombinationHandler(final RandomGenerator _randomGenerator) {
115 		Objects.requireNonNull(_randomGenerator);
116 
117 		this.randomGenerator = _randomGenerator;
118 		this.parentComparisonHandlerLocator = new ParentComparisonHandlerLocator();
119 	}
120 
121 	/**
122 	 * Determines whether this handler can process the given combination policy and chromosome specification.
123 	 * 
124 	 * <p>This handler specifically processes NeatCombination policies applied to NeatChromosomeSpec specifications,
125 	 * ensuring type compatibility for NEAT neural network genetic crossover.
126 	 * 
127 	 * @param chromosomeCombinatorResolver resolver for nested combination policies
128 	 * @param combinationPolicy            the combination policy to check
129 	 * @param chromosome                   the chromosome specification to check
130 	 * @return true if policy is NeatCombination and chromosome is NeatChromosomeSpec, false otherwise
131 	 * @throws IllegalArgumentException if any parameter is null
132 	 */
133 	@Override
134 	public boolean canHandle(final ChromosomeCombinatorResolver<T> chromosomeCombinatorResolver,
135 			final CombinationPolicy combinationPolicy, final ChromosomeSpec chromosome) {
136 		Objects.requireNonNull(chromosomeCombinatorResolver);
137 		Objects.requireNonNull(combinationPolicy);
138 		Objects.requireNonNull(chromosome);
139 
140 		return combinationPolicy instanceof NeatCombination && chromosome instanceof NeatChromosomeSpec;
141 	}
142 
143 	/**
144 	 * Resolves a NEAT combination policy into a concrete chromosome combinator.
145 	 * 
146 	 * <p>This method creates a NeatChromosomeCombinator configured with the appropriate parent comparison strategy. The
147 	 * parent comparison policy is resolved using the handler locator to determine how genetic inheritance should be
148 	 * managed during crossover.
149 	 * 
150 	 * <p>Resolution process:
151 	 * <ol>
152 	 * <li>Extract parent comparison policy from the NEAT combination configuration</li>
153 	 * <li>Locate appropriate parent comparison handler for the policy</li>
154 	 * <li>Create NeatChromosomeCombinator with resolved components</li>
155 	 * <li>Return configured combinator ready for genetic crossover</li>
156 	 * </ol>
157 	 * 
158 	 * @param chromosomeCombinatorResolver resolver for nested combination policies
159 	 * @param combinationPolicy            the NEAT combination policy to resolve
160 	 * @param chromosome                   the NEAT chromosome specification
161 	 * @return a configured chromosome combinator for NEAT genetic crossover
162 	 * @throws IllegalArgumentException if any parameter is null or of wrong type
163 	 * @throws IllegalStateException    if no parent comparison handler found for the policy
164 	 */
165 	@Override
166 	public ChromosomeCombinator<T> resolve(final ChromosomeCombinatorResolver<T> chromosomeCombinatorResolver,
167 			final CombinationPolicy combinationPolicy, final ChromosomeSpec chromosome) {
168 		Objects.requireNonNull(chromosomeCombinatorResolver);
169 		Objects.requireNonNull(combinationPolicy);
170 		Objects.requireNonNull(chromosome);
171 		Validate.isInstanceOf(NeatCombination.class, combinationPolicy);
172 		Validate.isInstanceOf(NeatChromosomeSpec.class, chromosome);
173 
174 		final var neatCombination = (NeatCombination) combinationPolicy;
175 
176 		final ParentComparisonPolicy parentComparisonPolicy = neatCombination.parentComparisonPolicy();
177 		final Optional<ParentComparisonHandler> parentComparisonHandlerOpt = parentComparisonHandlerLocator
178 				.find(parentComparisonPolicy);
179 		final ParentComparisonHandler parentComparisonHandler = parentComparisonHandlerOpt.orElseThrow(
180 				() -> new IllegalStateException(
181 						"Could not find a parent comparison handler for policy: " + parentComparisonPolicy));
182 
183 		return new NeatChromosomeCombinator<>(randomGenerator, neatCombination, parentComparisonHandler);
184 	}
185 }