Loading [MathJax]/extensions/TeX/AMSsymbols.js
Automatic Differentiation
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
hessian_block_diag.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_MIX_FUNCTOR_HESSIAN_BLOCK_DIAG_HPP
2#define STAN_MATH_MIX_FUNCTOR_HESSIAN_BLOCK_DIAG_HPP
3
6
7namespace stan {
8namespace math {
9
24template <typename F, typename... Args>
25inline Eigen::SparseMatrix<double> hessian_block_diag(
26 F&& f, const Eigen::VectorXd& x, const Eigen::Index hessian_block_size,
27 Args&&... args) {
28 using Eigen::MatrixXd;
29 using Eigen::VectorXd;
30
31 const Eigen::Index x_size = x.size();
32 Eigen::SparseMatrix<double> H(x_size, x_size);
33 H.reserve(Eigen::VectorXi::Constant(x_size, hessian_block_size));
34 VectorXd v(x_size);
35 Eigen::Index n_blocks = x_size / hessian_block_size;
36 Eigen::VectorXd Hv = Eigen::VectorXd::Zero(x_size);
37 for (Eigen::Index i = 0; i < hessian_block_size; ++i) {
38 v.setZero();
39 for (Eigen::Index j = i; j < x_size; j += hessian_block_size) {
40 v.coeffRef(j) = 1;
41 }
42 hessian_times_vector(f, Hv, x, v, args...);
43 for (int j = 0; j < n_blocks; ++j) {
44 for (int k = 0; k < hessian_block_size; ++k) {
45 H.insert(k + j * hessian_block_size, i + j * hessian_block_size)
46 = Hv(k + j * hessian_block_size);
47 }
48 }
49 }
50 return H;
51}
52
53} // namespace math
54} // namespace stan
55
56#endif
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...
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)
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...