1 package net.bmahe.genetics4j.neat.mutation.chromosome;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.Objects;
6 import java.util.random.RandomGenerator;
7
8 import org.apache.commons.collections4.CollectionUtils;
9 import org.apache.commons.lang3.Validate;
10 import org.apache.logging.log4j.LogManager;
11 import org.apache.logging.log4j.Logger;
12
13 import net.bmahe.genetics4j.core.chromosomes.Chromosome;
14 import net.bmahe.genetics4j.core.mutation.chromosome.ChromosomeMutationHandler;
15 import net.bmahe.genetics4j.core.spec.chromosome.ChromosomeSpec;
16 import net.bmahe.genetics4j.core.spec.mutation.MutationPolicy;
17 import net.bmahe.genetics4j.neat.Connection;
18 import net.bmahe.genetics4j.neat.ImmutableConnection;
19 import net.bmahe.genetics4j.neat.chromosomes.NeatChromosome;
20 import net.bmahe.genetics4j.neat.spec.NeatChromosomeSpec;
21
22 public abstract class AbstractNeatChromosomeConnectionMutationHandler<T>
23 implements ChromosomeMutationHandler<NeatChromosome>
24 {
25 public final Logger logger = LogManager.getLogger(this.getClass());
26
27 private final Class<T> mutationClazz;
28 private final RandomGenerator randomGenerator;
29
30 protected abstract List<Connection> mutateConnection(final T mutationPolicy, final NeatChromosome neatChromosome,
31 final Connection oldConnection, final int i);
32
33 protected Class<T> getMutationClazz() {
34 return mutationClazz;
35 }
36
37 protected RandomGenerator getRandomGenerator() {
38 return randomGenerator;
39 }
40
41 protected AbstractNeatChromosomeConnectionMutationHandler(final Class<T> _mutationClazz,
42 final RandomGenerator _randomGenerator) {
43 Objects.requireNonNull(_mutationClazz);
44 Objects.requireNonNull(_randomGenerator);
45
46 this.mutationClazz = _mutationClazz;
47 this.randomGenerator = _randomGenerator;
48 }
49
50 @Override
51 public boolean canHandle(final MutationPolicy mutationPolicy, final ChromosomeSpec chromosome) {
52 Objects.requireNonNull(mutationPolicy);
53 Objects.requireNonNull(chromosome);
54
55 return mutationClazz.isInstance(mutationPolicy) && chromosome instanceof NeatChromosomeSpec;
56 }
57
58 @Override
59 public NeatChromosome mutate(final MutationPolicy mutationPolicy, final Chromosome chromosome) {
60 Objects.requireNonNull(mutationPolicy);
61 Objects.requireNonNull(chromosome);
62 Validate.isInstanceOf(mutationClazz, mutationPolicy);
63 Validate.isInstanceOf(NeatChromosome.class, chromosome);
64
65 final var neatChromosome = (NeatChromosome) chromosome;
66
67 final var minValue = neatChromosome.getMinWeightValue();
68 final var maxValue = neatChromosome.getMaxWeightValue();
69
70 final var oldConnections = neatChromosome.getConnections();
71 final List<Connection> newConnections = new ArrayList<>();
72
73 if (CollectionUtils.isNotEmpty(oldConnections)) {
74
75 final int alleleFlipIndex = randomGenerator.nextInt(oldConnections.size());
76
77 int i = 0;
78
79
80
81 while (i < alleleFlipIndex) {
82 final var connection = oldConnections.get(i);
83 final var newConnection = ImmutableConnection.copyOf(connection);
84 newConnections.add(newConnection);
85
86 i++;
87 }
88
89
90
91
92 final var oldConnection = oldConnections.get(i);
93 final var mutatedConnection = mutateConnection(
94 mutationClazz.cast(mutationPolicy),
95 neatChromosome,
96 oldConnection,
97 i);
98 newConnections.addAll(mutatedConnection);
99 i++;
100
101
102
103
104 while (i < oldConnections.size()) {
105 final var connection = oldConnections.get(i);
106 final var newConnection = ImmutableConnection.copyOf(connection);
107 newConnections.add(newConnection);
108
109 i++;
110 }
111
112 }
113
114 return new NeatChromosome(neatChromosome.getNodeLayout(), minValue, maxValue, newConnections);
115 }
116 }