NeatChromosomeSpec.java

1
package net.bmahe.genetics4j.neat.spec;
2
3
import java.util.Objects;
4
5
import org.apache.commons.lang3.Validate;
6
import org.immutables.value.Value;
7
8
import net.bmahe.genetics4j.core.spec.chromosome.ChromosomeSpec;
9
10
/**
11
 * Specification for NEAT (NeuroEvolution of Augmenting Topologies) neural network chromosomes.
12
 *
13
 * <p>A specification defines the stable identities and vector order of the network's input and output nodes, the
14
 * namespace available to hidden nodes, and the bounds applied to connection weights. Chromosome factories and genetic
15
 * operators use the same {@link NeatNodeLayout} throughout an evolutionary run so structural mutations do not relabel
16
 * existing nodes.
17
 *
18
 * <p>Contiguous layouts preserve the traditional NEAT numbering scheme. Inputs start at zero, outputs immediately
19
 * follow the inputs, and hidden-node IDs start after the outputs:
20
 *
21
 * <pre>{@code
22
 * NeatChromosomeSpec xorSpec = NeatChromosomeSpec.of(
23
 * 		2, // input IDs [0, 1]
24
 * 			1, // output ID [2]
25
 * 			-1.0f, // minimum connection weight
26
 * 			1.0f); // maximum connection weight
27
 * }</pre>
28
 *
29
 * <p>Explicit layouts support stable, ordered, non-contiguous external IDs and a dedicated hidden-node range:
30
 *
31
 * <pre>{@code
32
 * NeatNodeLayout layout = NeatNodeLayout.explicit(
33
 * 		List.of(10, 1_000, 1_001), // ordered input IDs
34
 * 			List.of(102_000), // ordered output IDs
35
 * 			1_000_000, // hidden range start, inclusive
36
 * 			2_000_000); // hidden range end, exclusive
37
 *
38
 * NeatChromosomeSpec sparseSpec = new NeatChromosomeSpec.Builder().nodeLayout(layout)
39
 * 		.minWeightValue(-2.0f)
40
 * 		.maxWeightValue(2.0f)
41
 * 		.build();
42
 * }</pre>
43
 *
44
 * <p>Declaration order is significant: it defines how input and output vectors map to node IDs. Node IDs themselves
45
 * are opaque identities and need not be contiguous. A valid layout contains at least one input and one output, uses
46
 * unique non-negative external IDs, keeps input and output IDs disjoint, and reserves a non-empty hidden-node range
47
 * that does not overlap external IDs.
48
 *
49
 * <p>The minimum connection weight must be strictly less than the maximum. Factories use these bounds when creating
50
 * initial connections, and mutation operators use them when changing connection weights.
51
 *
52
 * @see NeatNodeLayout
53
 * @see net.bmahe.genetics4j.neat.chromosomes.NeatChromosome
54
 * @see net.bmahe.genetics4j.neat.chromosomes.factory.NeatConnectedChromosomeFactory
55
 * @see net.bmahe.genetics4j.core.spec.EAConfiguration
56
 */
57
@Value.Immutable
58
public abstract class NeatChromosomeSpec implements ChromosomeSpec {
59
60
	/**
61
	 * Returns the stable external node identities and hidden-node namespace for chromosomes created from this
62
	 * specification.
63
	 *
64
	 * @return the node layout
65
	 */
66
	@Value.Parameter
67
	public abstract NeatNodeLayout nodeLayout();
68
69
	/**
70
	 * Returns the minimum allowed connection weight.
71
	 *
72
	 * @return the inclusive lower bound for connection weights
73
	 */
74
	@Value.Parameter
75
	public abstract float minWeightValue();
76
77
	/**
78
	 * Returns the maximum allowed connection weight.
79
	 *
80
	 * @return the inclusive upper bound for connection weights
81
	 */
82
	@Value.Parameter
83
	public abstract float maxWeightValue();
84
85
	/**
86
	 * Returns the number of input nodes declared by {@link #nodeLayout()}.
87
	 *
88
	 * @return the positive number of input nodes
89
	 */
90
	public int numInputs() {
91 3 1. numInputs : replaced int return with 0 for net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec::numInputs → KILLED
2. numInputs : removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec::nodeLayout → KILLED
3. numInputs : removed call to net/bmahe/genetics4j/neat/spec/NeatNodeLayout::numInputs → KILLED
		return nodeLayout().numInputs();
92
	}
93
94
	/**
95
	 * Returns the number of output nodes declared by {@link #nodeLayout()}.
96
	 *
97
	 * @return the positive number of output nodes
98
	 */
99
	public int numOutputs() {
100 3 1. numOutputs : removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec::nodeLayout → KILLED
2. numOutputs : removed call to net/bmahe/genetics4j/neat/spec/NeatNodeLayout::numOutputs → KILLED
3. numOutputs : replaced int return with 0 for net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec::numOutputs → KILLED
		return nodeLayout().numOutputs();
101
	}
102
103
	@Value.Check
104
	protected void check() {
105
		Objects.requireNonNull(nodeLayout());
106
		Validate.isTrue(minWeightValue() < maxWeightValue(), "Minimum weight must be less than maximum weight");
107
	}
108
109
	/** Builds immutable NEAT chromosome specifications. */
110
	public static class Builder extends ImmutableNeatChromosomeSpec.Builder {
111
	}
112
113
	/**
114
	 * Creates a specification using the supplied node layout and connection-weight bounds.
115
	 *
116
	 * @param nodeLayout     stable external IDs and hidden-node namespace
117
	 * @param minWeightValue minimum allowed connection weight
118
	 * @param maxWeightValue maximum allowed connection weight
119
	 * @return a validated immutable chromosome specification
120
	 * @throws NullPointerException     if {@code nodeLayout} is {@code null}
121
	 * @throws IllegalArgumentException if {@code minWeightValue} is not less than {@code maxWeightValue}
122
	 */
123
	public static NeatChromosomeSpec of(final NeatNodeLayout nodeLayout, final float minWeightValue,
124
			final float maxWeightValue) {
125 9 1. of : replaced call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::nodeLayout with receiver → KILLED
2. of : replaced call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::maxWeightValue with receiver → KILLED
3. of : replaced call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::minWeightValue with receiver → KILLED
4. of : replaced return value with null for net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec::of → KILLED
5. of : removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::<init> → KILLED
6. of : removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::build → KILLED
7. of : removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::maxWeightValue → KILLED
8. of : removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::nodeLayout → KILLED
9. of : removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::minWeightValue → KILLED
		return new Builder().nodeLayout(nodeLayout).minWeightValue(minWeightValue).maxWeightValue(maxWeightValue).build();
126
	}
127
128
	/**
129
	 * Creates a specification using the traditional contiguous node layout.
130
	 *
131
	 * <p>Input IDs are {@code [0, numInputs)}, output IDs are {@code [numInputs, numInputs + numOutputs)}, and the
132
	 * hidden-node namespace starts at {@code numInputs + numOutputs}.
133
	 *
134
	 * @param numInputs      number of input nodes; must be positive
135
	 * @param numOutputs     number of output nodes; must be positive
136
	 * @param minWeightValue minimum allowed connection weight
137
	 * @param maxWeightValue maximum allowed connection weight
138
	 * @return a validated immutable chromosome specification
139
	 * @throws IllegalArgumentException if either node count is not positive or the weight bounds are not ordered
140
	 */
141
	public static NeatChromosomeSpec of(final int numInputs, final int numOutputs, final float minWeightValue,
142
			final float maxWeightValue) {
143 3 1. of : replaced return value with null for net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec::of → KILLED
2. of : removed call to net/bmahe/genetics4j/neat/spec/NeatNodeLayout::contiguous → KILLED
3. of : removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec::of → KILLED
		return of(NeatNodeLayout.contiguous(numInputs, numOutputs), minWeightValue, maxWeightValue);
144
	}
145
}

Mutations

91

1.1
Location : numInputs
Killed by : net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest]/[method:generate()]
replaced int return with 0 for net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec::numInputs → KILLED

2.2
Location : numInputs
Killed by : net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest]/[method:generate()]
removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec::nodeLayout → KILLED

3.3
Location : numInputs
Killed by : net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest]/[method:generate()]
removed call to net/bmahe/genetics4j/neat/spec/NeatNodeLayout::numInputs → KILLED

100

1.1
Location : numOutputs
Killed by : net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest]/[method:generate()]
removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec::nodeLayout → KILLED

2.2
Location : numOutputs
Killed by : net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest]/[method:generate()]
removed call to net/bmahe/genetics4j/neat/spec/NeatNodeLayout::numOutputs → KILLED

3.3
Location : numOutputs
Killed by : net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest]/[method:generate()]
replaced int return with 0 for net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec::numOutputs → KILLED

125

1.1
Location : of
Killed by : net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest]/[method:canHandle()]
replaced call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::nodeLayout with receiver → KILLED

2.2
Location : of
Killed by : net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest]/[method:canHandle()]
replaced call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::maxWeightValue with receiver → KILLED

3.3
Location : of
Killed by : net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest]/[method:canHandle()]
replaced call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::minWeightValue with receiver → KILLED

4.4
Location : of
Killed by : net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest]/[method:canHandle()]
replaced return value with null for net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec::of → KILLED

5.5
Location : of
Killed by : net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest]/[method:canHandle()]
removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::<init> → KILLED

6.6
Location : of
Killed by : net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest]/[method:canHandle()]
removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::build → KILLED

7.7
Location : of
Killed by : net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest]/[method:canHandle()]
removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::maxWeightValue → KILLED

8.8
Location : of
Killed by : net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest]/[method:canHandle()]
removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::nodeLayout → KILLED

9.9
Location : of
Killed by : net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest]/[method:canHandle()]
removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec$Builder::minWeightValue → KILLED

143

1.1
Location : of
Killed by : net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest]/[method:canHandle()]
replaced return value with null for net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec::of → KILLED

2.2
Location : of
Killed by : net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest]/[method:canHandle()]
removed call to net/bmahe/genetics4j/neat/spec/NeatNodeLayout::contiguous → KILLED

3.3
Location : of
Killed by : net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.neat.chromosomes.factory.NeatEmptyChromosomeFactoryTest]/[method:canHandle()]
removed call to net/bmahe/genetics4j/neat/spec/NeatChromosomeSpec::of → KILLED

Active mutators

Tests examined


Report generated by PIT 1.23.1 support