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 }