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 package org.apache.commons.math3.optim; 018 019 import org.apache.commons.math3.util.Incrementor; 020 import org.apache.commons.math3.exception.TooManyEvaluationsException; 021 import org.apache.commons.math3.exception.TooManyIterationsException; 022 023 /** 024 * Base class for implementing optimizers. 025 * It contains the boiler-plate code for counting the number of evaluations 026 * of the objective function and the number of iterations of the algorithm, 027 * and storing the convergence checker. 028 * <em>It is not a "user" class.</em> 029 * 030 * @param <PAIR> Type of the point/value pair returned by the optimization 031 * algorithm. 032 * 033 * @version $Id$ 034 * @since 3.1 035 */ 036 public abstract class BaseOptimizer<PAIR> { 037 /** Evaluations counter. */ 038 protected final Incrementor evaluations; 039 /** Iterations counter. */ 040 protected final Incrementor iterations; 041 /** Convergence checker. */ 042 private ConvergenceChecker<PAIR> checker; 043 044 /** 045 * @param checker Convergence checker. 046 */ 047 protected BaseOptimizer(ConvergenceChecker<PAIR> checker) { 048 this.checker = checker; 049 050 evaluations = new Incrementor(0, new MaxEvalCallback()); 051 iterations = new Incrementor(0, new MaxIterCallback()); 052 } 053 054 /** 055 * Gets the maximal number of function evaluations. 056 * 057 * @return the maximal number of function evaluations. 058 */ 059 public int getMaxEvaluations() { 060 return evaluations.getMaximalCount(); 061 } 062 063 /** 064 * Gets the number of evaluations of the objective function. 065 * The number of evaluations corresponds to the last call to the 066 * {@code optimize} method. It is 0 if the method has not been 067 * called yet. 068 * 069 * @return the number of evaluations of the objective function. 070 */ 071 public int getEvaluations() { 072 return evaluations.getCount(); 073 } 074 075 /** 076 * Gets the maximal number of iterations. 077 * 078 * @return the maximal number of iterations. 079 */ 080 public int getMaxIterations() { 081 return iterations.getMaximalCount(); 082 } 083 084 /** 085 * Gets the number of iterations performed by the algorithm. 086 * The number iterations corresponds to the last call to the 087 * {@code optimize} method. It is 0 if the method has not been 088 * called yet. 089 * 090 * @return the number of evaluations of the objective function. 091 */ 092 public int getIterations() { 093 return iterations.getCount(); 094 } 095 096 /** 097 * Gets the convergence checker. 098 * 099 * @return the object used to check for convergence. 100 */ 101 public ConvergenceChecker<PAIR> getConvergenceChecker() { 102 return checker; 103 } 104 105 /** 106 * Stores data and performs the optimization. 107 * 108 * @param optData Optimization data. The following data will be looked for: 109 * <ul> 110 * <li>{@link MaxEval}</li> 111 * <li>{@link MaxIter}</li> 112 * </ul> 113 * @return a point/value pair that satifies the convergence criteria. 114 * @throws TooManyEvaluationsException if the maximal number of 115 * evaluations is exceeded. 116 * @throws TooManyIterationsException if the maximal number of 117 * iterations is exceeded. 118 */ 119 public PAIR optimize(OptimizationData... optData) 120 throws TooManyEvaluationsException, 121 TooManyIterationsException { 122 // Retrieve settings. 123 parseOptimizationData(optData); 124 // Reset counters. 125 evaluations.resetCount(); 126 iterations.resetCount(); 127 // Perform optimization. 128 return doOptimize(); 129 } 130 131 /** 132 * Performs the bulk of the optimization algorithm. 133 * 134 * @return the point/value pair giving the optimal value of the 135 * objective function. 136 */ 137 protected abstract PAIR doOptimize(); 138 139 /** 140 * Increment the evaluation count. 141 * 142 * @throws TooManyEvaluationsException if the allowed evaluations 143 * have been exhausted. 144 */ 145 protected void incrementEvaluationCount() 146 throws TooManyEvaluationsException { 147 evaluations.incrementCount(); 148 } 149 150 /** 151 * Increment the iteration count. 152 * 153 * @throws TooManyIterationsException if the allowed iterations 154 * have been exhausted. 155 */ 156 protected void incrementIterationCount() 157 throws TooManyIterationsException { 158 iterations.incrementCount(); 159 } 160 161 /** 162 * Scans the list of (required and optional) optimization data that 163 * characterize the problem. 164 * 165 * @param optData Optimization data. 166 * The following data will be looked for: 167 * <ul> 168 * <li>{@link MaxEval}</li> 169 * <li>{@link MaxIter}</li> 170 * </ul> 171 */ 172 private void parseOptimizationData(OptimizationData... optData) { 173 // The existing values (as set by the previous call) are reused if 174 // not provided in the argument list. 175 for (OptimizationData data : optData) { 176 if (data instanceof MaxEval) { 177 evaluations.setMaximalCount(((MaxEval) data).getMaxEval()); 178 continue; 179 } 180 if (data instanceof MaxIter) { 181 iterations.setMaximalCount(((MaxIter) data).getMaxIter()); 182 continue; 183 } 184 } 185 } 186 187 /** 188 * Defines the action to perform when reaching the maximum number 189 * of evaluations. 190 */ 191 private static class MaxEvalCallback 192 implements Incrementor.MaxCountExceededCallback { 193 /** 194 * {@inheritDoc} 195 * @throws TooManyEvaluationsException. 196 */ 197 public void trigger(int max) { 198 throw new TooManyEvaluationsException(max); 199 } 200 } 201 202 /** 203 * Defines the action to perform when reaching the maximum number 204 * of evaluations. 205 */ 206 private static class MaxIterCallback 207 implements Incrementor.MaxCountExceededCallback { 208 /** 209 * {@inheritDoc} 210 * @throws TooManyIterationsException. 211 */ 212 public void trigger(int max) { 213 throw new TooManyIterationsException(max); 214 } 215 } 216 }