View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.math4.legacy.genetics;
18  
19  import java.util.List;
20  
21  import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
22  import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
23  import org.apache.commons.math4.legacy.exception.NumberIsTooLargeException;
24  import org.junit.Assert;
25  import org.junit.Test;
26  
27  public class NPointCrossoverTest {
28  
29      @Test(expected = DimensionMismatchException.class)
30      public void testCrossoverDimensionMismatchException() {
31          final Integer[] p1 = new Integer[] {1,0,1,0,0,1,0,1,1};
32          final Integer[] p2 = new Integer[] {0,1,1,0,1};
33  
34          final BinaryChromosome p1c = new DummyBinaryChromosome(p1);
35          final BinaryChromosome p2c = new DummyBinaryChromosome(p2);
36  
37          final CrossoverPolicy cp = new NPointCrossover<>(1);
38          cp.crossover(p1c,p2c);
39      }
40  
41      @Test(expected = NumberIsTooLargeException.class)
42      public void testNumberIsTooLargeException() {
43          final Integer[] p1 = new Integer[] {1,0,1,0,0,1,0,1,1};
44          final Integer[] p2 = new Integer[] {0,1,1,0,1,0,1,1,1};
45  
46          final BinaryChromosome p1c = new DummyBinaryChromosome(p1);
47          final BinaryChromosome p2c = new DummyBinaryChromosome(p2);
48  
49          final CrossoverPolicy cp = new NPointCrossover<>(15);
50          cp.crossover(p1c,p2c);
51      }
52  
53      @Test(expected = MathIllegalArgumentException.class)
54      public void testCrossoverInvalidFixedLengthChromosomeFirst() {
55          final Integer[] p1 = new Integer[] {1,0,1,0,0,1,0,1,1};
56          final BinaryChromosome p1c = new DummyBinaryChromosome(p1);
57          final Chromosome p2c = new Chromosome() {
58              @Override
59              public double fitness() {
60                  // Not important
61                  return 0;
62              }
63          };
64  
65          final CrossoverPolicy cp = new NPointCrossover<>(1);
66          cp.crossover(p1c,p2c);
67      }
68  
69      @Test(expected = MathIllegalArgumentException.class)
70      public void testCrossoverInvalidFixedLengthChromosomeSecond() {
71          final Integer[] p1 = new Integer[] {1,0,1,0,0,1,0,1,1};
72          final BinaryChromosome p2c = new DummyBinaryChromosome(p1);
73          final Chromosome p1c = new Chromosome() {
74              @Override
75              public double fitness() {
76                  // Not important
77                  return 0;
78              }
79          };
80  
81          final CrossoverPolicy cp = new NPointCrossover<>(1);
82          cp.crossover(p1c,p2c);
83      }
84  
85      @Test
86      public void testCrossover() {
87          Integer[] p1 = new Integer[] {1,0,1,0,1,0,1,0,1};
88          Integer[] p2 = new Integer[] {0,1,0,1,0,1,0,1,0};
89  
90          BinaryChromosome p1c = new DummyBinaryChromosome(p1);
91          BinaryChromosome p2c = new DummyBinaryChromosome(p2);
92  
93          final int order = 3;
94          NPointCrossover<Integer> npc = new NPointCrossover<>(order);
95  
96          // the two parent chromosomes are different at each position, so it is easy to detect
97          // the number of crossovers that happened for each child
98          for (int i=0; i<20; i++) {
99              ChromosomePair pair = npc.crossover(p1c,p2c);
100 
101             Integer[] c1 = new Integer[p1.length];
102             Integer[] c2 = new Integer[p2.length];
103 
104             c1 = ((BinaryChromosome) pair.getFirst()).getRepresentation().toArray(c1);
105             c2 = ((BinaryChromosome) pair.getSecond()).getRepresentation().toArray(c2);
106 
107             Assert.assertEquals(order, detectCrossoverPoints(p1c, p2c, (BinaryChromosome) pair.getFirst()));
108             Assert.assertEquals(order, detectCrossoverPoints(p2c, p1c, (BinaryChromosome) pair.getSecond()));
109         }
110     }
111 
112     private int detectCrossoverPoints(BinaryChromosome p1, BinaryChromosome p2, BinaryChromosome c) {
113         int crossovers = 0;
114         final int length = p1.getLength();
115 
116         final List<Integer> p1Rep = p1.getRepresentation();
117         final List<Integer> p2Rep = p2.getRepresentation();
118         final List<Integer> cRep = c.getRepresentation();
119 
120         List<Integer> rep = p1Rep;
121         for (int i = 0; i < length; i++) {
122             if (rep.get(i) != cRep.get(i)) {
123                 crossovers++;
124                 rep = rep == p1Rep ? p2Rep : p1Rep;
125             }
126         }
127 
128         return crossovers;
129     }
130 }