View Javadoc
1   package net.bmahe.genetics4j.neat;
2   
3   import java.util.concurrent.atomic.AtomicInteger;
4   
5   /**
6    * Generates unique identifiers for NEAT (NeuroEvolution of Augmenting Topologies) species.
7    * 
8    * <p>SpeciesIdGenerator provides thread-safe generation of unique species identifiers used
9    * to distinguish between different species in the NEAT population. Each species receives
10   * a unique ID that remains constant throughout its lifecycle, enabling species tracking
11   * across generations and proper species management.
12   * 
13   * <p>Key characteristics:
14   * <ul>
15   * <li><strong>Thread safety</strong>: Concurrent ID generation for parallel species creation</li>
16   * <li><strong>Uniqueness guarantee</strong>: Each generated ID is unique across the generator's lifetime</li>
17   * <li><strong>Sequential ordering</strong>: IDs are generated in sequential order for consistent tracking</li>
18   * <li><strong>Configurable start</strong>: Initial ID value can be customized for different scenarios</li>
19   * </ul>
20   * 
21   * <p>Species lifecycle integration:
22   * <ul>
23   * <li><strong>Species creation</strong>: New species receive unique IDs upon formation</li>
24   * <li><strong>Species tracking</strong>: IDs enable consistent species identification across generations</li>
25   * <li><strong>Population management</strong>: Species IDs facilitate population organization and statistics</li>
26   * <li><strong>Evolution monitoring</strong>: IDs enable tracking of species formation, growth, and extinction</li>
27   * </ul>
28   * 
29   * <p>Common usage patterns:
30   * <pre>{@code
31   * // Default species ID generator (starts from 0)
32   * SpeciesIdGenerator generator = new SpeciesIdGenerator();
33   * 
34   * // Custom starting ID
35   * SpeciesIdGenerator customGenerator = new SpeciesIdGenerator(1000);
36   * 
37   * // Generate unique species IDs
38   * int speciesId1 = generator.computeNewId();  // Returns 0
39   * int speciesId2 = generator.computeNewId();  // Returns 1
40   * int speciesId3 = generator.computeNewId();  // Returns 2
41   * 
42   * // Create species with generated IDs
43   * Species<Double> species1 = new Species<>(speciesId1, ancestors1);
44   * Species<Double> species2 = new Species<>(speciesId2, ancestors2);
45   * 
46   * // Thread-safe concurrent generation
47   * CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(generator::computeNewId);
48   * CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(generator::computeNewId);
49   * // Both futures will receive unique IDs
50   * }</pre>
51   * 
52   * <p>Integration with NEAT species management:
53   * <ul>
54   * <li><strong>Species formation</strong>: New species created during population organization get unique IDs</li>
55   * <li><strong>Selection handlers</strong>: Used by NeatSelectionPolicyHandler for species tracking</li>
56   * <li><strong>Population statistics</strong>: Enables species-based metrics and analysis</li>
57   * <li><strong>Evolution context</strong>: Integrated into NEAT execution contexts for species management</li>
58   * </ul>
59   * 
60   * <p>Thread safety considerations:
61   * <ul>
62   * <li><strong>Atomic operations</strong>: Uses AtomicInteger for thread-safe ID generation</li>
63   * <li><strong>Concurrent access</strong>: Multiple threads can safely generate IDs simultaneously</li>
64   * <li><strong>Lock-free</strong>: No synchronization overhead for high-performance scenarios</li>
65   * <li><strong>Consistency</strong>: Guarantees unique IDs even under high concurrency</li>
66   * </ul>
67   * 
68   * <p>Performance characteristics:
69   * <ul>
70   * <li><strong>O(1) generation</strong>: Constant time ID generation</li>
71   * <li><strong>Memory efficient</strong>: Minimal memory footprint with single atomic counter</li>
72   * <li><strong>High throughput</strong>: Suitable for high-frequency species creation</li>
73   * <li><strong>No contention</strong>: Lock-free implementation avoids thread contention</li>
74   * </ul>
75   * 
76   * @see Species
77   * @see net.bmahe.genetics4j.neat.selection.NeatSelectionPolicyHandler
78   * @see NeatEAExecutionContexts
79   */
80  public class SpeciesIdGenerator {
81  
82  	public static final int DEFAULT_INITIAL_ID = 0;
83  
84  	private final AtomicInteger currentId;
85  
86  	/**
87  	 * Constructs a new species ID generator with the specified initial value.
88  	 * 
89  	 * <p>The initial value determines the first ID that will be generated.
90  	 * Subsequent IDs will be incremented sequentially from this starting point.
91  	 * 
92  	 * @param initialValue the first ID value to generate
93  	 */
94  	public SpeciesIdGenerator(final int initialValue) {
95  		currentId = new AtomicInteger(initialValue);
96  	}
97  
98  	/**
99  	 * Constructs a new species ID generator with the default initial value (0).
100 	 */
101 	public SpeciesIdGenerator() {
102 		this(DEFAULT_INITIAL_ID);
103 	}
104 
105 	/**
106 	 * Generates and returns a new unique species ID.
107 	 * 
108 	 * <p>This method atomically increments the internal counter and returns
109 	 * the previous value, ensuring that each call produces a unique identifier.
110 	 * The operation is thread-safe and can be called concurrently from multiple
111 	 * threads without risk of duplicate IDs.
112 	 * 
113 	 * @return a unique species identifier
114 	 */
115 	public int computeNewId() {
116 		return currentId.getAndIncrement();
117 	}
118 }