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 }