001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.commons.math.optimization.direct; 019 020 import junit.framework.Test; 021 import junit.framework.TestCase; 022 import junit.framework.TestSuite; 023 024 import org.apache.commons.math.ConvergenceException; 025 import org.apache.commons.math.FunctionEvaluationException; 026 import org.apache.commons.math.analysis.MultivariateRealFunction; 027 import org.apache.commons.math.optimization.GoalType; 028 import org.apache.commons.math.optimization.RealPointValuePair; 029 import org.apache.commons.math.optimization.SimpleScalarValueChecker; 030 031 public class MultiDirectionalTest 032 extends TestCase { 033 034 public MultiDirectionalTest(String name) { 035 super(name); 036 } 037 038 public void testFunctionEvaluationExceptions() { 039 MultivariateRealFunction wrong = 040 new MultivariateRealFunction() { 041 private static final long serialVersionUID = 4751314470965489371L; 042 public double value(double[] x) throws FunctionEvaluationException { 043 if (x[0] < 0) { 044 throw new FunctionEvaluationException(x, "{0}", "oops"); 045 } else if (x[0] > 1) { 046 throw new FunctionEvaluationException(new RuntimeException("oops"), x); 047 } else { 048 return x[0] * (1 - x[0]); 049 } 050 } 051 }; 052 try { 053 MultiDirectional optimizer = new MultiDirectional(0.9, 1.9); 054 optimizer.optimize(wrong, GoalType.MINIMIZE, new double[] { -1.0 }); 055 fail("an exception should have been thrown"); 056 } catch (FunctionEvaluationException ce) { 057 // expected behavior 058 assertNull(ce.getCause()); 059 } catch (Exception e) { 060 fail("wrong exception caught: " + e.getMessage()); 061 } 062 try { 063 MultiDirectional optimizer = new MultiDirectional(0.9, 1.9); 064 optimizer.optimize(wrong, GoalType.MINIMIZE, new double[] { +2.0 }); 065 fail("an exception should have been thrown"); 066 } catch (FunctionEvaluationException ce) { 067 // expected behavior 068 assertNotNull(ce.getCause()); 069 } catch (Exception e) { 070 fail("wrong exception caught: " + e.getMessage()); 071 } 072 } 073 074 public void testMinimizeMaximize() 075 throws FunctionEvaluationException, ConvergenceException { 076 077 // the following function has 4 local extrema: 078 final double xM = -3.841947088256863675365; 079 final double yM = -1.391745200270734924416; 080 final double xP = 0.2286682237349059125691; 081 final double yP = -yM; 082 final double valueXmYm = 0.2373295333134216789769; // local maximum 083 final double valueXmYp = -valueXmYm; // local minimum 084 final double valueXpYm = -0.7290400707055187115322; // global minimum 085 final double valueXpYp = -valueXpYm; // global maximum 086 MultivariateRealFunction fourExtrema = new MultivariateRealFunction() { 087 private static final long serialVersionUID = -7039124064449091152L; 088 public double value(double[] variables) throws FunctionEvaluationException { 089 final double x = variables[0]; 090 final double y = variables[1]; 091 return ((x == 0) || (y == 0)) ? 0 : (Math.atan(x) * Math.atan(x + 2) * Math.atan(y) * Math.atan(y) / (x * y)); 092 } 093 }; 094 095 MultiDirectional optimizer = new MultiDirectional(); 096 optimizer.setConvergenceChecker(new SimpleScalarValueChecker(1.0e-10, 1.0e-30)); 097 optimizer.setMaxIterations(200); 098 optimizer.setStartConfiguration(new double[] { 0.2, 0.2 }); 099 RealPointValuePair optimum; 100 101 // minimization 102 optimum = optimizer.optimize(fourExtrema, GoalType.MINIMIZE, new double[] { -3.0, 0 }); 103 assertEquals(xM, optimum.getPoint()[0], 4.0e-6); 104 assertEquals(yP, optimum.getPoint()[1], 3.0e-6); 105 assertEquals(valueXmYp, optimum.getValue(), 8.0e-13); 106 assertTrue(optimizer.getEvaluations() > 120); 107 assertTrue(optimizer.getEvaluations() < 150); 108 109 optimum = optimizer.optimize(fourExtrema, GoalType.MINIMIZE, new double[] { +1, 0 }); 110 assertEquals(xP, optimum.getPoint()[0], 2.0e-8); 111 assertEquals(yM, optimum.getPoint()[1], 3.0e-6); 112 assertEquals(valueXpYm, optimum.getValue(), 2.0e-12); 113 assertTrue(optimizer.getEvaluations() > 120); 114 assertTrue(optimizer.getEvaluations() < 150); 115 116 // maximization 117 optimum = optimizer.optimize(fourExtrema, GoalType.MAXIMIZE, new double[] { -3.0, 0.0 }); 118 assertEquals(xM, optimum.getPoint()[0], 7.0e-7); 119 assertEquals(yM, optimum.getPoint()[1], 3.0e-7); 120 assertEquals(valueXmYm, optimum.getValue(), 2.0e-14); 121 assertTrue(optimizer.getEvaluations() > 120); 122 assertTrue(optimizer.getEvaluations() < 150); 123 124 optimum = optimizer.optimize(fourExtrema, GoalType.MAXIMIZE, new double[] { +1, 0 }); 125 assertEquals(xP, optimum.getPoint()[0], 2.0e-8); 126 assertEquals(yP, optimum.getPoint()[1], 3.0e-6); 127 assertEquals(valueXpYp, optimum.getValue(), 2.0e-12); 128 assertTrue(optimizer.getEvaluations() > 120); 129 assertTrue(optimizer.getEvaluations() < 150); 130 131 } 132 133 public void testRosenbrock() 134 throws FunctionEvaluationException, ConvergenceException { 135 136 MultivariateRealFunction rosenbrock = 137 new MultivariateRealFunction() { 138 private static final long serialVersionUID = -9044950469615237490L; 139 public double value(double[] x) throws FunctionEvaluationException { 140 ++count; 141 double a = x[1] - x[0] * x[0]; 142 double b = 1.0 - x[0]; 143 return 100 * a * a + b * b; 144 } 145 }; 146 147 count = 0; 148 MultiDirectional optimizer = new MultiDirectional(); 149 optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1, 1.0e-3)); 150 optimizer.setMaxIterations(100); 151 optimizer.setStartConfiguration(new double[][] { 152 { -1.2, 1.0 }, { 0.9, 1.2 } , { 3.5, -2.3 } 153 }); 154 RealPointValuePair optimum = 155 optimizer.optimize(rosenbrock, GoalType.MINIMIZE, new double[] { -1.2, 1.0 }); 156 157 assertEquals(count, optimizer.getEvaluations()); 158 assertTrue(optimizer.getEvaluations() > 70); 159 assertTrue(optimizer.getEvaluations() < 100); 160 assertTrue(optimum.getValue() > 1.0e-2); 161 162 } 163 164 public void testPowell() 165 throws FunctionEvaluationException, ConvergenceException { 166 167 MultivariateRealFunction powell = 168 new MultivariateRealFunction() { 169 private static final long serialVersionUID = -832162886102041840L; 170 public double value(double[] x) throws FunctionEvaluationException { 171 ++count; 172 double a = x[0] + 10 * x[1]; 173 double b = x[2] - x[3]; 174 double c = x[1] - 2 * x[2]; 175 double d = x[0] - x[3]; 176 return a * a + 5 * b * b + c * c * c * c + 10 * d * d * d * d; 177 } 178 }; 179 180 count = 0; 181 MultiDirectional optimizer = new MultiDirectional(); 182 optimizer.setConvergenceChecker(new SimpleScalarValueChecker(-1.0, 1.0e-3)); 183 optimizer.setMaxIterations(1000); 184 RealPointValuePair optimum = 185 optimizer.optimize(powell, GoalType.MINIMIZE, new double[] { 3.0, -1.0, 0.0, 1.0 }); 186 assertEquals(count, optimizer.getEvaluations()); 187 assertTrue(optimizer.getEvaluations() > 800); 188 assertTrue(optimizer.getEvaluations() < 900); 189 assertTrue(optimum.getValue() > 1.0e-2); 190 191 } 192 193 public static Test suite() { 194 return new TestSuite(MultiDirectionalTest.class); 195 } 196 197 private int count; 198 199 }