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    package org.apache.commons.math.optimization.univariate;
018    
019    import static org.junit.Assert.assertEquals;
020    import static org.junit.Assert.assertTrue;
021    import static org.junit.Assert.fail;
022    
023    import org.apache.commons.math.FunctionEvaluationException;
024    import org.apache.commons.math.MathException;
025    import org.apache.commons.math.MaxIterationsExceededException;
026    import org.apache.commons.math.analysis.QuinticFunction;
027    import org.apache.commons.math.analysis.SinFunction;
028    import org.apache.commons.math.analysis.UnivariateRealFunction;
029    import org.apache.commons.math.optimization.GoalType;
030    import org.apache.commons.math.optimization.UnivariateRealOptimizer;
031    import org.junit.Test;
032    
033    /**
034     * @version $Revision: 799857 $ $Date: 2009-08-01 09:07:12 -0400 (Sat, 01 Aug 2009) $ 
035     */
036    public final class BrentMinimizerTest {
037    
038        @Test
039        public void testSinMin() throws MathException {
040            UnivariateRealFunction f = new SinFunction();
041            UnivariateRealOptimizer minimizer = new BrentOptimizer();
042            minimizer.setMaxEvaluations(200);
043            assertEquals(200, minimizer.getMaxEvaluations());
044            try {
045                minimizer.getResult();
046                fail("an exception should have been thrown");
047            } catch (IllegalStateException ise) {
048                // expected
049            } catch (Exception e) {
050                fail("wrong exception caught");
051            }
052            assertEquals(3 * Math.PI / 2, minimizer.optimize(f, GoalType.MINIMIZE, 4, 5), 70 * minimizer.getAbsoluteAccuracy());
053            assertTrue(minimizer.getIterationCount() <= 50);
054            assertEquals(3 * Math.PI / 2, minimizer.optimize(f, GoalType.MINIMIZE, 1, 5), 70 * minimizer.getAbsoluteAccuracy());
055            assertTrue(minimizer.getIterationCount() <= 50);
056            assertTrue(minimizer.getEvaluations()    <= 100);
057            assertTrue(minimizer.getEvaluations()    >=  90);
058            minimizer.setMaxEvaluations(50);
059            try {
060                minimizer.optimize(f, GoalType.MINIMIZE, 4, 5);
061                fail("an exception should have been thrown");
062            } catch (FunctionEvaluationException fee) {
063                // expected
064            } catch (Exception e) {
065                fail("wrong exception caught");
066            }
067        }
068    
069        @Test
070        public void testQuinticMin() throws MathException {
071            // The quintic function has zeros at 0, +-0.5 and +-1.
072            // The function has extrema (first derivative is zero) at 0.27195613 and 0.82221643,
073            UnivariateRealFunction f = new QuinticFunction();
074            UnivariateRealOptimizer minimizer = new BrentOptimizer();
075            assertEquals(-0.27195613, minimizer.optimize(f, GoalType.MINIMIZE, -0.3, -0.2), 1.0e-8);
076            assertEquals( 0.82221643, minimizer.optimize(f, GoalType.MINIMIZE,  0.3,  0.9), 1.0e-8);
077            assertTrue(minimizer.getIterationCount() <= 50);
078    
079            // search in a large interval
080            assertEquals(-0.27195613, minimizer.optimize(f, GoalType.MINIMIZE, -1.0, 0.2), 1.0e-8);
081            assertTrue(minimizer.getIterationCount() <= 50);
082    
083        }
084    
085        @Test
086        public void testQuinticMax() throws MathException {
087            // The quintic function has zeros at 0, +-0.5 and +-1.
088            // The function has extrema (first derivative is zero) at 0.27195613 and 0.82221643,
089            UnivariateRealFunction f = new QuinticFunction();
090            UnivariateRealOptimizer minimizer = new BrentOptimizer();
091            assertEquals(0.27195613, minimizer.optimize(f, GoalType.MAXIMIZE, 0.2, 0.3), 1.0e-8);
092            minimizer.setMaximalIterationCount(30);
093            try {
094                minimizer.optimize(f, GoalType.MAXIMIZE, 0.2, 0.3);
095                fail("an exception should have been thrown");
096            } catch (MaxIterationsExceededException miee) {
097                // expected
098            } catch (Exception e) {
099                fail("wrong exception caught");
100            }
101        }
102    
103        @Test
104        public void testMinEndpoints() throws Exception {
105            UnivariateRealFunction f = new SinFunction();
106            UnivariateRealOptimizer solver = new BrentOptimizer();
107    
108            // endpoint is minimum
109            double result = solver.optimize(f, GoalType.MINIMIZE, 3 * Math.PI / 2, 5);
110            assertEquals(3 * Math.PI / 2, result, 70 * solver.getAbsoluteAccuracy());
111    
112            result = solver.optimize(f, GoalType.MINIMIZE, 4, 3 * Math.PI / 2);
113            assertEquals(3 * Math.PI / 2, result, 70 * solver.getAbsoluteAccuracy());
114    
115        }
116    
117    }