Connection.java
package net.bmahe.genetics4j.neat;
import org.apache.commons.lang3.Validate;
import org.immutables.value.Value;
/**
* Represents a neural network connection in the NEAT (NeuroEvolution of Augmenting Topologies) algorithm.
*
* <p>A Connection is a fundamental building block of NEAT neural networks, representing a weighted link
* between two nodes. Each connection carries essential information for network topology, genetic operations,
* and evolutionary tracking through innovation numbers. Connections can be enabled or disabled, allowing
* for dynamic network topology exploration during evolution.
*
* <p>Key properties:
* <ul>
* <li><strong>Source and target nodes</strong>: Define the directed connection in the network graph</li>
* <li><strong>Connection weight</strong>: Determines the strength and polarity of signal transmission</li>
* <li><strong>Enabled state</strong>: Controls whether the connection participates in network computation</li>
* <li><strong>Innovation number</strong>: Unique identifier for genetic alignment and historical tracking</li>
* </ul>
*
* <p>NEAT algorithm integration:
* <ul>
* <li><strong>Genetic crossover</strong>: Innovation numbers enable proper gene alignment between parents</li>
* <li><strong>Structural mutations</strong>: Connections can be added, removed, or have their state toggled</li>
* <li><strong>Weight evolution</strong>: Connection weights are subject to mutation and optimization</li>
* <li><strong>Topology innovation</strong>: New connections track the historical order of structural changes</li>
* </ul>
*
* <p>Network computation role:
* <ul>
* <li><strong>Signal propagation</strong>: Enabled connections transmit weighted signals between nodes</li>
* <li><strong>Network evaluation</strong>: Only enabled connections participate in forward propagation</li>
* <li><strong>Topology dynamics</strong>: Enable/disable states allow topology exploration without gene loss</li>
* <li><strong>Weight optimization</strong>: Connection weights are evolved to optimize network performance</li>
* </ul>
*
* <p>Common usage patterns:
* <pre>{@code
* // Create a new connection
* Connection connection = Connection.of(
* 0, // from node index
* 3, // to node index
* 0.75f, // connection weight
* true, // enabled state
* 42 // innovation number
* );
*
* // Builder pattern for complex construction
* Connection connection = Connection.builder()
* .fromNodeIndex(1)
* .toNodeIndex(4)
* .weight(-0.5f)
* .isEnabled(false)
* .innovation(15)
* .build();
*
* // Copy with modifications
* Connection modifiedConnection = Connection.builder()
* .from(connection)
* .weight(connection.weight() + 0.1f)
* .build();
* }</pre>
*
* <p>Innovation number significance:
* <ul>
* <li><strong>Historical marking</strong>: Tracks when each connection type first appeared in evolution</li>
* <li><strong>Genetic alignment</strong>: Enables meaningful crossover between different network topologies</li>
* <li><strong>Compatibility distance</strong>: Used to measure genetic similarity for speciation</li>
* <li><strong>Structural tracking</strong>: Maintains evolutionary history of network topology changes</li>
* </ul>
*
* <p>Connection state management:
* <ul>
* <li><strong>Enabled connections</strong>: Actively participate in network computation</li>
* <li><strong>Disabled connections</strong>: Preserved in genome but don't affect network output</li>
* <li><strong>State mutations</strong>: Can toggle between enabled/disabled states during evolution</li>
* <li><strong>Structural preservation</strong>: Disabled connections maintain genetic information</li>
* </ul>
*
* <p>Validation and constraints:
* <ul>
* <li><strong>Node indices</strong>: Must be non-negative and reference valid nodes in the network</li>
* <li><strong>Innovation numbers</strong>: Must be non-negative and unique within the population context</li>
* <li><strong>Self-connections</strong>: Typically not allowed (from and to nodes must be different)</li>
* <li><strong>Weight bounds</strong>: While not enforced, weights typically range within reasonable bounds</li>
* </ul>
*
* @see NeatChromosome
* @see InnovationManager
* @see FeedForwardNetwork
* @see net.bmahe.genetics4j.neat.mutation.AddConnectionPolicyHandler
*/
@Value.Immutable
public interface Connection {
/**
* Returns the index of the source node for this connection.
*
* @return the source node index (non-negative)
*/
@Value.Parameter
int fromNodeIndex();
/**
* Returns the index of the target node for this connection.
*
* @return the target node index (non-negative)
*/
@Value.Parameter
int toNodeIndex();
/**
* Returns the weight of this connection.
*
* <p>The weight determines the strength and polarity of signal transmission through
* this connection. Positive weights amplify signals, negative weights invert them,
* and zero weights effectively disable signal transmission.
*
* @return the connection weight
*/
@Value.Parameter
float weight();
/**
* Returns whether this connection is enabled.
*
* <p>Enabled connections participate in network computation and signal propagation.
* Disabled connections are preserved in the genome but do not affect network output,
* allowing for topology exploration without gene loss.
*
* @return true if the connection is enabled, false otherwise
*/
@Value.Parameter
boolean isEnabled();
/**
* Returns the innovation number for this connection.
*
* <p>Innovation numbers are unique identifiers that track the historical order of
* structural mutations in the NEAT algorithm. They enable proper gene alignment
* during crossover and are used to calculate compatibility distance for speciation.
*
* @return the innovation number (non-negative)
*/
@Value.Parameter
int innovation();
@Value.Check
default void check() {
Validate.isTrue(fromNodeIndex() >= 0);
Validate.isTrue(toNodeIndex() >= 0);
Validate.isTrue(innovation() >= 0);
}
static class Builder extends ImmutableConnection.Builder {
}
static Builder builder() {
return new Builder();
}
/**
* Creates a new connection with the specified parameters.
*
* @param from the source node index
* @param to the target node index
* @param weight the connection weight
* @param isEnabled whether the connection is enabled
* @param innovation the innovation number
* @return a new connection instance
* @throws IllegalArgumentException if node indices or innovation number are negative
*/
static Connection of(final int from, final int to, final float weight, final boolean isEnabled,
final int innovation) {
return ImmutableConnection.of(from, to, weight, isEnabled, innovation);
}
/**
* Creates a copy of the specified connection.
*
* @param original the connection to copy
* @return a new connection instance with the same properties as the original
*/
static Connection copyOf(Connection original) {
return ImmutableConnection.copyOf(original);
}
}