1 package net.bmahe.genetics4j.core.combination.multipointarithmetic;
2
3 import java.util.List;
4 import java.util.Objects;
5 import java.util.random.RandomGenerator;
6
7 import org.apache.commons.lang3.Validate;
8
9 import net.bmahe.genetics4j.core.chromosomes.Chromosome;
10 import net.bmahe.genetics4j.core.chromosomes.FloatChromosome;
11 import net.bmahe.genetics4j.core.combination.ChromosomeCombinator;
12 import net.bmahe.genetics4j.core.spec.AbstractEAConfiguration;
13 import net.bmahe.genetics4j.core.spec.combination.MultiPointArithmetic;
14
15 public class FloatChromosomeMultiPointArithmetic<T extends Comparable<T>> implements ChromosomeCombinator<T> {
16
17 private final RandomGenerator randomGenerator;
18
19 private final MultiPointArithmetic multiPointArithmeticPolicy;
20
21 public FloatChromosomeMultiPointArithmetic(final RandomGenerator _randomGenerator,
22 final MultiPointArithmetic _multiPointArithmeticPolicy) {
23 Objects.requireNonNull(_randomGenerator);
24 Objects.requireNonNull(_multiPointArithmeticPolicy);
25
26 this.randomGenerator = _randomGenerator;
27 this.multiPointArithmeticPolicy = _multiPointArithmeticPolicy;
28 }
29
30 @Override
31 public List<Chromosome> combine(final AbstractEAConfiguration<T> eaConfiguration, final Chromosome chromosome1,
32 final T firstParentFitness, final Chromosome chromosome2, final T secondParentFitness) {
33 Objects.requireNonNull(chromosome1);
34 Objects.requireNonNull(chromosome2);
35 Validate.isInstanceOf(FloatChromosome.class, chromosome1);
36 Validate.isInstanceOf(FloatChromosome.class, chromosome2);
37 Validate.isTrue(chromosome1.getNumAlleles() == chromosome2.getNumAlleles());
38
39 Validate.isTrue(multiPointArithmeticPolicy.numCrossovers() < chromosome1.getNumAlleles());
40 Validate.isTrue(multiPointArithmeticPolicy.numCrossovers() < chromosome2.getNumAlleles());
41
42 final int numCrossovers = multiPointArithmeticPolicy.numCrossovers();
43 final float alpha = (float) multiPointArithmeticPolicy.alpha();
44
45 final int[] alleleSplits = randomGenerator.ints(0, chromosome1.getNumAlleles())
46 .distinct()
47 .limit(numCrossovers)
48 .sorted()
49 .toArray();
50
51 final FloatChromosome floatChromosome1 = (FloatChromosome) chromosome1;
52 final FloatChromosome floatChromosome2 = (FloatChromosome) chromosome2;
53
54 final int numAlleles = chromosome1.getNumAlleles();
55 final float[] firstChildValues = new float[numAlleles];
56 final float[] secondChildValues = new float[numAlleles];
57
58 boolean useChromosome1 = true;
59 int splitIndex = 0;
60 for (int i = 0; i < floatChromosome1.getNumAlleles(); i++) {
61
62 if (splitIndex < alleleSplits.length && i == alleleSplits[splitIndex]) {
63 splitIndex++;
64 useChromosome1 = !useChromosome1;
65 }
66
67 final float firstAllele = floatChromosome1.getAllele(i);
68 final float secondAllele = floatChromosome2.getAllele(i);
69
70 if (useChromosome1) {
71 firstChildValues[i] = alpha * firstAllele + (1 - alpha) * secondAllele;
72 secondChildValues[i] = (1 - alpha) * firstAllele + alpha * secondAllele;
73 } else {
74 firstChildValues[i] = (1 - alpha) * firstAllele + alpha * secondAllele;
75 secondChildValues[i] = alpha * firstAllele + (1 - alpha) * secondAllele;
76 }
77 }
78
79
80
81
82 final float minValue = floatChromosome1.getMinValue();
83 final float maxValue = floatChromosome2.getMaxValue();
84
85 return List.of(
86 new FloatChromosome(numAlleles, minValue, maxValue, firstChildValues),
87 new FloatChromosome(numAlleles, minValue, maxValue, secondChildValues));
88 }
89 }