    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    }