Automatic Differentiation
 
Loading...
Searching...
No Matches
multinomial_logit_lpmf.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_PRIM_PROB_MULTINOMIAL_LOGIT_LPMF_HPP
2#define STAN_MATH_PRIM_PROB_MULTINOMIAL_LOGIT_LPMF_HPP
3
11#include <cmath>
12#include <vector>
13
14namespace stan {
15namespace math {
16
37template <bool propto, typename T_beta, typename T_prob = scalar_type_t<T_beta>,
38 require_eigen_col_vector_t<T_beta>* = nullptr>
39inline return_type_t<T_prob> multinomial_logit_lpmf(const std::vector<int>& ns,
40 const T_beta& beta) {
41 static constexpr const char* function = "multinomial_logit_lpmf";
42 check_size_match(function, "Size of number of trials variable", ns.size(),
43 "rows of log-probabilities parameter", beta.rows());
44 check_nonnegative(function, "Number of trials variable", ns);
45 const auto& beta_ref = to_ref(beta);
46
47 // An empty beta forces ns to be empty (checked above)
48 if (beta_ref.size() == 0) {
49 return 0.0;
50 }
51
52 // Autodiff args must be finite data may be +/-inf
53 if constexpr (is_constant_v<T_beta>) {
54 // Data Case: Throws in nan and all -inf case
55 check_not_nan(function, "log-probabilities parameter", beta_ref);
56 check_greater(function, "log-probabilities parameter", beta_ref.maxCoeff(),
58 } else {
59 // Autodiff Case: Throws in non-finite case
60 check_finite(function, "log-probabilities parameter", beta_ref);
61 }
62
64
65 decltype(auto) ns_map = as_array_or_scalar(ns);
66
67 if constexpr (include_summand<propto>::value) {
68 lp += lgamma(1 + ns_map.sum()) - lgamma(1 + ns_map).sum();
69 }
70
72 // softmax is NaN with +inf, so split probability evenly over the
73 // +inf entries and give every other entry zero probability
74 if constexpr (is_constant_v<T_beta>) {
75 int num_infty = (beta_ref.array() == INFTY).count();
76 if (num_infty > 0) {
77 for (unsigned int i = 0; i < ns.size(); ++i) {
78 if (ns[i] != 0) {
79 if (beta_ref.coeff(i) != INFTY) {
80 return NEGATIVE_INFTY;
81 }
82 lp -= ns[i] * std::log(num_infty);
83 }
84 }
85 return lp;
86 }
87 }
88
89 T_prob alpha = log_sum_exp(beta_ref);
90 for (unsigned int i = 0; i < ns.size(); ++i) {
91 if (ns[i] != 0) {
92 lp += ns[i] * (beta_ref.coeff(i) - alpha);
93 }
94 }
95 }
96
97 return lp;
98}
99
100template <typename T_beta, require_eigen_col_vector_t<T_beta>* = nullptr>
101inline return_type_t<T_beta> multinomial_logit_lpmf(const std::vector<int>& ns,
102 const T_beta& beta) {
103 return multinomial_logit_lpmf<false>(ns, beta);
104}
105
106} // namespace math
107} // namespace stan
108#endif
return_type_t< T_prob > multinomial_logit_lpmf(const std::vector< int > &ns, const T_beta &beta)
Multinomial log PMF in log parametrization.
typename return_type< Ts... >::type return_type_t
Convenience type for the return type of the specified template parameters.
T as_array_or_scalar(T &&v)
Returns specified input value.
void check_nonnegative(const char *function, const char *name, const T_y &y)
Check if y is non-negative.
static constexpr double NEGATIVE_INFTY
Negative infinity.
Definition constants.hpp:49
void check_finite(const char *function, const char *name, const T_y &y)
Return true if all values in y are finite.
fvar< T > lgamma(const fvar< T > &x)
Return the natural logarithm of the gamma function applied to the specified argument.
Definition lgamma.hpp:21
void check_not_nan(const char *function, const char *name, const T_y &y)
Check if y is not NaN.
ref_type_t< T && > to_ref(T &&a)
This evaluates expensive Eigen expressions.
Definition to_ref.hpp:18
void check_size_match(const char *function, const char *name_i, T_size1 i, const char *name_j, T_size2 j)
Check if the provided sizes match.
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
void check_greater(const char *function, const char *name, const T_y &y, const T_low &low, Idxs... idxs)
Throw an exception if y is not strictly greater than low.
static constexpr double INFTY
Positive infinity.
Definition constants.hpp:44
fvar< T > log_sum_exp(const fvar< T > &x1, const fvar< T > &x2)
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
Template metaprogram to calculate whether a summand needs to be included in a proportional (log) prob...