1 #ifndef STAN_MATH_PRIM_MAT_FUN_LOG_MIX_HPP 2 #define STAN_MATH_PRIM_MAT_FUN_LOG_MIX_HPP 40 template <
typename T_theta,
typename T_lam>
42 const T_lam& lambda) {
43 static const char*
function =
"log_mix";
47 typedef typename Eigen::Matrix<T_partials_return, -1, 1> T_partials_vec;
49 const int N =
length(theta);
59 T_partials_vec theta_dbl(N);
60 for (
int n = 0; n < N; ++n)
61 theta_dbl[n] =
value_of(theta_vec[n]);
64 T_partials_vec lam_dbl(N);
65 for (
int n = 0; n < N; ++n)
68 T_partials_return logp =
log_sum_exp((
log(theta_dbl) + lam_dbl).eval());
70 T_partials_vec theta_deriv(N);
71 theta_deriv.array() = (lam_dbl.array() - logp).
exp();
73 T_partials_vec lam_deriv = theta_deriv.cwiseProduct(theta_dbl);
77 for (
int n = 0; n < N; ++n)
78 ops_partials.
edge1_.partials_[n] = theta_deriv[n];
82 for (
int n = 0; n < N; ++n)
83 ops_partials.
edge2_.partials_[n] = lam_deriv[n];
86 return ops_partials.
build(logp);
116 template <
typename T_theta,
typename T_lam,
int R,
int C>
119 const std::vector<Eigen::Matrix<T_lam, R, C> >& lambda) {
120 static const char*
function =
"log_mix";
122 T_theta, std::vector<Eigen::Matrix<T_lam, R, C> > >::type
125 typedef typename Eigen::Matrix<T_partials_return, -1, 1> T_partials_vec;
127 typedef typename Eigen::Matrix<T_partials_return, -1, -1> T_partials_mat;
129 typedef typename std::vector<Eigen::Matrix<T_lam, R, C> > T_lamvec_type;
131 const int N =
length(lambda);
132 const int M = theta.size();
137 for (
int n = 0; n < N; ++n) {
144 T_partials_vec theta_dbl(M);
145 for (
int m = 0; m < M; ++m)
146 theta_dbl[m] =
value_of(theta_vec[m]);
148 T_partials_mat lam_dbl(M, N);
150 for (
int n = 0; n < N; ++n)
151 for (
int m = 0; m < M; ++m)
152 lam_dbl(m, n) =
value_of(lam_vec[n][m]);
154 T_partials_mat logp_tmp =
log(theta_dbl).replicate(1, N) + lam_dbl;
156 T_partials_vec logp(N);
157 for (
int n = 0; n < N; ++n)
163 T_partials_mat derivs
164 = (lam_dbl - logp.transpose().replicate(M, 1))
165 .unaryExpr([](T_partials_return x) {
return exp(x); });
167 for (
int m = 0; m < M; ++m)
168 ops_partials.
edge1_.partials_[m] = derivs.row(m).sum();
172 for (
int n = 0; n < N; ++n)
173 ops_partials.
edge2_.partials_vec_[n]
174 = derivs.col(n).cwiseProduct(theta_dbl);
177 return ops_partials.
build(logp.sum());
206 template <
typename T_theta,
typename T_lam>
208 const T_theta& theta,
const std::vector<std::vector<T_lam> >& lambda) {
209 static const char*
function =
"log_mix";
211 T_theta, std::vector<std::vector<T_lam> > >::type T_partials_return;
213 typedef typename Eigen::Matrix<T_partials_return, -1, 1> T_partials_vec;
215 typedef typename Eigen::Matrix<T_partials_return, -1, -1> T_partials_mat;
217 typedef typename std::vector<std::vector<T_lam> > T_lamvec_type;
219 const int N =
length(lambda);
220 const int M = theta.size();
225 for (
int n = 0; n < N; ++n) {
232 T_partials_vec theta_dbl(M);
233 for (
int m = 0; m < M; ++m)
234 theta_dbl[m] =
value_of(theta_vec[m]);
236 T_partials_mat lam_dbl(M, N);
237 for (
int n = 0; n < N; ++n)
238 for (
int m = 0; m < M; ++m)
239 lam_dbl(m, n) =
value_of(lambda[n][m]);
241 T_partials_mat logp_tmp =
log(theta_dbl).replicate(1, N) + lam_dbl;
243 T_partials_vec logp(N);
244 for (
int n = 0; n < N; ++n)
247 T_partials_mat derivs
248 = (lam_dbl - logp.transpose().replicate(M, 1))
249 .unaryExpr([](T_partials_return x) {
return exp(x); });
251 T_partials_mat lam_deriv(M, N);
252 for (
int n = 0; n < N; ++n)
253 lam_deriv.col(n) = derivs.col(n).cwiseProduct(theta_dbl);
257 for (
int m = 0; m < M; ++m)
258 ops_partials.
edge1_.partials_[m] = derivs.row(m).sum();
262 for (
int n = 0; n < N; ++n)
263 for (
int m = 0; m < M; ++m)
264 ops_partials.
edge2_.partials_vec_[n][m] = lam_deriv(m, n);
266 return ops_partials.
build(logp.sum());
void check_finite(const char *function, const char *name, const T_y &y)
Check if y is finite.
boost::math::tools::promote_args< double, typename partials_type< typename scalar_type< T >::type >::type, typename partials_return_type< T_pack... >::type >::type type
void check_bounded(const char *function, const char *name, const T_y &y, const T_low &low, const T_high &high)
Check if the value is between the low and high values, inclusively.
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Extends std::true_type when instantiated with zero or more template parameters, all of which extend t...
fvar< T > log(const fvar< T > &x)
scalar_seq_view provides a uniform sequence-like wrapper around either a scalar or a sequence of scal...
This template builds partial derivatives with respect to a set of operands.
size_t length(const std::vector< T > &x)
Returns the length of the provided std::vector.
Template metaprogram to calculate the base scalar return type resulting from promoting all the scalar...
fvar< T > log_sum_exp(const std::vector< fvar< T > > &v)
Template metaprogram to calculate the partial derivative type resulting from promoting all the scalar...
boost::math::tools::promote_args< double, typename scalar_type< T >::type, typename return_type< Types_pack... >::type >::type type
fvar< T > exp(const fvar< T > &x)
void check_not_nan(const char *function, const char *name, const T_y &y)
Check if y is not NaN.
T_return_type build(double value)
Build the node to be stored on the autodiff graph.
internal::ops_partials_edge< double, Op2 > edge2_
This class provides a low-cost wrapper for situations where you either need an Eigen Vector or RowVec...
fvar< T > log_mix(const fvar< T > &theta, const fvar< T > &lambda1, const fvar< T > &lambda2)
Return the log mixture density with specified mixing proportion and log densities and its derivative ...
void check_consistent_sizes(const char *function, const char *name1, const T1 &x1, const char *name2, const T2 &x2)
Check if the dimension of x1 is consistent with x2.
internal::ops_partials_edge< double, Op1 > edge1_