|
| 1 | +#include <stan/math/rev.hpp> |
| 2 | +#include <gtest/gtest.h> |
| 3 | +#include <test/unit/math/rev/fun/util.hpp> |
| 4 | +#include <iostream> |
| 5 | +#include <stdexcept> |
| 6 | +#include <vector> |
| 7 | + |
| 8 | +using Eigen::Dynamic; |
| 9 | +using Eigen::Matrix; |
| 10 | + |
| 11 | +namespace finite_diff_hessian_times_vector_test { |
| 12 | +// fun1(x, y) = (x^2 * y) + (3 * y^2) |
| 13 | +struct fun1 { |
| 14 | + template <typename T> |
| 15 | + inline T operator()(const Matrix<T, Dynamic, 1>& x) const { |
| 16 | + return x(0) * x(0) * x(1) + 3.0 * x(1) * x(1); |
| 17 | + } |
| 18 | +}; |
| 19 | + |
| 20 | +struct fun2 { |
| 21 | + // fun2(x, y) = (x^2 * y) + (3 * y^2) + (5 * x * y) + sin(x) |
| 22 | + // d/dx fun2(x, y) = (2 * x * y) + (5 * y) + cos(x) |
| 23 | + // d/dy fun2(x, y) = (x^2) + (6 * y) + (5 * x) |
| 24 | + // d^2/dx^2 fun2(x, y) = (2 * y) - (sin(x)) |
| 25 | + // d^2/dydx fun2(x, y) = (2 * x) + 5 |
| 26 | + // d^2/dxdy fun2(x, y) = (2 * x) + 5 |
| 27 | + // d^2/dy^2 fun2(x, y) = 6 |
| 28 | + template <typename T> |
| 29 | + inline T operator()(const Matrix<T, Dynamic, 1>& x) const { |
| 30 | + using std::sin; |
| 31 | + return x(0) * x(0) * x(1) + 3.0 * x(1) * x(1) + 5.0 * x(0) * x(1) |
| 32 | + + sin(x(0)); |
| 33 | + } |
| 34 | +}; |
| 35 | + |
| 36 | +TEST(RevFunctor, finiteDiffHessianTimesVector) { |
| 37 | + using stan::math::internal::finite_diff_hessian_times_vector_auto; |
| 38 | + |
| 39 | + fun1 f; |
| 40 | + |
| 41 | + Matrix<double, Dynamic, 1> x(2); |
| 42 | + x << 2, -3; |
| 43 | + |
| 44 | + Matrix<double, Dynamic, 1> v(2); |
| 45 | + v << 8, 5; |
| 46 | + |
| 47 | + Matrix<double, Dynamic, 1> Hv; |
| 48 | + double fx; |
| 49 | + finite_diff_hessian_times_vector_auto(f, x, v, fx, Hv); |
| 50 | + |
| 51 | + EXPECT_FLOAT_EQ(2 * 2 * -3 + 3.0 * -3 * -3, fx); |
| 52 | + |
| 53 | + EXPECT_EQ(2, Hv.size()); |
| 54 | + EXPECT_FLOAT_EQ(2 * x(1) * v(0) + 2 * x(0) * v(1), Hv(0)); |
| 55 | + EXPECT_FLOAT_EQ(2 * x(0) * v(0) + 6 * v(1), Hv(1)); |
| 56 | +} |
| 57 | + |
| 58 | +TEST(RevFunctor, finiteDiffHessianTimesVector2) { |
| 59 | + using stan::math::internal::finite_diff_hessian_times_vector_auto; |
| 60 | + |
| 61 | + fun2 f; |
| 62 | + |
| 63 | + Matrix<double, Dynamic, 1> x(2); |
| 64 | + x << 13, -4; |
| 65 | + |
| 66 | + Matrix<double, Dynamic, 1> v(2); |
| 67 | + v << 10, 0.2; |
| 68 | + |
| 69 | + Matrix<double, Dynamic, 1> Hv; |
| 70 | + double fx; |
| 71 | + finite_diff_hessian_times_vector_auto(f, x, v, fx, Hv); |
| 72 | + |
| 73 | + EXPECT_FLOAT_EQ(13 * 13 * -4 + 3 * -4 * -4 + 5 * 13 * -4 + std::sin(13), fx); |
| 74 | + |
| 75 | + EXPECT_EQ(2, Hv.size()); |
| 76 | + EXPECT_FLOAT_EQ((2 * x(1) - std::sin(x(0))) * v(0) + (2 * x(0) + 5) * v(1), |
| 77 | + Hv(0)); |
| 78 | + EXPECT_FLOAT_EQ((2 * x(0) + 5) * v(0) + 6 * v(1), Hv(1)); |
| 79 | +} |
| 80 | + |
| 81 | +} // namespace finite_diff_hessian_times_vector_test |
0 commit comments