Automatic Differentiation
 
Loading...
Searching...
No Matches
normal_id_glm_lpdf.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_PRIM_PROB_NORMAL_ID_GLM_LPDF_HPP
2#define STAN_MATH_PRIM_PROB_NORMAL_ID_GLM_LPDF_HPP
3
19#include <cmath>
20
21namespace stan {
22namespace math {
23
56template <bool propto, typename T_y, typename T_x, typename T_alpha,
57 typename T_beta, typename T_scale, require_matrix_t<T_x>* = nullptr>
59 const T_y& y, const T_x& x, const T_alpha& alpha, const T_beta& beta,
60 const T_scale& sigma) {
61 using Eigen::Array;
62 using Eigen::Dynamic;
63 using Eigen::Matrix;
64 using Eigen::VectorXd;
65 using std::isfinite;
66 constexpr int T_x_rows = T_x::RowsAtCompileTime;
67 using T_partials_return
69 using T_scale_val = typename std::conditional_t<
71 Eigen::Array<partials_return_t<T_scale>, -1, 1>,
73 using T_y_scaled_tmp =
74 typename std::conditional_t<T_x_rows == 1, T_partials_return,
75 Array<T_partials_return, Dynamic, 1>>;
76 using T_y_ref = ref_type_if_not_constant_t<T_y>;
77 using T_x_ref = ref_type_if_not_constant_t<T_x>;
78 using T_alpha_ref = ref_type_if_not_constant_t<T_alpha>;
79 using T_beta_ref = ref_type_if_not_constant_t<T_beta>;
80 using T_sigma_ref = ref_type_if_not_constant_t<T_scale>;
81
82 const size_t N_instances = T_x_rows == 1 ? stan::math::size(y) : x.rows();
83 const size_t N_attributes = x.cols();
84
85 static constexpr const char* function = "normal_id_glm_lpdf";
86 check_consistent_size(function, "Vector of dependent variables", y,
87 N_instances);
88 check_consistent_size(function, "Weight vector", beta, N_attributes);
89 check_consistent_size(function, "Vector of scale parameters", sigma,
90 N_instances);
91 check_consistent_size(function, "Vector of intercepts", alpha, N_instances);
92 T_sigma_ref sigma_ref = sigma;
93 const auto& sigma_val = value_of(sigma_ref);
94 const auto& sigma_val_vec = to_ref(as_column_vector_or_scalar(sigma_val));
95 check_positive_finite(function, "Scale vector", sigma_val_vec);
96
97 if (size_zero(y, sigma)) {
98 return 0;
99 }
100 if constexpr (!include_summand<propto, T_y, T_x, T_alpha, T_beta,
101 T_scale>::value) {
102 return 0;
103 }
104
105 T_y_ref y_ref = y;
106 T_x_ref x_ref = x;
107 T_alpha_ref alpha_ref = alpha;
108 T_beta_ref beta_ref = beta;
109
110 const auto& y_val = value_of(y_ref);
111 const auto& x_val = to_ref_if<is_autodiff_v<T_beta>>(value_of(x_ref));
112 const auto& alpha_val = value_of(alpha_ref);
113 const auto& beta_val = value_of(beta_ref);
114
115 const auto& y_val_vec = as_column_vector_or_scalar(y_val);
116 const auto& alpha_val_vec = as_column_vector_or_scalar(alpha_val);
117 const auto& beta_val_vec
118 = to_ref_if<is_autodiff_v<T_x>>(as_column_vector_or_scalar(beta_val));
119
120 T_scale_val inv_sigma = 1.0 / as_array_or_scalar(sigma_val_vec);
121
122 // the most efficient way to calculate this depends on template parameters
123 T_partials_return y_scaled_sq_sum;
124
125 Array<T_partials_return, Dynamic, 1> y_scaled(N_instances);
126 if constexpr (T_x_rows == 1) {
127 T_y_scaled_tmp y_scaled_tmp = (x_val * beta_val_vec).coeff(0, 0);
128 y_scaled = (as_array_or_scalar(y_val_vec) - y_scaled_tmp
129 - as_array_or_scalar(alpha_val_vec))
130 * inv_sigma;
131 } else {
132 y_scaled = multiply(x_val, beta_val_vec);
133 y_scaled = (as_array_or_scalar(y_val_vec) - y_scaled
134 - as_array_or_scalar(alpha_val_vec))
135 * inv_sigma;
136 }
137
138 auto ops_partials
139 = make_partials_propagator(y_ref, x_ref, alpha_ref, beta_ref, sigma_ref);
140
142 Matrix<T_partials_return, Dynamic, 1> mu_derivative = inv_sigma * y_scaled;
143 if constexpr (is_autodiff_v<T_y>) {
144 if constexpr (is_vector<T_y>::value) {
145 partials<0>(ops_partials) = -mu_derivative;
146 } else {
147 partials<0>(ops_partials)[0] = -mu_derivative.sum();
148 }
149 }
150 if constexpr (is_autodiff_v<T_x>) {
151 if constexpr (T_x_rows == 1) {
152 edge<1>(ops_partials).partials_ = beta_val_vec * sum(mu_derivative);
153 } else {
154 edge<1>(ops_partials).partials_
155 = (beta_val_vec * mu_derivative.transpose()).transpose();
156 }
157 }
158 if constexpr (is_autodiff_v<T_beta>) {
159 if constexpr (T_x_rows == 1) {
160 edge<3>(ops_partials).partials_ = mu_derivative.sum() * x_val;
161 } else if constexpr (T_x::ColsAtCompileTime == 1) {
162 partials<3>(ops_partials)[0] = dot_product(mu_derivative, x_val);
163 } else {
164 partials<3>(ops_partials) = multiply(mu_derivative.transpose(), x_val);
165 }
166 }
167 if constexpr (is_autodiff_v<T_alpha>) {
168 if constexpr (is_vector<T_alpha>::value) {
169 partials<2>(ops_partials) = mu_derivative;
170 } else {
171 partials<2>(ops_partials)[0] = sum(mu_derivative);
172 }
173 }
174 if constexpr (is_autodiff_v<T_scale>) {
175 if constexpr (is_vector<T_scale>::value) {
176 Array<T_partials_return, Dynamic, 1> y_scaled_sq = y_scaled * y_scaled;
177 y_scaled_sq_sum = sum(y_scaled_sq);
178 partials<4>(ops_partials) = (y_scaled_sq - 1) * inv_sigma;
179 } else {
180 y_scaled_sq_sum = sum(y_scaled * y_scaled);
181 partials<4>(ops_partials)[0]
182 = (y_scaled_sq_sum - N_instances) * inv_sigma;
183 }
184 } else {
185 y_scaled_sq_sum = sum(y_scaled * y_scaled);
186 }
187 } else {
188 y_scaled_sq_sum = sum(y_scaled * y_scaled);
189 }
190
191 if (!isfinite(y_scaled_sq_sum)) {
192 check_finite(function, "Vector of dependent variables", y_val_vec);
193 check_finite(function, "Weight vector", beta_val_vec);
194 check_finite(function, "Intercept", alpha_val_vec);
195 // if all other checks passed, next will only fail if x is not finite
196 check_finite(function, "Matrix of independent variables", y_scaled_sq_sum);
197 }
198
199 // Compute log probability.
200 T_partials_return logp(0.0);
201 if constexpr (include_summand<propto>::value) {
202 logp += NEG_LOG_SQRT_TWO_PI * N_instances;
203 }
205 if constexpr (is_vector<T_scale>::value) {
206 logp -= sum(log(sigma_val_vec));
207 } else {
208 logp -= N_instances * log(sigma_val_vec);
209 }
210 }
211 logp -= 0.5 * y_scaled_sq_sum;
212
213 return ops_partials.build(logp);
214}
215
216template <typename T_y, typename T_x, typename T_alpha, typename T_beta,
217 typename T_scale>
219 const T_y& y, const T_x& x, const T_alpha& alpha, const T_beta& beta,
220 const T_scale& sigma) {
221 return normal_id_glm_lpdf<false>(y, x, alpha, beta, sigma);
222}
223} // namespace math
224} // namespace stan
225#endif
isfinite_< as_operation_cl_t< T > > isfinite(T &&a)
auto as_column_vector_or_scalar(T &&a)
as_column_vector_or_scalar of a kernel generator expression.
auto transpose(Arg &&a)
Transposes a kernel generator expression.
return_type_t< T_y_cl, T_x_cl, T_alpha_cl, T_beta_cl, T_sigma_cl > normal_id_glm_lpdf(const T_y_cl &y, const T_x_cl &x, const T_alpha_cl &alpha, const T_beta_cl &beta, const T_sigma_cl &sigma)
Returns the log PDF of the Generalized Linear Model (GLM) with Normal distribution and id link functi...
typename return_type< Ts... >::type return_type_t
Convenience type for the return type of the specified template parameters.
int64_t size(const T &m)
Returns the size (number of the elements) of a matrix_cl or var_value<matrix_cl<T>>.
Definition size.hpp:19
T as_array_or_scalar(T &&v)
Returns specified input value.
auto multiply(Mat1 &&m1, Mat2 &&m2)
Return the product of the specified matrices.
Definition multiply.hpp:20
bool size_zero(const T &x)
Returns 1 if input is of length 0, returns 0 otherwise.
Definition size_zero.hpp:19
void check_consistent_size(const char *function, const char *name, const T &x, size_t expected_size)
Check if x is consistent with size expected_size.
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Definition value_of.hpp:18
fvar< T > log(const fvar< T > &x)
Definition log.hpp:18
void check_finite(const char *function, const char *name, const T_y &y)
Return true if all values in y are finite.
auto sum(const std::vector< T > &m)
Return the sum of the entries of the specified standard vector.
Definition sum.hpp:23
static constexpr double NEG_LOG_SQRT_TWO_PI
The value of minus the natural logarithm of the square root of , .
ref_type_t< T && > to_ref(T &&a)
This evaluates expensive Eigen expressions.
Definition to_ref.hpp:18
auto dot_product(const T_a &a, const T_b &b)
Returns the dot product of the specified vectors.
fvar< T > beta(const fvar< T > &x1, const fvar< T > &x2)
Return fvar with the beta function applied to the specified arguments and its gradient.
Definition beta.hpp:51
auto make_partials_propagator(Ops &&... ops)
Construct an partials_propagator.
void check_positive_finite(const char *function, const char *name, const T_y &y)
Check if y is positive and finite.
typename ref_type_if< is_autodiff_v< T >, T >::type ref_type_if_not_constant_t
Definition ref_type.hpp:63
typename partials_return_type< Args... >::type partials_return_t
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
If the input type T is either an eigen matrix with 1 column or 1 row at compile time or a standard ve...
Extends std::true_type when instantiated with zero or more template parameters, all of which extend t...
Template metaprogram to calculate whether a summand needs to be included in a proportional (log) prob...