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.ArrayList;
20  import java.util.List;
21  
22  import org.junit.Assert;
23  import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
24  import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
25  import org.apache.commons.math4.legacy.exception.OutOfRangeException;
26  import org.junit.BeforeClass;
27  import org.junit.Test;
28  
29  public class UniformCrossoverTest {
30      private static final int LEN = 10000;
31      private static final List<Integer> p1 = new ArrayList<>(LEN);
32      private static final List<Integer> p2 = new ArrayList<>(LEN);
33  
34      @SuppressWarnings("boxing")
35      @BeforeClass
36      public static void setUpBeforeClass() {
37          for (int i = 0; i < LEN; i++) {
38              p1.add(0);
39              p2.add(1);
40          }
41      }
42  
43      @Test(expected = OutOfRangeException.class)
44      public void testRatioTooLow() {
45          new UniformCrossover<>(-0.5d);
46      }
47  
48      @Test(expected = OutOfRangeException.class)
49      public void testRatioTooHigh() {
50          new UniformCrossover<>(1.5d);
51      }
52  
53      @Test
54      public void testCrossover() {
55          // test crossover with different ratios
56          performCrossover(0.5);
57          performCrossover(0.7);
58          performCrossover(0.2);
59      }
60  
61      private void performCrossover(double ratio) {
62          final DummyBinaryChromosome p1c = new DummyBinaryChromosome(p1);
63          final DummyBinaryChromosome p2c = new DummyBinaryChromosome(p2);
64  
65          final CrossoverPolicy cp = new UniformCrossover<>(ratio);
66  
67          // make a number of rounds
68          for (int i = 0; i < 20; i++) {
69              final ChromosomePair pair = cp.crossover(p1c, p2c);
70  
71              final List<Integer> c1 = ((DummyBinaryChromosome) pair.getFirst()).getRepresentation();
72              final List<Integer> c2 = ((DummyBinaryChromosome) pair.getSecond()).getRepresentation();
73  
74              int from1 = 0;
75              int from2 = 0;
76  
77              // check first child
78              for (int val : c1) {
79                  if (val == 0) {
80                      from1++;
81                  } else {
82                      from2++;
83                  }
84              }
85  
86              Assert.assertEquals(1.0 - ratio, (double) from1 / LEN, 0.1);
87              Assert.assertEquals(ratio, (double) from2 / LEN, 0.1);
88  
89              from1 = 0;
90              from2 = 0;
91  
92              // check second child
93              for (int val : c2) {
94                  if (val == 0) {
95                      from1++;
96                  } else {
97                      from2++;
98                  }
99              }
100 
101             Assert.assertEquals(ratio, (double) from1 / LEN, 0.1);
102             Assert.assertEquals(1.0 - ratio, (double) from2 / LEN, 0.1);
103         }
104     }
105 
106     @Test(expected = DimensionMismatchException.class)
107     public void testCrossoverDimensionMismatchException(){
108         @SuppressWarnings("boxing")
109         final Integer[] p1 = new Integer[] {1,0,1,0,0,1,0,1,1};
110         @SuppressWarnings("boxing")
111         final Integer[] p2 = new Integer[] {0,1,1,0,1};
112 
113         final BinaryChromosome p1c = new DummyBinaryChromosome(p1);
114         final BinaryChromosome p2c = new DummyBinaryChromosome(p2);
115 
116         final CrossoverPolicy cp = new UniformCrossover<>(0.5d);
117         cp.crossover(p1c, p2c);
118     }
119 
120     @Test(expected = MathIllegalArgumentException.class)
121     public void testCrossoverInvalidFixedLengthChromosomeFirst() {
122         @SuppressWarnings("boxing")
123         final Integer[] p1 = new Integer[] {1,0,1,0,0,1,0,1,1};
124         final BinaryChromosome p1c = new DummyBinaryChromosome(p1);
125         final Chromosome p2c = new Chromosome() {
126             @Override
127             public double fitness() {
128                 // Not important
129                 return 0;
130             }
131         };
132 
133         final CrossoverPolicy cp = new UniformCrossover<>(0.5d);
134         cp.crossover(p1c, p2c);
135     }
136 
137     @Test(expected = MathIllegalArgumentException.class)
138     public void testCrossoverInvalidFixedLengthChromosomeSecond() {
139         @SuppressWarnings("boxing")
140         final Integer[] p1 = new Integer[] {1,0,1,0,0,1,0,1,1};
141         final BinaryChromosome p2c = new DummyBinaryChromosome(p1);
142         final Chromosome p1c = new Chromosome() {
143             @Override
144             public double fitness() {
145                 // Not important
146                 return 0;
147             }
148         };
149 
150         final CrossoverPolicy cp = new UniformCrossover<>(0.5d);
151         cp.crossover(p1c, p2c);
152     }
153 }