MultiDirectionalSimplex.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 java.util.Comparator;

  19. import org.apache.commons.math3.analysis.MultivariateFunction;
  20. import org.apache.commons.math3.optimization.PointValuePair;

  21. /**
  22.  * This class implements the multi-directional direct search method.
  23.  *
  24.  * @deprecated As of 3.1 (to be removed in 4.0).
  25.  * @since 3.0
  26.  */
  27. @Deprecated
  28. public class MultiDirectionalSimplex extends AbstractSimplex {
  29.     /** Default value for {@link #khi}: {@value}. */
  30.     private static final double DEFAULT_KHI = 2;
  31.     /** Default value for {@link #gamma}: {@value}. */
  32.     private static final double DEFAULT_GAMMA = 0.5;
  33.     /** Expansion coefficient. */
  34.     private final double khi;
  35.     /** Contraction coefficient. */
  36.     private final double gamma;

  37.     /**
  38.      * Build a multi-directional simplex with default coefficients.
  39.      * The default values are 2.0 for khi and 0.5 for gamma.
  40.      *
  41.      * @param n Dimension of the simplex.
  42.      */
  43.     public MultiDirectionalSimplex(final int n) {
  44.         this(n, 1d);
  45.     }

  46.     /**
  47.      * Build a multi-directional simplex with default coefficients.
  48.      * The default values are 2.0 for khi and 0.5 for gamma.
  49.      *
  50.      * @param n Dimension of the simplex.
  51.      * @param sideLength Length of the sides of the default (hypercube)
  52.      * simplex. See {@link AbstractSimplex#AbstractSimplex(int,double)}.
  53.      */
  54.     public MultiDirectionalSimplex(final int n, double sideLength) {
  55.         this(n, sideLength, DEFAULT_KHI, DEFAULT_GAMMA);
  56.     }

  57.     /**
  58.      * Build a multi-directional simplex with specified coefficients.
  59.      *
  60.      * @param n Dimension of the simplex. See
  61.      * {@link AbstractSimplex#AbstractSimplex(int,double)}.
  62.      * @param khi Expansion coefficient.
  63.      * @param gamma Contraction coefficient.
  64.      */
  65.     public MultiDirectionalSimplex(final int n,
  66.                                    final double khi, final double gamma) {
  67.         this(n, 1d, khi, gamma);
  68.     }

  69.     /**
  70.      * Build a multi-directional simplex with specified coefficients.
  71.      *
  72.      * @param n Dimension of the simplex. See
  73.      * {@link AbstractSimplex#AbstractSimplex(int,double)}.
  74.      * @param sideLength Length of the sides of the default (hypercube)
  75.      * simplex. See {@link AbstractSimplex#AbstractSimplex(int,double)}.
  76.      * @param khi Expansion coefficient.
  77.      * @param gamma Contraction coefficient.
  78.      */
  79.     public MultiDirectionalSimplex(final int n, double sideLength,
  80.                                    final double khi, final double gamma) {
  81.         super(n, sideLength);

  82.         this.khi   = khi;
  83.         this.gamma = gamma;
  84.     }

  85.     /**
  86.      * Build a multi-directional simplex with default coefficients.
  87.      * The default values are 2.0 for khi and 0.5 for gamma.
  88.      *
  89.      * @param steps Steps along the canonical axes representing box edges.
  90.      * They may be negative but not zero. See
  91.      */
  92.     public MultiDirectionalSimplex(final double[] steps) {
  93.         this(steps, DEFAULT_KHI, DEFAULT_GAMMA);
  94.     }

  95.     /**
  96.      * Build a multi-directional simplex with specified coefficients.
  97.      *
  98.      * @param steps Steps along the canonical axes representing box edges.
  99.      * They may be negative but not zero. See
  100.      * {@link AbstractSimplex#AbstractSimplex(double[])}.
  101.      * @param khi Expansion coefficient.
  102.      * @param gamma Contraction coefficient.
  103.      */
  104.     public MultiDirectionalSimplex(final double[] steps,
  105.                                    final double khi, final double gamma) {
  106.         super(steps);

  107.         this.khi   = khi;
  108.         this.gamma = gamma;
  109.     }

  110.     /**
  111.      * Build a multi-directional simplex with default coefficients.
  112.      * The default values are 2.0 for khi and 0.5 for gamma.
  113.      *
  114.      * @param referenceSimplex Reference simplex. See
  115.      * {@link AbstractSimplex#AbstractSimplex(double[][])}.
  116.      */
  117.     public MultiDirectionalSimplex(final double[][] referenceSimplex) {
  118.         this(referenceSimplex, DEFAULT_KHI, DEFAULT_GAMMA);
  119.     }

  120.     /**
  121.      * Build a multi-directional simplex with specified coefficients.
  122.      *
  123.      * @param referenceSimplex Reference simplex. See
  124.      * {@link AbstractSimplex#AbstractSimplex(double[][])}.
  125.      * @param khi Expansion coefficient.
  126.      * @param gamma Contraction coefficient.
  127.      * @throws org.apache.commons.math3.exception.NotStrictlyPositiveException
  128.      * if the reference simplex does not contain at least one point.
  129.      * @throws org.apache.commons.math3.exception.DimensionMismatchException
  130.      * if there is a dimension mismatch in the reference simplex.
  131.      */
  132.     public MultiDirectionalSimplex(final double[][] referenceSimplex,
  133.                                    final double khi, final double gamma) {
  134.         super(referenceSimplex);

  135.         this.khi   = khi;
  136.         this.gamma = gamma;
  137.     }

  138.     /** {@inheritDoc} */
  139.     @Override
  140.     public void iterate(final MultivariateFunction evaluationFunction,
  141.                         final Comparator<PointValuePair> comparator) {
  142.         // Save the original simplex.
  143.         final PointValuePair[] original = getPoints();
  144.         final PointValuePair best = original[0];

  145.         // Perform a reflection step.
  146.         final PointValuePair reflected = evaluateNewSimplex(evaluationFunction,
  147.                                                                 original, 1, comparator);
  148.         if (comparator.compare(reflected, best) < 0) {
  149.             // Compute the expanded simplex.
  150.             final PointValuePair[] reflectedSimplex = getPoints();
  151.             final PointValuePair expanded = evaluateNewSimplex(evaluationFunction,
  152.                                                                    original, khi, comparator);
  153.             if (comparator.compare(reflected, expanded) <= 0) {
  154.                 // Keep the reflected simplex.
  155.                 setPoints(reflectedSimplex);
  156.             }
  157.             // Keep the expanded simplex.
  158.             return;
  159.         }

  160.         // Compute the contracted simplex.
  161.         evaluateNewSimplex(evaluationFunction, original, gamma, comparator);

  162.     }

  163.     /**
  164.      * Compute and evaluate a new simplex.
  165.      *
  166.      * @param evaluationFunction Evaluation function.
  167.      * @param original Original simplex (to be preserved).
  168.      * @param coeff Linear coefficient.
  169.      * @param comparator Comparator to use to sort simplex vertices from best
  170.      * to poorest.
  171.      * @return the best point in the transformed simplex.
  172.      * @throws org.apache.commons.math3.exception.TooManyEvaluationsException
  173.      * if the maximal number of evaluations is exceeded.
  174.      */
  175.     private PointValuePair evaluateNewSimplex(final MultivariateFunction evaluationFunction,
  176.                                                   final PointValuePair[] original,
  177.                                                   final double coeff,
  178.                                                   final Comparator<PointValuePair> comparator) {
  179.         final double[] xSmallest = original[0].getPointRef();
  180.         // Perform a linear transformation on all the simplex points,
  181.         // except the first one.
  182.         setPoint(0, original[0]);
  183.         final int dim = getDimension();
  184.         for (int i = 1; i < getSize(); i++) {
  185.             final double[] xOriginal = original[i].getPointRef();
  186.             final double[] xTransformed = new double[dim];
  187.             for (int j = 0; j < dim; j++) {
  188.                 xTransformed[j] = xSmallest[j] + coeff * (xSmallest[j] - xOriginal[j]);
  189.             }
  190.             setPoint(i, new PointValuePair(xTransformed, Double.NaN, false));
  191.         }

  192.         // Evaluate the simplex.
  193.         evaluate(evaluationFunction, comparator);

  194.         return getPoint(0);
  195.     }
  196. }