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.general;
019    
020    import org.apache.commons.math.FunctionEvaluationException;
021    import org.apache.commons.math.MaxEvaluationsExceededException;
022    import org.apache.commons.math.MaxIterationsExceededException;
023    import org.apache.commons.math.analysis.DifferentiableMultivariateRealFunction;
024    import org.apache.commons.math.analysis.MultivariateVectorialFunction;
025    import org.apache.commons.math.optimization.GoalType;
026    import org.apache.commons.math.optimization.OptimizationException;
027    import org.apache.commons.math.optimization.RealConvergenceChecker;
028    import org.apache.commons.math.optimization.DifferentiableMultivariateRealOptimizer;
029    import org.apache.commons.math.optimization.RealPointValuePair;
030    import org.apache.commons.math.optimization.SimpleScalarValueChecker;
031    
032    /**
033     * Base class for implementing optimizers for multivariate scalar functions.
034     * <p>This base class handles the boilerplate methods associated to thresholds
035     * settings, iterations and evaluations counting.</p>
036     * @version $Revision: 925812 $ $Date: 2010-03-21 11:49:31 -0400 (Sun, 21 Mar 2010) $
037     * @since 2.0
038     */
039    public abstract class AbstractScalarDifferentiableOptimizer
040        implements DifferentiableMultivariateRealOptimizer {
041    
042        /** Default maximal number of iterations allowed. */
043        public static final int DEFAULT_MAX_ITERATIONS = 100;
044    
045        /** Convergence checker. */
046        protected RealConvergenceChecker checker;
047    
048        /**
049         * Type of optimization.
050         * @since 2.1
051         */
052        protected GoalType goal;
053    
054        /** Current point set. */
055        protected double[] point;
056    
057        /** Maximal number of iterations allowed. */
058        private int maxIterations;
059    
060        /** Number of iterations already performed. */
061        private int iterations;
062    
063        /** Maximal number of evaluations allowed. */
064        private int maxEvaluations;
065    
066        /** Number of evaluations already performed. */
067        private int evaluations;
068    
069        /** Number of gradient evaluations. */
070        private int gradientEvaluations;
071    
072        /** Objective function. */
073        private DifferentiableMultivariateRealFunction function;
074    
075        /** Objective function gradient. */
076        private MultivariateVectorialFunction gradient;
077    
078        /** Simple constructor with default settings.
079         * <p>The convergence check is set to a {@link SimpleScalarValueChecker}
080         * and the maximal number of evaluation is set to its default value.</p>
081         */
082        protected AbstractScalarDifferentiableOptimizer() {
083            setConvergenceChecker(new SimpleScalarValueChecker());
084            setMaxIterations(DEFAULT_MAX_ITERATIONS);
085            setMaxEvaluations(Integer.MAX_VALUE);
086        }
087    
088        /** {@inheritDoc} */
089        public void setMaxIterations(int maxIterations) {
090            this.maxIterations = maxIterations;
091        }
092    
093        /** {@inheritDoc} */
094        public int getMaxIterations() {
095            return maxIterations;
096        }
097    
098        /** {@inheritDoc} */
099        public int getIterations() {
100            return iterations;
101        }
102    
103        /** {@inheritDoc} */
104        public void setMaxEvaluations(int maxEvaluations) {
105            this.maxEvaluations = maxEvaluations;
106        }
107    
108        /** {@inheritDoc} */
109        public int getMaxEvaluations() {
110            return maxEvaluations;
111        }
112    
113        /** {@inheritDoc} */
114        public int getEvaluations() {
115            return evaluations;
116        }
117    
118        /** {@inheritDoc} */
119        public int getGradientEvaluations() {
120            return gradientEvaluations;
121        }
122    
123        /** {@inheritDoc} */
124        public void setConvergenceChecker(RealConvergenceChecker convergenceChecker) {
125            this.checker = convergenceChecker;
126        }
127    
128        /** {@inheritDoc} */
129        public RealConvergenceChecker getConvergenceChecker() {
130            return checker;
131        }
132    
133        /** Increment the iterations counter by 1.
134         * @exception OptimizationException if the maximal number
135         * of iterations is exceeded
136         */
137        protected void incrementIterationsCounter()
138            throws OptimizationException {
139            if (++iterations > maxIterations) {
140                throw new OptimizationException(new MaxIterationsExceededException(maxIterations));
141            }
142        }
143    
144        /**
145         * Compute the gradient vector.
146         * @param evaluationPoint point at which the gradient must be evaluated
147         * @return gradient at the specified point
148         * @exception FunctionEvaluationException if the function gradient
149         */
150        protected double[] computeObjectiveGradient(final double[] evaluationPoint)
151            throws FunctionEvaluationException {
152            ++gradientEvaluations;
153            return gradient.value(evaluationPoint);
154        }
155    
156        /**
157         * Compute the objective function value.
158         * @param evaluationPoint point at which the objective function must be evaluated
159         * @return objective function value at specified point
160         * @exception FunctionEvaluationException if the function cannot be evaluated
161         * or its dimension doesn't match problem dimension or the maximal number
162         * of iterations is exceeded
163         */
164        protected double computeObjectiveValue(final double[] evaluationPoint)
165            throws FunctionEvaluationException {
166            if (++evaluations > maxEvaluations) {
167                throw new FunctionEvaluationException(new MaxEvaluationsExceededException(maxEvaluations),
168                                                      evaluationPoint);
169            }
170            return function.value(evaluationPoint);
171        }
172    
173        /** {@inheritDoc} */
174        public RealPointValuePair optimize(final DifferentiableMultivariateRealFunction f,
175                                             final GoalType goalType,
176                                             final double[] startPoint)
177            throws FunctionEvaluationException, OptimizationException, IllegalArgumentException {
178    
179            // reset counters
180            iterations          = 0;
181            evaluations         = 0;
182            gradientEvaluations = 0;
183    
184            // store optimization problem characteristics
185            function = f;
186            gradient = f.gradient();
187            goal     = goalType;
188            point    = startPoint.clone();
189    
190            return doOptimize();
191    
192        }
193    
194        /** Perform the bulk of optimization algorithm.
195         * @return the point/value pair giving the optimal value for objective function
196         * @exception FunctionEvaluationException if the objective function throws one during
197         * the search
198         * @exception OptimizationException if the algorithm failed to converge
199         * @exception IllegalArgumentException if the start point dimension is wrong
200         */
201        protected abstract RealPointValuePair doOptimize()
202            throws FunctionEvaluationException, OptimizationException, IllegalArgumentException;
203    
204    }