1#ifndef STAN_MATH_PRIM_PROB_ORDERED_LOGISTIC_GLM_LPMF_HPP
2#define STAN_MATH_PRIM_PROB_ORDERED_LOGISTIC_GLM_LPMF_HPP
46template <
bool propto,
typename T_y,
typename T_x,
typename T_beta,
47 typename T_cuts, require_matrix_t<T_x>* =
nullptr,
48 require_all_col_vector_t<T_beta, T_cuts>* =
nullptr>
50 const T_y& y,
const T_x& x,
const T_beta&
beta,
const T_cuts& cuts) {
54 using Eigen::VectorXd;
57 constexpr int T_x_rows = T_x::RowsAtCompileTime;
61 typedef typename std::conditional_t<
62 T_x_rows == 1, T_xbeta_partials,
63 Eigen::Matrix<T_xbeta_partials, Eigen::Dynamic, 1>>
71 const size_t N_attributes = x.cols();
74 static constexpr const char* function =
"ordered_logistic_glm_lpmf";
79 T_cuts_ref cuts_ref = cuts;
80 const auto& cuts_val =
value_of(cuts_ref);
82 check_bounded(function,
"Vector of dependent variables", y_ref, 1, N_classes);
86 check_finite(function,
"Final cut-point", cuts_val_vec[N_classes - 2]);
88 check_finite(function,
"First cut-point", cuts_val_vec[0]);
99 T_beta_ref beta_ref =
beta;
101 const auto& x_val = to_ref_if<!is_constant<T_beta>::value>(
value_of(x_ref));
102 const auto& beta_val =
value_of(beta_ref);
104 const auto& beta_val_vec = to_ref_if<!is_constant<T_x>::value>(
108 Array<T_cuts_partials, Dynamic, 1> cuts_y1(N_instances), cuts_y2(N_instances);
109 for (
int i = 0; i < N_instances; i++) {
111 if (c != N_classes) {
112 cuts_y1.coeffRef(i) = cuts_val_vec.coeff(c - 1);
114 cuts_y1.coeffRef(i) = INFINITY;
117 cuts_y2.coeffRef(i) = cuts_val_vec.coeff(c - 2);
119 cuts_y2.coeffRef(i) = -INFINITY;
123 T_location location = x_val * beta_val_vec;
126 check_finite(function,
"Matrix of independent variables", x);
129 Array<T_partials_return, Dynamic, 1> cut2
131 Array<T_partials_return, Dynamic, 1> cut1
135 auto m_log_1p_exp_cut1
136 = (cut1 > 0.0).
select(-cut1, 0) - (-cut1.abs()).
exp().log1p();
137 auto m_log_1p_exp_m_cut2
138 = (cut2 <= 0.0).
select(cut2, 0) - (-cut2.abs()).
exp().log1p();
140 T_partials_return logp(0);
142 Eigen::Map<const Eigen::Matrix<int, Eigen::Dynamic, 1>> y_vec(y_seq.data(),
144 logp = y_vec.cwiseEqual(1)
145 .select(m_log_1p_exp_cut1,
146 y_vec.cwiseEqual(N_classes).select(
148 m_log_1p_exp_m_cut2 +
log1m_exp(cut1 - cut2).array()
149 + m_log_1p_exp_cut1))
153 logp = m_log_1p_exp_cut1.sum();
154 }
else if (y_seq[0] == N_classes) {
155 logp = m_log_1p_exp_m_cut2.sum();
157 logp = (m_log_1p_exp_m_cut2 +
log1m_exp(cut1 - cut2).array()
165 Array<T_partials_return, Dynamic, 1> exp_m_cut1 =
exp(-cut1);
166 Array<T_partials_return, Dynamic, 1> exp_m_cut2 =
exp(-cut2);
167 Array<T_partials_return, Dynamic, 1> exp_cuts_diff =
exp(cuts_y2 - cuts_y1);
168 Array<T_partials_return, Dynamic, 1> d1
169 = (cut2 > 0).
select(exp_m_cut2 / (1 + exp_m_cut2), 1 / (1 +
exp(cut2)))
170 - exp_cuts_diff / (exp_cuts_diff - 1);
171 Array<T_partials_return, Dynamic, 1> d2
172 = 1 / (1 - exp_cuts_diff)
173 - (cut1 > 0).select(exp_m_cut1 / (1 + exp_m_cut1),
174 1 / (1 +
exp(cut1)));
176 Matrix<T_partials_return, 1, Dynamic> location_derivative = d1 - d2;
179 edge<0>(ops_partials).partials_
180 = beta_val_vec * location_derivative.sum();
182 edge<0>(ops_partials).partials_
183 = (beta_val_vec * location_derivative).
transpose();
188 edge<1>(ops_partials).partials_
189 = (location_derivative * x_val.replicate(N_instances, 1))
192 edge<1>(ops_partials).partials_
193 = (location_derivative * x_val).
transpose();
198 for (
int i = 0; i < N_instances; i++) {
200 if (c != N_classes) {
201 partials<2>(ops_partials)[c - 1] += d2.coeff(i);
204 partials<2>(ops_partials)[c - 2] -= d1.coeff(i);
209 return ops_partials.build(logp);
212template <
typename T_y,
typename T_x,
typename T_beta,
typename T_cuts>
214 const T_y& y,
const T_x& x,
const T_beta&
beta,
const T_cuts& cuts) {
215 return ordered_logistic_glm_lpmf<false>(y, x,
beta, cuts);
scalar_seq_view provides a uniform sequence-like wrapper around either a scalar or a sequence of scal...
isfinite_< as_operation_cl_t< T > > isfinite(T &&a)
select_< as_operation_cl_t< T_condition >, as_operation_cl_t< T_then >, as_operation_cl_t< T_else > > select(T_condition &&condition, T_then &&then, T_else &&els)
Selection operation on kernel generator expressions.
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_x, T_beta, T_cuts > ordered_logistic_glm_lpmf(const T_y &y, const T_x &x, const T_beta &beta, const T_cuts &cuts)
Returns the log PMF of the ordinal regression Generalized Linear Model (GLM).
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>>.
T as_array_or_scalar(T &&v)
Returns specified input value.
bool size_zero(const T &x)
Returns 1 if input is of length 0, returns 0 otherwise.
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.
fvar< T > log1m_exp(const fvar< T > &x)
Return the natural logarithm of one minus the exponentiation of the specified argument.
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.
ref_type_t< T && > to_ref(T &&a)
This evaluates expensive Eigen expressions.
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.
void check_ordered(const char *function, const char *name, const T_y &y)
Throw an exception if the specified vector is not sorted into strictly increasing order.
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.
auto make_partials_propagator(Ops &&... ops)
Construct an partials_propagator.
fvar< T > exp(const fvar< T > &x)
typename ref_type_if<!is_constant< T >::value, T >::type ref_type_if_not_constant_t
typename ref_type_if< true, T >::type ref_type_t
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...