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 }