View Javadoc
1   /*
2    * Copyright (C) 2012 Alberto Irurueta Carro (alberto@irurueta.com)
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.irurueta.numerical;
17  
18  /**
19   * This class evaluates a multidimensional function and obtains its gradient
20   * along a line; such line is defined by an input point and a given direction.
21   * Using provided input point and direction, the multidimensional function's
22   * input parameters are determined, so they all lay on a line.
23   */
24  public class DirectionalDerivativeEvaluator extends DirectionalEvaluator {
25  
26      /**
27       * Listener to evaluate a multidimensional function's gradient.
28       */
29      private GradientFunctionEvaluatorListener gradientListener;
30  
31      /**
32       * Array containing gradient at point p. This is used internally.
33       */
34      final double[] dft;
35  
36      /**
37       * Constructor.
38       *
39       * @param listener         Listener to evaluate a multidimensional function.
40       * @param gradientListener Listener to evaluate a multidimensional
41       *                         function's gradient.
42       * @param point            Point used as a reference to determine the function's input
43       *                         parameters along a line.
44       * @param direction        Vector indicating the direction of the line where the
45       *                         function is evaluated.
46       * @throws IllegalArgumentException Raised if point and direction don't have
47       *                                  the same length.
48       */
49      public DirectionalDerivativeEvaluator(
50              final MultiDimensionFunctionEvaluatorListener listener,
51              final GradientFunctionEvaluatorListener gradientListener, final double[] point, final double[] direction) {
52          super(listener, point, direction);
53  
54          this.gradientListener = gradientListener;
55          dft = new double[point.length];
56      }
57  
58      /**
59       * Returns gradient listener that evaluates a multidimensional function
60       * gradient.
61       * If the gradient expression is not known (e.g. is not a closed
62       * expression), then a GradientEstimator can be used internally in the
63       * listener implementation.
64       *
65       * @return Gradient listener.
66       */
67      public GradientFunctionEvaluatorListener getGradientListener() {
68          return gradientListener;
69      }
70  
71      /**
72       * Sets gradient listener that evaluates a multidimensional function
73       * gradient.
74       * If the gradient expression is not known (e.g. is not a closed
75       * expression), then a GradientEstimator can be used internally in the
76       * listener implementation being provided.
77       *
78       * @param gradientListener Gradient listener
79       */
80      public void setGradientListener(final GradientFunctionEvaluatorListener gradientListener) {
81          this.gradientListener = gradientListener;
82      }
83  
84      /**
85       * Computes derivative on current direction of a function at distance x from
86       * current point and using current listener and gradient listener.
87       *
88       * @param x Distance from current point using current direction where
89       *          function is being evaluated.
90       * @return Result of evaluating function.
91       * @throws EvaluationException Thrown if function evaluation fails.
92       */
93      public double differentiateAt(final double x) throws EvaluationException {
94          final var length = point.length;
95  
96          for (var i = 0; i < length; i++) {
97              p[i] = point[i] + x * direction[i];
98          }
99  
100         // Compute gradient at such point
101         gradientListener.evaluateGradient(p, dft);
102 
103         // Obtain 1D derivative on corresponding direction
104         var df1 = 0.0;
105         for (var i = 0; i < length; i++) {
106             df1 += dft[i] * direction[i];
107         }
108         return df1;
109     }
110 }