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 10 * between two nodes. Each connection carries essential information for network topology, genetic operations, 11 * and evolutionary tracking through innovation numbers. Connections can be enabled or disabled, allowing 12 * for dynamic network topology 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 * <pre>{@code 40 * // Create a new connection 41 * Connection connection = Connection.of( 42 * 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 117 * this connection. Positive weights amplify signals, negative weights invert them, 118 * and zero weights effectively disable signal transmission. 119 * 120 * @return the connection weight 121 */ 122 @Value.Parameter 123 float weight(); 124 125 /** 126 * Returns whether this connection is enabled. 127 * 128 * <p>Enabled connections participate in network computation and signal propagation. 129 * Disabled connections are preserved in the genome but do not affect network output, 130 * allowing for topology exploration without gene loss. 131 * 132 * @return true if the connection is enabled, false otherwise 133 */ 134 @Value.Parameter 135 boolean isEnabled(); 136 137 /** 138 * Returns the innovation number for this connection. 139 * 140 * <p>Innovation numbers are unique identifiers that track the historical order of 141 * structural mutations in the NEAT algorithm. They enable proper gene alignment 142 * during crossover and are used to calculate compatibility distance for speciation. 143 * 144 * @return the innovation number (non-negative) 145 */ 146 @Value.Parameter 147 int innovation(); 148 149 @Value.Check 150 default void check() { 151 Validate.isTrue(fromNodeIndex() >= 0); 152 Validate.isTrue(toNodeIndex() >= 0); 153 Validate.isTrue(innovation() >= 0); 154 } 155 156 static class Builder extends ImmutableConnection.Builder { 157 } 158 159 static Builder builder() { 160 return new Builder(); 161 } 162 163 /** 164 * Creates a new connection with the specified parameters. 165 * 166 * @param from the source node index 167 * @param to the target node index 168 * @param weight the connection weight 169 * @param isEnabled whether the connection is enabled 170 * @param innovation the innovation number 171 * @return a new connection instance 172 * @throws IllegalArgumentException if node indices or innovation number are negative 173 */ 174 static Connection of(final int from, final int to, final float weight, final boolean isEnabled, 175 final int innovation) { 176 return ImmutableConnection.of(from, to, weight, isEnabled, innovation); 177 } 178 179 /** 180 * Creates a copy of the specified connection. 181 * 182 * @param original the connection to copy 183 * @return a new connection instance with the same properties as the original 184 */ 185 static Connection copyOf(Connection original) { 186 return ImmutableConnection.copyOf(original); 187 } 188 }