| | 255 | //forward declaration |
| | 256 | class mstudent; |
| | 257 | |
| | 258 | /*! distribution of multivariate Student t density |
| | 259 | |
| | 260 | Based on article by Genest and Zidek, |
| | 261 | */ |
| | 262 | template<class sq_T> |
| | 263 | class estudent : public eEF{ |
| | 264 | protected: |
| | 265 | //! mena value |
| | 266 | vec mu; |
| | 267 | //! matrix H |
| | 268 | sq_T H; |
| | 269 | //! degrees of freedom |
| | 270 | double delta; |
| | 271 | public: |
| | 272 | double evallog_nn(const vec &val) const{ |
| | 273 | double tmp = -0.5*H.logdet() - 0.5*(delta + dim) * log(1+ H.invqform(val - mu)/delta); |
| | 274 | return tmp; |
| | 275 | } |
| | 276 | double lognc() const { |
| | 277 | //log(pi) = 1.14472988584940 |
| | 278 | double tmp = -lgamma(0.5*(delta+dim))+lgamma(0.5*delta) + 0.5*dim*(log(delta) + 1.14472988584940); |
| | 279 | return tmp; |
| | 280 | } |
| | 281 | void marginal (const RV &rvm, estudent<sq_T> &marg) const { |
| | 282 | ivec ind = rvm.findself_ids(rv); // indeces of rvm in rv |
| | 283 | marg._mu() = mu(ind); |
| | 284 | marg._H() = sq_T(H,ind); |
| | 285 | marg._delta() = delta; |
| | 286 | marg.validate(); |
| | 287 | } |
| | 288 | shared_ptr<epdf> marginal(const RV &rvm) const { |
| | 289 | shared_ptr<estudent<sq_T> > tmp = new estudent<sq_T>; |
| | 290 | marginal(rvm, *tmp); |
| | 291 | return tmp; |
| | 292 | } |
| | 293 | vec sample() const NOT_IMPLEMENTED(vec(0)) |
| | 294 | |
| | 295 | vec mean() const {return mu;} |
| | 296 | mat covariance() const {return delta/(delta-2)*H.to_mat();} |
| | 297 | vec variance() const {return diag(covariance());} |
| | 298 | //! \name access |
| | 299 | //! @{ |
| | 300 | //! access function |
| | 301 | vec& _mu() {return mu;} |
| | 302 | //! access function |
| | 303 | sq_T& _H() {return H;} |
| | 304 | //! access function |
| | 305 | double& _delta() {return delta;} |
| | 306 | //!@} |
| | 307 | //! todo |
| | 308 | void from_setting(const Setting &set){ |
| | 309 | epdf::from_setting(set); |
| | 310 | mat H0; |
| | 311 | UI::get(H0,set, "H"); |
| | 312 | H= H0; // conversion!! |
| | 313 | UI::get(delta,set,"delta"); |
| | 314 | UI::get(mu,set,"mu"); |
| | 315 | } |
| | 316 | void to_setting(Setting &set) const{ |
| | 317 | epdf::to_setting(set); |
| | 318 | UI::save(H.to_mat(), set, "H"); |
| | 319 | UI::save(delta, set, "delta"); |
| | 320 | UI::save(mu, set, "mu"); |
| | 321 | } |
| | 322 | void validate() { |
| | 323 | dim = H.rows(); |
| | 324 | } |
| | 325 | }; |
| | 326 | UIREGISTER2(estudent,fsqmat); |
| | 327 | UIREGISTER2(estudent,ldmat); |
| | 328 | UIREGISTER2(estudent,chmat); |
| | 380 | //! marginal density (only student for now) |
| | 381 | shared_ptr<epdf> marginal(const RV &rvm) const { |
| | 382 | bdm_assert(dimx==1, "Not supported"); |
| | 383 | //TODO - this is too trivial!!! |
| | 384 | ivec ind = rvm.findself_ids(rv); |
| | 385 | if (min(ind)==0) { //assume it si |
| | 386 | shared_ptr<estudent<ldmat> > tmp = new estudent<ldmat>; |
| | 387 | mat M; |
| | 388 | ldmat Vz; |
| | 389 | ldmat Lam; |
| | 390 | factorize(M,Vz,Lam); |
| | 391 | |
| | 392 | tmp->_mu() = M.get_col(0); |
| | 393 | ldmat H; |
| | 394 | Vz.inv(H); |
| | 395 | H *=Lam._D()(0)/nu; |
| | 396 | tmp->_H() = H; |
| | 397 | tmp->_delta() = nu; |
| | 398 | tmp->validate(); |
| | 399 | return tmp; |
| | 400 | } |
| | 401 | return NULL; |
| | 402 | } |