NeatNodeLayoutValidation.java

package net.bmahe.genetics4j.neat.spec;

import java.util.HashSet;
import java.util.List;
import java.util.Objects;

import org.apache.commons.lang3.Validate;

class NeatNodeLayoutValidation {

	private NeatNodeLayoutValidation() {
	}

	static void validate(final List<Integer> inputNodeIds, final List<Integer> outputNodeIds,
			final long hiddenNodeIdStartInclusive, final long hiddenNodeIdEndExclusive) {
		Objects.requireNonNull(inputNodeIds);
		Objects.requireNonNull(outputNodeIds);
		Validate.isTrue(inputNodeIds.isEmpty() == false, "At least one input node is required");
		Validate.isTrue(outputNodeIds.isEmpty() == false, "At least one output node is required");
		Validate.isTrue(hiddenNodeIdStartInclusive >= 0, "Hidden-node range start must be non-negative");
		Validate.isTrue(hiddenNodeIdStartInclusive < hiddenNodeIdEndExclusive, "Hidden-node range must not be empty");
		Validate.isTrue(
				hiddenNodeIdEndExclusive <= NeatNodeLayout.MAX_NODE_ID_EXCLUSIVE,
					"Hidden-node range exceeds the non-negative int domain");

		final var inputIds = new HashSet<Integer>();
		for (final Integer nodeId : inputNodeIds) {
			validateExternalId(nodeId, hiddenNodeIdStartInclusive, hiddenNodeIdEndExclusive);
			Validate.isTrue(inputIds.add(nodeId), "Duplicate input node ID: %d", nodeId);
		}

		final var outputIds = new HashSet<Integer>();
		for (final Integer nodeId : outputNodeIds) {
			validateExternalId(nodeId, hiddenNodeIdStartInclusive, hiddenNodeIdEndExclusive);
			Validate.isTrue(outputIds.add(nodeId), "Duplicate output node ID: %d", nodeId);
			Validate.isTrue(inputIds.contains(nodeId) == false, "Node ID is both an input and output: %d", nodeId);
		}
	}

	private static void validateExternalId(final Integer nodeId, final long hiddenNodeIdStartInclusive,
			final long hiddenNodeIdEndExclusive) {
		Objects.requireNonNull(nodeId);
		Validate.isTrue(nodeId >= 0, "External node ID must be non-negative: %d", nodeId);
		Validate.isTrue(
				nodeId < hiddenNodeIdStartInclusive || nodeId >= hiddenNodeIdEndExclusive,
					"External node ID %d conflicts with the hidden-node range",
					nodeId);
	}
}