stan-dev / stanc3

The Stan transpiler (from Stan to C++ and beyond).
BSD 3-Clause "New" or "Revised" License
138 stars 44 forks source link

[BUG] eigenvalues_sym fails to compile in expression context #1294

Closed andrjohns closed 1 year ago

andrjohns commented 1 year ago

Opening the issue here, but it might be better suited to the Math library, so feel free to move.

The following model fails to compile:

data {
  real y_mean;
}

parameters {
  real y;
}

transformed parameters {
  matrix[2, 2] M = rep_matrix(y, 2, 2);
  real lp = normal_lpdf(eigenvalues_sym(M) | 0, 1);
}

model {
  y ~ normal(y_mean, 1);
}

With the error:

In file included from examples/test.hpp:1:
In file included from stan/src/stan/model/model_header.hpp:4:
In file included from /Users/andrew/.cmdstan/cmdstan-2.31.0/stan/lib/stan_math/stan/math.hpp:19:
In file included from /Users/andrew/.cmdstan/cmdstan-2.31.0/stan/lib/stan_math/stan/math/rev.hpp:10:
In file included from /Users/andrew/.cmdstan/cmdstan-2.31.0/stan/lib/stan_math/stan/math/rev/fun.hpp:55:
In file included from /Users/andrew/.cmdstan/cmdstan-2.31.0/stan/lib/stan_math/stan/math/rev/fun/elt_multiply.hpp:9:
In file included from /Users/andrew/.cmdstan/cmdstan-2.31.0/stan/lib/stan_math/stan/math/rev/fun/multiply.hpp:7:
In file included from /Users/andrew/.cmdstan/cmdstan-2.31.0/stan/lib/stan_math/stan/math/prim/fun.hpp:19:
/Users/andrew/.cmdstan/cmdstan-2.31.0/stan/lib/stan_math/stan/math/prim/fun/as_value_column_array_or_scalar.hpp:24:26: error: no matching function for call to 'as_column_vector_or_scalar'
      as_array_or_scalar(as_column_vector_or_scalar(std::forward<T>(a))));
                         ^~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/andrew/.cmdstan/cmdstan-2.31.0/stan/lib/stan_math/stan/math/prim/prob/normal_lpdf.hpp:58:33: note: in instantiation of function template specialization 'stan::math::as_value_column_array_or_scalar<const Eigen::Matrix<stan::math::var_value<double>, -1, -1, 0> &>' requested here
  decltype(auto) y_val = to_ref(as_value_column_array_or_scalar(y_ref));
                                ^
examples/test.hpp:96:24: note: in instantiation of function template specialization 'stan::math::normal_lpdf<false, Eigen::Matrix<stan::math::var_value<double>, -1, -1, 0>, int, int, nullptr>' requested here
      lp = stan::math::normal_lpdf<false>(stan::math::eigenvalues_sym(M), 0,
                       ^
examples/test.hpp:311:14: note: in instantiation of function template specialization 'test_model_namespace::test_model::log_prob_impl<false, false, Eigen::Matrix<stan::math::var_value<double>, -1, 1, 0>, Eigen::Matrix<int, -1, 1, 0>, nullptr, nullptr>' requested here
      return log_prob_impl<propto__, jacobian__>(params_r, params_i, pstream);
             ^
/Users/andrew/.cmdstan/cmdstan-2.31.0/stan/src/stan/model/model_base_crtp.hpp:98:50: note: in instantiation of function template specialization 'test_model_namespace::test_model::log_prob<false, false, stan::math::var_value<double>>' requested here
    return static_cast<const M*>(this)->template log_prob<false, false>(theta,
                                                 ^
examples/test.hpp:29:3: note: in instantiation of member function 'stan::model::model_base_crtp<test_model_namespace::test_model>::log_prob' requested here
  ~test_model() { }
  ^
/Users/andrew/.cmdstan/cmdstan-2.31.0/stan/lib/stan_math/stan/math/prim/fun/as_column_vector_or_scalar.hpp:22:10: note: candidate template ignored: requirement 'is_stan_scalar<Eigen::Matrix<stan::math::var_value<double, void>, -1, -1, 0, -1, -1>>::value' was not satisfied [with T = Eigen::Matrix<stan::math::var_value<double>, -1, -1, 0>]
inline T as_column_vector_or_scalar(const T& a) {
         ^
/Users/andrew/.cmdstan/cmdstan-2.31.0/stan/lib/stan_math/stan/math/prim/fun/as_column_vector_or_scalar.hpp:32:46: note: candidate template ignored: could not match 'empty_broadcast_array' against 'Matrix'
internal::empty_broadcast_array<T, S, void>& as_column_vector_or_scalar(
                                             ^
/Users/andrew/.cmdstan/cmdstan-2.31.0/stan/lib/stan_math/stan/math/prim/fun/as_column_vector_or_scalar.hpp:44:12: note: candidate template ignored: requirement 'is_eigen_col_vector<Eigen::Matrix<stan::math::var_value<double, void>, -1, -1, 0, -1, -1>>::value' was not satisfied [with T = const Eigen::Matrix<stan::math::var_value<double>, -1, -1, 0> &]
inline T&& as_column_vector_or_scalar(T&& a) {
           ^
/Users/andrew/.cmdstan/cmdstan-2.31.0/stan/lib/stan_math/stan/math/prim/fun/as_column_vector_or_scalar.hpp:59:13: note: candidate template ignored: requirement 'is_eigen_row_vector<Eigen::Matrix<stan::math::var_value<double, void>, -1, -1, 0, -1, -1>>::value' was not satisfied [with T = const Eigen::Matrix<stan::math::var_value<double>, -1, -1, 0> &]
inline auto as_column_vector_or_scalar(T&& a) {
            ^
/Users/andrew/.cmdstan/cmdstan-2.31.0/stan/lib/stan_math/stan/math/prim/fun/as_column_vector_or_scalar.hpp:71:13: note: candidate template ignored: requirement 'is_std_vector<Eigen::Matrix<stan::math::var_value<double, void>, -1, -1, 0, -1, -1>, void>::value' was not satisfied [with T = const Eigen::Matrix<stan::math::var_value<double>, -1, -1, 0> &]
inline auto as_column_vector_or_scalar(T&& a) {
            ^
/Users/andrew/.cmdstan/cmdstan-2.31.0/stan/lib/stan_math/stan/math/rev/fun/as_column_vector_or_scalar.hpp:19:13: note: candidate template ignored: requirement 'is_var_col_vector<Eigen::Matrix<stan::math::var_value<double, void>, -1, -1, 0, -1, -1>>::value' was not satisfied [with T = const Eigen::Matrix<stan::math::var_value<double>, -1, -1, 0> &]
inline auto as_column_vector_or_scalar(T&& a) {
            ^
/Users/andrew/.cmdstan/cmdstan-2.31.0/stan/lib/stan_math/stan/math/rev/fun/as_column_vector_or_scalar.hpp:32:13: note: candidate template ignored: requirement 'is_var_row_vector<Eigen::Matrix<stan::math::var_value<double, void>, -1, -1, 0, -1, -1>>::value' was not satisfied [with T = const Eigen::Matrix<stan::math::var_value<double>, -1, -1, 0> &]
inline auto as_column_vector_or_scalar(T&& a) {
            ^
1 warning and 1 error generated.
make: *** [examples/test] Error 1

But works if the eigenvalues_sym(M) is assigned to a temporary first:


data {
  real y_mean;
}

parameters {
  real y;
}

transformed parameters {
  matrix[2, 2] M = rep_matrix(y, 2, 2);
  vector[2] tmp = eigenvalues_sym(M);
  real lp = normal_lpdf(tmp | 0, 1);
}

model {
  y ~ normal(y_mean, 1);
}
WardBrian commented 1 year ago

The compiler is just generating stan::math::normal_lpdf<false>(stan::math::eigenvalues_sym(M), 0, 1), which to me suggests this is a bug in the Math library.

andrjohns commented 1 year ago

Ah found the Math problem

WardBrian commented 1 year ago

Nice catch, should be an easy fix in the math library