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