/* Copyright 2009-2016 David Hadka
*
* This file is part of the MOEA Framework.
*
* The MOEA Framework is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* The MOEA Framework is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the MOEA Framework. If not, see <http://www.gnu.org/licenses/>.
*/
package org.moeaframework.algorithm;
import java.io.IOException;
import java.util.Properties;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.moeaframework.RetryOnTravis;
import org.moeaframework.TestUtils;
import org.moeaframework.TravisRunner;
import org.moeaframework.core.FitnessEvaluator;
import org.moeaframework.core.Population;
import org.moeaframework.core.Problem;
import org.moeaframework.core.Solution;
import org.moeaframework.core.operator.RandomInitialization;
import org.moeaframework.core.spi.OperatorFactory;
import org.moeaframework.core.spi.ProblemFactory;
import org.moeaframework.problem.MockRealProblem;
/**
* Tests the {@link SPEA2} class.
*/
@RunWith(TravisRunner.class)
@RetryOnTravis
public class SPEA2Test extends AlgorithmTest {
@Test
public void testDTLZ1() throws IOException {
test("DTLZ1_2", "SPEA2", "SPEA2-JMetal", true);
}
@Test
public void testDTLZ2() throws IOException {
test("DTLZ2_2", "SPEA2", "SPEA2-JMetal", true);
}
@Test
public void testDTLZ7() throws IOException {
test("DTLZ7_2", "SPEA2", "SPEA2-JMetal", true);
}
@Test
public void testUF1() throws IOException {
test("UF1", "SPEA2", "SPEA2-JMetal", true);
}
@Test
public void testComputeDistances() {
SPEA2 spea2 = new SPEA2(new MockRealProblem(), null, null, 0, 1);
Solution solution1 = TestUtils.newSolution(0.0, 1.0);
Solution solution2 = TestUtils.newSolution(1.0, 0.0);
Solution solution3 = TestUtils.newSolution(0.5, 0.5);
Population population = new Population();
population.add(solution1);
population.add(solution2);
population.add(solution3);
double[][] distances = spea2.computeDistanceMatrix(population);
TestUtils.assertEquals(0.0, distances[0][0]);
TestUtils.assertEquals(0.0, distances[1][1]);
TestUtils.assertEquals(0.0, distances[2][2]);
TestUtils.assertEquals(Math.sqrt(2), distances[0][1]);
TestUtils.assertEquals(Math.sqrt(2), distances[1][0]);
TestUtils.assertEquals(Math.sqrt(0.5), distances[0][2]);
TestUtils.assertEquals(Math.sqrt(0.5), distances[2][0]);
TestUtils.assertEquals(Math.sqrt(0.5), distances[1][2]);
TestUtils.assertEquals(Math.sqrt(0.5), distances[2][1]);
}
@Test
public void testTruncate1() {
SPEA2 spea2 = new SPEA2(new MockRealProblem(), null, null, 0, 1);
Solution solution1 = TestUtils.newSolution(0.0, 1.0);
Solution solution2 = TestUtils.newSolution(1.0, 0.0);
Solution solution3 = TestUtils.newSolution(0.5, 0.5);
Population population = new Population();
population.add(solution1);
population.add(solution2);
population.add(solution3);
spea2.fitnessEvaluator.evaluate(population);
Population result = spea2.truncate(population, 2);
Assert.assertEquals(2, result.size());
Assert.assertTrue(result.contains(solution1));
Assert.assertTrue(result.contains(solution2));
Assert.assertFalse(result.contains(solution3));
}
@Test
public void testTruncate2() {
SPEA2 spea2 = new SPEA2(new MockRealProblem(), null, null, 0, 1);
Solution solution1 = TestUtils.newSolution(0.0, 1.0);
Solution solution2 = TestUtils.newSolution(1.0, 0.0);
Solution solution3 = TestUtils.newSolution(0.5, 0.5);
Population population = new Population();
population.add(solution1);
population.add(solution2);
population.add(solution3);
spea2.fitnessEvaluator.evaluate(population);
Population result = spea2.truncate(population, 1);
Assert.assertEquals(1, result.size());
Assert.assertTrue(result.contains(solution1) || result.contains(solution2));
Assert.assertFalse(result.contains(solution3));
}
@Test
public void testFitnessNondominated() {
SPEA2 spea2 = new SPEA2(new MockRealProblem(), null, null, 0, 1);
Solution solution1 = TestUtils.newSolution(0.0, 1.0);
Solution solution2 = TestUtils.newSolution(1.0, 0.0);
Solution solution3 = TestUtils.newSolution(0.5, 0.5);
Population population = new Population();
population.add(solution1);
population.add(solution2);
population.add(solution3);
spea2.fitnessEvaluator.evaluate(population);
assertFitnessInRange(solution1, 0, 0.9999);
assertFitnessInRange(solution2, 0, 0.9999);
assertFitnessInRange(solution3, 0, 0.9999);
}
@Test
public void testFitnessDominated() {
SPEA2 spea2 = new SPEA2(new MockRealProblem(), null, null, 0, 1);
Solution solution1 = TestUtils.newSolution(0.0, 0.0);
Solution solution2 = TestUtils.newSolution(1.0, 1.0);
Solution solution3 = TestUtils.newSolution(2.0, 2.0);
Population population = new Population();
population.add(solution1);
population.add(solution2);
population.add(solution3);
spea2.fitnessEvaluator.evaluate(population);
assertFitnessInRange(solution1, 0, 0.9999);
assertFitnessInRange(solution2, 2, 2.9999); // ~= S(1) = 2
assertFitnessInRange(solution3, 3, 3.9999); // ~= S(1) + S(2) = 3
}
private void assertFitnessInRange(Solution solution, double min, double max) {
double fitness = (Double)solution.getAttribute(FitnessEvaluator.FITNESS_ATTRIBUTE);
if ((fitness < min) || (fitness > max)) {
Assert.fail("fitness " + fitness + " not within bounds [" + min + ", " + max + "]");
}
}
@Test(expected = ArrayIndexOutOfBoundsException.class)
public void testLargeK() {
Problem problem = ProblemFactory.getInstance().getProblem("DTLZ2_2");
SPEA2 spea2 = new SPEA2(problem,
new RandomInitialization(problem, 100),
OperatorFactory.getInstance().getVariation(null, new Properties(), problem),
0,
10000);
for (int i = 0; i < 10; i++) {
spea2.step();
}
}
}