NodeIdManagerRegistry.java

package net.bmahe.genetics4j.neat;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.Validate;

import net.bmahe.genetics4j.neat.spec.NeatNodeLayout;

/**
 * Maintains one population-scoped {@link NodeIdManager} per semantic node layout.
 *
 * <p>Layouts are keyed by their ordered input IDs, ordered output IDs, and hidden-node range rather than their concrete
 * implementation class. Semantically equivalent layout implementations therefore share allocation history.
 */
public class NodeIdManagerRegistry {

	private record LayoutKey(List<Integer> inputNodeIds, List<Integer> outputNodeIds, long hiddenStart, long hiddenEnd) {
		private LayoutKey(final NeatNodeLayout layout) {
			this(List.copyOf(layout.inputNodeIds()),
					List.copyOf(layout.outputNodeIds()),
					layout.hiddenNodeIdStartInclusive(),
					layout.hiddenNodeIdEndExclusive());
		}
	}

	private final ConcurrentHashMap<LayoutKey, NodeIdManager> managers = new ConcurrentHashMap<>();

	/**
	 * Returns the shared node-ID manager for a layout, creating it when first requested.
	 *
	 * @param nodeLayout node layout used by a population
	 * @return the shared manager for the layout's semantic key
	 * @throws NullPointerException if {@code nodeLayout} is {@code null}
	 */
	public NodeIdManager managerFor(final NeatNodeLayout nodeLayout) {
		Validate.notNull(nodeLayout);
		return managers.computeIfAbsent(new LayoutKey(nodeLayout), ignored -> new NodeIdManager(nodeLayout));
	}
}