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