1#ifndef STAN_MATH_MIX_FUNCTOR_LAPLACE_LIKELIHOOD_HPP
2#define STAN_MATH_MIX_FUNCTOR_LAPLACE_LIKELIHOOD_HPP
22namespace laplace_likelihood {
35template <
typename F,
typename Theta,
typename Stream,
typename... Args,
37inline auto log_likelihood(F&& f, Theta&& theta, Stream* msgs, Args&&... args) {
38 return std::forward<F>(f)(std::forward<Theta>(theta),
39 std::forward<Args>(args)..., msgs);
55template <
typename F,
typename Theta,
typename Stream,
typename... Args,
57inline auto theta_grad(F&& f, Theta&& theta, Stream* msgs, Args&&... args) {
62 var f_var = f(theta_var, args..., msgs);
64 return theta_var.adj().eval();
80template <
typename F,
typename Theta,
typename Stream,
typename... Args,
82inline void ll_arg_grad(F&& f, Theta&& theta, Stream* msgs, Args&&... args) {
86 var f_var = f(theta, args..., msgs);
106template <
typename F,
typename Theta,
typename Stream,
typename... Args,
110 using Eigen::Dynamic;
112 const Eigen::Index theta_size = theta.size();
113 auto v = Eigen::VectorXd::Ones(theta_size);
114 Eigen::VectorXd hessian_v = Eigen::VectorXd::Zero(theta_size);
117 return (-hessian_v).eval();
136template <
typename F,
typename Theta,
typename Stream,
typename... Args,
139 const Eigen::Index hessian_block_size, Stream* msgs,
141 using Eigen::Dynamic;
143 const Eigen::Index theta_size = theta.size();
144 if (hessian_block_size == 1) {
145 auto v = Eigen::VectorXd::Ones(theta_size);
146 Eigen::VectorXd hessian_v = Eigen::VectorXd::Zero(theta_size);
149 Eigen::SparseMatrix<double> hessian_theta(theta_size, theta_size);
150 hessian_theta.reserve(Eigen::VectorXi::Constant(theta_size, 1));
151 for (Eigen::Index i = 0; i < theta_size; i++) {
152 hessian_theta.insert(i, i) = hessian_v(i);
154 return (-hessian_theta).eval();
157 hessian_block_size,
value_of(args)..., msgs))
179template <
typename F,
typename Theta,
typename Stream,
typename... Args,
181inline auto diff(F&& f, Theta&& theta,
const Eigen::Index hessian_block_size,
182 Stream* msgs, Args&&... args) {
183 using Eigen::Dynamic;
185 const Eigen::Index theta_size = theta.size();
186 auto theta_gradient = [&theta, &f, &msgs](
auto&&... args) {
188 Matrix<var, Dynamic, 1> theta_var = theta;
189 var f_var = f(theta_var, args..., msgs);
191 return theta_var.adj().eval();
193 if (hessian_block_size == 1) {
194 auto v = Eigen::VectorXd::Ones(theta_size);
195 Eigen::VectorXd hessian_v = Eigen::VectorXd::Zero(theta_size);
198 Eigen::SparseMatrix<double> hessian_theta(theta_size, theta_size);
199 hessian_theta.reserve(Eigen::VectorXi::Constant(theta_size, 1));
200 for (Eigen::Index i = 0; i < theta_size; i++) {
201 hessian_theta.insert(i, i) = hessian_v(i);
203 return std::make_pair(std::move(theta_gradient), (-hessian_theta).
eval());
205 return std::make_pair(
206 std::move(theta_gradient),
226template <
typename F,
typename Theta,
typename Stream,
typename... Args,
228inline Eigen::VectorXd
third_diff(F&& f, Theta&& theta, Stream&& msgs,
231 const Eigen::Index theta_size = theta.size();
233 = std::forward<Theta>(theta);
236 for (Eigen::Index i = 0; i < theta_size; ++i) {
240 grad(ftheta_ffvar.
d_.d_.vi_);
241 return theta_var.adj().eval();
265template <
typename F,
typename Theta,
typename AMat,
typename Stream,
268 const int hessian_block_size, Stream* msgs,
270 using Eigen::Dynamic;
272 using Eigen::MatrixXd;
273 using Eigen::VectorXd;
276 const Eigen::Index theta_size = theta.size();
278 int n_blocks = theta_size / hessian_block_size;
281 Matrix<fvar<fvar<var>>, Dynamic, 1> theta_ffvar(theta_size);
282 auto shallow_copy_args
283 = stan::math::internal::shallow_copy_vargs<fvar<fvar<var>>>(
284 std::forward_as_tuple(args...));
285 for (Eigen::Index i = 0; i < hessian_block_size; ++i) {
288 for (
int j = i; j < theta_size; j += hessian_block_size) {
292 for (
int j = 0; j < n_blocks; ++j) {
293 for (
int k = 0; k < hessian_block_size; ++k) {
294 w(k + j * hessian_block_size)
295 = A(k + j * hessian_block_size, i + j * hessian_block_size);
298 for (
int j = 0; j < theta_size; ++j) {
302 [](
auto&& f,
auto&& theta_ffvar,
auto&& msgs,
auto&&... inner_args) {
303 return f(theta_ffvar, inner_args..., msgs);
305 shallow_copy_args, f, theta_ffvar, msgs);
306 grad(target_ffvar.
d_.d_.vi_);
308 return (0.5 * theta_var.adj()).eval();
330template <
typename F,
typename V_t,
typename Theta,
typename Stream,
334 using Eigen::Dynamic;
336 using Eigen::VectorXd;
338 if constexpr (!contains_var) {
342 const Eigen::Index theta_size = theta.size();
344 Matrix<fvar<var>, Dynamic, 1> theta_fvar(theta_size);
345 for (Eigen::Index i = 0; i < theta_size; i++) {
346 theta_fvar(i) =
fvar<var>(theta_var(i), v(i));
348 auto shallow_copy_args = stan::math::internal::shallow_copy_vargs<fvar<var>>(
349 std::forward_as_tuple(args...));
351 [](
auto&& f,
auto&& theta_fvar,
auto&& msgs,
auto&&... inner_args) {
352 return f(theta_fvar, inner_args..., msgs);
354 shallow_copy_args, f, theta_fvar, msgs);
371template <
typename F,
typename Theta,
typename TupleArgs,
typename Stream,
374inline auto theta_grad(F&& f, Theta&& theta, TupleArgs&& ll_tup,
375 Stream* msgs =
nullptr) {
377 [](
auto&& f,
auto&& theta,
auto&& msgs,
auto&&... args) {
379 std::forward<
decltype(theta)>(theta), msgs,
380 std::forward<
decltype(args)>(args)...);
382 std::forward<TupleArgs>(ll_tup), std::forward<F>(f),
383 std::forward<Theta>(theta), msgs);
386template <
typename F,
typename Theta,
typename TupleArgs,
typename Stream,
390 Stream* msgs =
nullptr) {
392 [](
auto&& f,
auto&& theta,
auto&& msgs,
auto&&... args) {
394 std::forward<
decltype(theta)>(theta), msgs,
395 std::forward<
decltype(args)>(args)...);
397 std::forward<TupleArgs>(ll_tup), std::forward<F>(f),
398 std::forward<Theta>(theta), msgs);
401template <
typename F,
typename Theta,
typename TupleArgs,
typename Stream,
407 [](
auto&& f,
auto&& theta,
auto* msgs,
auto&&... args) {
409 std::forward<
decltype(f)>(f), std::forward<
decltype(theta)>(theta),
410 msgs, std::forward<
decltype(args)>(args)...);
412 std::forward<TupleArgs>(ll_tuple), std::forward<F>(f),
413 std::forward<Theta>(theta), msgs);
416template <
typename F,
typename Theta,
typename TupleArgs,
typename Stream,
420 const Eigen::Index hessian_block_size,
421 TupleArgs&& ll_tuple, Stream* msgs) {
423 [](
auto&& f,
auto&& theta,
auto hessian_block_size,
auto* msgs,
426 std::forward<
decltype(f)>(f), std::forward<
decltype(theta)>(theta),
427 hessian_block_size, msgs, std::forward<
decltype(args)>(args)...);
429 std::forward<TupleArgs>(ll_tuple), std::forward<F>(f),
430 std::forward<Theta>(theta), hessian_block_size, msgs);
444template <
typename F,
typename Theta,
typename TupleArgs,
typename Stream,
450 [](
auto&& f,
auto&& theta,
auto&& msgs,
auto&&... args) {
452 std::forward<
decltype(f)>(f), std::forward<
decltype(theta)>(theta),
453 msgs, std::forward<
decltype(args)>(args)...);
455 std::forward<TupleArgs>(ll_tup), std::forward<F>(f),
456 std::forward<Theta>(theta), msgs);
472template <
typename F,
typename Theta,
typename TupleArgs,
typename Stream,
475inline auto diff(F&& f, Theta&& theta,
const Eigen::Index hessian_block_size,
476 TupleArgs&& ll_tuple, Stream* msgs) {
478 [](
auto&& f,
auto&& theta,
auto hessian_block_size,
auto* msgs,
481 std::forward<
decltype(f)>(f), std::forward<
decltype(theta)>(theta),
482 hessian_block_size, msgs, std::forward<
decltype(args)>(args)...);
484 std::forward<TupleArgs>(ll_tuple), std::forward<F>(f),
485 std::forward<Theta>(theta), hessian_block_size, msgs);
499template <
typename F,
typename Theta,
typename TupleArgs,
typename Stream,
502inline Eigen::VectorXd
third_diff(F&& f, Theta&& theta, TupleArgs&& ll_args,
505 [](
auto&& f,
auto&& theta,
auto&& msgs,
auto&&... args) {
507 std::forward<
decltype(theta)>(theta), msgs,
508 std::forward<
decltype(args)>(args)...);
510 std::forward<TupleArgs>(ll_args), std::forward<F>(f),
511 std::forward<Theta>(theta), msgs);
529template <
typename F,
typename Theta,
typename AMat,
typename TupleArgs,
532inline auto compute_s2(F&& f, Theta&& theta, AMat&& A,
int hessian_block_size,
533 TupleArgs&& ll_args, Stream* msgs) {
535 [](
auto&& f,
auto&& theta,
auto&& A,
auto hessian_block_size,
auto* msgs,
538 std::forward<
decltype(f)>(f), std::forward<
decltype(theta)>(theta),
539 std::forward<
decltype(A)>(A), hessian_block_size, msgs,
540 std::forward<
decltype(args)>(args)...);
542 std::forward<TupleArgs>(ll_args), std::forward<F>(f),
543 std::forward<Theta>(theta), std::forward<AMat>(A), hessian_block_size,
560template <
typename F,
typename V_t,
typename Theta,
typename TupleArgs,
564 TupleArgs&& ll_args, Stream* msgs) {
566 [](
auto&& f,
auto&& v,
auto&& theta,
auto&& msgs,
auto&&... args) {
568 std::forward<
decltype(f)>(f), std::forward<
decltype(v)>(v),
569 std::forward<
decltype(theta)>(theta), msgs,
570 std::forward<
decltype(args)>(args)...);
572 std::forward<TupleArgs>(ll_args), std::forward<F>(f),
573 std::forward<V_t>(v), std::forward<Theta>(theta), msgs);
A class following the RAII idiom to start and recover nested autodiff scopes.
require_t< is_eigen_vector< std::decay_t< T > > > require_eigen_vector_t
Require type satisfies is_eigen_vector.
require_t< container_type_check_base< is_eigen_vector, value_type_t, TypeCheck, Check... > > require_eigen_vector_vt
Require type satisfies is_eigen_vector.
require_t< is_tuple< std::decay_t< T > > > require_tuple_t
Require type satisfies is_tuple.
auto block_hessian(F &&f, Theta &&theta, const Eigen::Index hessian_block_size, Stream *msgs, Args &&... args)
Computes negative block diagonal Hessian of f wrttheta and args...
Eigen::VectorXd third_diff(F &&f, Theta &&theta, Stream &&msgs, Args &&... args)
Compute third order derivative of f wrt theta and args...
auto diff_eta_implicit(F &&f, V_t &&v, Theta &&theta, Stream *msgs, Args &&... args)
Compute second order gradient of f wrt theta and args...
auto log_likelihood(F &&f, Theta &&theta, Stream *msgs, Args &&... args)
auto diff(F &&f, Theta &&theta, const Eigen::Index hessian_block_size, Stream *msgs, Args &&... args)
Computes theta gradient and negative block diagonal Hessian of f wrt theta and args....
auto diagonal_hessian(F &&f, Theta &&theta, Stream *msgs, Args &&... args)
Computes negative diagonal Hessian of f wrttheta and args...
void ll_arg_grad(F &&f, Theta &&theta, Stream *msgs, Args &&... args)
Computes likelihood argument gradient of f
auto compute_s2(F &&f, Theta &&theta, AMat &&A, const int hessian_block_size, Stream *msgs, Args &&... args)
The derivative of the log likelihood wrt theta evaluated at the mode.
auto theta_grad(F &&f, Theta &&theta, Stream *msgs, Args &&... args)
Computes theta gradient f wrt theta and args...
auto compute_s2(F &&f, Theta &&theta, AMat &&A, int hessian_block_size, TupleArgs &&ll_args, Stream *msgs)
A wrapper that accepts a tuple as arguments.
auto diff(F &&f, Theta &&theta, const Eigen::Index hessian_block_size, TupleArgs &&ll_tuple, Stream *msgs)
A wrapper that accepts a tuple as arguments.
auto diagonal_hessian(F &&f, Theta &&theta, TupleArgs &&ll_tuple, Stream *msgs)
auto diff_eta_implicit(F &&f, V_t &&v, Theta &&theta, TupleArgs &&ll_args, Stream *msgs)
A wrapper that accepts a tuple as arguments.
auto log_likelihood(F &&f, Theta &&theta, TupleArgs &&ll_tup, Stream *msgs)
A wrapper that accepts a tuple as arguments.
auto block_hessian(F &&f, Theta &&theta, const Eigen::Index hessian_block_size, TupleArgs &&ll_tuple, Stream *msgs)
auto theta_grad(F &&f, Theta &&theta, TupleArgs &&ll_tup, Stream *msgs=nullptr)
A wrapper that accepts a tuple as arguments.
auto ll_arg_grad(F &&f, Theta &&theta, TupleArgs &&ll_tup, Stream *msgs=nullptr)
Eigen::VectorXd third_diff(F &&f, Theta &&theta, TupleArgs &&ll_args, Stream *msgs)
A wrapper that accepts a tuple as arguments.
Eigen::SparseMatrix< double > hessian_block_diag(F &&f, const Eigen::VectorXd &x, const Eigen::Index hessian_block_size, Args &&... args)
Returns a block diagonal Hessian by computing the relevant directional derivatives and storing them i...
T eval(T &&arg)
Inputs which have a plain_type equal to the own time are forwarded unmodified (for Eigen expressions ...
T value_of(const fvar< T > &v)
Return the value of the specified variable.
void hessian_times_vector(const F &f, const Eigen::Matrix< double, Eigen::Dynamic, 1 > &x, const Eigen::Matrix< double, Eigen::Dynamic, 1 > &v, double &fx, Eigen::Matrix< double, Eigen::Dynamic, 1 > &Hv)
static void grad()
Compute the gradient for all variables starting from the end of the AD tape.
constexpr decltype(auto) apply(F &&f, Tuple &&t, PreArgs &&... pre_args)
typename internal::arena_type_impl< std::decay_t< T > >::type arena_t
Determines a type that can be used in place of T that does any dynamic allocations on the AD stack.
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
Scalar d_
The tangent (derivative) of this variable.
This template class represents scalars used in forward-mode automatic differentiation,...