1#ifndef STAN_MATH_REV_CONSTRAINT_SUM_TO_ZERO_CONSTRAIN_HPP
2#define STAN_MATH_REV_CONSTRAINT_SUM_TO_ZERO_CONSTRAIN_HPP
29 const auto N = y_adj.size();
32 for (
int i = 0; i < N; ++i) {
33 double n =
static_cast<double>(i + 1);
36 sum_u_adj += z_adj.coeff(i);
39 double v_adj = -z_adj.coeff(i + 1) * n;
41 double w_adj = v_adj + sum_u_adj;
43 y_adj.coeffRef(i) += w_adj /
sqrt(n * (n + 1));
73template <
typename T, require_rev_col_vector_t<T>* =
nullptr>
79 auto arena_y =
to_arena(std::forward<T>(y));
99template <
typename T, require_rev_matrix_t<T>* =
nullptr,
100 require_not_t<is_rev_vector<T>>* =
nullptr>
106 auto arena_x =
to_arena(std::forward<T>(x));
110 const auto Nf = arena_x.val().
rows();
111 const auto Mf = arena_x.val().
cols();
113 Eigen::VectorXd d_beta = Eigen::VectorXd::Zero(Nf);
115 for (
int j = 0; j < Mf; ++j) {
116 double a_j =
inv_sqrt((j + 1.0) * (j + 2.0));
117 double b_j = (j + 1.0) * a_j;
121 for (
int i = 0; i < Nf; ++i) {
122 double a_i =
inv_sqrt((i + 1.0) * (i + 2.0));
123 double b_i = (i + 1.0) * a_i;
125 double dY = arena_z.adj().coeff(i, j) - arena_z.adj().coeff(Nf, j)
126 + arena_z.adj().coeff(Nf, Mf) - arena_z.adj().coeff(i, Mf);
127 double dI_from_beta = a_j * d_beta.coeff(i);
128 d_beta.coeffRef(i) += -dY;
130 double dI_from_alpha = b_j * dY;
131 double dI = dI_from_alpha + dI_from_beta;
132 arena_x.adj().coeffRef(i, j) += b_i * dI + a_i * d_ax;
166template <
typename T,
typename Lp, is_rev_matrix<T>* =
nullptr>
int64_t cols(const T_x &x)
Returns the number of columns in the specified kernel generator expression.
int64_t rows(const T_x &x)
Returns the number of rows in the specified kernel generator expression.
void sum_to_zero_vector_backprop(T &&y_adj, const Eigen::VectorXd &z_adj)
The reverse pass backprop for the sum_to_zero_constrain on vectors.
void reverse_pass_callback(F &&functor)
Puts a callback on the autodiff stack to be called in reverse pass.
arena_t< T > to_arena(const T &a)
Converts given argument into a type that either has any dynamic allocation on AD stack or schedules i...
fvar< T > sqrt(const fvar< T > &x)
plain_type_t< Vec > sum_to_zero_constrain(const Vec &y)
Return a vector with sum zero corresponding to the specified free vector.
fvar< T > inv_sqrt(const fvar< T > &x)
typename plain_type< std::decay_t< T > >::type plain_type_t
typename internal::arena_type_impl< std::decay_t< T > >::type arena_t
Determines a type that can be used in place of T that does any dynamic allocations on the AD stack.
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...