diff options
Diffstat (limited to 'src/main/java/org/apache/commons/math3/optimization/direct/BaseAbstractMultivariateOptimizer.java')
-rw-r--r-- | src/main/java/org/apache/commons/math3/optimization/direct/BaseAbstractMultivariateOptimizer.java | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/src/main/java/org/apache/commons/math3/optimization/direct/BaseAbstractMultivariateOptimizer.java b/src/main/java/org/apache/commons/math3/optimization/direct/BaseAbstractMultivariateOptimizer.java new file mode 100644 index 0000000..d148d8c --- /dev/null +++ b/src/main/java/org/apache/commons/math3/optimization/direct/BaseAbstractMultivariateOptimizer.java @@ -0,0 +1,318 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.math3.optimization.direct; + +import org.apache.commons.math3.util.Incrementor; +import org.apache.commons.math3.exception.MaxCountExceededException; +import org.apache.commons.math3.exception.TooManyEvaluationsException; +import org.apache.commons.math3.analysis.MultivariateFunction; +import org.apache.commons.math3.optimization.BaseMultivariateOptimizer; +import org.apache.commons.math3.optimization.OptimizationData; +import org.apache.commons.math3.optimization.GoalType; +import org.apache.commons.math3.optimization.InitialGuess; +import org.apache.commons.math3.optimization.SimpleBounds; +import org.apache.commons.math3.optimization.ConvergenceChecker; +import org.apache.commons.math3.optimization.PointValuePair; +import org.apache.commons.math3.optimization.SimpleValueChecker; +import org.apache.commons.math3.exception.DimensionMismatchException; +import org.apache.commons.math3.exception.NumberIsTooSmallException; +import org.apache.commons.math3.exception.NumberIsTooLargeException; + +/** + * Base class for implementing optimizers for multivariate scalar functions. + * This base class handles the boiler-plate methods associated to thresholds, + * evaluations counting, initial guess and simple bounds settings. + * + * @param <FUNC> Type of the objective function to be optimized. + * + * @deprecated As of 3.1 (to be removed in 4.0). + * @since 2.2 + */ +@Deprecated +public abstract class BaseAbstractMultivariateOptimizer<FUNC extends MultivariateFunction> + implements BaseMultivariateOptimizer<FUNC> { + /** Evaluations counter. */ + protected final Incrementor evaluations = new Incrementor(); + /** Convergence checker. */ + private ConvergenceChecker<PointValuePair> checker; + /** Type of optimization. */ + private GoalType goal; + /** Initial guess. */ + private double[] start; + /** Lower bounds. */ + private double[] lowerBound; + /** Upper bounds. */ + private double[] upperBound; + /** Objective function. */ + private MultivariateFunction function; + + /** + * Simple constructor with default settings. + * The convergence check is set to a {@link SimpleValueChecker}. + * @deprecated See {@link SimpleValueChecker#SimpleValueChecker()} + */ + @Deprecated + protected BaseAbstractMultivariateOptimizer() { + this(new SimpleValueChecker()); + } + /** + * @param checker Convergence checker. + */ + protected BaseAbstractMultivariateOptimizer(ConvergenceChecker<PointValuePair> checker) { + this.checker = checker; + } + + /** {@inheritDoc} */ + public int getMaxEvaluations() { + return evaluations.getMaximalCount(); + } + + /** {@inheritDoc} */ + public int getEvaluations() { + return evaluations.getCount(); + } + + /** {@inheritDoc} */ + public ConvergenceChecker<PointValuePair> getConvergenceChecker() { + return checker; + } + + /** + * Compute the objective function value. + * + * @param point Point at which the objective function must be evaluated. + * @return the objective function value at the specified point. + * @throws TooManyEvaluationsException if the maximal number of + * evaluations is exceeded. + */ + protected double computeObjectiveValue(double[] point) { + try { + evaluations.incrementCount(); + } catch (MaxCountExceededException e) { + throw new TooManyEvaluationsException(e.getMax()); + } + return function.value(point); + } + + /** + * {@inheritDoc} + * + * @deprecated As of 3.1. Please use + * {@link #optimize(int,MultivariateFunction,GoalType,OptimizationData[])} + * instead. + */ + @Deprecated + public PointValuePair optimize(int maxEval, FUNC f, GoalType goalType, + double[] startPoint) { + return optimizeInternal(maxEval, f, goalType, new InitialGuess(startPoint)); + } + + /** + * Optimize an objective function. + * + * @param maxEval Allowed number of evaluations of the objective function. + * @param f Objective function. + * @param goalType Optimization type. + * @param optData Optimization data. The following data will be looked for: + * <ul> + * <li>{@link InitialGuess}</li> + * <li>{@link SimpleBounds}</li> + * </ul> + * @return the point/value pair giving the optimal value of the objective + * function. + * @since 3.1 + */ + public PointValuePair optimize(int maxEval, + FUNC f, + GoalType goalType, + OptimizationData... optData) { + return optimizeInternal(maxEval, f, goalType, optData); + } + + /** + * Optimize an objective function. + * + * @param f Objective function. + * @param goalType Type of optimization goal: either + * {@link GoalType#MAXIMIZE} or {@link GoalType#MINIMIZE}. + * @param startPoint Start point for optimization. + * @param maxEval Maximum number of function evaluations. + * @return the point/value pair giving the optimal value for objective + * function. + * @throws org.apache.commons.math3.exception.DimensionMismatchException + * if the start point dimension is wrong. + * @throws org.apache.commons.math3.exception.TooManyEvaluationsException + * if the maximal number of evaluations is exceeded. + * @throws org.apache.commons.math3.exception.NullArgumentException if + * any argument is {@code null}. + * @deprecated As of 3.1. Please use + * {@link #optimize(int,MultivariateFunction,GoalType,OptimizationData[])} + * instead. + */ + @Deprecated + protected PointValuePair optimizeInternal(int maxEval, FUNC f, GoalType goalType, + double[] startPoint) { + return optimizeInternal(maxEval, f, goalType, new InitialGuess(startPoint)); + } + + /** + * Optimize an objective function. + * + * @param maxEval Allowed number of evaluations of the objective function. + * @param f Objective function. + * @param goalType Optimization type. + * @param optData Optimization data. The following data will be looked for: + * <ul> + * <li>{@link InitialGuess}</li> + * <li>{@link SimpleBounds}</li> + * </ul> + * @return the point/value pair giving the optimal value of the objective + * function. + * @throws TooManyEvaluationsException if the maximal number of + * evaluations is exceeded. + * @since 3.1 + */ + protected PointValuePair optimizeInternal(int maxEval, + FUNC f, + GoalType goalType, + OptimizationData... optData) + throws TooManyEvaluationsException { + // Set internal state. + evaluations.setMaximalCount(maxEval); + evaluations.resetCount(); + function = f; + goal = goalType; + // Retrieve other settings. + parseOptimizationData(optData); + // Check input consistency. + checkParameters(); + // Perform computation. + return doOptimize(); + } + + /** + * Scans the list of (required and optional) optimization data that + * characterize the problem. + * + * @param optData Optimization data. The following data will be looked for: + * <ul> + * <li>{@link InitialGuess}</li> + * <li>{@link SimpleBounds}</li> + * </ul> + */ + private void parseOptimizationData(OptimizationData... optData) { + // The existing values (as set by the previous call) are reused if + // not provided in the argument list. + for (OptimizationData data : optData) { + if (data instanceof InitialGuess) { + start = ((InitialGuess) data).getInitialGuess(); + continue; + } + if (data instanceof SimpleBounds) { + final SimpleBounds bounds = (SimpleBounds) data; + lowerBound = bounds.getLower(); + upperBound = bounds.getUpper(); + continue; + } + } + } + + /** + * @return the optimization type. + */ + public GoalType getGoalType() { + return goal; + } + + /** + * @return the initial guess. + */ + public double[] getStartPoint() { + return start == null ? null : start.clone(); + } + /** + * @return the lower bounds. + * @since 3.1 + */ + public double[] getLowerBound() { + return lowerBound == null ? null : lowerBound.clone(); + } + /** + * @return the upper bounds. + * @since 3.1 + */ + public double[] getUpperBound() { + return upperBound == null ? null : upperBound.clone(); + } + + /** + * Perform the bulk of the optimization algorithm. + * + * @return the point/value pair giving the optimal value of the + * objective function. + */ + protected abstract PointValuePair doOptimize(); + + /** + * Check parameters consistency. + */ + private void checkParameters() { + if (start != null) { + final int dim = start.length; + if (lowerBound != null) { + if (lowerBound.length != dim) { + throw new DimensionMismatchException(lowerBound.length, dim); + } + for (int i = 0; i < dim; i++) { + final double v = start[i]; + final double lo = lowerBound[i]; + if (v < lo) { + throw new NumberIsTooSmallException(v, lo, true); + } + } + } + if (upperBound != null) { + if (upperBound.length != dim) { + throw new DimensionMismatchException(upperBound.length, dim); + } + for (int i = 0; i < dim; i++) { + final double v = start[i]; + final double hi = upperBound[i]; + if (v > hi) { + throw new NumberIsTooLargeException(v, hi, true); + } + } + } + + // If the bounds were not specified, the allowed interval is + // assumed to be [-inf, +inf]. + if (lowerBound == null) { + lowerBound = new double[dim]; + for (int i = 0; i < dim; i++) { + lowerBound[i] = Double.NEGATIVE_INFINITY; + } + } + if (upperBound == null) { + upperBound = new double[dim]; + for (int i = 0; i < dim; i++) { + upperBound[i] = Double.POSITIVE_INFINITY; + } + } + } + } +} |