1 | package net.bmahe.genetics4j.neat.spec; | |
2 | ||
3 | import org.apache.commons.lang3.Validate; | |
4 | import org.immutables.value.Value; | |
5 | ||
6 | import net.bmahe.genetics4j.core.spec.chromosome.ChromosomeSpec; | |
7 | ||
8 | /** | |
9 | * Specification for NEAT (NeuroEvolution of Augmenting Topologies) neural network chromosomes. | |
10 | * | |
11 | * <p>NeatChromosomeSpec defines the structural parameters and constraints for creating NEAT neural network | |
12 | * chromosomes. This specification is used by chromosome factories to generate initial network topologies | |
13 | * and by genetic operators to understand network boundaries and weight constraints. | |
14 | * | |
15 | * <p>Key parameters: | |
16 | * <ul> | |
17 | * <li><strong>Network topology</strong>: Defines the number of input and output nodes</li> | |
18 | * <li><strong>Weight constraints</strong>: Specifies minimum and maximum connection weight values</li> | |
19 | * <li><strong>Network structure</strong>: Establishes the foundation for topology evolution</li> | |
20 | * <li><strong>Genetic boundaries</strong>: Provides constraints for mutation and crossover operations</li> | |
21 | * </ul> | |
22 | * | |
23 | * <p>NEAT network architecture: | |
24 | * <ul> | |
25 | * <li><strong>Input layer</strong>: Fixed number of input nodes (indices 0 to numInputs-1)</li> | |
26 | * <li><strong>Output layer</strong>: Fixed number of output nodes (indices numInputs to numInputs+numOutputs-1)</li> | |
27 | * <li><strong>Hidden layers</strong>: Variable number of hidden nodes added through evolution</li> | |
28 | * <li><strong>Connections</strong>: Weighted links between nodes with enable/disable states</li> | |
29 | * </ul> | |
30 | * | |
31 | * <p>Common usage patterns: | |
32 | * <pre>{@code | |
33 | * // Simple XOR problem specification | |
34 | * NeatChromosomeSpec xorSpec = NeatChromosomeSpec.of( | |
35 | * 2, // 2 inputs (A, B) | |
36 | * 1, // 1 output (A XOR B) | |
37 | * -1.0f, // minimum weight | |
38 | * 1.0f // maximum weight | |
39 | * ); | |
40 | * | |
41 | * // Complex classification problem | |
42 | * NeatChromosomeSpec classificationSpec = NeatChromosomeSpec.of( | |
43 | * 784, // 28x28 pixel inputs | |
44 | * 10, // 10 class outputs | |
45 | * -2.0f, // wider weight range | |
46 | * 2.0f | |
47 | * ); | |
48 | * | |
49 | * // Builder pattern for complex construction | |
50 | * NeatChromosomeSpec spec = new NeatChromosomeSpec.Builder() | |
51 | * .numInputs(5) | |
52 | * .numOutputs(3) | |
53 | * .minWeightValue(-1.5f) | |
54 | * .maxWeightValue(1.5f) | |
55 | * .build(); | |
56 | * }</pre> | |
57 | * | |
58 | * <p>Integration with NEAT ecosystem: | |
59 | * <ul> | |
60 | * <li><strong>Chromosome factories</strong>: Used by NeatConnectedChromosomeFactory for initial network generation</li> | |
61 | * <li><strong>Genetic operators</strong>: Provides constraints for weight mutations and structural changes</li> | |
62 | * <li><strong>Network evaluation</strong>: Defines input/output interfaces for fitness computation</li> | |
63 | * <li><strong>Evolution configuration</strong>: Establishes network parameters for entire evolutionary run</li> | |
64 | * </ul> | |
65 | * | |
66 | * <p>Weight constraint management: | |
67 | * <ul> | |
68 | * <li><strong>Mutation boundaries</strong>: Weight mutations respect min/max bounds</li> | |
69 | * <li><strong>Initial generation</strong>: New connections use weights within specified range</li> | |
70 | * <li><strong>Crossover inheritance</strong>: Parent weights may be clipped to child bounds</li> | |
71 | * <li><strong>Network stability</strong>: Bounded weights help prevent gradient explosion/vanishing</li> | |
72 | * </ul> | |
73 | * | |
74 | * <p>Validation and constraints: | |
75 | * <ul> | |
76 | * <li><strong>Positive node counts</strong>: Both input and output counts must be greater than zero</li> | |
77 | * <li><strong>Weight ordering</strong>: Minimum weight value should be less than maximum (not enforced)</li> | |
78 | * <li><strong>Reasonable bounds</strong>: Weight ranges should be appropriate for the problem domain</li> | |
79 | * <li><strong>Network capacity</strong>: Input/output counts should match problem requirements</li> | |
80 | * </ul> | |
81 | * | |
82 | * <p>Problem domain considerations: | |
83 | * <ul> | |
84 | * <li><strong>Classification</strong>: Output count should match number of classes</li> | |
85 | * <li><strong>Regression</strong>: Single or multiple outputs for continuous value prediction</li> | |
86 | * <li><strong>Control problems</strong>: Outputs correspond to control signals or actions</li> | |
87 | * <li><strong>Feature extraction</strong>: Input count should match feature dimensionality</li> | |
88 | * </ul> | |
89 | * | |
90 | * @see net.bmahe.genetics4j.neat.chromosomes.NeatChromosome | |
91 | * @see net.bmahe.genetics4j.neat.chromosomes.factory.NeatConnectedChromosomeFactory | |
92 | * @see net.bmahe.genetics4j.core.spec.EAConfiguration | |
93 | * @see ChromosomeSpec | |
94 | */ | |
95 | @Value.Immutable | |
96 | public abstract class NeatChromosomeSpec implements ChromosomeSpec { | |
97 | ||
98 | /** | |
99 | * Returns the number of input nodes for the neural network. | |
100 | * | |
101 | * <p>Input nodes receive external data and form the first layer of the network. | |
102 | * They are assigned indices 0 through numInputs-1 and do not apply activation | |
103 | * functions to their values. | |
104 | * | |
105 | * @return the number of input nodes (must be positive) | |
106 | */ | |
107 | @Value.Parameter | |
108 | public abstract int numInputs(); | |
109 | ||
110 | /** | |
111 | * Returns the number of output nodes for the neural network. | |
112 | * | |
113 | * <p>Output nodes produce the final results of network computation and form the | |
114 | * last layer of the network. They are assigned indices numInputs through | |
115 | * numInputs+numOutputs-1 and apply activation functions to their weighted sums. | |
116 | * | |
117 | * @return the number of output nodes (must be positive) | |
118 | */ | |
119 | @Value.Parameter | |
120 | public abstract int numOutputs(); | |
121 | ||
122 | /** | |
123 | * Returns the minimum allowed connection weight value. | |
124 | * | |
125 | * <p>This constraint is used by genetic operators to bound weight mutations | |
126 | * and ensure network stability. New connections and weight perturbations | |
127 | * should respect this lower bound. | |
128 | * | |
129 | * @return the minimum connection weight value | |
130 | */ | |
131 | @Value.Parameter | |
132 | public abstract float minWeightValue(); | |
133 | ||
134 | /** | |
135 | * Returns the maximum allowed connection weight value. | |
136 | * | |
137 | * <p>This constraint is used by genetic operators to bound weight mutations | |
138 | * and ensure network stability. New connections and weight perturbations | |
139 | * should respect this upper bound. | |
140 | * | |
141 | * @return the maximum connection weight value | |
142 | */ | |
143 | @Value.Parameter | |
144 | public abstract float maxWeightValue(); | |
145 | ||
146 | @Value.Check | |
147 | protected void check() { | |
148 | Validate.isTrue(numInputs() > 0); | |
149 | Validate.isTrue(numOutputs() > 0); | |
150 | } | |
151 | ||
152 | public static class Builder extends ImmutableNeatChromosomeSpec.Builder { | |
153 | } | |
154 | ||
155 | /** | |
156 | * Creates a new NEAT chromosome specification with the given parameters. | |
157 | * | |
158 | * <p>This is a convenience factory method for creating chromosome specifications | |
159 | * with all required parameters. The specification will be validated to ensure | |
160 | * positive input and output counts. | |
161 | * | |
162 | * @param numInputs number of input nodes (must be positive) | |
163 | * @param numOutputs number of output nodes (must be positive) | |
164 | * @param minWeightValue minimum allowed connection weight | |
165 | * @param maxWeightValue maximum allowed connection weight | |
166 | * @return a new chromosome specification with the specified parameters | |
167 | * @throws IllegalArgumentException if numInputs <= 0 or numOutputs <= 0 | |
168 | */ | |
169 | public static NeatChromosomeSpec of(final int numInputs, final int numOutputs, final float minWeightValue, | |
170 | final float maxWeightValue) { | |
171 |
4
1. of : replaced return value with null for net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec::of → KILLED 2. of : replaced call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::numInputs with receiver → KILLED 3. of : removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::<init> → KILLED 4. of : removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::numInputs → KILLED |
return new Builder().numInputs(numInputs) |
172 |
2
1. of : removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::numOutputs → KILLED 2. of : replaced call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::numOutputs with receiver → KILLED |
.numOutputs(numOutputs) |
173 |
2
1. of : removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::minWeightValue → KILLED 2. of : replaced call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::minWeightValue with receiver → KILLED |
.minWeightValue(minWeightValue) |
174 |
2
1. of : replaced call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::maxWeightValue with receiver → KILLED 2. of : removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::maxWeightValue → KILLED |
.maxWeightValue(maxWeightValue) |
175 |
1
1. of : removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::build → KILLED |
.build(); |
176 | } | |
177 | } | |
Mutations | ||
171 |
1.1 2.2 3.3 4.4 |
|
172 |
1.1 2.2 |
|
173 |
1.1 2.2 |
|
174 |
1.1 2.2 |
|
175 |
1.1 |