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 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 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 return ImmutableConnection.copyOf(original); 185 } 186 }