View Javadoc
1   package net.bmahe.genetics4j.neat;
2   
3   import java.util.List;
4   import java.util.Objects;
5   import java.util.concurrent.ConcurrentHashMap;
6   
7   import net.bmahe.genetics4j.neat.spec.NeatNodeLayout;
8   
9   /**
10   * Maintains one population-scoped {@link NodeIdManager} per semantic node layout.
11   *
12   * <p>Layouts are keyed by their ordered input IDs, ordered output IDs, and hidden-node range rather than their concrete
13   * implementation class. Semantically equivalent layout implementations therefore share allocation history.
14   */
15  public class NodeIdManagerRegistry {
16  
17  	private record LayoutKey(List<Integer> inputNodeIds, List<Integer> outputNodeIds, long hiddenStart, long hiddenEnd) {
18  		private LayoutKey(final NeatNodeLayout layout) {
19  			this(List.copyOf(layout.inputNodeIds()),
20  					List.copyOf(layout.outputNodeIds()),
21  					layout.hiddenNodeIdStartInclusive(),
22  					layout.hiddenNodeIdEndExclusive());
23  		}
24  	}
25  
26  	private final ConcurrentHashMap<LayoutKey, NodeIdManager> managers = new ConcurrentHashMap<>();
27  
28  	/**
29  	 * Returns the shared node-ID manager for a layout, creating it when first requested.
30  	 *
31  	 * @param nodeLayout node layout used by a population
32  	 * @return the shared manager for the layout's semantic key
33  	 * @throws NullPointerException if {@code nodeLayout} is {@code null}
34  	 */
35  	public NodeIdManager managerFor(final NeatNodeLayout nodeLayout) {
36  		Objects.requireNonNull(nodeLayout);
37  		return managers.computeIfAbsent(new LayoutKey(nodeLayout), ignored -> new NodeIdManager(nodeLayout));
38  	}
39  }