BaseAbstractMultivariateOptimizer.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.  *      http://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. package org.apache.commons.math3.optimization.direct;

  18. import org.apache.commons.math3.util.Incrementor;
  19. import org.apache.commons.math3.exception.MaxCountExceededException;
  20. import org.apache.commons.math3.exception.TooManyEvaluationsException;
  21. import org.apache.commons.math3.analysis.MultivariateFunction;
  22. import org.apache.commons.math3.optimization.BaseMultivariateOptimizer;
  23. import org.apache.commons.math3.optimization.OptimizationData;
  24. import org.apache.commons.math3.optimization.GoalType;
  25. import org.apache.commons.math3.optimization.InitialGuess;
  26. import org.apache.commons.math3.optimization.SimpleBounds;
  27. import org.apache.commons.math3.optimization.ConvergenceChecker;
  28. import org.apache.commons.math3.optimization.PointValuePair;
  29. import org.apache.commons.math3.optimization.SimpleValueChecker;
  30. import org.apache.commons.math3.exception.DimensionMismatchException;
  31. import org.apache.commons.math3.exception.NumberIsTooSmallException;
  32. import org.apache.commons.math3.exception.NumberIsTooLargeException;

  33. /**
  34.  * Base class for implementing optimizers for multivariate scalar functions.
  35.  * This base class handles the boiler-plate methods associated to thresholds,
  36.  * evaluations counting, initial guess and simple bounds settings.
  37.  *
  38.  * @param <FUNC> Type of the objective function to be optimized.
  39.  *
  40.  * @deprecated As of 3.1 (to be removed in 4.0).
  41.  * @since 2.2
  42.  */
  43. @Deprecated
  44. public abstract class BaseAbstractMultivariateOptimizer<FUNC extends MultivariateFunction>
  45.     implements BaseMultivariateOptimizer<FUNC> {
  46.     /** Evaluations counter. */
  47.     protected final Incrementor evaluations = new Incrementor();
  48.     /** Convergence checker. */
  49.     private ConvergenceChecker<PointValuePair> checker;
  50.     /** Type of optimization. */
  51.     private GoalType goal;
  52.     /** Initial guess. */
  53.     private double[] start;
  54.     /** Lower bounds. */
  55.     private double[] lowerBound;
  56.     /** Upper bounds. */
  57.     private double[] upperBound;
  58.     /** Objective function. */
  59.     private MultivariateFunction function;

  60.     /**
  61.      * Simple constructor with default settings.
  62.      * The convergence check is set to a {@link SimpleValueChecker}.
  63.      * @deprecated See {@link SimpleValueChecker#SimpleValueChecker()}
  64.      */
  65.     @Deprecated
  66.     protected BaseAbstractMultivariateOptimizer() {
  67.         this(new SimpleValueChecker());
  68.     }
  69.     /**
  70.      * @param checker Convergence checker.
  71.      */
  72.     protected BaseAbstractMultivariateOptimizer(ConvergenceChecker<PointValuePair> checker) {
  73.         this.checker = checker;
  74.     }

  75.     /** {@inheritDoc} */
  76.     public int getMaxEvaluations() {
  77.         return evaluations.getMaximalCount();
  78.     }

  79.     /** {@inheritDoc} */
  80.     public int getEvaluations() {
  81.         return evaluations.getCount();
  82.     }

  83.     /** {@inheritDoc} */
  84.     public ConvergenceChecker<PointValuePair> getConvergenceChecker() {
  85.         return checker;
  86.     }

  87.     /**
  88.      * Compute the objective function value.
  89.      *
  90.      * @param point Point at which the objective function must be evaluated.
  91.      * @return the objective function value at the specified point.
  92.      * @throws TooManyEvaluationsException if the maximal number of
  93.      * evaluations is exceeded.
  94.      */
  95.     protected double computeObjectiveValue(double[] point) {
  96.         try {
  97.             evaluations.incrementCount();
  98.         } catch (MaxCountExceededException e) {
  99.             throw new TooManyEvaluationsException(e.getMax());
  100.         }
  101.         return function.value(point);
  102.     }

  103.     /**
  104.      * {@inheritDoc}
  105.      *
  106.      * @deprecated As of 3.1. Please use
  107.      * {@link #optimize(int,MultivariateFunction,GoalType,OptimizationData[])}
  108.      * instead.
  109.      */
  110.     @Deprecated
  111.     public PointValuePair optimize(int maxEval, FUNC f, GoalType goalType,
  112.                                    double[] startPoint) {
  113.         return optimizeInternal(maxEval, f, goalType, new InitialGuess(startPoint));
  114.     }

  115.     /**
  116.      * Optimize an objective function.
  117.      *
  118.      * @param maxEval Allowed number of evaluations of the objective function.
  119.      * @param f Objective function.
  120.      * @param goalType Optimization type.
  121.      * @param optData Optimization data. The following data will be looked for:
  122.      * <ul>
  123.      *  <li>{@link InitialGuess}</li>
  124.      *  <li>{@link SimpleBounds}</li>
  125.      * </ul>
  126.      * @return the point/value pair giving the optimal value of the objective
  127.      * function.
  128.      * @since 3.1
  129.      */
  130.     public PointValuePair optimize(int maxEval,
  131.                                    FUNC f,
  132.                                    GoalType goalType,
  133.                                    OptimizationData... optData) {
  134.         return optimizeInternal(maxEval, f, goalType, optData);
  135.     }

  136.     /**
  137.      * Optimize an objective function.
  138.      *
  139.      * @param f Objective function.
  140.      * @param goalType Type of optimization goal: either
  141.      * {@link GoalType#MAXIMIZE} or {@link GoalType#MINIMIZE}.
  142.      * @param startPoint Start point for optimization.
  143.      * @param maxEval Maximum number of function evaluations.
  144.      * @return the point/value pair giving the optimal value for objective
  145.      * function.
  146.      * @throws org.apache.commons.math3.exception.DimensionMismatchException
  147.      * if the start point dimension is wrong.
  148.      * @throws org.apache.commons.math3.exception.TooManyEvaluationsException
  149.      * if the maximal number of evaluations is exceeded.
  150.      * @throws org.apache.commons.math3.exception.NullArgumentException if
  151.      * any argument is {@code null}.
  152.      * @deprecated As of 3.1. Please use
  153.      * {@link #optimize(int,MultivariateFunction,GoalType,OptimizationData[])}
  154.      * instead.
  155.      */
  156.     @Deprecated
  157.     protected PointValuePair optimizeInternal(int maxEval, FUNC f, GoalType goalType,
  158.                                               double[] startPoint) {
  159.         return optimizeInternal(maxEval, f, goalType, new InitialGuess(startPoint));
  160.     }

  161.     /**
  162.      * Optimize an objective function.
  163.      *
  164.      * @param maxEval Allowed number of evaluations of the objective function.
  165.      * @param f Objective function.
  166.      * @param goalType Optimization type.
  167.      * @param optData Optimization data. The following data will be looked for:
  168.      * <ul>
  169.      *  <li>{@link InitialGuess}</li>
  170.      *  <li>{@link SimpleBounds}</li>
  171.      * </ul>
  172.      * @return the point/value pair giving the optimal value of the objective
  173.      * function.
  174.      * @throws TooManyEvaluationsException if the maximal number of
  175.      * evaluations is exceeded.
  176.      * @since 3.1
  177.      */
  178.     protected PointValuePair optimizeInternal(int maxEval,
  179.                                               FUNC f,
  180.                                               GoalType goalType,
  181.                                               OptimizationData... optData)
  182.         throws TooManyEvaluationsException {
  183.         // Set internal state.
  184.         evaluations.setMaximalCount(maxEval);
  185.         evaluations.resetCount();
  186.         function = f;
  187.         goal = goalType;
  188.         // Retrieve other settings.
  189.         parseOptimizationData(optData);
  190.         // Check input consistency.
  191.         checkParameters();
  192.         // Perform computation.
  193.         return doOptimize();
  194.     }

  195.     /**
  196.      * Scans the list of (required and optional) optimization data that
  197.      * characterize the problem.
  198.      *
  199.      * @param optData Optimization data. The following data will be looked for:
  200.      * <ul>
  201.      *  <li>{@link InitialGuess}</li>
  202.      *  <li>{@link SimpleBounds}</li>
  203.      * </ul>
  204.      */
  205.     private void parseOptimizationData(OptimizationData... optData) {
  206.         // The existing values (as set by the previous call) are reused if
  207.         // not provided in the argument list.
  208.         for (OptimizationData data : optData) {
  209.             if (data instanceof InitialGuess) {
  210.                 start = ((InitialGuess) data).getInitialGuess();
  211.                 continue;
  212.             }
  213.             if (data instanceof SimpleBounds) {
  214.                 final SimpleBounds bounds = (SimpleBounds) data;
  215.                 lowerBound = bounds.getLower();
  216.                 upperBound = bounds.getUpper();
  217.                 continue;
  218.             }
  219.         }
  220.     }

  221.     /**
  222.      * @return the optimization type.
  223.      */
  224.     public GoalType getGoalType() {
  225.         return goal;
  226.     }

  227.     /**
  228.      * @return the initial guess.
  229.      */
  230.     public double[] getStartPoint() {
  231.         return start == null ? null : start.clone();
  232.     }
  233.     /**
  234.      * @return the lower bounds.
  235.      * @since 3.1
  236.      */
  237.     public double[] getLowerBound() {
  238.         return lowerBound == null ? null : lowerBound.clone();
  239.     }
  240.     /**
  241.      * @return the upper bounds.
  242.      * @since 3.1
  243.      */
  244.     public double[] getUpperBound() {
  245.         return upperBound == null ? null : upperBound.clone();
  246.     }

  247.     /**
  248.      * Perform the bulk of the optimization algorithm.
  249.      *
  250.      * @return the point/value pair giving the optimal value of the
  251.      * objective function.
  252.      */
  253.     protected abstract PointValuePair doOptimize();

  254.     /**
  255.      * Check parameters consistency.
  256.      */
  257.     private void checkParameters() {
  258.         if (start != null) {
  259.             final int dim = start.length;
  260.             if (lowerBound != null) {
  261.                 if (lowerBound.length != dim) {
  262.                     throw new DimensionMismatchException(lowerBound.length, dim);
  263.                 }
  264.                 for (int i = 0; i < dim; i++) {
  265.                     final double v = start[i];
  266.                     final double lo = lowerBound[i];
  267.                     if (v < lo) {
  268.                         throw new NumberIsTooSmallException(v, lo, true);
  269.                     }
  270.                 }
  271.             }
  272.             if (upperBound != null) {
  273.                 if (upperBound.length != dim) {
  274.                     throw new DimensionMismatchException(upperBound.length, dim);
  275.                 }
  276.                 for (int i = 0; i < dim; i++) {
  277.                     final double v = start[i];
  278.                     final double hi = upperBound[i];
  279.                     if (v > hi) {
  280.                         throw new NumberIsTooLargeException(v, hi, true);
  281.                     }
  282.                 }
  283.             }

  284.             // If the bounds were not specified, the allowed interval is
  285.             // assumed to be [-inf, +inf].
  286.             if (lowerBound == null) {
  287.                 lowerBound = new double[dim];
  288.                 for (int i = 0; i < dim; i++) {
  289.                     lowerBound[i] = Double.NEGATIVE_INFINITY;
  290.                 }
  291.             }
  292.             if (upperBound == null) {
  293.                 upperBound = new double[dim];
  294.                 for (int i = 0; i < dim; i++) {
  295.                     upperBound[i] = Double.POSITIVE_INFINITY;
  296.                 }
  297.             }
  298.         }
  299.     }
  300. }