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 }