View Javadoc
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>&gt; 0.5</strong>: Bias toward fitter parent, promotes convergence</li>
70   * <li><strong>&lt; 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>&gt; 0.5</strong>: Bias toward fitter parent, promotes convergence to good solutions</li>
121 	 * <li><strong>&lt; 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 }