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 018package org.apache.commons.math3.optimization.direct; 019 020import org.apache.commons.math3.util.Incrementor; 021import org.apache.commons.math3.exception.MaxCountExceededException; 022import org.apache.commons.math3.exception.TooManyEvaluationsException; 023import org.apache.commons.math3.exception.DimensionMismatchException; 024import org.apache.commons.math3.exception.NullArgumentException; 025import org.apache.commons.math3.analysis.MultivariateVectorFunction; 026import org.apache.commons.math3.optimization.OptimizationData; 027import org.apache.commons.math3.optimization.InitialGuess; 028import org.apache.commons.math3.optimization.Target; 029import org.apache.commons.math3.optimization.Weight; 030import org.apache.commons.math3.optimization.BaseMultivariateVectorOptimizer; 031import org.apache.commons.math3.optimization.ConvergenceChecker; 032import org.apache.commons.math3.optimization.PointVectorValuePair; 033import org.apache.commons.math3.optimization.SimpleVectorValueChecker; 034import org.apache.commons.math3.linear.RealMatrix; 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 * settings, iterations and evaluations counting. 040 * 041 * @param <FUNC> the type of the objective function to be optimized 042 * 043 * @deprecated As of 3.1 (to be removed in 4.0). 044 * @since 3.0 045 */ 046@Deprecated 047public abstract class BaseAbstractMultivariateVectorOptimizer<FUNC extends MultivariateVectorFunction> 048 implements BaseMultivariateVectorOptimizer<FUNC> { 049 /** Evaluations counter. */ 050 protected final Incrementor evaluations = new Incrementor(); 051 /** Convergence checker. */ 052 private ConvergenceChecker<PointVectorValuePair> checker; 053 /** Target value for the objective functions at optimum. */ 054 private double[] target; 055 /** Weight matrix. */ 056 private RealMatrix weightMatrix; 057 /** Weight for the least squares cost computation. 058 * @deprecated 059 */ 060 @Deprecated 061 private double[] weight; 062 /** Initial guess. */ 063 private double[] start; 064 /** Objective function. */ 065 private FUNC function; 066 067 /** 068 * Simple constructor with default settings. 069 * The convergence check is set to a {@link SimpleVectorValueChecker}. 070 * @deprecated See {@link SimpleVectorValueChecker#SimpleVectorValueChecker()} 071 */ 072 @Deprecated 073 protected BaseAbstractMultivariateVectorOptimizer() { 074 this(new SimpleVectorValueChecker()); 075 } 076 /** 077 * @param checker Convergence checker. 078 */ 079 protected BaseAbstractMultivariateVectorOptimizer(ConvergenceChecker<PointVectorValuePair> checker) { 080 this.checker = checker; 081 } 082 083 /** {@inheritDoc} */ 084 public int getMaxEvaluations() { 085 return evaluations.getMaximalCount(); 086 } 087 088 /** {@inheritDoc} */ 089 public int getEvaluations() { 090 return evaluations.getCount(); 091 } 092 093 /** {@inheritDoc} */ 094 public ConvergenceChecker<PointVectorValuePair> getConvergenceChecker() { 095 return checker; 096 } 097 098 /** 099 * Compute the objective function value. 100 * 101 * @param point Point at which the objective function must be evaluated. 102 * @return the objective function value at the specified point. 103 * @throws TooManyEvaluationsException if the maximal number of evaluations is 104 * exceeded. 105 */ 106 protected double[] computeObjectiveValue(double[] point) { 107 try { 108 evaluations.incrementCount(); 109 } catch (MaxCountExceededException e) { 110 throw new TooManyEvaluationsException(e.getMax()); 111 } 112 return function.value(point); 113 } 114 115 /** {@inheritDoc} 116 * 117 * @deprecated As of 3.1. Please use 118 * {@link #optimize(int,MultivariateVectorFunction,OptimizationData[])} 119 * instead. 120 */ 121 @Deprecated 122 public PointVectorValuePair optimize(int maxEval, FUNC f, double[] t, double[] w, 123 double[] startPoint) { 124 return optimizeInternal(maxEval, f, t, w, startPoint); 125 } 126 127 /** 128 * Optimize an objective function. 129 * 130 * @param maxEval Allowed number of evaluations of the objective function. 131 * @param f Objective function. 132 * @param optData Optimization data. The following data will be looked for: 133 * <ul> 134 * <li>{@link Target}</li> 135 * <li>{@link Weight}</li> 136 * <li>{@link InitialGuess}</li> 137 * </ul> 138 * @return the point/value pair giving the optimal value of the objective 139 * function. 140 * @throws TooManyEvaluationsException if the maximal number of 141 * evaluations is exceeded. 142 * @throws DimensionMismatchException if the initial guess, target, and weight 143 * arguments have inconsistent dimensions. 144 * 145 * @since 3.1 146 */ 147 protected PointVectorValuePair optimize(int maxEval, 148 FUNC f, 149 OptimizationData... optData) 150 throws TooManyEvaluationsException, 151 DimensionMismatchException { 152 return optimizeInternal(maxEval, f, optData); 153 } 154 155 /** 156 * Optimize an objective function. 157 * Optimization is considered to be a weighted least-squares minimization. 158 * The cost function to be minimized is 159 * <code>∑weight<sub>i</sub>(objective<sub>i</sub> - target<sub>i</sub>)<sup>2</sup></code> 160 * 161 * @param f Objective function. 162 * @param t Target value for the objective functions at optimum. 163 * @param w Weights for the least squares cost computation. 164 * @param startPoint Start point for optimization. 165 * @return the point/value pair giving the optimal value for objective 166 * function. 167 * @param maxEval Maximum number of function evaluations. 168 * @throws org.apache.commons.math3.exception.DimensionMismatchException 169 * if the start point dimension is wrong. 170 * @throws org.apache.commons.math3.exception.TooManyEvaluationsException 171 * if the maximal number of evaluations is exceeded. 172 * @throws org.apache.commons.math3.exception.NullArgumentException if 173 * any argument is {@code null}. 174 * @deprecated As of 3.1. Please use 175 * {@link #optimizeInternal(int,MultivariateVectorFunction,OptimizationData[])} 176 * instead. 177 */ 178 @Deprecated 179 protected PointVectorValuePair optimizeInternal(final int maxEval, final FUNC f, 180 final double[] t, final double[] w, 181 final double[] startPoint) { 182 // Checks. 183 if (f == null) { 184 throw new NullArgumentException(); 185 } 186 if (t == null) { 187 throw new NullArgumentException(); 188 } 189 if (w == null) { 190 throw new NullArgumentException(); 191 } 192 if (startPoint == null) { 193 throw new NullArgumentException(); 194 } 195 if (t.length != w.length) { 196 throw new DimensionMismatchException(t.length, w.length); 197 } 198 199 return optimizeInternal(maxEval, f, 200 new Target(t), 201 new Weight(w), 202 new InitialGuess(startPoint)); 203 } 204 205 /** 206 * Optimize an objective function. 207 * 208 * @param maxEval Allowed number of evaluations of the objective function. 209 * @param f Objective function. 210 * @param optData Optimization data. The following data will be looked for: 211 * <ul> 212 * <li>{@link Target}</li> 213 * <li>{@link Weight}</li> 214 * <li>{@link InitialGuess}</li> 215 * </ul> 216 * @return the point/value pair giving the optimal value of the objective 217 * function. 218 * @throws TooManyEvaluationsException if the maximal number of 219 * evaluations is exceeded. 220 * @throws DimensionMismatchException if the initial guess, target, and weight 221 * arguments have inconsistent dimensions. 222 * 223 * @since 3.1 224 */ 225 protected PointVectorValuePair optimizeInternal(int maxEval, 226 FUNC f, 227 OptimizationData... optData) 228 throws TooManyEvaluationsException, 229 DimensionMismatchException { 230 // Set internal state. 231 evaluations.setMaximalCount(maxEval); 232 evaluations.resetCount(); 233 function = f; 234 // Retrieve other settings. 235 parseOptimizationData(optData); 236 // Check input consistency. 237 checkParameters(); 238 // Allow subclasses to reset their own internal state. 239 setUp(); 240 // Perform computation. 241 return doOptimize(); 242 } 243 244 /** 245 * Gets the initial values of the optimized parameters. 246 * 247 * @return the initial guess. 248 */ 249 public double[] getStartPoint() { 250 return start.clone(); 251 } 252 253 /** 254 * Gets the weight matrix of the observations. 255 * 256 * @return the weight matrix. 257 * @since 3.1 258 */ 259 public RealMatrix getWeight() { 260 return weightMatrix.copy(); 261 } 262 /** 263 * Gets the observed values to be matched by the objective vector 264 * function. 265 * 266 * @return the target values. 267 * @since 3.1 268 */ 269 public double[] getTarget() { 270 return target.clone(); 271 } 272 273 /** 274 * Gets the objective vector function. 275 * Note that this access bypasses the evaluation counter. 276 * 277 * @return the objective vector function. 278 * @since 3.1 279 */ 280 protected FUNC getObjectiveFunction() { 281 return function; 282 } 283 284 /** 285 * Perform the bulk of the optimization algorithm. 286 * 287 * @return the point/value pair giving the optimal value for the 288 * objective function. 289 */ 290 protected abstract PointVectorValuePair doOptimize(); 291 292 /** 293 * @return a reference to the {@link #target array}. 294 * @deprecated As of 3.1. 295 */ 296 @Deprecated 297 protected double[] getTargetRef() { 298 return target; 299 } 300 /** 301 * @return a reference to the {@link #weight array}. 302 * @deprecated As of 3.1. 303 */ 304 @Deprecated 305 protected double[] getWeightRef() { 306 return weight; 307 } 308 309 /** 310 * Method which a subclass <em>must</em> override whenever its internal 311 * state depend on the {@link OptimizationData input} parsed by this base 312 * class. 313 * It will be called after the parsing step performed in the 314 * {@link #optimize(int,MultivariateVectorFunction,OptimizationData[]) 315 * optimize} method and just before {@link #doOptimize()}. 316 * 317 * @since 3.1 318 */ 319 protected void setUp() { 320 // XXX Temporary code until the new internal data is used everywhere. 321 final int dim = target.length; 322 weight = new double[dim]; 323 for (int i = 0; i < dim; i++) { 324 weight[i] = weightMatrix.getEntry(i, i); 325 } 326 } 327 328 /** 329 * Scans the list of (required and optional) optimization data that 330 * characterize the problem. 331 * 332 * @param optData Optimization data. The following data will be looked for: 333 * <ul> 334 * <li>{@link Target}</li> 335 * <li>{@link Weight}</li> 336 * <li>{@link InitialGuess}</li> 337 * </ul> 338 */ 339 private void parseOptimizationData(OptimizationData... optData) { 340 // The existing values (as set by the previous call) are reused if 341 // not provided in the argument list. 342 for (OptimizationData data : optData) { 343 if (data instanceof Target) { 344 target = ((Target) data).getTarget(); 345 continue; 346 } 347 if (data instanceof Weight) { 348 weightMatrix = ((Weight) data).getWeight(); 349 continue; 350 } 351 if (data instanceof InitialGuess) { 352 start = ((InitialGuess) data).getInitialGuess(); 353 continue; 354 } 355 } 356 } 357 358 /** 359 * Check parameters consistency. 360 * 361 * @throws DimensionMismatchException if {@link #target} and 362 * {@link #weightMatrix} have inconsistent dimensions. 363 */ 364 private void checkParameters() { 365 if (target.length != weightMatrix.getColumnDimension()) { 366 throw new DimensionMismatchException(target.length, 367 weightMatrix.getColumnDimension()); 368 } 369 } 370}