1 package net.bmahe.genetics4j.neat.spec.combination; 2 3 import org.apache.commons.lang3.Validate; 4 import org.immutables.value.Value; 5 6 import net.bmahe.genetics4j.core.spec.combination.CombinationPolicy; 7 import net.bmahe.genetics4j.neat.spec.combination.parentcompare.ParentComparisonPolicy; 8 import net.bmahe.genetics4j.neat.spec.combination.parentcompare.FitnessComparison; 9 10 /** 11 * Configuration policy for NEAT (NeuroEvolution of Augmenting Topologies) genetic crossover operations. 12 * 13 * <p>NeatCombination defines how neural network chromosomes should be recombined during genetic crossover, 14 * including inheritance biases, gene re-enabling policies, and parent comparison strategies. This policy 15 * controls the fundamental genetic operators that shape network topology evolution in NEAT. 16 * 17 * <p>Key crossover parameters: 18 * <ul> 19 * <li><strong>Inheritance threshold</strong>: Bias toward fitter parent for gene inheritance</li> 20 * <li><strong>Gene re-enabling</strong>: Probability of re-enabling disabled genes during crossover</li> 21 * <li><strong>Parent comparison</strong>: Strategy for determining relative parent fitness</li> 22 * <li><strong>Genetic alignment</strong>: Innovation-number-based gene matching</li> 23 * </ul> 24 * 25 * <p>NEAT genetic crossover process: 26 * <ol> 27 * <li><strong>Gene alignment</strong>: Match genes by innovation number between parents</li> 28 * <li><strong>Matching genes</strong>: Randomly inherit from either parent (biased by inheritance threshold)</li> 29 * <li><strong>Disjoint genes</strong>: Inherit from fitter parent based on parent comparison</li> 30 * <li><strong>Excess genes</strong>: Inherit from fitter parent beyond less fit parent's range</li> 31 * <li><strong>Gene state</strong>: Apply re-enabling policy to disabled genes</li> 32 * </ol> 33 * 34 * <p>Gene inheritance strategies: 35 * <ul> 36 * <li><strong>Matching genes</strong>: Present in both parents with same innovation number</li> 37 * <li><strong>Disjoint genes</strong>: Present in one parent within other parent's innovation range</li> 38 * <li><strong>Excess genes</strong>: Present in one parent beyond other parent's highest innovation</li> 39 * <li><strong>Disabled genes</strong>: May be re-enabled based on re-enabling threshold</li> 40 * </ul> 41 * 42 * <p>Common usage patterns: 43 * <pre>{@code 44 * // Default NEAT crossover configuration 45 * NeatCombination defaultPolicy = NeatCombination.build(); 46 * 47 * // Custom crossover with fitness bias 48 * NeatCombination biasedPolicy = NeatCombination.builder() 49 * .inheritanceThresold(0.7) // 70% bias toward fitter parent 50 * .reenableGeneInheritanceThresold(0.3) // 30% chance to re-enable genes 51 * .parentComparisonPolicy(FitnessComparison.build()) 52 * .build(); 53 * 54 * // Unbiased crossover for diversity 55 * NeatCombination unbiasedPolicy = NeatCombination.builder() 56 * .inheritanceThresold(0.5) // No bias toward either parent 57 * .reenableGeneInheritanceThresold(0.1) // Low re-enabling rate 58 * .build(); 59 * 60 * // Use in EA configuration 61 * var combinationSpec = ChromosomeCombinatorSpec.builder() 62 * .combinationPolicy(biasedPolicy) 63 * .build(); 64 * }</pre> 65 * 66 * <p>Inheritance threshold effects: 67 * <ul> 68 * <li><strong>0.5 (default)</strong>: Unbiased inheritance, equal probability from both parents</li> 69 * <li><strong>> 0.5</strong>: Bias toward fitter parent, promotes convergence</li> 70 * <li><strong>< 0.5</strong>: Bias toward less fit parent, increases diversity</li> 71 * <li><strong>1.0</strong>: Always inherit from fitter parent (if determinable)</li> 72 * </ul> 73 * 74 * <p>Gene re-enabling mechanism: 75 * <ul> 76 * <li><strong>Historical information</strong>: Disabled genes preserve connection topology</li> 77 * <li><strong>Re-activation chance</strong>: Allows previously disabled connections to contribute again</li> 78 * <li><strong>Topology exploration</strong>: Enables rediscovery of useful connection patterns</li> 79 * <li><strong>Genetic diversity</strong>: Prevents permanent loss of structural information</li> 80 * </ul> 81 * 82 * <p>Parent comparison integration: 83 * <ul> 84 * <li><strong>Fitness comparison</strong>: Standard fitness-based parent ranking</li> 85 * <li><strong>Custom strategies</strong>: Pluggable comparison policies for different problem domains</li> 86 * <li><strong>Multi-objective support</strong>: Compatible with complex fitness landscapes</li> 87 * <li><strong>Equal fitness handling</strong>: Special rules when parents have identical fitness</li> 88 * </ul> 89 * 90 * <p>Performance considerations: 91 * <ul> 92 * <li><strong>Innovation sorting</strong>: Leverages pre-sorted connection lists for O(n) crossover</li> 93 * <li><strong>Memory efficiency</strong>: Minimal allocation during gene inheritance</li> 94 * <li><strong>Cache-friendly</strong>: Sequential access patterns for better cache performance</li> 95 * <li><strong>Parallelizable</strong>: Crossover operations can be executed concurrently</li> 96 * </ul> 97 * 98 * @see ParentComparisonPolicy 99 * @see FitnessComparison 100 * @see net.bmahe.genetics4j.neat.combination.NeatChromosomeCombinator 101 * @see CombinationPolicy 102 */ 103 @Value.Immutable 104 public interface NeatCombination extends CombinationPolicy { 105 106 public static final double DEFAULT_INHERITANCE_THRESHOLD = 0.5d; 107 108 public static final double DEFAULT_REENABLE_GENE_INHERITANCE_THRESHOLD = 0.25d; 109 110 /** 111 * Returns the inheritance threshold for biasing gene selection toward fitter parents. 112 * 113 * <p>This threshold controls the probability of inheriting genes from the fitter parent 114 * during crossover. Higher values bias inheritance toward the better performing parent, 115 * while lower values provide more equal inheritance or even bias toward the less fit parent. 116 * 117 * <p>Inheritance behavior: 118 * <ul> 119 * <li><strong>0.5 (default)</strong>: Unbiased inheritance, equal probability from both parents</li> 120 * <li><strong>> 0.5</strong>: Bias toward fitter parent, promotes convergence to good solutions</li> 121 * <li><strong>< 0.5</strong>: Bias toward less fit parent, increases population diversity</li> 122 * <li><strong>1.0</strong>: Always inherit from fitter parent when fitness differs</li> 123 * <li><strong>0.0</strong>: Always inherit from less fit parent when fitness differs</li> 124 * </ul> 125 * 126 * @return inheritance threshold value between 0.0 and 1.0 (inclusive) 127 */ 128 @Value.Default 129 default public double inheritanceThresold() { 130 return DEFAULT_INHERITANCE_THRESHOLD; 131 } 132 133 /** 134 * Returns the threshold for re-enabling disabled genes during crossover. 135 * 136 * <p>When a gene (connection) is disabled in one parent but enabled in the other, 137 * this threshold determines the probability that the gene will be enabled in the 138 * offspring. This mechanism prevents permanent loss of potentially useful connections 139 * and allows rediscovery of structural innovations. 140 * 141 * <p>Re-enabling behavior: 142 * <ul> 143 * <li><strong>0.25 (default)</strong>: 25% chance to re-enable disabled connections</li> 144 * <li><strong>0.0</strong>: Never re-enable disabled connections</li> 145 * <li><strong>1.0</strong>: Always re-enable connections that are enabled in either parent</li> 146 * <li><strong>Higher values</strong>: More aggressive topology exploration</li> 147 * <li><strong>Lower values</strong>: More conservative structural preservation</li> 148 * </ul> 149 * 150 * @return re-enabling threshold value between 0.0 and 1.0 (inclusive) 151 */ 152 @Value.Default 153 default public double reenableGeneInheritanceThresold() { 154 return DEFAULT_REENABLE_GENE_INHERITANCE_THRESHOLD; 155 } 156 157 /** 158 * Returns the policy used to compare parent fitness for inheritance decisions. 159 * 160 * <p>The parent comparison policy determines which parent is considered "fitter" 161 * for the purposes of biased gene inheritance. This affects how disjoint and excess 162 * genes are inherited and how the inheritance threshold is applied. 163 * 164 * <p>Available comparison strategies: 165 * <ul> 166 * <li><strong>FitnessComparison (default)</strong>: Compare parents based on their fitness values</li> 167 * <li><strong>Custom policies</strong>: Pluggable strategies for domain-specific comparisons</li> 168 * <li><strong>Multi-objective</strong>: Specialized comparisons for multi-objective optimization</li> 169 * <li><strong>Equal fitness handling</strong>: Specific behavior when parents have identical fitness</li> 170 * </ul> 171 * 172 * @return the parent comparison policy (defaults to fitness-based comparison) 173 */ 174 @Value.Default 175 default public ParentComparisonPolicy parentComparisonPolicy() { 176 return FitnessComparison.build(); 177 } 178 179 @Value.Check 180 default void check() { 181 Validate.inclusiveBetween(0, 1, inheritanceThresold()); 182 Validate.inclusiveBetween(0, 1, reenableGeneInheritanceThresold()); 183 } 184 185 class Builder extends ImmutableNeatCombination.Builder { 186 } 187 188 static Builder builder() { 189 return new Builder(); 190 } 191 192 /** 193 * Creates a NEAT combination policy with default settings. 194 * 195 * <p>Default configuration: 196 * <ul> 197 * <li>Inheritance threshold: 0.5 (unbiased)</li> 198 * <li>Gene re-enabling threshold: 0.25 (25% chance)</li> 199 * <li>Parent comparison: Fitness-based comparison</li> 200 * </ul> 201 * 202 * @return a new NEAT combination policy with default settings 203 */ 204 static NeatCombination build() { 205 return builder().build(); 206 } 207 208 }