Mix/hessian

Something changed with the Hessian calculations in the last version or two of Stan Math and now the StanHeaders vignette will not build with it.

The line in question is

and the relevant parts of the compiler errors are:

file19611604473d.cpp:41:62: required from ‘H(Eigen::VectorXd, Eigen::VectorXd)::<lambda(auto:36)> [with auto:36 = Eigen::Matrix<stan::math::fvarstan::math::var, -1, 1>]’
/tmp/Rtmp6OO1UC/Rinst184f61b2d181/StanHeaders/include/stan/math/mix/functor/hessian.hpp:61:26: required from ‘void stan::math::hessian(const F&, const Eigen::Matrix<double, -1, 1>&, double&, Eigen::Matrix<double, -1, 1>&, Eigen::Matrix<double, -1, -1>&) [with F = H(Eigen::VectorXd, Eigen::VectorXd)::<lambda(auto:36)>]’
file19611604473d.cpp:42:40: required from here
/home/ben/r-devel/library/RcppEigen/include/Eigen/src/Core/functors/BinaryFunctors.h:324:95: error: no type named ‘ReturnType’ in ‘struct Eigen::ScalarBinaryOpTraits<stan::math::fvarstan::math::var, double, Eigen::internal::scalar_difference_op<stan::math::fvarstan::math::var, double> >’
typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_difference_op>::ReturnType result_type;
^~~~~~~~~~~

file19611604473d.cpp:41:53: error: invalid use of void expression
stan::math::hessian([&a](auto x) { return dot_self(subtract(x, a)); },
^~~~~~~~

In file included from file19611604473d.cpp:5:
/tmp/Rtmp6OO1UC/Rinst184f61b2d181/StanHeaders/include/stan/math/mix/functor/hessian.hpp: In instantiation of ‘void stan::math::hessian(const F&, const Eigen::Matrix<double, -1, 1>&, double&, Eigen::Matrix<double, -1, 1>&, Eigen::Matrix<double, -1, -1>&) [with F = H(Eigen::VectorXd, Eigen::VectorXd)::<lambda(auto:36)>]’:
file19611604473d.cpp:42:40: required from here
/tmp/Rtmp6OO1UC/Rinst184f61b2d181/StanHeaders/include/stan/math/mix/functor/hessian.hpp:61:26: error: conversion from ‘void’ to non-scalar type ‘stan::math::fvarstan::math::var’ requested
fvar fx_fvar = f(x_fvar);
~^~~~~~~~

Does anyone know how about this?

2 Likes

Sorry you haven’t seena response for this. I’d suggest making an issue in the math lib.

I think @stevebronder has been upgrading all the calls, so he may know.

Sorry this slipped by Ben, what version of stan math are you using? I changed the test for dot_self (which should run the hessian) to do the dot_self(subtract()) and it seems to work on dev.

More info below but if you have this up on a branch somewhere I can take a look tmrw. I think the actual error may not be in the pieces you posted. It looks like this is failing for an expression Eigen is trying to use but it can’t deduce the return type when the scalars for the binary op are fvar and double

TEST(MathMixMatFun, dotSelf) {
  auto f = [](const auto& x, const auto& y) { 
   return stan::math::dot_self(stan::math::subtract(x, y)); 
};

  Eigen::VectorXd x0(0);
  Eigen::VectorXd x1(1);
  x1 << 2;

  Eigen::VectorXd x2(2);
  x2 << 2, 3;

  Eigen::VectorXd x3(3);
  x3 << 2, 3, 4;
  for (const auto& a : std::vector<Eigen::VectorXd>{x0, x1, x2, x3}) {
      stan::test::expect_ad(f, a, a);      
  }
}

This part is particularly odd,

RcppEigen/include/Eigen/src/Core/functors/BinaryFunctors.h:324:95:
 error: no type named ‘ReturnType’ in 
‘struct Eigen::ScalarBinaryOpTraits<stan::math::fvar<stan::math::var>, double,
   Eigen::internal::scalar_difference_op<stan::math::fvar<stan::math::var>, double>>’
typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar,scalar_difference_op>::ReturnType result_type;

Since we have a specialization of ScalarBinaryOpTraits for fvar and double

template <typename T, typename BinaryOp>
struct ScalarBinaryOpTraits<stan::math::fvar<T>, double, BinaryOp> {
  using ReturnType = stan::math::fvar<T>;
};

The last time I saw this was for the complex Eigen type traits which was a whole monster

The void errors like

error: conversion from ‘void’ to non-scalar type ‘stan::math::fvarstan::math::var’ requested
fvar fx_fvar = f(x_fvar);

and

error: invalid use of void expression
stan::math::hessian([&a](auto x) { return dot_self(subtract(x, a)); },

Are compiler artifacts because the lambda expression can’t deduce it’s type (since it failed) and so it’s return is void.

1 Like

Also this

Eigen::internal::scalar_difference_op<stan::math::fvarstan::math::var, double> >’

is from subtract() specialized for two eigen types, do you just include stan/math/mix.hpp or something else?