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 to distinguish between
9 * different species in the NEAT population. Each species receives a unique ID that remains constant throughout its
10 * lifecycle, enabling species tracking across generations and proper species management.
11 *
12 * <p>Key characteristics:
13 * <ul>
14 * <li><strong>Thread safety</strong>: Concurrent ID generation for parallel species creation</li>
15 * <li><strong>Uniqueness guarantee</strong>: Each generated ID is unique across the generator's lifetime</li>
16 * <li><strong>Sequential ordering</strong>: IDs are generated in sequential order for consistent tracking</li>
17 * <li><strong>Configurable start</strong>: Initial ID value can be customized for different scenarios</li>
18 * </ul>
19 *
20 * <p>Species lifecycle integration:
21 * <ul>
22 * <li><strong>Species creation</strong>: New species receive unique IDs upon formation</li>
23 * <li><strong>Species tracking</strong>: IDs enable consistent species identification across generations</li>
24 * <li><strong>Population management</strong>: Species IDs facilitate population organization and statistics</li>
25 * <li><strong>Evolution monitoring</strong>: IDs enable tracking of species formation, growth, and extinction</li>
26 * </ul>
27 *
28 * <p>Common usage patterns:
29 *
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. Subsequent IDs will be incremented
90 * 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 the previous value, ensuring that each call
109 * produces a unique identifier. The operation is thread-safe and can be called concurrently from multiple threads
110 * without risk of duplicate IDs.
111 *
112 * @return a unique species identifier
113 */
114 public int computeNewId() {
115 return currentId.getAndIncrement();
116 }
117 }