1 package net.bmahe.genetics4j.core.mutation.chromosome.creepmutation;
2
3 import java.util.Arrays;
4 import java.util.Objects;
5 import java.util.function.Supplier;
6 import java.util.random.RandomGenerator;
7
8 import org.apache.commons.lang3.Validate;
9
10 import net.bmahe.genetics4j.core.chromosomes.Chromosome;
11 import net.bmahe.genetics4j.core.chromosomes.DoubleChromosome;
12 import net.bmahe.genetics4j.core.mutation.chromosome.ChromosomeMutationHandler;
13 import net.bmahe.genetics4j.core.spec.chromosome.ChromosomeSpec;
14 import net.bmahe.genetics4j.core.spec.chromosome.DoubleChromosomeSpec;
15 import net.bmahe.genetics4j.core.spec.mutation.CreepMutation;
16 import net.bmahe.genetics4j.core.spec.mutation.MutationPolicy;
17 import net.bmahe.genetics4j.core.spec.statistics.distributions.Distribution;
18 import net.bmahe.genetics4j.core.util.DistributionUtils;
19
20 public class DoubleChromosomeCreepMutationHandler implements ChromosomeMutationHandler<DoubleChromosome> {
21
22 private final RandomGenerator randomGenerator;
23
24 public DoubleChromosomeCreepMutationHandler(final RandomGenerator _randomGenerator) {
25 Objects.requireNonNull(_randomGenerator);
26
27 this.randomGenerator = _randomGenerator;
28 }
29
30 @Override
31 public boolean canHandle(final MutationPolicy mutationPolicy, final ChromosomeSpec chromosome) {
32 Objects.requireNonNull(mutationPolicy);
33 Objects.requireNonNull(chromosome);
34
35 return mutationPolicy instanceof CreepMutation && chromosome instanceof DoubleChromosomeSpec;
36 }
37
38 @Override
39 public DoubleChromosome mutate(final MutationPolicy mutationPolicy, final Chromosome chromosome) {
40 Objects.requireNonNull(mutationPolicy);
41 Objects.requireNonNull(chromosome);
42 Validate.isInstanceOf(CreepMutation.class, mutationPolicy);
43 Validate.isInstanceOf(DoubleChromosome.class, chromosome);
44
45 final var doubleChromosome = (DoubleChromosome) chromosome;
46 final var creepMutation = (CreepMutation) mutationPolicy;
47
48 final var minValue = doubleChromosome.getMinValue();
49 final var maxValue = doubleChromosome.getMaxValue();
50 final Distribution distribution = creepMutation.distribution();
51
52 final Supplier<Double> distributionValueSupplier = DistributionUtils
53 .distributionValueSupplier(randomGenerator, minValue, maxValue, distribution);
54
55 final double[] newValues = Arrays.copyOf(doubleChromosome.getValues(), doubleChromosome.getNumAlleles());
56
57 final int alleleFlipIndex = randomGenerator.nextInt(doubleChromosome.getNumAlleles());
58 newValues[alleleFlipIndex] += distributionValueSupplier.get();
59
60 if (newValues[alleleFlipIndex] > maxValue) {
61 newValues[alleleFlipIndex] = maxValue;
62 } else if (newValues[alleleFlipIndex] < minValue) {
63 newValues[alleleFlipIndex] = minValue;
64 }
65
66 return new DoubleChromosome(doubleChromosome.getSize(),
67 doubleChromosome.getMinValue(),
68 doubleChromosome.getMaxValue(),
69 newValues);
70 }
71 }