| 1 | package net.bmahe.genetics4j.neat; | |
| 2 | ||
| 3 | import org.apache.commons.lang3.Validate; | |
| 4 | import org.immutables.value.Value; | |
| 5 | ||
| 6 | /** | |
| 7 | * Represents a neural network connection in the NEAT (NeuroEvolution of Augmenting Topologies) algorithm. | |
| 8 | * | |
| 9 | * <p>A Connection is a fundamental building block of NEAT neural networks, representing a weighted link between two | |
| 10 | * nodes. Each connection carries essential information for network topology, genetic operations, and evolutionary | |
| 11 | * tracking through innovation numbers. Connections can be enabled or disabled, allowing for dynamic network topology | |
| 12 | * exploration during evolution. | |
| 13 | * | |
| 14 | * <p>Key properties: | |
| 15 | * <ul> | |
| 16 | * <li><strong>Source and target nodes</strong>: Define the directed connection in the network graph</li> | |
| 17 | * <li><strong>Connection weight</strong>: Determines the strength and polarity of signal transmission</li> | |
| 18 | * <li><strong>Enabled state</strong>: Controls whether the connection participates in network computation</li> | |
| 19 | * <li><strong>Innovation number</strong>: Unique identifier for genetic alignment and historical tracking</li> | |
| 20 | * </ul> | |
| 21 | * | |
| 22 | * <p>NEAT algorithm integration: | |
| 23 | * <ul> | |
| 24 | * <li><strong>Genetic crossover</strong>: Innovation numbers enable proper gene alignment between parents</li> | |
| 25 | * <li><strong>Structural mutations</strong>: Connections can be added, removed, or have their state toggled</li> | |
| 26 | * <li><strong>Weight evolution</strong>: Connection weights are subject to mutation and optimization</li> | |
| 27 | * <li><strong>Topology innovation</strong>: New connections track the historical order of structural changes</li> | |
| 28 | * </ul> | |
| 29 | * | |
| 30 | * <p>Network computation role: | |
| 31 | * <ul> | |
| 32 | * <li><strong>Signal propagation</strong>: Enabled connections transmit weighted signals between nodes</li> | |
| 33 | * <li><strong>Network evaluation</strong>: Only enabled connections participate in forward propagation</li> | |
| 34 | * <li><strong>Topology dynamics</strong>: Enable/disable states allow topology exploration without gene loss</li> | |
| 35 | * <li><strong>Weight optimization</strong>: Connection weights are evolved to optimize network performance</li> | |
| 36 | * </ul> | |
| 37 | * | |
| 38 | * <p>Common usage patterns: | |
| 39 | * | |
| 40 | * <pre>{@code | |
| 41 | * // Create a new connection | |
| 42 | * Connection connection = Connection.of(0, // from node index | |
| 43 | * 3, // to node index | |
| 44 | * 0.75f, // connection weight | |
| 45 | * true, // enabled state | |
| 46 | * 42 // innovation number | |
| 47 | * ); | |
| 48 | * | |
| 49 | * // Builder pattern for complex construction | |
| 50 | * Connection connection = Connection.builder() | |
| 51 | * .fromNodeIndex(1) | |
| 52 | * .toNodeIndex(4) | |
| 53 | * .weight(-0.5f) | |
| 54 | * .isEnabled(false) | |
| 55 | * .innovation(15) | |
| 56 | * .build(); | |
| 57 | * | |
| 58 | * // Copy with modifications | |
| 59 | * Connection modifiedConnection = Connection.builder() | |
| 60 | * .from(connection) | |
| 61 | * .weight(connection.weight() + 0.1f) | |
| 62 | * .build(); | |
| 63 | * }</pre> | |
| 64 | * | |
| 65 | * <p>Innovation number significance: | |
| 66 | * <ul> | |
| 67 | * <li><strong>Historical marking</strong>: Tracks when each connection type first appeared in evolution</li> | |
| 68 | * <li><strong>Genetic alignment</strong>: Enables meaningful crossover between different network topologies</li> | |
| 69 | * <li><strong>Compatibility distance</strong>: Used to measure genetic similarity for speciation</li> | |
| 70 | * <li><strong>Structural tracking</strong>: Maintains evolutionary history of network topology changes</li> | |
| 71 | * </ul> | |
| 72 | * | |
| 73 | * <p>Connection state management: | |
| 74 | * <ul> | |
| 75 | * <li><strong>Enabled connections</strong>: Actively participate in network computation</li> | |
| 76 | * <li><strong>Disabled connections</strong>: Preserved in genome but don't affect network output</li> | |
| 77 | * <li><strong>State mutations</strong>: Can toggle between enabled/disabled states during evolution</li> | |
| 78 | * <li><strong>Structural preservation</strong>: Disabled connections maintain genetic information</li> | |
| 79 | * </ul> | |
| 80 | * | |
| 81 | * <p>Validation and constraints: | |
| 82 | * <ul> | |
| 83 | * <li><strong>Node indices</strong>: Must be non-negative and reference valid nodes in the network</li> | |
| 84 | * <li><strong>Innovation numbers</strong>: Must be non-negative and unique within the population context</li> | |
| 85 | * <li><strong>Self-connections</strong>: Typically not allowed (from and to nodes must be different)</li> | |
| 86 | * <li><strong>Weight bounds</strong>: While not enforced, weights typically range within reasonable bounds</li> | |
| 87 | * </ul> | |
| 88 | * | |
| 89 | * @see NeatChromosome | |
| 90 | * @see InnovationManager | |
| 91 | * @see FeedForwardNetwork | |
| 92 | * @see net.bmahe.genetics4j.neat.mutation.AddConnectionPolicyHandler | |
| 93 | */ | |
| 94 | @Value.Immutable | |
| 95 | public interface Connection { | |
| 96 | ||
| 97 | /** | |
| 98 | * Returns the index of the source node for this connection. | |
| 99 | * | |
| 100 | * @return the source node index (non-negative) | |
| 101 | */ | |
| 102 | @Value.Parameter | |
| 103 | int fromNodeIndex(); | |
| 104 | ||
| 105 | /** | |
| 106 | * Returns the index of the target node for this connection. | |
| 107 | * | |
| 108 | * @return the target node index (non-negative) | |
| 109 | */ | |
| 110 | @Value.Parameter | |
| 111 | int toNodeIndex(); | |
| 112 | ||
| 113 | /** | |
| 114 | * Returns the weight of this connection. | |
| 115 | * | |
| 116 | * <p>The weight determines the strength and polarity of signal transmission through this connection. Positive | |
| 117 | * weights amplify signals, negative weights invert them, and zero weights effectively disable signal transmission. | |
| 118 | * | |
| 119 | * @return the connection weight | |
| 120 | */ | |
| 121 | @Value.Parameter | |
| 122 | float weight(); | |
| 123 | ||
| 124 | /** | |
| 125 | * Returns whether this connection is enabled. | |
| 126 | * | |
| 127 | * <p>Enabled connections participate in network computation and signal propagation. Disabled connections are | |
| 128 | * preserved in the genome but do not affect network output, allowing for topology exploration without gene loss. | |
| 129 | * | |
| 130 | * @return true if the connection is enabled, false otherwise | |
| 131 | */ | |
| 132 | @Value.Parameter | |
| 133 | boolean isEnabled(); | |
| 134 | ||
| 135 | /** | |
| 136 | * Returns the innovation number for this connection. | |
| 137 | * | |
| 138 | * <p>Innovation numbers are unique identifiers that track the historical order of structural mutations in the NEAT | |
| 139 | * algorithm. They enable proper gene alignment during crossover and are used to calculate compatibility distance for | |
| 140 | * speciation. | |
| 141 | * | |
| 142 | * @return the innovation number (non-negative) | |
| 143 | */ | |
| 144 | @Value.Parameter | |
| 145 | int innovation(); | |
| 146 | ||
| 147 | @Value.Check | |
| 148 | default void check() { | |
| 149 | Validate.isTrue(fromNodeIndex() >= 0); | |
| 150 | Validate.isTrue(toNodeIndex() >= 0); | |
| 151 | Validate.isTrue(innovation() >= 0); | |
| 152 | } | |
| 153 | ||
| 154 | static class Builder extends ImmutableConnection.Builder { | |
| 155 | } | |
| 156 | ||
| 157 | static Builder builder() { | |
| 158 |
2
1. builder : removed call to net/bmahe/genetics4j/neat/Connection$Builder::<init> → KILLED 2. builder : replaced return value with null for net/bmahe/genetics4j/neat/Connection::builder → KILLED |
return new Builder(); |
| 159 | } | |
| 160 | ||
| 161 | /** | |
| 162 | * Creates a new connection with the specified parameters. | |
| 163 | * | |
| 164 | * @param from the source node index | |
| 165 | * @param to the target node index | |
| 166 | * @param weight the connection weight | |
| 167 | * @param isEnabled whether the connection is enabled | |
| 168 | * @param innovation the innovation number | |
| 169 | * @return a new connection instance | |
| 170 | * @throws IllegalArgumentException if node indices or innovation number are negative | |
| 171 | */ | |
| 172 | static Connection of(final int from, final int to, final float weight, final boolean isEnabled, | |
| 173 | final int innovation) { | |
| 174 |
2
1. of : replaced return value with null for net/bmahe/genetics4j/neat/Connection::of → KILLED 2. of : removed call to net/bmahe/genetics4j/neat/ImmutableConnection::of → KILLED |
return ImmutableConnection.of(from, to, weight, isEnabled, innovation); |
| 175 | } | |
| 176 | ||
| 177 | /** | |
| 178 | * Creates a copy of the specified connection. | |
| 179 | * | |
| 180 | * @param original the connection to copy | |
| 181 | * @return a new connection instance with the same properties as the original | |
| 182 | */ | |
| 183 | static Connection copyOf(Connection original) { | |
| 184 |
3
1. copyOf : replaced call to net/bmahe/genetics4j/neat/ImmutableConnection::copyOf with argument → SURVIVED 2. copyOf : removed call to net/bmahe/genetics4j/neat/ImmutableConnection::copyOf → KILLED 3. copyOf : replaced return value with null for net/bmahe/genetics4j/neat/Connection::copyOf → KILLED |
return ImmutableConnection.copyOf(original); |
| 185 | } | |
| 186 | } | |
Mutations | ||
| 158 |
1.1 2.2 |
|
| 174 |
1.1 2.2 |
|
| 184 |
1.1 2.2 3.3 |