/* 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.util.List; import org.junit.Assert; import org.junit.Test; import org.moeaframework.TestUtils; import org.moeaframework.core.PRNG; import org.moeaframework.core.Settings; import org.moeaframework.core.Solution; import org.moeaframework.util.Vector; /** * Tests the {@link ReferenceVectorGuidedPopulation} class. */ public class ReferenceVectorGuidedPopulationTest { @Test public void testCosine() { Assert.assertEquals(Math.sqrt(2.0) / 2.0, ReferenceVectorGuidedPopulation.cosine( Vector.normalize(new double[] { 2.0, 2.0 }), new double[] { 0.0, 3.0 }), Settings.EPS); Assert.assertEquals(1.0, ReferenceVectorGuidedPopulation.cosine( Vector.normalize(new double[] { 2.0, 2.0 }), new double[] { 2.0, 2.0 }), 1e-7); } @Test public void testACosine() { Assert.assertEquals(Math.PI / 4.0, ReferenceVectorGuidedPopulation.acosine( Vector.normalize(new double[] { 2.0, 2.0 }), new double[] { 0.0, 3.0 }), Settings.EPS); Assert.assertEquals(0.0, ReferenceVectorGuidedPopulation.acosine( Vector.normalize(new double[] { 2.0, 2.0 }), new double[] { 2.0, 2.0 }), 1e-7); } @Test public void testCalculateIdealPoint() { ReferenceVectorGuidedPopulation population = new ReferenceVectorGuidedPopulation(2, 4, 2.0); population.add(TestUtils.newSolution(0.5, 0.5)); population.add(TestUtils.newSolution(0.0, 1.0)); population.calculateIdealPoint(); Assert.assertEquals(0.0, population.idealPoint[0], Settings.EPS); Assert.assertEquals(0.5, population.idealPoint[1], Settings.EPS); } @Test public void testTranslateByIdealPoint() { ReferenceVectorGuidedPopulation population = new ReferenceVectorGuidedPopulation(2, 4, 2.0); population.add(TestUtils.newSolution(0.5, 0.5)); population.add(TestUtils.newSolution(0.0, 1.0)); population.calculateIdealPoint(); population.translateByIdealPoint(); double[] objectives = (double[])population.get(0).getAttribute( ReferencePointNondominatedSortingPopulation.NORMALIZED_OBJECTIVES); Assert.assertEquals(0.5, objectives[0], Settings.EPS); Assert.assertEquals(0.0, objectives[1], Settings.EPS); } @Test public void testAssociateToReferencePoint() { ReferenceVectorGuidedPopulation population = new ReferenceVectorGuidedPopulation(2, 1, 2.0); Solution s1 = TestUtils.newSolution(0.5, 0.5); Solution s2 = TestUtils.newSolution(0.25, 0.75); Solution s3 = TestUtils.newSolution(0.75, 0.25); Solution[] solutions = new Solution[] { s1, s2, s3 }; PRNG.shuffle(solutions); population.addAll(solutions); population.calculateIdealPoint(); population.translateByIdealPoint(); List<List<Solution>> members = population.associateToReferencePoint(population); Assert.assertTrue(members.get(0).contains(s2)); Assert.assertTrue(members.get(1).contains(s3)); } /** * Tests that the truncate method works correctly with a small scaling * factor. While s2 and s3 are closer to the weight vectors, s1 will be * retained since it is closer to the origin and a scaling factor of 0.0 * favors convergence over diversity. */ @Test public void testTruncate1() { ReferenceVectorGuidedPopulation population = new ReferenceVectorGuidedPopulation(2, 1, 2.0); Solution s1 = TestUtils.newSolution(0.5, 0.5); Solution s2 = TestUtils.newSolution(0.25, 0.75); Solution s3 = TestUtils.newSolution(0.75, 0.25); Solution[] solutions = new Solution[] { s1, s2, s3 }; PRNG.shuffle(solutions); population.addAll(solutions); population.truncate(); Assert.assertTrue(population.size() == 2); Assert.assertTrue(population.contains(s1)); Assert.assertTrue(population.contains(s2) || population.contains(s3)); } /** * Tests that the truncate method works correctly with a large scaling * factor. With a scaling factor of 1.0, the algorithm prefers diversity * and selects the two solutions closer to the weight vectors, s2 and s3. */ @Test public void testTruncate2() { ReferenceVectorGuidedPopulation population = new ReferenceVectorGuidedPopulation(2, 1, 2.0); Solution s1 = TestUtils.newSolution(0.5, 0.5); Solution s2 = TestUtils.newSolution(0.25, 0.75); Solution s3 = TestUtils.newSolution(0.75, 0.25); Solution[] solutions = new Solution[] { s1, s2, s3 }; PRNG.shuffle(solutions); population.addAll(solutions); population.setScalingFactor(1.0); population.truncate(); Assert.assertTrue(population.size() == 2); Assert.assertTrue(population.contains(s2)); Assert.assertTrue(population.contains(s3)); } /** * Tests if the {@code adapt} method works correctly by ensuring that * (a) the boundary weights remain on the primary axis (e.g., (0, 1) or * (1, 0)) and (b) intermediate weights appear to be scaled correctly. */ @Test public void testAdapt() { ReferenceVectorGuidedPopulation population = new ReferenceVectorGuidedPopulation(2, 2, 2.0); population.add(TestUtils.newSolution(0.4, 0.5)); population.add(TestUtils.newSolution(0.25, 2.75)); population.adapt(); Assert.assertArrayEquals(new double[] { 0.0, 1.0 }, population.weights.get(0), Settings.EPS); Assert.assertArrayEquals(new double[] { 1.0, 0.0 }, population.weights.get(2), Settings.EPS); Assert.assertTrue(population.weights.get(1)[0] <= population.weights.get(1)[1]); } }