1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * https://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 /* 19 * This is not the original file distributed by the Apache Software Foundation 20 * It has been modified by the Hipparchus project 21 */ 22 package org.hipparchus.optim; 23 24 import org.hipparchus.exception.MathIllegalStateException; 25 import org.hipparchus.util.Incrementor; 26 27 /** 28 * Base class for implementing optimizers. 29 * It contains the boiler-plate code for counting the number of evaluations 30 * of the objective function and the number of iterations of the algorithm, 31 * and storing the convergence checker. 32 * <em>It is not a "user" class.</em> 33 * 34 * @param <P> Type of the point/value pair returned by the optimization 35 * algorithm. 36 * 37 */ 38 public abstract class BaseOptimizer<P> { 39 /** Evaluations counter. */ 40 protected Incrementor evaluations; 41 /** Iterations counter. */ 42 protected Incrementor iterations; 43 /** Convergence checker. */ 44 private final ConvergenceChecker<P> checker; 45 46 /** Simple constructor. 47 * @param checker Convergence checker. 48 */ 49 protected BaseOptimizer(ConvergenceChecker<P> checker) { 50 this(checker, 0, Integer.MAX_VALUE); 51 } 52 53 /** Simple constructor. 54 * @param checker Convergence checker. 55 * @param maxEval Maximum number of objective function evaluations. 56 * @param maxIter Maximum number of algorithm iterations. 57 */ 58 protected BaseOptimizer(ConvergenceChecker<P> checker, 59 int maxEval, 60 int maxIter) { 61 this.checker = checker; 62 63 evaluations = new Incrementor(maxEval); 64 iterations = new Incrementor(maxIter); 65 } 66 67 /** 68 * Gets the maximal number of function evaluations. 69 * 70 * @return the maximal number of function evaluations. 71 */ 72 public int getMaxEvaluations() { 73 return evaluations.getMaximalCount(); 74 } 75 76 /** 77 * Gets the number of evaluations of the objective function. 78 * The number of evaluations corresponds to the last call to the 79 * {@code optimize} method. It is 0 if the method has not been 80 * called yet. 81 * 82 * @return the number of evaluations of the objective function. 83 */ 84 public int getEvaluations() { 85 return evaluations.getCount(); 86 } 87 88 /** 89 * Gets the maximal number of iterations. 90 * 91 * @return the maximal number of iterations. 92 */ 93 public int getMaxIterations() { 94 return iterations.getMaximalCount(); 95 } 96 97 /** 98 * Gets the number of iterations performed by the algorithm. 99 * The number iterations corresponds to the last call to the 100 * {@code optimize} method. It is 0 if the method has not been 101 * called yet. 102 * 103 * @return the number of evaluations of the objective function. 104 */ 105 public int getIterations() { 106 return iterations.getCount(); 107 } 108 109 /** 110 * Gets the convergence checker. 111 * 112 * @return the object used to check for convergence. 113 */ 114 public ConvergenceChecker<P> getConvergenceChecker() { 115 return checker; 116 } 117 118 /** 119 * Stores data and performs the optimization. 120 * <p> 121 * The list of parameters is open-ended so that sub-classes can extend it 122 * with arguments specific to their concrete implementations. 123 * <p> 124 * When the method is called multiple times, instance data is overwritten 125 * only when actually present in the list of arguments: when not specified, 126 * data set in a previous call is retained (and thus is optional in 127 * subsequent calls). 128 * <p> 129 * Important note: Subclasses <em>must</em> override 130 * {@link #parseOptimizationData(OptimizationData[])} if they need to register 131 * their own options; but then, they <em>must</em> also call 132 * {@code super.parseOptimizationData(optData)} within that method. 133 * 134 * @param optData Optimization data. 135 * This method will register the following data: 136 * <ul> 137 * <li>{@link MaxEval}</li> 138 * <li>{@link MaxIter}</li> 139 * </ul> 140 * @return a point/value pair that satisfies the convergence criteria. 141 * @throws MathIllegalStateException if the maximal number of 142 * evaluations is exceeded. 143 * @throws MathIllegalStateException if the maximal number of 144 * iterations is exceeded. 145 */ 146 public P optimize(OptimizationData... optData) 147 throws MathIllegalStateException { 148 // Parse options. 149 parseOptimizationData(optData); 150 151 // Reset counters. 152 evaluations.reset(); 153 iterations.reset(); 154 // Perform optimization. 155 return doOptimize(); 156 } 157 158 /** 159 * Performs the optimization. 160 * 161 * @return a point/value pair that satisfies the convergence criteria. 162 * @throws MathIllegalStateException if the maximal number of 163 * evaluations is exceeded. 164 * @throws MathIllegalStateException if the maximal number of 165 * iterations is exceeded. 166 */ 167 public P optimize() 168 throws MathIllegalStateException { 169 // Reset counters. 170 evaluations.reset(); 171 iterations.reset(); 172 // Perform optimization. 173 return doOptimize(); 174 } 175 176 /** 177 * Performs the bulk of the optimization algorithm. 178 * 179 * @return the point/value pair giving the optimal value of the 180 * objective function. 181 */ 182 protected abstract P doOptimize(); 183 184 /** 185 * Increment the evaluation count. 186 * 187 * @throws MathIllegalStateException if the allowed evaluations 188 * have been exhausted. 189 */ 190 protected void incrementEvaluationCount() 191 throws MathIllegalStateException { 192 evaluations.increment(); 193 } 194 195 /** 196 * Increment the iteration count. 197 * 198 * @throws MathIllegalStateException if the allowed iterations 199 * have been exhausted. 200 */ 201 protected void incrementIterationCount() 202 throws MathIllegalStateException { 203 iterations.increment(); 204 } 205 206 /** 207 * Scans the list of (required and optional) optimization data that 208 * characterize the problem. 209 * 210 * @param optData Optimization data. 211 * The following data will be looked for: 212 * <ul> 213 * <li>{@link MaxEval}</li> 214 * <li>{@link MaxIter}</li> 215 * </ul> 216 */ 217 protected void parseOptimizationData(OptimizationData... optData) { 218 // The existing values (as set by the previous call) are reused if 219 // not provided in the argument list. 220 for (OptimizationData data : optData) { 221 if (data instanceof MaxEval) { 222 evaluations = evaluations.withMaximalCount(((MaxEval) data).getMaxEval()); 223 continue; 224 } 225 if (data instanceof MaxIter) { 226 iterations = iterations.withMaximalCount(((MaxIter) data).getMaxIter()); 227 continue; 228 } 229 } 230 } 231 }