BaseOptimizer.java

  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.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */
  21. package org.hipparchus.optim;

  22. import org.hipparchus.exception.MathIllegalStateException;
  23. import org.hipparchus.util.Incrementor;

  24. /**
  25.  * Base class for implementing optimizers.
  26.  * It contains the boiler-plate code for counting the number of evaluations
  27.  * of the objective function and the number of iterations of the algorithm,
  28.  * and storing the convergence checker.
  29.  * <em>It is not a "user" class.</em>
  30.  *
  31.  * @param <P> Type of the point/value pair returned by the optimization
  32.  * algorithm.
  33.  *
  34.  */
  35. public abstract class BaseOptimizer<P> {
  36.     /** Evaluations counter. */
  37.     protected Incrementor evaluations;
  38.     /** Iterations counter. */
  39.     protected Incrementor iterations;
  40.     /** Convergence checker. */
  41.     private final ConvergenceChecker<P> checker;

  42.     /** Simple constructor.
  43.      * @param checker Convergence checker.
  44.      */
  45.     protected BaseOptimizer(ConvergenceChecker<P> checker) {
  46.         this(checker, 0, Integer.MAX_VALUE);
  47.     }

  48.     /** Simple constructor.
  49.      * @param checker Convergence checker.
  50.      * @param maxEval Maximum number of objective function evaluations.
  51.      * @param maxIter Maximum number of algorithm iterations.
  52.      */
  53.     protected BaseOptimizer(ConvergenceChecker<P> checker,
  54.                             int maxEval,
  55.                             int maxIter) {
  56.         this.checker = checker;

  57.         evaluations = new Incrementor(maxEval);
  58.         iterations  = new Incrementor(maxIter);
  59.     }

  60.     /**
  61.      * Gets the maximal number of function evaluations.
  62.      *
  63.      * @return the maximal number of function evaluations.
  64.      */
  65.     public int getMaxEvaluations() {
  66.         return evaluations.getMaximalCount();
  67.     }

  68.     /**
  69.      * Gets the number of evaluations of the objective function.
  70.      * The number of evaluations corresponds to the last call to the
  71.      * {@code optimize} method. It is 0 if the method has not been
  72.      * called yet.
  73.      *
  74.      * @return the number of evaluations of the objective function.
  75.      */
  76.     public int getEvaluations() {
  77.         return evaluations.getCount();
  78.     }

  79.     /**
  80.      * Gets the maximal number of iterations.
  81.      *
  82.      * @return the maximal number of iterations.
  83.      */
  84.     public int getMaxIterations() {
  85.         return iterations.getMaximalCount();
  86.     }

  87.     /**
  88.      * Gets the number of iterations performed by the algorithm.
  89.      * The number iterations corresponds to the last call to the
  90.      * {@code optimize} method. It is 0 if the method has not been
  91.      * called yet.
  92.      *
  93.      * @return the number of evaluations of the objective function.
  94.      */
  95.     public int getIterations() {
  96.         return iterations.getCount();
  97.     }

  98.     /**
  99.      * Gets the convergence checker.
  100.      *
  101.      * @return the object used to check for convergence.
  102.      */
  103.     public ConvergenceChecker<P> getConvergenceChecker() {
  104.         return checker;
  105.     }

  106.     /**
  107.      * Stores data and performs the optimization.
  108.      * <p>
  109.      * The list of parameters is open-ended so that sub-classes can extend it
  110.      * with arguments specific to their concrete implementations.
  111.      * <p>
  112.      * When the method is called multiple times, instance data is overwritten
  113.      * only when actually present in the list of arguments: when not specified,
  114.      * data set in a previous call is retained (and thus is optional in
  115.      * subsequent calls).
  116.      * <p>
  117.      * Important note: Subclasses <em>must</em> override
  118.      * {@link #parseOptimizationData(OptimizationData[])} if they need to register
  119.      * their own options; but then, they <em>must</em> also call
  120.      * {@code super.parseOptimizationData(optData)} within that method.
  121.      *
  122.      * @param optData Optimization data.
  123.      * This method will register the following data:
  124.      * <ul>
  125.      *  <li>{@link MaxEval}</li>
  126.      *  <li>{@link MaxIter}</li>
  127.      * </ul>
  128.      * @return a point/value pair that satisfies the convergence criteria.
  129.      * @throws MathIllegalStateException if the maximal number of
  130.      * evaluations is exceeded.
  131.      * @throws MathIllegalStateException if the maximal number of
  132.      * iterations is exceeded.
  133.      */
  134.     public P optimize(OptimizationData... optData)
  135.         throws MathIllegalStateException {
  136.         // Parse options.
  137.         parseOptimizationData(optData);

  138.         // Reset counters.
  139.         evaluations.reset();
  140.         iterations.reset();
  141.         // Perform optimization.
  142.         return doOptimize();
  143.     }

  144.     /**
  145.      * Performs the optimization.
  146.      *
  147.      * @return a point/value pair that satisfies the convergence criteria.
  148.      * @throws MathIllegalStateException if the maximal number of
  149.      * evaluations is exceeded.
  150.      * @throws MathIllegalStateException if the maximal number of
  151.      * iterations is exceeded.
  152.      */
  153.     public P optimize()
  154.         throws MathIllegalStateException {
  155.         // Reset counters.
  156.         evaluations.reset();
  157.         iterations.reset();
  158.         // Perform optimization.
  159.         return doOptimize();
  160.     }

  161.     /**
  162.      * Performs the bulk of the optimization algorithm.
  163.      *
  164.      * @return the point/value pair giving the optimal value of the
  165.      * objective function.
  166.      */
  167.     protected abstract P doOptimize();

  168.     /**
  169.      * Increment the evaluation count.
  170.      *
  171.      * @throws MathIllegalStateException if the allowed evaluations
  172.      * have been exhausted.
  173.      */
  174.     protected void incrementEvaluationCount()
  175.         throws MathIllegalStateException {
  176.         evaluations.increment();
  177.     }

  178.     /**
  179.      * Increment the iteration count.
  180.      *
  181.      * @throws MathIllegalStateException if the allowed iterations
  182.      * have been exhausted.
  183.      */
  184.     protected void incrementIterationCount()
  185.         throws MathIllegalStateException {
  186.         iterations.increment();
  187.     }

  188.     /**
  189.      * Scans the list of (required and optional) optimization data that
  190.      * characterize the problem.
  191.      *
  192.      * @param optData Optimization data.
  193.      * The following data will be looked for:
  194.      * <ul>
  195.      *  <li>{@link MaxEval}</li>
  196.      *  <li>{@link MaxIter}</li>
  197.      * </ul>
  198.      */
  199.     protected void parseOptimizationData(OptimizationData... optData) {
  200.         // The existing values (as set by the previous call) are reused if
  201.         // not provided in the argument list.
  202.         for (OptimizationData data : optData) {
  203.             if (data instanceof MaxEval) {
  204.                 evaluations = evaluations.withMaximalCount(((MaxEval) data).getMaxEval());
  205.                 continue;
  206.             }
  207.             if (data instanceof MaxIter) {
  208.                 iterations = iterations.withMaximalCount(((MaxIter) data).getMaxIter());
  209.                 continue;
  210.             }
  211.         }
  212.     }
  213. }