Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion doxygen/doxygen.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -2747,7 +2747,6 @@ ALIASES += laplace_options="\
- theta_0 the initial guess for the Laplace approximation. \
- tolerance controls the convergence criterion when finding the mode in the Laplace approximation. \
- max_num_steps maximum number of steps before the Newton solver breaks and returns an error. \
- hessian_block_size Block size of Hessian of log likelihood w.r.t latent Gaussian variable theta. \
- solver Type of Newton solver. Each corresponds to a distinct choice of B matrix (i.e. application SWM formula): \
1. computes square-root of negative Hessian. \
2. computes square-root of covariance matrix. \
Expand Down
53 changes: 35 additions & 18 deletions stan/math/mix/functor/laplace_marginal_density_estimator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <stan/math/mix/functor/barzilai_borwein_step_size.hpp>
#include <stan/math/prim/fun/to_ref.hpp>
#include <stan/math/prim/fun/quad_form_diag.hpp>
#include <stan/math/prim/fun/value_of.hpp>
#include <stan/math/prim/functor/iter_tuple_nested.hpp>
#include <unsupported/Eigen/MatrixFunctions>
#include <cmath>
Expand Down Expand Up @@ -75,7 +76,13 @@ template <bool HasInitTheta>
struct laplace_options;

template <>
struct laplace_options<false> : public laplace_options_base {};
struct laplace_options<false> : public laplace_options_base {
laplace_options() = default;

explicit laplace_options(int hessian_block_size_) {
hessian_block_size = hessian_block_size_;
}
};

template <>
struct laplace_options<true> : public laplace_options_base {
Expand All @@ -89,7 +96,7 @@ struct laplace_options<true> : public laplace_options_base {
: laplace_options_base(hessian_block_size_, solver_, tolerance_,
max_num_steps_, allow_fallthrough_,
max_steps_line_search_),
theta_0(std::forward<ThetaVec>(theta_0_)) {}
theta_0(value_of(std::forward<ThetaVec>(theta_0_))) {}
};

using laplace_options_default = laplace_options<false>;
Expand All @@ -102,10 +109,25 @@ using laplace_options_user_supplied = laplace_options<true>;
*/
inline auto generate_laplace_options(int theta_0_size) {
auto ops = laplace_options_default{};
return std::make_tuple(
Eigen::VectorXd::Zero(theta_0_size).eval(), // 0 -> 6
ops.tolerance, ops.max_num_steps, ops.hessian_block_size, ops.solver,
ops.line_search.max_iterations, static_cast<int>(ops.allow_fallthrough));
return std::make_tuple(Eigen::VectorXd::Zero(theta_0_size).eval(),
ops.tolerance, ops.max_num_steps, ops.solver,
ops.line_search.max_iterations,
static_cast<int>(ops.allow_fallthrough));
}

/**
* User function for generating laplace options tuple
* @tparam ThetaVec An Eigen vector type for user supplied initial theta
* @param theta_0 User supplied initial theta
* @return tuple representing laplace options exposed to user.
*/
template <typename ThetaVec, require_eigen_t<ThetaVec>* = nullptr>
inline auto generate_laplace_options(ThetaVec&& theta_0) {
auto ops = laplace_options_default{};
return std::make_tuple(std::forward<ThetaVec>(theta_0), ops.tolerance,
ops.max_num_steps, ops.solver,
ops.line_search.max_iterations,
static_cast<int>(ops.allow_fallthrough));
}

namespace internal {
Expand Down Expand Up @@ -135,41 +157,36 @@ inline constexpr auto tuple_to_laplace_options(Options&& ops) {
"the laplace approximation.");
}
if constexpr (!stan::is_inner_tuple_type_v<3, Ops, int>) {
static_assert(
sizeof(std::decay_t<Ops>*) == 0,
"ERROR:(laplace_marginal_lpdf) The fifth laplace argument is "
"expected to be an int representing the hessian block size.");
}
if constexpr (!stan::is_inner_tuple_type_v<4, Ops, int>) {
static_assert(
sizeof(std::decay_t<Ops>*) == 0,
"ERROR:(laplace_marginal_lpdf) The fourth laplace argument is "
"expected to be an int representing the solver.");
}
if constexpr (!stan::is_inner_tuple_type_v<5, Ops, int>) {
if constexpr (!stan::is_inner_tuple_type_v<4, Ops, int>) {
static_assert(
sizeof(std::decay_t<Ops>*) == 0,
"ERROR:(laplace_marginal_lpdf) The sixth laplace argument is "
"ERROR:(laplace_marginal_lpdf) The fifth laplace argument is "
"expected to be an int representing the max steps for the laplace "
"approximaton's wolfe line search.");
}
constexpr bool is_fallthrough
= stan::is_inner_tuple_type_v<
6, Ops, int> || stan::is_inner_tuple_type_v<6, Ops, bool>;
5, Ops, int> || stan::is_inner_tuple_type_v<5, Ops, bool>;
if constexpr (!is_fallthrough) {
static_assert(
sizeof(std::decay_t<Ops>*) == 0,
"ERROR:(laplace_marginal_lpdf) The seventh laplace argument is "
"ERROR:(laplace_marginal_lpdf) The sixth laplace argument is "
"expected to be an int representing allow fallthrough (0/1).");
}
auto defaults = laplace_options_default{};
return laplace_options_user_supplied{
value_of(std::get<0>(std::forward<Ops>(ops))),
std::get<1>(ops),
std::get<2>(ops),
defaults.hessian_block_size,
std::get<3>(ops),
std::get<4>(ops),
std::get<5>(ops),
(std::get<6>(ops) > 0) ? true : false,
(std::get<5>(ops) > 0) ? true : false,
};
} else {
return std::forward<Ops>(ops);
Expand Down
23 changes: 14 additions & 9 deletions stan/math/mix/prob/laplace_latent_bernoulli_logit_rng.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ namespace math {
* @param[in] n_samples Vector of number of trials.
* @param[in] mean the mean of the latent normal variable.
* \laplace_common_args
* @param[in] hessian_block_size Block size for the Hessian approximation with
* respect to the latent gaussian variable theta.
* \laplace_options
* \rng_arg
* \msg_arg
Expand All @@ -32,15 +34,16 @@ template <typename Mean, typename CovarFun, typename CovarArgs,
typename OpsTuple, typename RNG>
inline Eigen::VectorXd laplace_latent_tol_bernoulli_logit_rng(
const std::vector<int>& y, const std::vector<int>& n_samples, Mean&& mean,
CovarFun&& covariance_function, CovarArgs&& covar_args, OpsTuple&& ops,
RNG& rng, std::ostream* msgs) {
int hessian_block_size, CovarFun&& covariance_function,
CovarArgs&& covar_args, OpsTuple&& ops, RNG& rng, std::ostream* msgs) {
auto options
= internal::tuple_to_laplace_options(std::forward<OpsTuple>(ops));
options.hessian_block_size = hessian_block_size;
return laplace_base_rng(
bernoulli_logit_likelihood{},
std::forward_as_tuple(to_vector(y), n_samples, std::forward<Mean>(mean)),
std::forward<CovarFun>(covariance_function),
std::forward<CovarArgs>(covar_args),
internal::tuple_to_laplace_options(std::forward<OpsTuple>(ops)), rng,
msgs);
std::forward<CovarArgs>(covar_args), std::move(options), rng, msgs);
}

/**
Expand All @@ -59,20 +62,22 @@ inline Eigen::VectorXd laplace_latent_tol_bernoulli_logit_rng(
* @param[in] n_samples Vector of number of trials.
* @param[in] mean the mean of the latent normal variable.
* \laplace_common_args
* @param[in] hessian_block_size Block size for the Hessian approximation with
* respect to the latent gaussian variable theta.
* \rng_arg
* \msg_arg
*/
template <typename Mean, typename CovarFun, typename CovarArgs, typename RNG>
inline Eigen::VectorXd laplace_latent_bernoulli_logit_rng(
const std::vector<int>& y, const std::vector<int>& n_samples, Mean&& mean,
CovarFun&& covariance_function, CovarArgs&& covar_args, RNG& rng,
std::ostream* msgs) {
int hessian_block_size, CovarFun&& covariance_function,
CovarArgs&& covar_args, RNG& rng, std::ostream* msgs) {
auto options = laplace_options_default{hessian_block_size};
return laplace_base_rng(
bernoulli_logit_likelihood{},
std::forward_as_tuple(to_vector(y), n_samples, std::forward<Mean>(mean)),
std::forward<CovarFun>(covariance_function),
std::forward<CovarArgs>(covar_args), laplace_options_default{}, rng,
msgs);
std::forward<CovarArgs>(covar_args), options, rng, msgs);
}

} // namespace math
Expand Down
23 changes: 14 additions & 9 deletions stan/math/mix/prob/laplace_latent_neg_binomial_2_log_rng.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ namespace math {
* @param[in] eta Overdisperison parameter.
* @param[in] mean The mean of the latent normal variable.
* \laplace_common_args
* @param[in] hessian_block_size Block size for the Hessian approximation with
* respect to the latent gaussian variable theta.
* \laplace_options
* \rng_arg
* \msg_arg
Expand All @@ -39,16 +41,17 @@ template <typename Eta, typename Mean, typename CovarFun, typename CovarArgs,
typename OpsTuple, typename RNG>
inline Eigen::VectorXd laplace_latent_tol_neg_binomial_2_log_rng(
const std::vector<int>& y, const std::vector<int>& y_index, Eta&& eta,
Mean&& mean, CovarFun&& covariance_function, CovarArgs&& covar_args,
OpsTuple&& ops, RNG& rng, std::ostream* msgs) {
Mean&& mean, int hessian_block_size, CovarFun&& covariance_function,
CovarArgs&& covar_args, OpsTuple&& ops, RNG& rng, std::ostream* msgs) {
auto options
= internal::tuple_to_laplace_options(std::forward<OpsTuple>(ops));
options.hessian_block_size = hessian_block_size;
return laplace_base_rng(
neg_binomial_2_log_likelihood{},
std::forward_as_tuple(std::forward<Eta>(eta), y, y_index,
std::forward<Mean>(mean)),
std::forward<CovarFun>(covariance_function),
std::forward<CovarArgs>(covar_args),
internal::tuple_to_laplace_options(std::forward<OpsTuple>(ops)), rng,
msgs);
std::forward<CovarArgs>(covar_args), std::move(options), rng, msgs);
}

/**
Expand All @@ -72,22 +75,24 @@ inline Eigen::VectorXd laplace_latent_tol_neg_binomial_2_log_rng(
* @param[in] eta Overdisperison parameter.
* @param[in] mean The mean of the latent normal variable.
* \laplace_common_args
* @param[in] hessian_block_size Block size for the Hessian approximation with
* respect to the latent gaussian variable theta.
* \rng_arg
* \msg_arg
*/
template <typename Eta, typename Mean, typename CovarFun, typename CovarArgs,
typename RNG>
inline Eigen::VectorXd laplace_latent_neg_binomial_2_log_rng(
const std::vector<int>& y, const std::vector<int>& y_index, Eta&& eta,
Mean&& mean, CovarFun&& covariance_function, CovarArgs&& covar_args,
RNG& rng, std::ostream* msgs) {
Mean&& mean, int hessian_block_size, CovarFun&& covariance_function,
CovarArgs&& covar_args, RNG& rng, std::ostream* msgs) {
auto options = laplace_options_default{hessian_block_size};
return laplace_base_rng(
neg_binomial_2_log_likelihood{},
std::forward_as_tuple(std::forward<Eta>(eta), y, y_index,
std::forward<Mean>(mean)),
std::forward<CovarFun>(covariance_function),
std::forward<CovarArgs>(covar_args), laplace_options_default{}, rng,
msgs);
std::forward<CovarArgs>(covar_args), options, rng, msgs);
}

} // namespace math
Expand Down
23 changes: 14 additions & 9 deletions stan/math/mix/prob/laplace_latent_poisson_log_rng.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ namespace math {
* @param[in] y_index Index indicating which group each observation belongs to.
* @param[in] mean The mean of the latent normal variable.
* \laplace_common_args
* @param[in] hessian_block_size Block size for the Hessian approximation with
* respect to the latent gaussian variable theta.
* \laplace_options
* \rng_arg
* \msg_arg
Expand All @@ -34,15 +36,16 @@ template <typename Mean, typename CovarFun, typename CovarArgs,
typename OpsTuple, typename RNG>
inline Eigen::VectorXd laplace_latent_tol_poisson_log_rng(
const std::vector<int>& y, const std::vector<int>& y_index, Mean&& mean,
CovarFun&& covariance_function, CovarArgs&& covar_args, OpsTuple&& ops,
RNG& rng, std::ostream* msgs) {
int hessian_block_size, CovarFun&& covariance_function,
CovarArgs&& covar_args, OpsTuple&& ops, RNG& rng, std::ostream* msgs) {
auto options
= internal::tuple_to_laplace_options(std::forward<OpsTuple>(ops));
options.hessian_block_size = hessian_block_size;
return laplace_base_rng(
poisson_log_likelihood{},
std::forward_as_tuple(y, y_index, std::forward<Mean>(mean)),
std::forward<CovarFun>(covariance_function),
std::forward<CovarArgs>(covar_args),
internal::tuple_to_laplace_options(std::forward<OpsTuple>(ops)), rng,
msgs);
std::forward<CovarArgs>(covar_args), std::move(options), rng, msgs);
}

/**
Expand All @@ -62,20 +65,22 @@ inline Eigen::VectorXd laplace_latent_tol_poisson_log_rng(
* @param[in] y_index Index indicating which group each observation belongs to.
* @param[in] mean The mean of the latent normal variable.
* \laplace_common_args
* @param[in] hessian_block_size Block size for the Hessian approximation with
* respect to the latent gaussian variable theta.
* \rng_arg
* \msg_arg
*/
template <typename CovarFun, typename CovarArgs, typename RNG, typename Mean>
inline Eigen::VectorXd laplace_latent_poisson_log_rng(
const std::vector<int>& y, const std::vector<int>& y_index, Mean&& mean,
CovarFun&& covariance_function, CovarArgs&& covar_args, RNG& rng,
std::ostream* msgs) {
int hessian_block_size, CovarFun&& covariance_function,
CovarArgs&& covar_args, RNG& rng, std::ostream* msgs) {
auto options = laplace_options_default{hessian_block_size};
return laplace_base_rng(
poisson_log_likelihood{},
std::forward_as_tuple(y, y_index, std::forward<Mean>(mean)),
std::forward<CovarFun>(covariance_function),
std::forward<CovarArgs>(covar_args), laplace_options_default{}, rng,
msgs);
std::forward<CovarArgs>(covar_args), options, rng, msgs);
}

} // namespace math
Expand Down
23 changes: 15 additions & 8 deletions stan/math/mix/prob/laplace_latent_rng.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,26 @@ namespace math {
* @param[in] L_f Function that returns log likelihood.
* @param[in] ll_args Arguments for likelihood function.
* \laplace_common_args
* @param[in] hessian_block_size Block size for the Hessian approximation with
* respect to the latent gaussian variable theta.
* \laplace_options
* \rng_arg
* \msg_arg
*/
template <typename LLFunc, typename LLArgs, typename CovarFun,
typename CovarArgs, typename OpsTuple, typename RNG>
inline auto laplace_latent_tol_rng(LLFunc&& L_f, LLArgs&& ll_args,
int hessian_block_size,
CovarFun&& covariance_function,
CovarArgs&& covar_args, OpsTuple&& ops,
RNG& rng, std::ostream* msgs) {
auto options
= internal::tuple_to_laplace_options(std::forward<OpsTuple>(ops));
options.hessian_block_size = hessian_block_size;
return laplace_base_rng(
std::forward<LLFunc>(L_f), std::forward<LLArgs>(ll_args),
std::forward<CovarFun>(covariance_function),
std::forward<CovarArgs>(covar_args),
internal::tuple_to_laplace_options(std::forward<OpsTuple>(ops)), rng,
msgs);
std::forward<CovarArgs>(covar_args), std::move(options), rng, msgs);
}

/**
Expand All @@ -58,20 +62,23 @@ inline auto laplace_latent_tol_rng(LLFunc&& L_f, LLArgs&& ll_args,
* @param[in] L_f Function that returns log likelihood.
* @param[in] ll_args Arguments for likelihood function.
* \laplace_common_args
* @param[in] hessian_block_size Block size for the Hessian approximation with
* respect to the latent gaussian variable theta.
* \rng_arg
* \msg_arg
*/
template <typename LLFunc, typename LLArgs, typename CovarFun,
typename CovarArgs, typename RNG>
inline auto laplace_latent_rng(LLFunc&& L_f, LLArgs&& ll_args,
int hessian_block_size,
CovarFun&& covariance_function,
CovarArgs&& covar_args, RNG& rng,
std::ostream* msgs) {
return laplace_base_rng(std::forward<LLFunc>(L_f),
std::forward<LLArgs>(ll_args),
std::forward<CovarFun>(covariance_function),
std::forward<CovarArgs>(covar_args),
laplace_options_default{}, rng, msgs);
auto options = laplace_options_default{hessian_block_size};
return laplace_base_rng(
std::forward<LLFunc>(L_f), std::forward<LLArgs>(ll_args),
std::forward<CovarFun>(covariance_function),
std::forward<CovarArgs>(covar_args), options, rng, msgs);
}

} // namespace math
Expand Down
Loading