1 package net.bmahe.genetics4j.core.combination.ordercrossover;
2
3 import java.util.HashSet;
4 import java.util.List;
5 import java.util.Objects;
6 import java.util.Set;
7 import java.util.random.RandomGenerator;
8
9 import org.apache.commons.lang3.Validate;
10
11 import net.bmahe.genetics4j.core.chromosomes.Chromosome;
12 import net.bmahe.genetics4j.core.chromosomes.IntChromosome;
13 import net.bmahe.genetics4j.core.combination.ChromosomeCombinator;
14 import net.bmahe.genetics4j.core.spec.AbstractEAConfiguration;
15
16 public class IntChromosomeOrderCrossover<T extends Comparable<T>> implements ChromosomeCombinator<T> {
17
18 private final RandomGenerator randomGenerator;
19
20 public IntChromosomeOrderCrossover(final RandomGenerator _randomGenerator) {
21 Objects.requireNonNull(_randomGenerator);
22
23 this.randomGenerator = _randomGenerator;
24 }
25
26 @Override
27 public List<Chromosome> combine(final AbstractEAConfiguration<T> eaConfiguration, final Chromosome chromosome1,
28 final T firstParentFitness, final Chromosome chromosome2, final T secondParentFitness) {
29 Objects.requireNonNull(chromosome1);
30 Objects.requireNonNull(chromosome2);
31 Validate.isInstanceOf(IntChromosome.class, chromosome1);
32 Validate.isInstanceOf(IntChromosome.class, chromosome2);
33 Validate.isTrue(chromosome1.getNumAlleles() == chromosome2.getNumAlleles());
34
35 final IntChromosome intChromosome1 = (IntChromosome) chromosome1;
36 final IntChromosome intChromosome2 = (IntChromosome) chromosome2;
37
38 final int numAlleles = chromosome1.getNumAlleles();
39 final int[] newValues = new int[numAlleles];
40
41 final int random1 = randomGenerator.nextInt(numAlleles);
42 final int random2 = randomGenerator.nextInt(numAlleles);
43
44 final int rangeStart = Math.min(random1, random2);
45 final int rangeEnd = Math.max(random1, random2);
46
47 final Set<Integer> valuesInRange = new HashSet<>();
48 for (int i = rangeStart; i < rangeEnd; i++) {
49 valuesInRange.add(intChromosome1.getAllele(i));
50 }
51
52 int newValueIndex = 0;
53 int chromosome2Idx = 0;
54
55 while (newValueIndex < numAlleles) {
56 if (newValueIndex < rangeStart || newValueIndex >= rangeEnd) {
57 final int chromosome2Value = intChromosome2.getAllele(chromosome2Idx);
58 if (valuesInRange.contains(chromosome2Value) == false) {
59 newValues[newValueIndex] = chromosome2Value;
60 newValueIndex++;
61 }
62 chromosome2Idx++;
63 } else if (newValueIndex < rangeEnd) {
64 newValues[newValueIndex] = intChromosome1.getAllele(newValueIndex);
65 newValueIndex++;
66 }
67
68 if (chromosome2Idx >= numAlleles) {
69 chromosome2Idx = 0;
70 }
71 }
72
73 return List
74 .of(new IntChromosome(numAlleles, intChromosome1.getMinValue(), intChromosome1.getMaxValue(), newValues));
75 }
76 }