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.math3.optimization.direct; 019 020 import org.apache.commons.math3.util.Incrementor; 021 import org.apache.commons.math3.exception.MaxCountExceededException; 022 import org.apache.commons.math3.exception.TooManyEvaluationsException; 023 import org.apache.commons.math3.analysis.MultivariateFunction; 024 import org.apache.commons.math3.optimization.BaseMultivariateOptimizer; 025 import org.apache.commons.math3.optimization.OptimizationData; 026 import org.apache.commons.math3.optimization.GoalType; 027 import org.apache.commons.math3.optimization.InitialGuess; 028 import org.apache.commons.math3.optimization.SimpleBounds; 029 import org.apache.commons.math3.optimization.ConvergenceChecker; 030 import org.apache.commons.math3.optimization.PointValuePair; 031 import org.apache.commons.math3.optimization.SimpleValueChecker; 032 import org.apache.commons.math3.exception.DimensionMismatchException; 033 import org.apache.commons.math3.exception.NumberIsTooSmallException; 034 import org.apache.commons.math3.exception.NumberIsTooLargeException; 035 036 /** 037 * Base class for implementing optimizers for multivariate scalar functions. 038 * This base class handles the boiler-plate methods associated to thresholds, 039 * evaluations counting, initial guess and simple bounds settings. 040 * 041 * @param <FUNC> Type of the objective function to be optimized. 042 * 043 * @version $Id: BaseAbstractMultivariateOptimizer.java 1422313 2012-12-15 18:53:41Z psteitz $ 044 * @deprecated As of 3.1 (to be removed in 4.0). 045 * @since 2.2 046 */ 047 @Deprecated 048 public abstract class BaseAbstractMultivariateOptimizer<FUNC extends MultivariateFunction> 049 implements BaseMultivariateOptimizer<FUNC> { 050 /** Evaluations counter. */ 051 protected final Incrementor evaluations = new Incrementor(); 052 /** Convergence checker. */ 053 private ConvergenceChecker<PointValuePair> checker; 054 /** Type of optimization. */ 055 private GoalType goal; 056 /** Initial guess. */ 057 private double[] start; 058 /** Lower bounds. */ 059 private double[] lowerBound; 060 /** Upper bounds. */ 061 private double[] upperBound; 062 /** Objective function. */ 063 private MultivariateFunction function; 064 065 /** 066 * Simple constructor with default settings. 067 * The convergence check is set to a {@link SimpleValueChecker}. 068 * @deprecated See {@link SimpleValueChecker#SimpleValueChecker()} 069 */ 070 @Deprecated 071 protected BaseAbstractMultivariateOptimizer() { 072 this(new SimpleValueChecker()); 073 } 074 /** 075 * @param checker Convergence checker. 076 */ 077 protected BaseAbstractMultivariateOptimizer(ConvergenceChecker<PointValuePair> checker) { 078 this.checker = checker; 079 } 080 081 /** {@inheritDoc} */ 082 public int getMaxEvaluations() { 083 return evaluations.getMaximalCount(); 084 } 085 086 /** {@inheritDoc} */ 087 public int getEvaluations() { 088 return evaluations.getCount(); 089 } 090 091 /** {@inheritDoc} */ 092 public ConvergenceChecker<PointValuePair> getConvergenceChecker() { 093 return checker; 094 } 095 096 /** 097 * Compute the objective function value. 098 * 099 * @param point Point at which the objective function must be evaluated. 100 * @return the objective function value at the specified point. 101 * @throws TooManyEvaluationsException if the maximal number of 102 * evaluations is exceeded. 103 */ 104 protected double computeObjectiveValue(double[] point) { 105 try { 106 evaluations.incrementCount(); 107 } catch (MaxCountExceededException e) { 108 throw new TooManyEvaluationsException(e.getMax()); 109 } 110 return function.value(point); 111 } 112 113 /** 114 * {@inheritDoc} 115 * 116 * @deprecated As of 3.1. Please use 117 * {@link #optimize(int,MultivariateFunction,GoalType,OptimizationData[])} 118 * instead. 119 */ 120 @Deprecated 121 public PointValuePair optimize(int maxEval, FUNC f, GoalType goalType, 122 double[] startPoint) { 123 return optimizeInternal(maxEval, f, goalType, new InitialGuess(startPoint)); 124 } 125 126 /** 127 * Optimize an objective function. 128 * 129 * @param maxEval Allowed number of evaluations of the objective function. 130 * @param f Objective function. 131 * @param goalType Optimization type. 132 * @param optData Optimization data. The following data will be looked for: 133 * <ul> 134 * <li>{@link InitialGuess}</li> 135 * <li>{@link SimpleBounds}</li> 136 * </ul> 137 * @return the point/value pair giving the optimal value of the objective 138 * function. 139 * @since 3.1 140 */ 141 public PointValuePair optimize(int maxEval, 142 FUNC f, 143 GoalType goalType, 144 OptimizationData... optData) { 145 return optimizeInternal(maxEval, f, goalType, optData); 146 } 147 148 /** 149 * Optimize an objective function. 150 * 151 * @param f Objective function. 152 * @param goalType Type of optimization goal: either 153 * {@link GoalType#MAXIMIZE} or {@link GoalType#MINIMIZE}. 154 * @param startPoint Start point for optimization. 155 * @param maxEval Maximum number of function evaluations. 156 * @return the point/value pair giving the optimal value for objective 157 * function. 158 * @throws org.apache.commons.math3.exception.DimensionMismatchException 159 * if the start point dimension is wrong. 160 * @throws org.apache.commons.math3.exception.TooManyEvaluationsException 161 * if the maximal number of evaluations is exceeded. 162 * @throws org.apache.commons.math3.exception.NullArgumentException if 163 * any argument is {@code null}. 164 * @deprecated As of 3.1. Please use 165 * {@link #optimize(int,MultivariateFunction,GoalType,OptimizationData[])} 166 * instead. 167 */ 168 @Deprecated 169 protected PointValuePair optimizeInternal(int maxEval, FUNC f, GoalType goalType, 170 double[] startPoint) { 171 return optimizeInternal(maxEval, f, goalType, new InitialGuess(startPoint)); 172 } 173 174 /** 175 * Optimize an objective function. 176 * 177 * @param maxEval Allowed number of evaluations of the objective function. 178 * @param f Objective function. 179 * @param goalType Optimization type. 180 * @param optData Optimization data. The following data will be looked for: 181 * <ul> 182 * <li>{@link InitialGuess}</li> 183 * <li>{@link SimpleBounds}</li> 184 * </ul> 185 * @return the point/value pair giving the optimal value of the objective 186 * function. 187 * @throws TooManyEvaluationsException if the maximal number of 188 * evaluations is exceeded. 189 * @since 3.1 190 */ 191 protected PointValuePair optimizeInternal(int maxEval, 192 FUNC f, 193 GoalType goalType, 194 OptimizationData... optData) 195 throws TooManyEvaluationsException { 196 // Set internal state. 197 evaluations.setMaximalCount(maxEval); 198 evaluations.resetCount(); 199 function = f; 200 goal = goalType; 201 // Retrieve other settings. 202 parseOptimizationData(optData); 203 // Check input consistency. 204 checkParameters(); 205 // Perform computation. 206 return doOptimize(); 207 } 208 209 /** 210 * Scans the list of (required and optional) optimization data that 211 * characterize the problem. 212 * 213 * @param optData Optimization data. The following data will be looked for: 214 * <ul> 215 * <li>{@link InitialGuess}</li> 216 * <li>{@link SimpleBounds}</li> 217 * </ul> 218 */ 219 private void parseOptimizationData(OptimizationData... optData) { 220 // The existing values (as set by the previous call) are reused if 221 // not provided in the argument list. 222 for (OptimizationData data : optData) { 223 if (data instanceof InitialGuess) { 224 start = ((InitialGuess) data).getInitialGuess(); 225 continue; 226 } 227 if (data instanceof SimpleBounds) { 228 final SimpleBounds bounds = (SimpleBounds) data; 229 lowerBound = bounds.getLower(); 230 upperBound = bounds.getUpper(); 231 continue; 232 } 233 } 234 } 235 236 /** 237 * @return the optimization type. 238 */ 239 public GoalType getGoalType() { 240 return goal; 241 } 242 243 /** 244 * @return the initial guess. 245 */ 246 public double[] getStartPoint() { 247 return start == null ? null : start.clone(); 248 } 249 /** 250 * @return the lower bounds. 251 * @since 3.1 252 */ 253 public double[] getLowerBound() { 254 return lowerBound == null ? null : lowerBound.clone(); 255 } 256 /** 257 * @return the upper bounds. 258 * @since 3.1 259 */ 260 public double[] getUpperBound() { 261 return upperBound == null ? null : upperBound.clone(); 262 } 263 264 /** 265 * Perform the bulk of the optimization algorithm. 266 * 267 * @return the point/value pair giving the optimal value of the 268 * objective function. 269 */ 270 protected abstract PointValuePair doOptimize(); 271 272 /** 273 * Check parameters consistency. 274 */ 275 private void checkParameters() { 276 if (start != null) { 277 final int dim = start.length; 278 if (lowerBound != null) { 279 if (lowerBound.length != dim) { 280 throw new DimensionMismatchException(lowerBound.length, dim); 281 } 282 for (int i = 0; i < dim; i++) { 283 final double v = start[i]; 284 final double lo = lowerBound[i]; 285 if (v < lo) { 286 throw new NumberIsTooSmallException(v, lo, true); 287 } 288 } 289 } 290 if (upperBound != null) { 291 if (upperBound.length != dim) { 292 throw new DimensionMismatchException(upperBound.length, dim); 293 } 294 for (int i = 0; i < dim; i++) { 295 final double v = start[i]; 296 final double hi = upperBound[i]; 297 if (v > hi) { 298 throw new NumberIsTooLargeException(v, hi, true); 299 } 300 } 301 } 302 303 // If the bounds were not specified, the allowed interval is 304 // assumed to be [-inf, +inf]. 305 if (lowerBound == null) { 306 lowerBound = new double[dim]; 307 for (int i = 0; i < dim; i++) { 308 lowerBound[i] = Double.NEGATIVE_INFINITY; 309 } 310 } 311 if (upperBound == null) { 312 upperBound = new double[dim]; 313 for (int i = 0; i < dim; i++) { 314 upperBound[i] = Double.POSITIVE_INFINITY; 315 } 316 } 317 } 318 } 319 }