1 package net.bmahe.genetics4j.core.combination.multipointcrossover;
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.IntChromosome;
11 import net.bmahe.genetics4j.core.combination.ChromosomeCombinator;
12 import net.bmahe.genetics4j.core.spec.AbstractEAConfiguration;
13 import net.bmahe.genetics4j.core.spec.combination.MultiPointCrossover;
14
15 public class IntChromosomeMultiPointCrossover<T extends Comparable<T>> implements ChromosomeCombinator<T> {
16
17 private final RandomGenerator randomGenerator;
18
19 private final MultiPointCrossover multiPointCrossoverPolicy;
20
21 public IntChromosomeMultiPointCrossover(final RandomGenerator _randomGenerator,
22 final MultiPointCrossover _multiPointCrossoverPolicy) {
23 Objects.requireNonNull(_randomGenerator);
24 Objects.requireNonNull(_multiPointCrossoverPolicy);
25
26 this.randomGenerator = _randomGenerator;
27 this.multiPointCrossoverPolicy = _multiPointCrossoverPolicy;
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(IntChromosome.class, chromosome1);
36 Validate.isInstanceOf(IntChromosome.class, chromosome2);
37 Validate.isTrue(chromosome1.getNumAlleles() == chromosome2.getNumAlleles());
38
39 Validate.isTrue(multiPointCrossoverPolicy.numCrossovers() < chromosome1.getNumAlleles());
40 Validate.isTrue(multiPointCrossoverPolicy.numCrossovers() < chromosome2.getNumAlleles());
41
42 final int[] alleleSplits = randomGenerator.ints(0, chromosome1.getNumAlleles())
43 .distinct()
44 .limit(multiPointCrossoverPolicy.numCrossovers())
45 .sorted()
46 .toArray();
47
48 final IntChromosome intChromosome1 = (IntChromosome) chromosome1;
49 final IntChromosome intChromosome2 = (IntChromosome) chromosome2;
50
51 final int numAlleles = chromosome1.getNumAlleles();
52 final int[] firstChildValues = new int[numAlleles];
53 final int[] secondChildValues = new int[numAlleles];
54
55 boolean useChromosome1 = true;
56 int splitIndex = 0;
57 for (int i = 0; i < intChromosome1.getNumAlleles(); i++) {
58
59 if (splitIndex < alleleSplits.length && i == alleleSplits[splitIndex]) {
60 splitIndex++;
61 useChromosome1 = !useChromosome1;
62 }
63
64 if (useChromosome1) {
65 firstChildValues[i] = intChromosome1.getAllele(i);
66 secondChildValues[i] = intChromosome2.getAllele(i);
67 } else {
68 firstChildValues[i] = intChromosome2.getAllele(i);
69 secondChildValues[i] = intChromosome1.getAllele(i);
70 }
71 }
72
73 return List.of(
74 new IntChromosome(numAlleles, intChromosome1.getMinValue(), intChromosome2.getMaxValue(), firstChildValues),
75 new IntChromosome(numAlleles,
76 intChromosome1.getMinValue(),
77 intChromosome2.getMaxValue(),
78 secondChildValues));
79 }
80 }