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