[8] | 1 | /*! |
---|
| 2 | \file |
---|
| 3 | \brief Probability distributions for Exponential Family models. |
---|
| 4 | \author Vaclav Smidl. |
---|
| 5 | |
---|
| 6 | ----------------------------------- |
---|
| 7 | BDM++ - C++ library for Bayesian Decision Making under Uncertainty |
---|
| 8 | |
---|
| 9 | Using IT++ for numerical operations |
---|
| 10 | ----------------------------------- |
---|
| 11 | */ |
---|
| 12 | |
---|
| 13 | #ifndef EF_H |
---|
| 14 | #define EF_H |
---|
| 15 | |
---|
[262] | 16 | |
---|
[461] | 17 | #include "../shared_ptr.h" |
---|
[384] | 18 | #include "../base/bdmbase.h" |
---|
[262] | 19 | #include "../math/chmat.h" |
---|
[8] | 20 | |
---|
[294] | 21 | namespace bdm |
---|
| 22 | { |
---|
[8] | 23 | |
---|
[32] | 24 | |
---|
| 25 | //! Global Uniform_RNG |
---|
[294] | 26 | extern Uniform_RNG UniRNG; |
---|
[33] | 27 | //! Global Normal_RNG |
---|
[294] | 28 | extern Normal_RNG NorRNG; |
---|
[33] | 29 | //! Global Gamma_RNG |
---|
[294] | 30 | extern Gamma_RNG GamRNG; |
---|
[32] | 31 | |
---|
[294] | 32 | /*! |
---|
| 33 | * \brief General conjugate exponential family posterior density. |
---|
[8] | 34 | |
---|
[294] | 35 | * More?... |
---|
| 36 | */ |
---|
[28] | 37 | |
---|
[294] | 38 | class eEF : public epdf |
---|
| 39 | { |
---|
| 40 | public: |
---|
[32] | 41 | // eEF() :epdf() {}; |
---|
[294] | 42 | //! default constructor |
---|
| 43 | eEF ( ) :epdf ( ) {}; |
---|
| 44 | //! logarithm of the normalizing constant, \f$\mathcal{I}\f$ |
---|
| 45 | virtual double lognc() const =0; |
---|
| 46 | //!TODO decide if it is really needed |
---|
| 47 | virtual void dupdate ( mat &v ) {it_error ( "Not implemented" );}; |
---|
| 48 | //!Evaluate normalized log-probability |
---|
| 49 | virtual double evallog_nn ( const vec &val ) const{it_error ( "Not implemented" );return 0.0;}; |
---|
| 50 | //!Evaluate normalized log-probability |
---|
[395] | 51 | virtual double evallog ( const vec &val ) const { |
---|
| 52 | double tmp; |
---|
| 53 | tmp= evallog_nn ( val )-lognc(); |
---|
[404] | 54 | // it_assert_debug ( std::isfinite ( tmp ),"Infinite value" ); |
---|
[395] | 55 | return tmp;} |
---|
[294] | 56 | //!Evaluate normalized log-probability for many samples |
---|
| 57 | virtual vec evallog ( const mat &Val ) const |
---|
| 58 | { |
---|
| 59 | vec x ( Val.cols() ); |
---|
| 60 | for ( int i=0;i<Val.cols();i++ ) {x ( i ) =evallog_nn ( Val.get_col ( i ) ) ;} |
---|
| 61 | return x-lognc(); |
---|
| 62 | } |
---|
| 63 | //!Power of the density, used e.g. to flatten the density |
---|
| 64 | virtual void pow ( double p ) {it_error ( "Not implemented" );}; |
---|
| 65 | }; |
---|
[8] | 66 | |
---|
[294] | 67 | /*! |
---|
| 68 | * \brief Exponential family model. |
---|
[33] | 69 | |
---|
[294] | 70 | * More?... |
---|
| 71 | */ |
---|
[33] | 72 | |
---|
[294] | 73 | class mEF : public mpdf |
---|
| 74 | { |
---|
[8] | 75 | |
---|
[294] | 76 | public: |
---|
| 77 | //! Default constructor |
---|
| 78 | mEF ( ) :mpdf ( ) {}; |
---|
| 79 | }; |
---|
[8] | 80 | |
---|
[170] | 81 | //! Estimator for Exponential family |
---|
[294] | 82 | class BMEF : public BM |
---|
| 83 | { |
---|
| 84 | protected: |
---|
| 85 | //! forgetting factor |
---|
| 86 | double frg; |
---|
| 87 | //! cached value of lognc() in the previous step (used in evaluation of \c ll ) |
---|
| 88 | double last_lognc; |
---|
| 89 | public: |
---|
| 90 | //! Default constructor (=empty constructor) |
---|
| 91 | BMEF ( double frg0=1.0 ) :BM ( ), frg ( frg0 ) {} |
---|
| 92 | //! Copy constructor |
---|
| 93 | BMEF ( const BMEF &B ) :BM ( B ), frg ( B.frg ), last_lognc ( B.last_lognc ) {} |
---|
| 94 | //!get statistics from another model |
---|
| 95 | virtual void set_statistics ( const BMEF* BM0 ) {it_error ( "Not implemented" );}; |
---|
| 96 | //! Weighted update of sufficient statistics (Bayes rule) |
---|
| 97 | virtual void bayes ( const vec &data, const double w ) {}; |
---|
| 98 | //original Bayes |
---|
| 99 | void bayes ( const vec &dt ); |
---|
| 100 | //!Flatten the posterior according to the given BMEF (of the same type!) |
---|
| 101 | virtual void flatten ( const BMEF * B ) {it_error ( "Not implemented" );} |
---|
| 102 | //!Flatten the posterior as if to keep nu0 data |
---|
[197] | 103 | // virtual void flatten ( double nu0 ) {it_error ( "Not implemented" );} |
---|
[198] | 104 | |
---|
[294] | 105 | BMEF* _copy_ () const {it_error ( "function _copy_ not implemented for this BM" ); return NULL;}; |
---|
| 106 | }; |
---|
[170] | 107 | |
---|
[294] | 108 | template<class sq_T> |
---|
| 109 | class mlnorm; |
---|
[178] | 110 | |
---|
[294] | 111 | /*! |
---|
| 112 | * \brief Gaussian density with positive definite (decomposed) covariance matrix. |
---|
[8] | 113 | |
---|
[294] | 114 | * More?... |
---|
| 115 | */ |
---|
| 116 | template<class sq_T> |
---|
| 117 | class enorm : public eEF |
---|
| 118 | { |
---|
| 119 | protected: |
---|
| 120 | //! mean value |
---|
| 121 | vec mu; |
---|
| 122 | //! Covariance matrix in decomposed form |
---|
| 123 | sq_T R; |
---|
| 124 | public: |
---|
| 125 | //!\name Constructors |
---|
| 126 | //!@{ |
---|
[270] | 127 | |
---|
[294] | 128 | enorm ( ) :eEF ( ), mu ( ),R ( ) {}; |
---|
| 129 | enorm ( const vec &mu,const sq_T &R ) {set_parameters ( mu,R );} |
---|
| 130 | void set_parameters ( const vec &mu,const sq_T &R ); |
---|
[384] | 131 | void from_setting(const Setting &root); |
---|
[395] | 132 | void validate() { |
---|
| 133 | it_assert(mu.length()==R.rows(),"parameters mismatch"); |
---|
| 134 | dim = mu.length(); |
---|
| 135 | } |
---|
[294] | 136 | //!@} |
---|
[270] | 137 | |
---|
[294] | 138 | //! \name Mathematical operations |
---|
| 139 | //!@{ |
---|
[270] | 140 | |
---|
[294] | 141 | //! dupdate in exponential form (not really handy) |
---|
| 142 | void dupdate ( mat &v,double nu=1.0 ); |
---|
[28] | 143 | |
---|
[294] | 144 | vec sample() const; |
---|
[450] | 145 | |
---|
[294] | 146 | double evallog_nn ( const vec &val ) const; |
---|
| 147 | double lognc () const; |
---|
| 148 | vec mean() const {return mu;} |
---|
| 149 | vec variance() const {return diag ( R.to_mat() );} |
---|
[299] | 150 | // mlnorm<sq_T>* condition ( const RV &rvn ) const ; <=========== fails to cmpile. Why? |
---|
[294] | 151 | mpdf* condition ( const RV &rvn ) const ; |
---|
[384] | 152 | enorm<sq_T>* marginal ( const RV &rv ) const; |
---|
[299] | 153 | // epdf* marginal ( const RV &rv ) const; |
---|
[294] | 154 | //!@} |
---|
[270] | 155 | |
---|
[294] | 156 | //! \name Access to attributes |
---|
| 157 | //!@{ |
---|
[270] | 158 | |
---|
[294] | 159 | vec& _mu() {return mu;} |
---|
| 160 | void set_mu ( const vec mu0 ) { mu=mu0;} |
---|
| 161 | sq_T& _R() {return R;} |
---|
| 162 | const sq_T& _R() const {return R;} |
---|
| 163 | //!@} |
---|
[28] | 164 | |
---|
[294] | 165 | }; |
---|
[388] | 166 | UIREGISTER(enorm<chmat>); |
---|
| 167 | UIREGISTER(enorm<ldmat>); |
---|
| 168 | UIREGISTER(enorm<fsqmat>); |
---|
[8] | 169 | |
---|
[388] | 170 | |
---|
[294] | 171 | /*! |
---|
| 172 | * \brief Gauss-inverse-Wishart density stored in LD form |
---|
[96] | 173 | |
---|
[294] | 174 | * For \f$p\f$-variate densities, given rv.count() should be \f$p\times\f$ V.rows(). |
---|
| 175 | * |
---|
| 176 | */ |
---|
| 177 | class egiw : public eEF |
---|
| 178 | { |
---|
| 179 | protected: |
---|
| 180 | //! Extended information matrix of sufficient statistics |
---|
| 181 | ldmat V; |
---|
| 182 | //! Number of data records (degrees of freedom) of sufficient statistics |
---|
| 183 | double nu; |
---|
| 184 | //! Dimension of the output |
---|
| 185 | int dimx; |
---|
| 186 | //! Dimension of the regressor |
---|
| 187 | int nPsi; |
---|
| 188 | public: |
---|
| 189 | //!\name Constructors |
---|
| 190 | //!@{ |
---|
| 191 | egiw() :eEF() {}; |
---|
| 192 | egiw ( int dimx0, ldmat V0, double nu0=-1.0 ) :eEF() {set_parameters ( dimx0,V0, nu0 );}; |
---|
[270] | 193 | |
---|
[294] | 194 | void set_parameters ( int dimx0, ldmat V0, double nu0=-1.0 ) |
---|
| 195 | { |
---|
| 196 | dimx=dimx0; |
---|
| 197 | nPsi = V0.rows()-dimx; |
---|
| 198 | dim = dimx* ( dimx+nPsi ); // size(R) + size(Theta) |
---|
[270] | 199 | |
---|
[294] | 200 | V=V0; |
---|
| 201 | if ( nu0<0 ) |
---|
| 202 | { |
---|
| 203 | nu = 0.1 +nPsi +2*dimx +2; // +2 assures finite expected value of R |
---|
| 204 | // terms before that are sufficient for finite normalization |
---|
| 205 | } |
---|
| 206 | else |
---|
| 207 | { |
---|
| 208 | nu=nu0; |
---|
| 209 | } |
---|
| 210 | } |
---|
| 211 | //!@} |
---|
[96] | 212 | |
---|
[294] | 213 | vec sample() const; |
---|
| 214 | vec mean() const; |
---|
| 215 | vec variance() const; |
---|
[330] | 216 | |
---|
| 217 | //! LS estimate of \f$\theta\f$ |
---|
| 218 | vec est_theta() const; |
---|
| 219 | |
---|
| 220 | //! Covariance of the LS estimate |
---|
| 221 | ldmat est_theta_cov() const; |
---|
| 222 | |
---|
[294] | 223 | void mean_mat ( mat &M, mat&R ) const; |
---|
| 224 | //! In this instance, val= [theta, r]. For multivariate instances, it is stored columnwise val = [theta_1 theta_2 ... r_1 r_2 ] |
---|
| 225 | double evallog_nn ( const vec &val ) const; |
---|
| 226 | double lognc () const; |
---|
| 227 | void pow ( double p ) {V*=p;nu*=p;}; |
---|
[96] | 228 | |
---|
[294] | 229 | //! \name Access attributes |
---|
| 230 | //!@{ |
---|
[270] | 231 | |
---|
[294] | 232 | ldmat& _V() {return V;} |
---|
| 233 | const ldmat& _V() const {return V;} |
---|
| 234 | double& _nu() {return nu;} |
---|
| 235 | const double& _nu() const {return nu;} |
---|
[395] | 236 | void from_setting(const Setting &set){ |
---|
[476] | 237 | UI::get(nu, set, "nu", UI::compulsory); |
---|
| 238 | UI::get(dimx, set, "dimx", UI::compulsory); |
---|
[395] | 239 | mat V; |
---|
[471] | 240 | UI::get(V,set,"V", UI::compulsory); |
---|
[395] | 241 | set_parameters(dimx, V, nu); |
---|
[471] | 242 | RV* rv=UI::build<RV>(set,"rv", UI::compulsory); |
---|
[395] | 243 | set_rv(*rv); |
---|
| 244 | delete rv; |
---|
| 245 | } |
---|
[294] | 246 | //!@} |
---|
| 247 | }; |
---|
[395] | 248 | UIREGISTER(egiw); |
---|
[96] | 249 | |
---|
[294] | 250 | /*! \brief Dirichlet posterior density |
---|
[173] | 251 | |
---|
[294] | 252 | Continuous Dirichlet density of \f$n\f$-dimensional variable \f$x\f$ |
---|
| 253 | \f[ |
---|
| 254 | f(x|\beta) = \frac{\Gamma[\gamma]}{\prod_{i=1}^{n}\Gamma(\beta_i)} \prod_{i=1}^{n}x_i^{\beta_i-1} |
---|
| 255 | \f] |
---|
| 256 | where \f$\gamma=\sum_i \beta_i\f$. |
---|
| 257 | */ |
---|
| 258 | class eDirich: public eEF |
---|
| 259 | { |
---|
| 260 | protected: |
---|
| 261 | //!sufficient statistics |
---|
| 262 | vec beta; |
---|
| 263 | public: |
---|
| 264 | //!\name Constructors |
---|
| 265 | //!@{ |
---|
[270] | 266 | |
---|
[294] | 267 | eDirich () : eEF ( ) {}; |
---|
| 268 | eDirich ( const eDirich &D0 ) : eEF () {set_parameters ( D0.beta );}; |
---|
| 269 | eDirich ( const vec &beta0 ) {set_parameters ( beta0 );}; |
---|
| 270 | void set_parameters ( const vec &beta0 ) |
---|
| 271 | { |
---|
| 272 | beta= beta0; |
---|
| 273 | dim = beta.length(); |
---|
| 274 | } |
---|
| 275 | //!@} |
---|
[270] | 276 | |
---|
[294] | 277 | vec sample() const {it_error ( "Not implemented" );return vec_1 ( 0.0 );}; |
---|
[310] | 278 | vec mean() const {return beta/sum(beta);}; |
---|
| 279 | vec variance() const {double gamma =sum(beta); return elem_mult ( beta, ( beta+1 ) ) / ( gamma* ( gamma+1 ) );} |
---|
[294] | 280 | //! In this instance, val is ... |
---|
| 281 | double evallog_nn ( const vec &val ) const |
---|
| 282 | { |
---|
[404] | 283 | double tmp; tmp= ( beta-1 ) *log ( val ); |
---|
| 284 | // it_assert_debug ( std::isfinite ( tmp ),"Infinite value" ); |
---|
[294] | 285 | return tmp; |
---|
| 286 | }; |
---|
| 287 | double lognc () const |
---|
| 288 | { |
---|
| 289 | double tmp; |
---|
| 290 | double gam=sum ( beta ); |
---|
| 291 | double lgb=0.0; |
---|
| 292 | for ( int i=0;i<beta.length();i++ ) {lgb+=lgamma ( beta ( i ) );} |
---|
| 293 | tmp= lgb-lgamma ( gam ); |
---|
[404] | 294 | // it_assert_debug ( std::isfinite ( tmp ),"Infinite value" ); |
---|
[294] | 295 | return tmp; |
---|
| 296 | }; |
---|
| 297 | //!access function |
---|
| 298 | vec& _beta() {return beta;} |
---|
| 299 | //!Set internal parameters |
---|
[270] | 300 | }; |
---|
[96] | 301 | |
---|
[181] | 302 | //! \brief Estimator for Multinomial density |
---|
[294] | 303 | class multiBM : public BMEF |
---|
| 304 | { |
---|
| 305 | protected: |
---|
| 306 | //! Conjugate prior and posterior |
---|
| 307 | eDirich est; |
---|
| 308 | //! Pointer inside est to sufficient statistics |
---|
| 309 | vec β |
---|
| 310 | public: |
---|
| 311 | //!Default constructor |
---|
| 312 | multiBM ( ) : BMEF ( ),est ( ),beta ( est._beta() ) |
---|
| 313 | { |
---|
| 314 | if ( beta.length() >0 ) {last_lognc=est.lognc();} |
---|
| 315 | else{last_lognc=0.0;} |
---|
| 316 | } |
---|
| 317 | //!Copy constructor |
---|
| 318 | multiBM ( const multiBM &B ) : BMEF ( B ),est ( B.est ),beta ( est._beta() ) {} |
---|
| 319 | //! Sets sufficient statistics to match that of givefrom mB0 |
---|
| 320 | void set_statistics ( const BM* mB0 ) {const multiBM* mB=dynamic_cast<const multiBM*> ( mB0 ); beta=mB->beta;} |
---|
| 321 | void bayes ( const vec &dt ) |
---|
| 322 | { |
---|
| 323 | if ( frg<1.0 ) {beta*=frg;last_lognc=est.lognc();} |
---|
| 324 | beta+=dt; |
---|
| 325 | if ( evalll ) {ll=est.lognc()-last_lognc;} |
---|
| 326 | } |
---|
| 327 | double logpred ( const vec &dt ) const |
---|
| 328 | { |
---|
| 329 | eDirich pred ( est ); |
---|
| 330 | vec &beta = pred._beta(); |
---|
[176] | 331 | |
---|
[294] | 332 | double lll; |
---|
| 333 | if ( frg<1.0 ) |
---|
| 334 | {beta*=frg;lll=pred.lognc();} |
---|
| 335 | else |
---|
| 336 | if ( evalll ) {lll=last_lognc;} |
---|
| 337 | else{lll=pred.lognc();} |
---|
[170] | 338 | |
---|
[294] | 339 | beta+=dt; |
---|
| 340 | return pred.lognc()-lll; |
---|
| 341 | } |
---|
| 342 | void flatten ( const BMEF* B ) |
---|
| 343 | { |
---|
| 344 | const multiBM* E=dynamic_cast<const multiBM*> ( B ); |
---|
| 345 | // sum(beta) should be equal to sum(B.beta) |
---|
| 346 | const vec &Eb=E->beta;//const_cast<multiBM*> ( E )->_beta(); |
---|
| 347 | beta*= ( sum ( Eb ) /sum ( beta ) ); |
---|
| 348 | if ( evalll ) {last_lognc=est.lognc();} |
---|
| 349 | } |
---|
| 350 | const epdf& posterior() const {return est;}; |
---|
| 351 | const eDirich* _e() const {return &est;}; |
---|
| 352 | void set_parameters ( const vec &beta0 ) |
---|
| 353 | { |
---|
| 354 | est.set_parameters ( beta0 ); |
---|
| 355 | if ( evalll ) {last_lognc=est.lognc();} |
---|
| 356 | } |
---|
| 357 | }; |
---|
[170] | 358 | |
---|
[294] | 359 | /*! |
---|
| 360 | \brief Gamma posterior density |
---|
[32] | 361 | |
---|
[294] | 362 | Multivariate Gamma density as product of independent univariate densities. |
---|
| 363 | \f[ |
---|
| 364 | f(x|\alpha,\beta) = \prod f(x_i|\alpha_i,\beta_i) |
---|
| 365 | \f] |
---|
| 366 | */ |
---|
[32] | 367 | |
---|
[294] | 368 | class egamma : public eEF |
---|
| 369 | { |
---|
| 370 | protected: |
---|
| 371 | //! Vector \f$\alpha\f$ |
---|
| 372 | vec alpha; |
---|
| 373 | //! Vector \f$\beta\f$ |
---|
| 374 | vec beta; |
---|
| 375 | public : |
---|
| 376 | //! \name Constructors |
---|
| 377 | //!@{ |
---|
| 378 | egamma ( ) :eEF ( ), alpha ( 0 ), beta ( 0 ) {}; |
---|
| 379 | egamma ( const vec &a, const vec &b ) {set_parameters ( a, b );}; |
---|
| 380 | void set_parameters ( const vec &a, const vec &b ) {alpha=a,beta=b;dim = alpha.length();}; |
---|
| 381 | //!@} |
---|
[270] | 382 | |
---|
[294] | 383 | vec sample() const; |
---|
| 384 | //! TODO: is it used anywhere? |
---|
[102] | 385 | // mat sample ( int N ) const; |
---|
[294] | 386 | double evallog ( const vec &val ) const; |
---|
| 387 | double lognc () const; |
---|
| 388 | //! Returns poiter to alpha and beta. Potentially dengerous: use with care! |
---|
| 389 | vec& _alpha() {return alpha;} |
---|
| 390 | vec& _beta() {return beta;} |
---|
| 391 | vec mean() const {return elem_div ( alpha,beta );} |
---|
| 392 | vec variance() const {return elem_div ( alpha,elem_mult ( beta,beta ) ); } |
---|
[395] | 393 | |
---|
| 394 | //! Load from structure with elements: |
---|
| 395 | //! \code |
---|
| 396 | //! { alpha = [...]; // vector of alpha |
---|
| 397 | //! beta = [...]; // vector of beta |
---|
| 398 | //! rv = {class="RV",...} // description |
---|
| 399 | //! } |
---|
| 400 | //! \endcode |
---|
| 401 | //!@} |
---|
| 402 | void from_setting(const Setting &set){ |
---|
| 403 | epdf::from_setting(set); // reads rv |
---|
[471] | 404 | UI::get(alpha,set,"alpha", UI::compulsory); |
---|
| 405 | UI::get(beta,set,"beta", UI::compulsory); |
---|
[395] | 406 | validate(); |
---|
| 407 | } |
---|
| 408 | void validate(){ |
---|
| 409 | it_assert(alpha.length() ==beta.length(), "parameters do not match"); |
---|
| 410 | dim =alpha.length(); |
---|
| 411 | } |
---|
[294] | 412 | }; |
---|
[395] | 413 | UIREGISTER(egamma); |
---|
[294] | 414 | /*! |
---|
| 415 | \brief Inverse-Gamma posterior density |
---|
[225] | 416 | |
---|
[294] | 417 | Multivariate inverse-Gamma density as product of independent univariate densities. |
---|
| 418 | \f[ |
---|
| 419 | f(x|\alpha,\beta) = \prod f(x_i|\alpha_i,\beta_i) |
---|
| 420 | \f] |
---|
[225] | 421 | |
---|
[294] | 422 | Vector \f$\beta\f$ has different meaning (in fact it is 1/beta as used in definition of iG) |
---|
[283] | 423 | |
---|
[294] | 424 | Inverse Gamma can be converted to Gamma using \f[ |
---|
| 425 | x\sim iG(a,b) => 1/x\sim G(a,1/b) |
---|
| 426 | \f] |
---|
| 427 | This relation is used in sampling. |
---|
| 428 | */ |
---|
[225] | 429 | |
---|
[294] | 430 | class eigamma : public egamma |
---|
| 431 | { |
---|
| 432 | protected: |
---|
| 433 | public : |
---|
| 434 | //! \name Constructors |
---|
| 435 | //! All constructors are inherited |
---|
| 436 | //!@{ |
---|
| 437 | //!@} |
---|
[270] | 438 | |
---|
[294] | 439 | vec sample() const {return 1.0/egamma::sample();}; |
---|
| 440 | //! Returns poiter to alpha and beta. Potentially dangerous: use with care! |
---|
| 441 | vec mean() const {return elem_div ( beta,alpha-1 );} |
---|
| 442 | vec variance() const {vec mea=mean(); return elem_div ( elem_mult ( mea,mea ),alpha-2 );} |
---|
| 443 | }; |
---|
| 444 | /* |
---|
| 445 | //! Weighted mixture of epdfs with external owned components. |
---|
| 446 | class emix : public epdf { |
---|
| 447 | protected: |
---|
| 448 | int n; |
---|
| 449 | vec &w; |
---|
| 450 | Array<epdf*> Coms; |
---|
| 451 | public: |
---|
| 452 | //! Default constructor |
---|
| 453 | emix ( const RV &rv, vec &w0): epdf(rv), n(w0.length()), w(w0), Coms(n) {}; |
---|
| 454 | void set_parameters( int &i, double wi, epdf* ep){w(i)=wi;Coms(i)=ep;} |
---|
| 455 | vec mean(){vec pom; for(int i=0;i<n;i++){pom+=Coms(i)->mean()*w(i);} return pom;}; |
---|
| 456 | vec sample() {it_error ( "Not implemented" );return 0;} |
---|
| 457 | }; |
---|
| 458 | */ |
---|
[32] | 459 | |
---|
| 460 | //! Uniform distributed density on a rectangular support |
---|
| 461 | |
---|
[294] | 462 | class euni: public epdf |
---|
| 463 | { |
---|
| 464 | protected: |
---|
[32] | 465 | //! lower bound on support |
---|
[294] | 466 | vec low; |
---|
[32] | 467 | //! upper bound on support |
---|
[294] | 468 | vec high; |
---|
[32] | 469 | //! internal |
---|
[294] | 470 | vec distance; |
---|
[32] | 471 | //! normalizing coefficients |
---|
[294] | 472 | double nk; |
---|
[33] | 473 | //! cache of log( \c nk ) |
---|
[294] | 474 | double lnk; |
---|
| 475 | public: |
---|
| 476 | //! \name Constructors |
---|
| 477 | //!@{ |
---|
| 478 | euni ( ) :epdf ( ) {} |
---|
| 479 | euni ( const vec &low0, const vec &high0 ) {set_parameters ( low0,high0 );} |
---|
| 480 | void set_parameters ( const vec &low0, const vec &high0 ) |
---|
| 481 | { |
---|
| 482 | distance = high0-low0; |
---|
| 483 | it_assert_debug ( min ( distance ) >0.0,"bad support" ); |
---|
| 484 | low = low0; |
---|
| 485 | high = high0; |
---|
| 486 | nk = prod ( 1.0/distance ); |
---|
| 487 | lnk = log ( nk ); |
---|
| 488 | dim = low.length(); |
---|
| 489 | } |
---|
| 490 | //!@} |
---|
[270] | 491 | |
---|
[294] | 492 | double eval ( const vec &val ) const {return nk;} |
---|
[404] | 493 | double evallog ( const vec &val ) const { |
---|
| 494 | if (any(val<low) && any(val>high)) {return inf;} |
---|
| 495 | else return lnk; |
---|
| 496 | } |
---|
[294] | 497 | vec sample() const |
---|
| 498 | { |
---|
| 499 | vec smp ( dim ); |
---|
[270] | 500 | #pragma omp critical |
---|
[294] | 501 | UniRNG.sample_vector ( dim ,smp ); |
---|
| 502 | return low+elem_mult ( distance,smp ); |
---|
| 503 | } |
---|
| 504 | //! set values of \c low and \c high |
---|
| 505 | vec mean() const {return ( high-low ) /2.0;} |
---|
| 506 | vec variance() const {return ( pow ( high,2 ) +pow ( low,2 ) +elem_mult ( high,low ) ) /3.0;} |
---|
[395] | 507 | //! Load from structure with elements: |
---|
| 508 | //! \code |
---|
| 509 | //! { high = [...]; // vector of upper bounds |
---|
| 510 | //! low = [...]; // vector of lower bounds |
---|
| 511 | //! rv = {class="RV",...} // description of RV |
---|
| 512 | //! } |
---|
| 513 | //! \endcode |
---|
| 514 | //!@} |
---|
| 515 | void from_setting(const Setting &set){ |
---|
| 516 | epdf::from_setting(set); // reads rv and rvc |
---|
[471] | 517 | |
---|
| 518 | UI::get(high,set,"high", UI::compulsory); |
---|
| 519 | UI::get(low,set,"low", UI::compulsory); |
---|
[395] | 520 | } |
---|
[294] | 521 | }; |
---|
[32] | 522 | |
---|
| 523 | |
---|
[294] | 524 | /*! |
---|
| 525 | \brief Normal distributed linear function with linear function of mean value; |
---|
[32] | 526 | |
---|
[294] | 527 | Mean value \f$mu=A*rvc+mu_0\f$. |
---|
| 528 | */ |
---|
| 529 | template<class sq_T> |
---|
| 530 | class mlnorm : public mEF |
---|
| 531 | { |
---|
| 532 | protected: |
---|
| 533 | //! Internal epdf that arise by conditioning on \c rvc |
---|
[461] | 534 | shared_ptr<enorm<sq_T> > iepdf; |
---|
[294] | 535 | mat A; |
---|
| 536 | vec mu_const; |
---|
| 537 | vec& _mu; //cached epdf.mu; |
---|
| 538 | public: |
---|
| 539 | //! \name Constructors |
---|
| 540 | //!@{ |
---|
[461] | 541 | mlnorm():iepdf(new enorm<sq_T>()), _mu(iepdf->_mu()) { set_ep(iepdf); }; |
---|
| 542 | mlnorm (const mat &A, const vec &mu0, const sq_T &R ) :iepdf(new enorm<sq_T>()), _mu(iepdf->_mu()) |
---|
[294] | 543 | { |
---|
[461] | 544 | set_ep(iepdf); set_parameters ( A,mu0,R ); |
---|
| 545 | } |
---|
| 546 | |
---|
[294] | 547 | //! Set \c A and \c R |
---|
| 548 | void set_parameters ( const mat &A, const vec &mu0, const sq_T &R ); |
---|
| 549 | //!@} |
---|
| 550 | //! Set value of \c rvc . Result of this operation is stored in \c epdf use function \c _ep to access it. |
---|
| 551 | void condition ( const vec &cond ); |
---|
[198] | 552 | |
---|
[294] | 553 | //!access function |
---|
| 554 | vec& _mu_const() {return mu_const;} |
---|
| 555 | //!access function |
---|
| 556 | mat& _A() {return A;} |
---|
| 557 | //!access function |
---|
[461] | 558 | mat _R() { return iepdf->_R().to_mat(); } |
---|
[198] | 559 | |
---|
[294] | 560 | template<class sq_M> |
---|
| 561 | friend std::ostream &operator<< ( std::ostream &os, mlnorm<sq_M> &ml ); |
---|
[429] | 562 | |
---|
| 563 | void from_setting(const Setting &set){ |
---|
[471] | 564 | mpdf::from_setting(set); |
---|
| 565 | |
---|
| 566 | UI::get(A,set,"A", UI::compulsory); |
---|
| 567 | UI::get(mu_const,set,"const", UI::compulsory); |
---|
[429] | 568 | mat R0; |
---|
[471] | 569 | UI::get(R0,set,"R", UI::compulsory); |
---|
[429] | 570 | set_parameters(A,mu_const,R0); |
---|
| 571 | }; |
---|
[294] | 572 | }; |
---|
[429] | 573 | UIREGISTER(mlnorm<ldmat>); |
---|
| 574 | UIREGISTER(mlnorm<fsqmat>); |
---|
| 575 | UIREGISTER(mlnorm<chmat>); |
---|
[8] | 576 | |
---|
[280] | 577 | //! Mpdf with general function for mean value |
---|
[294] | 578 | template<class sq_T> |
---|
| 579 | class mgnorm : public mEF |
---|
| 580 | { |
---|
| 581 | protected: |
---|
| 582 | //! Internal epdf that arise by conditioning on \c rvc |
---|
[461] | 583 | shared_ptr<enorm<sq_T> > iepdf; |
---|
[294] | 584 | vec μ |
---|
| 585 | fnc* g; |
---|
| 586 | public: |
---|
| 587 | //!default constructor |
---|
[461] | 588 | mgnorm():iepdf(new enorm<sq_T>()), mu(iepdf->_mu()) { set_ep(iepdf); } |
---|
[294] | 589 | //!set mean function |
---|
[461] | 590 | void set_parameters ( fnc* g0, const sq_T &R0 ) {g=g0; iepdf->set_parameters ( zeros ( g->dimension() ), R0 );} |
---|
[294] | 591 | void condition ( const vec &cond ) {mu=g->eval ( cond );}; |
---|
[357] | 592 | |
---|
| 593 | |
---|
| 594 | /*! UI for mgnorm |
---|
| 595 | |
---|
| 596 | The mgnorm is constructed from a structure with fields: |
---|
| 597 | \code |
---|
| 598 | system = { |
---|
| 599 | type = "mgnorm"; |
---|
| 600 | // function for mean value evolution |
---|
| 601 | g = {type="fnc"; ... } |
---|
| 602 | |
---|
| 603 | // variance |
---|
| 604 | R = [1, 0, |
---|
| 605 | 0, 1]; |
---|
| 606 | // --OR -- |
---|
| 607 | dR = [1, 1]; |
---|
| 608 | |
---|
| 609 | // == OPTIONAL == |
---|
| 610 | |
---|
| 611 | // description of y variables |
---|
| 612 | y = {type="rv"; names=["y", "u"];}; |
---|
| 613 | // description of u variable |
---|
| 614 | u = {type="rv"; names=[];} |
---|
| 615 | }; |
---|
| 616 | \endcode |
---|
| 617 | |
---|
| 618 | Result if |
---|
| 619 | */ |
---|
| 620 | |
---|
[377] | 621 | void from_setting( const Setting &set ) |
---|
[357] | 622 | { |
---|
[471] | 623 | fnc* g = UI::build<fnc>( set, "g", UI::compulsory ); |
---|
[357] | 624 | |
---|
[471] | 625 | mat R; |
---|
| 626 | vec dR; |
---|
| 627 | if ( UI::get( dR, set, "dR" ) ) |
---|
[357] | 628 | R=diag(dR); |
---|
| 629 | else |
---|
[471] | 630 | UI::get( R, set, "R", UI::compulsory); |
---|
[357] | 631 | |
---|
| 632 | set_parameters(g,R); |
---|
| 633 | } |
---|
[294] | 634 | }; |
---|
[280] | 635 | |
---|
[357] | 636 | UIREGISTER(mgnorm<chmat>); |
---|
| 637 | |
---|
| 638 | |
---|
[294] | 639 | /*! (Approximate) Student t density with linear function of mean value |
---|
[262] | 640 | |
---|
[294] | 641 | The internal epdf of this class is of the type of a Gaussian (enorm). |
---|
| 642 | However, each conditioning is trying to assure the best possible approximation by taking into account the zeta function. See [] for reference. |
---|
[262] | 643 | |
---|
[294] | 644 | Perhaps a moment-matching technique? |
---|
| 645 | */ |
---|
| 646 | class mlstudent : public mlnorm<ldmat> |
---|
| 647 | { |
---|
| 648 | protected: |
---|
| 649 | ldmat Lambda; |
---|
| 650 | ldmat &_R; |
---|
| 651 | ldmat Re; |
---|
| 652 | public: |
---|
| 653 | mlstudent ( ) :mlnorm<ldmat> (), |
---|
[461] | 654 | Lambda (), _R ( iepdf->_R() ) {} |
---|
[294] | 655 | void set_parameters ( const mat &A0, const vec &mu0, const ldmat &R0, const ldmat& Lambda0 ) |
---|
| 656 | { |
---|
| 657 | it_assert_debug ( A0.rows() ==mu0.length(),"" ); |
---|
| 658 | it_assert_debug ( R0.rows() ==A0.rows(),"" ); |
---|
[270] | 659 | |
---|
[461] | 660 | iepdf->set_parameters ( mu0,Lambda ); // |
---|
[294] | 661 | A = A0; |
---|
| 662 | mu_const = mu0; |
---|
| 663 | Re=R0; |
---|
| 664 | Lambda = Lambda0; |
---|
| 665 | } |
---|
| 666 | void condition ( const vec &cond ) |
---|
| 667 | { |
---|
| 668 | _mu = A*cond + mu_const; |
---|
| 669 | double zeta; |
---|
| 670 | //ugly hack! |
---|
| 671 | if ( ( cond.length() +1 ) ==Lambda.rows() ) |
---|
| 672 | { |
---|
| 673 | zeta = Lambda.invqform ( concat ( cond, vec_1 ( 1.0 ) ) ); |
---|
| 674 | } |
---|
| 675 | else |
---|
| 676 | { |
---|
| 677 | zeta = Lambda.invqform ( cond ); |
---|
| 678 | } |
---|
| 679 | _R = Re; |
---|
| 680 | _R*= ( 1+zeta );// / ( nu ); << nu is in Re!!!!!! |
---|
| 681 | }; |
---|
| 682 | |
---|
[198] | 683 | }; |
---|
[294] | 684 | /*! |
---|
| 685 | \brief Gamma random walk |
---|
[198] | 686 | |
---|
[294] | 687 | Mean value, \f$\mu\f$, of this density is given by \c rvc . |
---|
| 688 | Standard deviation of the random walk is proportional to one \f$k\f$-th the mean. |
---|
| 689 | This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$. |
---|
[32] | 690 | |
---|
[294] | 691 | The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$. |
---|
| 692 | */ |
---|
| 693 | class mgamma : public mEF |
---|
| 694 | { |
---|
| 695 | protected: |
---|
| 696 | //! Internal epdf that arise by conditioning on \c rvc |
---|
[461] | 697 | shared_ptr<egamma> iepdf; |
---|
| 698 | |
---|
[294] | 699 | //! Constant \f$k\f$ |
---|
| 700 | double k; |
---|
[461] | 701 | |
---|
| 702 | //! cache of iepdf.beta |
---|
[294] | 703 | vec &_beta; |
---|
[32] | 704 | |
---|
[294] | 705 | public: |
---|
| 706 | //! Constructor |
---|
[461] | 707 | mgamma():iepdf(new egamma()), k(0), |
---|
| 708 | _beta(iepdf->_beta()) { |
---|
| 709 | set_ep(iepdf); |
---|
| 710 | } |
---|
| 711 | |
---|
[294] | 712 | //! Set value of \c k |
---|
[461] | 713 | void set_parameters(double k, const vec &beta0); |
---|
| 714 | |
---|
[294] | 715 | void condition ( const vec &val ) {_beta=k/val;}; |
---|
[395] | 716 | //! Load from structure with elements: |
---|
| 717 | //! \code |
---|
| 718 | //! { alpha = [...]; // vector of alpha |
---|
| 719 | //! k = 1.1; // multiplicative constant k |
---|
| 720 | //! rv = {class="RV",...} // description of RV |
---|
| 721 | //! rvc = {class="RV",...} // description of RV in condition |
---|
| 722 | //! } |
---|
| 723 | //! \endcode |
---|
| 724 | //!@} |
---|
| 725 | void from_setting(const Setting &set){ |
---|
| 726 | mpdf::from_setting(set); // reads rv and rvc |
---|
| 727 | vec betatmp; // ugly but necessary |
---|
[471] | 728 | UI::get(betatmp,set,"beta", UI::compulsory); |
---|
| 729 | UI::get(k,set,"k", UI::compulsory); |
---|
[395] | 730 | set_parameters(k,betatmp); |
---|
| 731 | } |
---|
[294] | 732 | }; |
---|
[395] | 733 | UIREGISTER(mgamma); |
---|
| 734 | |
---|
[294] | 735 | /*! |
---|
| 736 | \brief Inverse-Gamma random walk |
---|
[32] | 737 | |
---|
[294] | 738 | Mean value, \f$ \mu \f$, of this density is given by \c rvc . |
---|
| 739 | Standard deviation of the random walk is proportional to one \f$ k \f$-th the mean. |
---|
| 740 | This is achieved by setting \f$ \alpha=\mu/k^2+2 \f$ and \f$ \beta=\mu(\alpha-1)\f$. |
---|
[225] | 741 | |
---|
[294] | 742 | The standard deviation of the walk is then: \f$ \mu/\sqrt(k)\f$. |
---|
| 743 | */ |
---|
| 744 | class migamma : public mEF |
---|
| 745 | { |
---|
| 746 | protected: |
---|
| 747 | //! Internal epdf that arise by conditioning on \c rvc |
---|
[461] | 748 | shared_ptr<eigamma> iepdf; |
---|
| 749 | |
---|
[294] | 750 | //! Constant \f$k\f$ |
---|
| 751 | double k; |
---|
[461] | 752 | |
---|
| 753 | //! cache of iepdf.alpha |
---|
[294] | 754 | vec &_alpha; |
---|
[461] | 755 | |
---|
| 756 | //! cache of iepdf.beta |
---|
[294] | 757 | vec &_beta; |
---|
[225] | 758 | |
---|
[294] | 759 | public: |
---|
| 760 | //! \name Constructors |
---|
| 761 | //!@{ |
---|
[461] | 762 | migamma():iepdf(new eigamma()), |
---|
| 763 | k(0), |
---|
| 764 | _alpha(iepdf->_alpha()), |
---|
| 765 | _beta(iepdf->_beta()) { |
---|
| 766 | set_ep(iepdf); |
---|
| 767 | } |
---|
| 768 | |
---|
| 769 | migamma(const migamma &m):iepdf(m.iepdf), |
---|
| 770 | k(0), |
---|
| 771 | _alpha(iepdf->_alpha()), |
---|
| 772 | _beta(iepdf->_beta()) { |
---|
| 773 | set_ep(iepdf); |
---|
| 774 | } |
---|
[294] | 775 | //!@} |
---|
[225] | 776 | |
---|
[294] | 777 | //! Set value of \c k |
---|
| 778 | void set_parameters ( int len, double k0 ) |
---|
| 779 | { |
---|
| 780 | k=k0; |
---|
[461] | 781 | iepdf->set_parameters ( ( 1.0/ ( k*k ) +2.0 ) *ones ( len ) /*alpha*/, ones ( len ) /*beta*/ ); |
---|
[294] | 782 | dimc = dimension(); |
---|
| 783 | }; |
---|
| 784 | void condition ( const vec &val ) |
---|
| 785 | { |
---|
| 786 | _beta=elem_mult ( val, ( _alpha-1.0 ) ); |
---|
| 787 | }; |
---|
[270] | 788 | }; |
---|
[225] | 789 | |
---|
[357] | 790 | |
---|
[294] | 791 | /*! |
---|
| 792 | \brief Gamma random walk around a fixed point |
---|
[60] | 793 | |
---|
[294] | 794 | Mean value, \f$\mu\f$, of this density is given by a geometric combination of \c rvc and given fixed point, \f$p\f$. \f$l\f$ is the coefficient of the geometric combimation |
---|
| 795 | \f[ \mu = \mu_{t-1} ^{l} p^{1-l}\f] |
---|
[60] | 796 | |
---|
[294] | 797 | Standard deviation of the random walk is proportional to one \f$k\f$-th the mean. |
---|
| 798 | This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$. |
---|
[60] | 799 | |
---|
[294] | 800 | The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$. |
---|
| 801 | */ |
---|
| 802 | class mgamma_fix : public mgamma |
---|
| 803 | { |
---|
| 804 | protected: |
---|
| 805 | //! parameter l |
---|
| 806 | double l; |
---|
| 807 | //! reference vector |
---|
| 808 | vec refl; |
---|
| 809 | public: |
---|
| 810 | //! Constructor |
---|
| 811 | mgamma_fix ( ) : mgamma ( ),refl () {}; |
---|
| 812 | //! Set value of \c k |
---|
| 813 | void set_parameters ( double k0 , vec ref0, double l0 ) |
---|
| 814 | { |
---|
| 815 | mgamma::set_parameters ( k0, ref0 ); |
---|
| 816 | refl=pow ( ref0,1.0-l0 );l=l0; |
---|
| 817 | dimc=dimension(); |
---|
| 818 | }; |
---|
| 819 | |
---|
| 820 | void condition ( const vec &val ) {vec mean=elem_mult ( refl,pow ( val,l ) ); _beta=k/mean;}; |
---|
[60] | 821 | }; |
---|
| 822 | |
---|
| 823 | |
---|
[294] | 824 | /*! |
---|
| 825 | \brief Inverse-Gamma random walk around a fixed point |
---|
[225] | 826 | |
---|
[294] | 827 | Mean value, \f$\mu\f$, of this density is given by a geometric combination of \c rvc and given fixed point, \f$p\f$. \f$l\f$ is the coefficient of the geometric combimation |
---|
| 828 | \f[ \mu = \mu_{t-1} ^{l} p^{1-l}\f] |
---|
[225] | 829 | |
---|
[294] | 830 | ==== Check == vv = |
---|
| 831 | Standard deviation of the random walk is proportional to one \f$k\f$-th the mean. |
---|
| 832 | This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$. |
---|
[225] | 833 | |
---|
[294] | 834 | The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$. |
---|
| 835 | */ |
---|
| 836 | class migamma_ref : public migamma |
---|
| 837 | { |
---|
| 838 | protected: |
---|
| 839 | //! parameter l |
---|
| 840 | double l; |
---|
| 841 | //! reference vector |
---|
| 842 | vec refl; |
---|
| 843 | public: |
---|
| 844 | //! Constructor |
---|
| 845 | migamma_ref ( ) : migamma (),refl ( ) {}; |
---|
| 846 | //! Set value of \c k |
---|
| 847 | void set_parameters ( double k0 , vec ref0, double l0 ) |
---|
| 848 | { |
---|
| 849 | migamma::set_parameters ( ref0.length(), k0 ); |
---|
| 850 | refl=pow ( ref0,1.0-l0 ); |
---|
| 851 | l=l0; |
---|
| 852 | dimc = dimension(); |
---|
| 853 | }; |
---|
[225] | 854 | |
---|
[294] | 855 | void condition ( const vec &val ) |
---|
| 856 | { |
---|
| 857 | vec mean=elem_mult ( refl,pow ( val,l ) ); |
---|
| 858 | migamma::condition ( mean ); |
---|
| 859 | }; |
---|
[357] | 860 | |
---|
| 861 | /*! UI for migamma_ref |
---|
| 862 | |
---|
| 863 | The migamma_ref is constructed from a structure with fields: |
---|
| 864 | \code |
---|
| 865 | system = { |
---|
| 866 | type = "migamma_ref"; |
---|
| 867 | ref = [1e-5; 1e-5; 1e-2 1e-3]; // reference vector |
---|
| 868 | l = 0.999; // constant l |
---|
| 869 | k = 0.1; // constant k |
---|
| 870 | |
---|
| 871 | // == OPTIONAL == |
---|
| 872 | // description of y variables |
---|
| 873 | y = {type="rv"; names=["y", "u"];}; |
---|
| 874 | // description of u variable |
---|
| 875 | u = {type="rv"; names=[];} |
---|
| 876 | }; |
---|
| 877 | \endcode |
---|
| 878 | |
---|
| 879 | Result if |
---|
| 880 | */ |
---|
[377] | 881 | void from_setting( const Setting &set ); |
---|
[357] | 882 | |
---|
[377] | 883 | // TODO dodelat void to_setting( Setting &set ) const; |
---|
[270] | 884 | }; |
---|
[225] | 885 | |
---|
[357] | 886 | |
---|
| 887 | UIREGISTER(migamma_ref); |
---|
| 888 | |
---|
[294] | 889 | /*! Log-Normal probability density |
---|
| 890 | only allow diagonal covariances! |
---|
| 891 | |
---|
[384] | 892 | Density of the form \f$ \log(x)\sim \mathcal{N}(\mu,\sigma^2) \f$ , i.e. |
---|
[294] | 893 | \f[ |
---|
| 894 | x \sim \frac{1}{x\sigma\sqrt{2\pi}}\exp{-\frac{1}{2\sigma^2}(\log(x)-\mu)} |
---|
| 895 | \f] |
---|
| 896 | |
---|
| 897 | */ |
---|
| 898 | class elognorm: public enorm<ldmat> |
---|
| 899 | { |
---|
| 900 | public: |
---|
| 901 | vec sample() const {return exp ( enorm<ldmat>::sample() );}; |
---|
| 902 | vec mean() const {vec var=enorm<ldmat>::variance();return exp ( mu - 0.5*var );}; |
---|
| 903 | |
---|
[270] | 904 | }; |
---|
[285] | 905 | |
---|
[294] | 906 | /*! |
---|
| 907 | \brief Log-Normal random walk |
---|
[285] | 908 | |
---|
[294] | 909 | Mean value, \f$\mu\f$, is... |
---|
[285] | 910 | |
---|
[294] | 911 | ==== Check == vv = |
---|
| 912 | Standard deviation of the random walk is proportional to one \f$k\f$-th the mean. |
---|
| 913 | This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$. |
---|
[285] | 914 | |
---|
[294] | 915 | The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$. |
---|
| 916 | */ |
---|
| 917 | class mlognorm : public mpdf |
---|
| 918 | { |
---|
| 919 | protected: |
---|
[461] | 920 | shared_ptr<elognorm> eno; |
---|
| 921 | |
---|
[294] | 922 | //! parameter 1/2*sigma^2 |
---|
| 923 | double sig2; |
---|
[461] | 924 | |
---|
[294] | 925 | //! access |
---|
| 926 | vec μ |
---|
| 927 | public: |
---|
| 928 | //! Constructor |
---|
[461] | 929 | mlognorm():eno(new elognorm()), |
---|
| 930 | sig2(0), |
---|
| 931 | mu(eno->_mu()) { |
---|
| 932 | set_ep(eno); |
---|
| 933 | } |
---|
| 934 | |
---|
[294] | 935 | //! Set value of \c k |
---|
| 936 | void set_parameters ( int size, double k ) |
---|
| 937 | { |
---|
| 938 | sig2 = 0.5*log ( k*k+1 ); |
---|
[461] | 939 | eno->set_parameters ( zeros ( size ),2*sig2*eye ( size ) ); |
---|
[285] | 940 | |
---|
[294] | 941 | dimc = size; |
---|
| 942 | }; |
---|
[285] | 943 | |
---|
[294] | 944 | void condition ( const vec &val ) |
---|
| 945 | { |
---|
| 946 | mu=log ( val )-sig2;//elem_mult ( refl,pow ( val,l ) ); |
---|
| 947 | }; |
---|
[357] | 948 | |
---|
| 949 | /*! UI for mlognorm |
---|
| 950 | |
---|
| 951 | The mlognorm is constructed from a structure with fields: |
---|
| 952 | \code |
---|
| 953 | system = { |
---|
| 954 | type = "mlognorm"; |
---|
| 955 | k = 0.1; // constant k |
---|
| 956 | mu0 = [1., 1.]; |
---|
| 957 | |
---|
| 958 | // == OPTIONAL == |
---|
| 959 | // description of y variables |
---|
| 960 | y = {type="rv"; names=["y", "u"];}; |
---|
| 961 | // description of u variable |
---|
| 962 | u = {type="rv"; names=[];} |
---|
| 963 | }; |
---|
| 964 | \endcode |
---|
| 965 | |
---|
| 966 | */ |
---|
[377] | 967 | void from_setting( const Setting &set ); |
---|
[357] | 968 | |
---|
[377] | 969 | // TODO dodelat void to_setting( Setting &set ) const; |
---|
[357] | 970 | |
---|
[294] | 971 | }; |
---|
[357] | 972 | |
---|
| 973 | UIREGISTER(mlognorm); |
---|
[285] | 974 | |
---|
[294] | 975 | /*! inverse Wishart density defined on Choleski decomposition |
---|
| 976 | |
---|
| 977 | */ |
---|
| 978 | class eWishartCh : public epdf |
---|
| 979 | { |
---|
| 980 | protected: |
---|
| 981 | //! Upper-Triagle of Choleski decomposition of \f$ \Psi \f$ |
---|
| 982 | chmat Y; |
---|
| 983 | //! dimension of matrix \f$ \Psi \f$ |
---|
| 984 | int p; |
---|
| 985 | //! degrees of freedom \f$ \nu \f$ |
---|
| 986 | double delta; |
---|
| 987 | public: |
---|
| 988 | void set_parameters ( const mat &Y0, const double delta0 ) {Y=chmat ( Y0 );delta=delta0; p=Y.rows(); dim = p*p; } |
---|
| 989 | mat sample_mat() const |
---|
| 990 | { |
---|
| 991 | mat X=zeros ( p,p ); |
---|
| 992 | |
---|
| 993 | //sample diagonal |
---|
| 994 | for ( int i=0;i<p;i++ ) |
---|
| 995 | { |
---|
| 996 | GamRNG.setup ( 0.5* ( delta-i ) , 0.5 ); // no +1 !! index if from 0 |
---|
| 997 | #pragma omp critical |
---|
| 998 | X ( i,i ) =sqrt ( GamRNG() ); |
---|
| 999 | } |
---|
| 1000 | //do the rest |
---|
| 1001 | for ( int i=0;i<p;i++ ) |
---|
| 1002 | { |
---|
| 1003 | for ( int j=i+1;j<p;j++ ) |
---|
| 1004 | { |
---|
| 1005 | #pragma omp critical |
---|
| 1006 | X ( i,j ) =NorRNG.sample(); |
---|
| 1007 | } |
---|
| 1008 | } |
---|
| 1009 | return X*Y._Ch();// return upper triangular part of the decomposition |
---|
| 1010 | } |
---|
| 1011 | vec sample () const |
---|
| 1012 | { |
---|
| 1013 | return vec ( sample_mat()._data(),p*p ); |
---|
| 1014 | } |
---|
| 1015 | //! fast access function y0 will be copied into Y.Ch. |
---|
| 1016 | void setY ( const mat &Ch0 ) {copy_vector ( dim,Ch0._data(), Y._Ch()._data() );} |
---|
| 1017 | //! fast access function y0 will be copied into Y.Ch. |
---|
| 1018 | void _setY ( const vec &ch0 ) {copy_vector ( dim, ch0._data(), Y._Ch()._data() ); } |
---|
| 1019 | //! access function |
---|
| 1020 | const chmat& getY()const {return Y;} |
---|
| 1021 | }; |
---|
| 1022 | |
---|
| 1023 | class eiWishartCh: public epdf |
---|
| 1024 | { |
---|
| 1025 | protected: |
---|
| 1026 | eWishartCh W; |
---|
| 1027 | int p; |
---|
| 1028 | double delta; |
---|
| 1029 | public: |
---|
| 1030 | void set_parameters ( const mat &Y0, const double delta0) { |
---|
| 1031 | delta = delta0; |
---|
| 1032 | W.set_parameters ( inv ( Y0 ),delta0 ); |
---|
| 1033 | dim = W.dimension(); p=Y0.rows(); |
---|
| 1034 | } |
---|
| 1035 | vec sample() const {mat iCh; iCh=inv ( W.sample_mat() ); return vec ( iCh._data(),dim );} |
---|
| 1036 | void _setY ( const vec &y0 ) |
---|
| 1037 | { |
---|
| 1038 | mat Ch ( p,p ); |
---|
| 1039 | mat iCh ( p,p ); |
---|
| 1040 | copy_vector ( dim, y0._data(), Ch._data() ); |
---|
| 1041 | |
---|
| 1042 | iCh=inv ( Ch ); |
---|
| 1043 | W.setY ( iCh ); |
---|
| 1044 | } |
---|
| 1045 | virtual double evallog ( const vec &val ) const { |
---|
| 1046 | chmat X(p); |
---|
| 1047 | const chmat& Y=W.getY(); |
---|
| 1048 | |
---|
| 1049 | copy_vector(p*p,val._data(),X._Ch()._data()); |
---|
| 1050 | chmat iX(p);X.inv(iX); |
---|
| 1051 | // compute |
---|
| 1052 | // \frac{ |\Psi|^{m/2}|X|^{-(m+p+1)/2}e^{-tr(\Psi X^{-1})/2} }{ 2^{mp/2}\Gamma_p(m/2)}, |
---|
| 1053 | mat M=Y.to_mat()*iX.to_mat(); |
---|
| 1054 | |
---|
| 1055 | double log1 = 0.5*p*(2*Y.logdet())-0.5*(delta+p+1)*(2*X.logdet())-0.5*trace(M); |
---|
| 1056 | //Fixme! Multivariate gamma omitted!! it is ok for sampling, but not otherwise!! |
---|
| 1057 | |
---|
| 1058 | /* if (0) { |
---|
| 1059 | mat XX=X.to_mat(); |
---|
| 1060 | mat YY=Y.to_mat(); |
---|
| 1061 | |
---|
| 1062 | double log2 = 0.5*p*log(det(YY))-0.5*(delta+p+1)*log(det(XX))-0.5*trace(YY*inv(XX)); |
---|
| 1063 | cout << log1 << "," << log2 << endl; |
---|
| 1064 | }*/ |
---|
| 1065 | return log1; |
---|
| 1066 | }; |
---|
[285] | 1067 | |
---|
[294] | 1068 | }; |
---|
[285] | 1069 | |
---|
[294] | 1070 | class rwiWishartCh : public mpdf |
---|
| 1071 | { |
---|
| 1072 | protected: |
---|
[461] | 1073 | shared_ptr<eiWishartCh> eiW; |
---|
[294] | 1074 | //!square root of \f$ \nu-p-1 \f$ - needed for computation of \f$ \Psi \f$ from conditions |
---|
| 1075 | double sqd; |
---|
| 1076 | //reference point for diagonal |
---|
| 1077 | vec refl; |
---|
| 1078 | double l; |
---|
| 1079 | int p; |
---|
[461] | 1080 | |
---|
[294] | 1081 | public: |
---|
[461] | 1082 | rwiWishartCh():eiW(new eiWishartCh()), |
---|
| 1083 | sqd(0), l(0), p(0) { |
---|
| 1084 | set_ep(eiW); |
---|
| 1085 | } |
---|
| 1086 | |
---|
[294] | 1087 | void set_parameters ( int p0, double k, vec ref0, double l0 ) |
---|
| 1088 | { |
---|
| 1089 | p=p0; |
---|
| 1090 | double delta = 2/(k*k)+p+3; |
---|
| 1091 | sqd=sqrt ( delta-p-1 ); |
---|
| 1092 | l=l0; |
---|
| 1093 | refl=pow(ref0,1-l); |
---|
| 1094 | |
---|
[461] | 1095 | eiW->set_parameters ( eye ( p ),delta ); |
---|
| 1096 | dimc=eiW->dimension(); |
---|
[294] | 1097 | } |
---|
| 1098 | void condition ( const vec &c ) { |
---|
| 1099 | vec z=c; |
---|
| 1100 | int ri=0; |
---|
| 1101 | for(int i=0;i<p*p;i+=(p+1)){//trace diagonal element |
---|
| 1102 | z(i) = pow(z(i),l)*refl(ri); |
---|
| 1103 | ri++; |
---|
| 1104 | } |
---|
[285] | 1105 | |
---|
[461] | 1106 | eiW->_setY ( sqd*z ); |
---|
[294] | 1107 | } |
---|
| 1108 | }; |
---|
[285] | 1109 | |
---|
[32] | 1110 | //! Switch between various resampling methods. |
---|
[294] | 1111 | enum RESAMPLING_METHOD { MULTINOMIAL = 0, STRATIFIED = 1, SYSTEMATIC = 3 }; |
---|
| 1112 | /*! |
---|
| 1113 | \brief Weighted empirical density |
---|
[32] | 1114 | |
---|
[294] | 1115 | Used e.g. in particle filters. |
---|
| 1116 | */ |
---|
| 1117 | class eEmp: public epdf |
---|
| 1118 | { |
---|
| 1119 | protected : |
---|
| 1120 | //! Number of particles |
---|
| 1121 | int n; |
---|
| 1122 | //! Sample weights \f$w\f$ |
---|
| 1123 | vec w; |
---|
| 1124 | //! Samples \f$x^{(i)}, i=1..n\f$ |
---|
| 1125 | Array<vec> samples; |
---|
| 1126 | public: |
---|
| 1127 | //! \name Constructors |
---|
| 1128 | //!@{ |
---|
| 1129 | eEmp ( ) :epdf ( ),w ( ),samples ( ) {}; |
---|
[384] | 1130 | //! copy constructor |
---|
[294] | 1131 | eEmp ( const eEmp &e ) : epdf ( e ), w ( e.w ), samples ( e.samples ) {}; |
---|
| 1132 | //!@} |
---|
[280] | 1133 | |
---|
[294] | 1134 | //! Set samples and weights |
---|
| 1135 | void set_statistics ( const vec &w0, const epdf* pdf0 ); |
---|
| 1136 | //! Set samples and weights |
---|
| 1137 | void set_statistics ( const epdf* pdf0 , int n ) {set_statistics ( ones ( n ) /n,pdf0 );}; |
---|
| 1138 | //! Set sample |
---|
| 1139 | void set_samples ( const epdf* pdf0 ); |
---|
| 1140 | //! Set sample |
---|
| 1141 | void set_parameters ( int n0, bool copy=true ) {n=n0; w.set_size ( n0,copy );samples.set_size ( n0,copy );}; |
---|
| 1142 | //! Potentially dangerous, use with care. |
---|
| 1143 | vec& _w() {return w;}; |
---|
| 1144 | //! Potentially dangerous, use with care. |
---|
| 1145 | const vec& _w() const {return w;}; |
---|
| 1146 | //! access function |
---|
| 1147 | Array<vec>& _samples() {return samples;}; |
---|
| 1148 | //! access function |
---|
| 1149 | const Array<vec>& _samples() const {return samples;}; |
---|
| 1150 | //! Function performs resampling, i.e. removal of low-weight samples and duplication of high-weight samples such that the new samples represent the same density. |
---|
| 1151 | ivec resample ( RESAMPLING_METHOD method=SYSTEMATIC ); |
---|
| 1152 | //! inherited operation : NOT implemneted |
---|
| 1153 | vec sample() const {it_error ( "Not implemented" );return 0;} |
---|
| 1154 | //! inherited operation : NOT implemneted |
---|
| 1155 | double evallog ( const vec &val ) const {it_error ( "Not implemented" );return 0.0;} |
---|
| 1156 | vec mean() const |
---|
| 1157 | { |
---|
| 1158 | vec pom=zeros ( dim ); |
---|
| 1159 | for ( int i=0;i<n;i++ ) {pom+=samples ( i ) *w ( i );} |
---|
| 1160 | return pom; |
---|
[283] | 1161 | } |
---|
[294] | 1162 | vec variance() const |
---|
| 1163 | { |
---|
| 1164 | vec pom=zeros ( dim ); |
---|
| 1165 | for ( int i=0;i<n;i++ ) {pom+=pow ( samples ( i ),2 ) *w ( i );} |
---|
| 1166 | return pom-pow ( mean(),2 ); |
---|
| 1167 | } |
---|
| 1168 | //! For this class, qbounds are minimum and maximum value of the population! |
---|
| 1169 | void qbounds ( vec &lb, vec &ub, double perc=0.95 ) const |
---|
| 1170 | { |
---|
| 1171 | // lb in inf so than it will be pushed below; |
---|
| 1172 | lb.set_size ( dim ); |
---|
| 1173 | ub.set_size ( dim ); |
---|
| 1174 | lb = std::numeric_limits<double>::infinity(); |
---|
| 1175 | ub = -std::numeric_limits<double>::infinity(); |
---|
| 1176 | int j; |
---|
| 1177 | for ( int i=0;i<n;i++ ) |
---|
| 1178 | { |
---|
| 1179 | for ( j=0;j<dim; j++ ) |
---|
| 1180 | { |
---|
| 1181 | if ( samples ( i ) ( j ) <lb ( j ) ) {lb ( j ) =samples ( i ) ( j );} |
---|
| 1182 | if ( samples ( i ) ( j ) >ub ( j ) ) {ub ( j ) =samples ( i ) ( j );} |
---|
| 1183 | } |
---|
| 1184 | } |
---|
| 1185 | } |
---|
| 1186 | }; |
---|
[32] | 1187 | |
---|
| 1188 | |
---|
[8] | 1189 | //////////////////////// |
---|
| 1190 | |
---|
[294] | 1191 | template<class sq_T> |
---|
| 1192 | void enorm<sq_T>::set_parameters ( const vec &mu0, const sq_T &R0 ) |
---|
| 1193 | { |
---|
[28] | 1194 | //Fixme test dimensions of mu0 and R0; |
---|
[294] | 1195 | mu = mu0; |
---|
| 1196 | R = R0; |
---|
[395] | 1197 | validate(); |
---|
[294] | 1198 | }; |
---|
[8] | 1199 | |
---|
[294] | 1200 | template<class sq_T> |
---|
[395] | 1201 | void enorm<sq_T>::from_setting(const Setting &set){ |
---|
| 1202 | epdf::from_setting(set); //reads rv |
---|
[384] | 1203 | |
---|
[471] | 1204 | UI::get(mu,set,"mu", UI::compulsory); |
---|
[395] | 1205 | mat Rtmp;// necessary for conversion |
---|
[471] | 1206 | UI::get(Rtmp,set,"R", UI::compulsory); |
---|
[395] | 1207 | R=Rtmp; // conversion |
---|
| 1208 | validate(); |
---|
[384] | 1209 | } |
---|
| 1210 | |
---|
| 1211 | template<class sq_T> |
---|
[294] | 1212 | void enorm<sq_T>::dupdate ( mat &v, double nu ) |
---|
| 1213 | { |
---|
| 1214 | // |
---|
| 1215 | }; |
---|
[8] | 1216 | |
---|
[178] | 1217 | // template<class sq_T> |
---|
| 1218 | // void enorm<sq_T>::tupdate ( double phi, mat &vbar, double nubar ) { |
---|
| 1219 | // // |
---|
| 1220 | // }; |
---|
[8] | 1221 | |
---|
[294] | 1222 | template<class sq_T> |
---|
| 1223 | vec enorm<sq_T>::sample() const |
---|
| 1224 | { |
---|
| 1225 | vec x ( dim ); |
---|
[270] | 1226 | #pragma omp critical |
---|
[294] | 1227 | NorRNG.sample_vector ( dim,x ); |
---|
| 1228 | vec smp = R.sqrt_mult ( x ); |
---|
[12] | 1229 | |
---|
[294] | 1230 | smp += mu; |
---|
| 1231 | return smp; |
---|
| 1232 | }; |
---|
[8] | 1233 | |
---|
[214] | 1234 | // template<class sq_T> |
---|
| 1235 | // double enorm<sq_T>::eval ( const vec &val ) const { |
---|
| 1236 | // double pdfl,e; |
---|
| 1237 | // pdfl = evallog ( val ); |
---|
| 1238 | // e = exp ( pdfl ); |
---|
| 1239 | // return e; |
---|
| 1240 | // }; |
---|
[8] | 1241 | |
---|
[294] | 1242 | template<class sq_T> |
---|
| 1243 | double enorm<sq_T>::evallog_nn ( const vec &val ) const |
---|
| 1244 | { |
---|
| 1245 | // 1.83787706640935 = log(2pi) |
---|
| 1246 | double tmp=-0.5* ( R.invqform ( mu-val ) );// - lognc(); |
---|
| 1247 | return tmp; |
---|
| 1248 | }; |
---|
[28] | 1249 | |
---|
[294] | 1250 | template<class sq_T> |
---|
| 1251 | inline double enorm<sq_T>::lognc () const |
---|
| 1252 | { |
---|
| 1253 | // 1.83787706640935 = log(2pi) |
---|
| 1254 | double tmp=0.5* ( R.cols() * 1.83787706640935 +R.logdet() ); |
---|
| 1255 | return tmp; |
---|
| 1256 | }; |
---|
[28] | 1257 | |
---|
[294] | 1258 | template<class sq_T> |
---|
| 1259 | void mlnorm<sq_T>::set_parameters ( const mat &A0, const vec &mu0, const sq_T &R0 ) |
---|
| 1260 | { |
---|
| 1261 | it_assert_debug ( A0.rows() ==mu0.length(),"" ); |
---|
| 1262 | it_assert_debug ( A0.rows() ==R0.rows(),"" ); |
---|
[8] | 1263 | |
---|
[461] | 1264 | iepdf->set_parameters(zeros(A0.rows()), R0); |
---|
[294] | 1265 | A = A0; |
---|
| 1266 | mu_const = mu0; |
---|
[461] | 1267 | dimc = A0.cols(); |
---|
[294] | 1268 | } |
---|
[8] | 1269 | |
---|
[192] | 1270 | // template<class sq_T> |
---|
| 1271 | // vec mlnorm<sq_T>::samplecond (const vec &cond, double &lik ) { |
---|
| 1272 | // this->condition ( cond ); |
---|
| 1273 | // vec smp = epdf.sample(); |
---|
| 1274 | // lik = epdf.eval ( smp ); |
---|
| 1275 | // return smp; |
---|
| 1276 | // } |
---|
[8] | 1277 | |
---|
[192] | 1278 | // template<class sq_T> |
---|
| 1279 | // mat mlnorm<sq_T>::samplecond (const vec &cond, vec &lik, int n ) { |
---|
| 1280 | // int i; |
---|
| 1281 | // int dim = rv.count(); |
---|
| 1282 | // mat Smp ( dim,n ); |
---|
| 1283 | // vec smp ( dim ); |
---|
| 1284 | // this->condition ( cond ); |
---|
[198] | 1285 | // |
---|
[192] | 1286 | // for ( i=0; i<n; i++ ) { |
---|
| 1287 | // smp = epdf.sample(); |
---|
| 1288 | // lik ( i ) = epdf.eval ( smp ); |
---|
| 1289 | // Smp.set_col ( i ,smp ); |
---|
| 1290 | // } |
---|
[198] | 1291 | // |
---|
[192] | 1292 | // return Smp; |
---|
| 1293 | // } |
---|
[28] | 1294 | |
---|
[294] | 1295 | template<class sq_T> |
---|
| 1296 | void mlnorm<sq_T>::condition ( const vec &cond ) |
---|
| 1297 | { |
---|
| 1298 | _mu = A*cond + mu_const; |
---|
[12] | 1299 | //R is already assigned; |
---|
[294] | 1300 | } |
---|
[8] | 1301 | |
---|
[294] | 1302 | template<class sq_T> |
---|
[299] | 1303 | enorm<sq_T>* enorm<sq_T>::marginal ( const RV &rvn ) const |
---|
[294] | 1304 | { |
---|
| 1305 | it_assert_debug ( isnamed(), "rv description is not assigned" ); |
---|
| 1306 | ivec irvn = rvn.dataind ( rv ); |
---|
[178] | 1307 | |
---|
[294] | 1308 | sq_T Rn ( R,irvn ); //select rows and columns of R |
---|
[280] | 1309 | |
---|
[294] | 1310 | enorm<sq_T>* tmp = new enorm<sq_T>; |
---|
| 1311 | tmp->set_rv ( rvn ); |
---|
| 1312 | tmp->set_parameters ( mu ( irvn ), Rn ); |
---|
| 1313 | return tmp; |
---|
| 1314 | } |
---|
[178] | 1315 | |
---|
[294] | 1316 | template<class sq_T> |
---|
| 1317 | mpdf* enorm<sq_T>::condition ( const RV &rvn ) const |
---|
| 1318 | { |
---|
[178] | 1319 | |
---|
[294] | 1320 | it_assert_debug ( isnamed(),"rvs are not assigned" ); |
---|
[270] | 1321 | |
---|
[294] | 1322 | RV rvc = rv.subt ( rvn ); |
---|
| 1323 | it_assert_debug ( ( rvc._dsize() +rvn._dsize() ==rv._dsize() ),"wrong rvn" ); |
---|
| 1324 | //Permutation vector of the new R |
---|
| 1325 | ivec irvn = rvn.dataind ( rv ); |
---|
| 1326 | ivec irvc = rvc.dataind ( rv ); |
---|
| 1327 | ivec perm=concat ( irvn , irvc ); |
---|
| 1328 | sq_T Rn ( R,perm ); |
---|
[178] | 1329 | |
---|
[294] | 1330 | //fixme - could this be done in general for all sq_T? |
---|
| 1331 | mat S=Rn.to_mat(); |
---|
| 1332 | //fixme |
---|
| 1333 | int n=rvn._dsize()-1; |
---|
| 1334 | int end=R.rows()-1; |
---|
| 1335 | mat S11 = S.get ( 0,n, 0, n ); |
---|
| 1336 | mat S12 = S.get ( 0, n , rvn._dsize(), end ); |
---|
| 1337 | mat S22 = S.get ( rvn._dsize(), end, rvn._dsize(), end ); |
---|
[178] | 1338 | |
---|
[294] | 1339 | vec mu1 = mu ( irvn ); |
---|
| 1340 | vec mu2 = mu ( irvc ); |
---|
| 1341 | mat A=S12*inv ( S22 ); |
---|
| 1342 | sq_T R_n ( S11 - A *S12.T() ); |
---|
[178] | 1343 | |
---|
[294] | 1344 | mlnorm<sq_T>* tmp=new mlnorm<sq_T> ( ); |
---|
| 1345 | tmp->set_rv ( rvn ); tmp->set_rvc ( rvc ); |
---|
| 1346 | tmp->set_parameters ( A,mu1-A*mu2,R_n ); |
---|
| 1347 | return tmp; |
---|
| 1348 | } |
---|
[178] | 1349 | |
---|
[28] | 1350 | /////////// |
---|
| 1351 | |
---|
[294] | 1352 | template<class sq_T> |
---|
| 1353 | std::ostream &operator<< ( std::ostream &os, mlnorm<sq_T> &ml ) |
---|
| 1354 | { |
---|
| 1355 | os << "A:"<< ml.A<<endl; |
---|
| 1356 | os << "mu:"<< ml.mu_const<<endl; |
---|
[461] | 1357 | os << "R:" << ml.iepdf->_R().to_mat() <<endl; |
---|
[294] | 1358 | return os; |
---|
| 1359 | }; |
---|
[28] | 1360 | |
---|
[254] | 1361 | } |
---|
[8] | 1362 | #endif //EF_H |
---|