Stan  1.3
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
wishart.hpp
Go to the documentation of this file.
1 #ifndef __STAN__PROB__DISTRIBUTIONS__MULTIVARIATE__CONTINUOUS__WISHART_HPP__
2 #define __STAN__PROB__DISTRIBUTIONS__MULTIVARIATE__CONTINUOUS__WISHART_HPP__
3 
7 #include <stan/agrad/matrix.hpp>
8 #include <stan/prob/traits.hpp>
9 #include <boost/concept_check.hpp>
18 
19 namespace stan {
20 
21  namespace prob {
22 
23  // Wishart(Sigma|n,Omega) [Sigma, Omega symmetric, non-neg, definite;
24  // Sigma.dims() = Omega.dims();
25  // n > Sigma.rows() - 1]
53  template <bool propto,
54  typename T_y, typename T_dof, typename T_scale,
55  class Policy>
56  typename boost::math::tools::promote_args<T_y,T_dof,T_scale>::type
57  wishart_log(const Eigen::Matrix<T_y,Eigen::Dynamic,Eigen::Dynamic>& W,
58  const T_dof& nu,
59  const Eigen::Matrix<T_scale,Eigen::Dynamic,Eigen::Dynamic>& S,
60  const Policy&) {
61  static const char* function = "stan::prob::wishart_log(%1%)";
62 
65  using boost::math::tools::promote_args;
66 
68  typename promote_args<T_y,T_dof,T_scale>::type lp(0.0);
69  if (!check_greater(function, nu, k-1,
70  "Degrees of freedom parameter", &lp, Policy()))
71  return lp;
72  if (!check_size_match(function,
73  W.rows(), "Rows of random variable",
74  W.cols(), "columns of random variable",
75  &lp, Policy()))
76  return lp;
77  if (!check_size_match(function,
78  S.rows(), "Rows of scale parameter",
79  S.cols(), "columns of scale parameter",
80  &lp, Policy()))
81  return lp;
82  if (!check_size_match(function,
83  W.rows(), "Rows of random variable",
84  S.rows(), "columns of scale parameter",
85  &lp, Policy()))
86  return lp;
87  // FIXME: domain checks
88 
89  Eigen::LLT< Eigen::Matrix<T_y,Eigen::Dynamic,Eigen::Dynamic> > LLT_W = W.llt();
90  if (LLT_W.info() != Eigen::Success) {
91  lp = stan::math::policies::raise_domain_error<T_y>(function,
92  "W is not positive definite (%1%)",
93  0,Policy());
94  return lp;
95  }
96  Eigen::LLT< Eigen::Matrix<T_scale,Eigen::Dynamic,Eigen::Dynamic> > LLT_S = S.llt();
97  if (LLT_S.info() != Eigen::Success) {
98  lp = stan::math::policies::raise_domain_error<T_scale>(function,
99  "S is not positive definite (%1%)",
100  0,Policy());
101  return lp;
102  }
103 
104  Eigen::Matrix<T_y,Eigen::Dynamic,Eigen::Dynamic> L_W = LLT_W.matrixL();
105  Eigen::Matrix<T_scale,Eigen::Dynamic,Eigen::Dynamic> L_S = LLT_S.matrixL();
106 
109  using stan::math::crossprod;
110  using stan::math::lmgamma;
112  lp += nu * k * NEG_LOG_TWO_OVER_TWO;
113 
115  lp -= lmgamma(k, 0.5 * nu);
116 
118  lp -= nu * L_S.diagonal().array().log().sum();
119 
121  L_S = crossprod(mdivide_left_tri_low(L_S));
122  Eigen::Matrix<T_scale,Eigen::Dynamic,1> S_inv_vec = Eigen::Map<
123  const Eigen::Matrix<T_scale,Eigen::Dynamic,Eigen::Dynamic> >(
124  &L_S(0), L_S.size(), 1);
125  Eigen::Matrix<T_y,Eigen::Dynamic,1> W_vec = Eigen::Map<
126  const Eigen::Matrix<T_y,Eigen::Dynamic,Eigen::Dynamic> >(
127  &W(0), W.size(), 1);
128  lp -= 0.5 * dot_product(S_inv_vec, W_vec); // trace(S^-1 * W)
129  }
130 
131  if (include_summand<propto,T_y,T_dof>::value && nu != (k + 1))
132  lp += (nu - k - 1.0) * L_W.diagonal().array().log().sum();
133  return lp;
134  }
135 
136  template <bool propto,
137  typename T_y, typename T_dof, typename T_scale>
138  inline
139  typename boost::math::tools::promote_args<T_y,T_dof,T_scale>::type
140  wishart_log(const Eigen::Matrix<T_y,Eigen::Dynamic,Eigen::Dynamic>& W,
141  const T_dof& nu,
142  const Eigen::Matrix<T_scale,Eigen::Dynamic,Eigen::Dynamic>& S) {
143  return wishart_log<propto>(W,nu,S,stan::math::default_policy());
144  }
145 
146 
147  template <typename T_y, typename T_dof, typename T_scale,
148  class Policy>
149  inline
150  typename boost::math::tools::promote_args<T_y,T_dof,T_scale>::type
151  wishart_log(const Eigen::Matrix<T_y,Eigen::Dynamic,Eigen::Dynamic>& W,
152  const T_dof& nu,
153  const Eigen::Matrix<T_scale,Eigen::Dynamic,Eigen::Dynamic>& S,
154  const Policy&) {
155  return wishart_log<false>(W,nu,S,Policy());
156  }
157 
158 
159  template <typename T_y, typename T_dof, typename T_scale>
160  inline
161  typename boost::math::tools::promote_args<T_y,T_dof,T_scale>::type
162  wishart_log(const Eigen::Matrix<T_y,Eigen::Dynamic,Eigen::Dynamic>& W,
163  const T_dof& nu,
164  const Eigen::Matrix<T_scale,Eigen::Dynamic,Eigen::Dynamic>& S) {
165  return wishart_log<false>(W,nu,S,stan::math::default_policy());
166  }
167 
168  template <class RNG>
169  inline Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>
170  wishart_rng(const double nu,
171  const Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic>& S,
172  RNG& rng) {
173 
174  Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> B(S.rows(), S.cols());
175  B.setZero();
176 
177  for(int i = 0; i < S.cols(); i++) {
178  B(i,i) = std::sqrt(chi_square_rng(nu - i, rng));
179  for(int j = 0; j < i; j++)
180  B(j,i) = normal_rng(0,1,rng);
181  }
182 
183  return stan::math::multiply_lower_tri_self_transpose(S.llt().matrixL() * B);
184  }
185  }
186 }
187 #endif

     [ Stan Home Page ] © 2011–2013, Stan Development Team.