root/library/bdm/stat/exp_family.h @ 795

Revision 795, 41.5 kB (checked in by mido, 14 years ago)

validate() finally included into UI::build mechanism and removed from some from_setting methods,
from that point StateDS test does not pass, I do not understand why

  • Property svn:eol-style set to native
RevLine 
[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
[737]21namespace bdm {
[8]22
[32]23
24//! Global Uniform_RNG
[488]25extern Uniform_RNG UniRNG;
[33]26//! Global Normal_RNG
[488]27extern Normal_RNG NorRNG;
[33]28//! Global Gamma_RNG
[488]29extern Gamma_RNG GamRNG;
[32]30
[488]31/*!
32* \brief General conjugate exponential family posterior density.
[8]33
[488]34* More?...
35*/
[28]36
[737]37class eEF : public epdf {
38public:
[32]39//      eEF() :epdf() {};
[737]40        //! default constructor
41        eEF () : epdf () {};
42        //! logarithm of the normalizing constant, \f$\mathcal{I}\f$
43        virtual double lognc() const = 0;
[565]44
[737]45        //!Evaluate normalized log-probability
[766]46        virtual double evallog_nn ( const vec &val ) const NOT_IMPLEMENTED(0);
[565]47
[737]48        //!Evaluate normalized log-probability
49        virtual double evallog ( const vec &val ) const {
50                double tmp;
51                tmp = evallog_nn ( val ) - lognc();
52                return tmp;
53        }
54        //!Evaluate normalized log-probability for many samples
55        virtual vec evallog_mat ( const mat &Val ) const {
56                vec x ( Val.cols() );
57                for ( int i = 0; i < Val.cols(); i++ ) {
58                        x ( i ) = evallog_nn ( Val.get_col ( i ) ) ;
[488]59                }
[737]60                return x - lognc();
61        }
62        //!Evaluate normalized log-probability for many samples
63        virtual vec evallog_mat ( const Array<vec> &Val ) const {
64                vec x ( Val.length() );
65                for ( int i = 0; i < Val.length(); i++ ) {
66                        x ( i ) = evallog_nn ( Val ( i ) ) ;
[488]67                }
[737]68                return x - lognc();
69        }
[565]70
[737]71        //!Power of the density, used e.g. to flatten the density
[766]72        virtual void pow ( double p ) NOT_IMPLEMENTED_VOID;
[488]73};
[8]74
[33]75
[170]76//! Estimator for Exponential family
[737]77class BMEF : public BM {
78protected:
79        //! forgetting factor
80        double frg;
81        //! cached value of lognc() in the previous step (used in evaluation of \c ll )
82        double last_lognc;
83public:
84        //! Default constructor (=empty constructor)
85        BMEF ( double frg0 = 1.0 ) : BM (), frg ( frg0 ) {}
86        //! Copy constructor
87        BMEF ( const BMEF &B ) : BM ( B ), frg ( B.frg ), last_lognc ( B.last_lognc ) {}
88        //!get statistics from another model
[766]89        virtual void set_statistics ( const BMEF* BM0 ) NOT_IMPLEMENTED_VOID;
[565]90
[737]91        //! Weighted update of sufficient statistics (Bayes rule)
92        virtual void bayes_weighted ( const vec &data, const vec &cond = empty_vec, const double w = 1.0 ) {};
93        //original Bayes
94        void bayes ( const vec &yt, const vec &cond = empty_vec );
[565]95
[737]96        //!Flatten the posterior according to the given BMEF (of the same type!)
[766]97        virtual void flatten ( const BMEF * B ) NOT_IMPLEMENTED_VOID;
[198]98
[766]99        double logpred ( const vec &yt ) const NOT_IMPLEMENTED(0);
100       
101        virtual epdf* epredictor() const NOT_IMPLEMENTED(NULL);
[746]102
[766]103        virtual pdf* predictor() const NOT_IMPLEMENTED(NULL);
104
[746]105        void to_setting ( Setting &set ) const
106        {                       
107                BM::to_setting( set );
[766]108                // TODO DOPLNIT? ALE MOMENTALNE CHYBI FROM_SETTING PRO INSPIRACI
[746]109        } 
[488]110};
[170]111
[504]112template<class sq_T, template <typename> class TEpdf>
[488]113class mlnorm;
[178]114
[488]115/*!
116* \brief Gaussian density with positive definite (decomposed) covariance matrix.
[8]117
[488]118* More?...
119*/
120template<class sq_T>
[737]121class enorm : public eEF {
122protected:
123        //! mean value
124        vec mu;
125        //! Covariance matrix in decomposed form
126        sq_T R;
127public:
128        //!\name Constructors
129        //!@{
[270]130
[737]131        enorm () : eEF (), mu (), R () {};
132        enorm ( const vec &mu, const sq_T &R ) {
133                set_parameters ( mu, R );
134        }
135        void set_parameters ( const vec &mu, const sq_T &R );
136        /*! Create Normal density
137        \f[ f(rv) = N(\mu, R) \f]
138        from structure
139        \code
140        class = 'enorm<ldmat>', (OR) 'enorm<chmat>', (OR) 'enorm<fsqmat>';
141        mu    = [];                  // mean value
142        R     = [];                  // variance, square matrix of appropriate dimension
143        \endcode
144        */
145        void from_setting ( const Setting &root );
[773]146        void to_setting ( Setting &root ) const ;
147       
[737]148        void validate() {
149                bdm_assert ( mu.length() == R.rows(), "mu and R parameters do not match" );
150                dim = mu.length();
151        }
152        //!@}
[270]153
[737]154        //! \name Mathematical operations
155        //!@{
[270]156
[737]157        //! dupdate in exponential form (not really handy)
158        void dupdate ( mat &v, double nu = 1.0 );
[28]159
[737]160        vec sample() const;
[450]161
[737]162        double evallog_nn ( const vec &val ) const;
163        double lognc () const;
164        vec mean() const {
165                return mu;
166        }
167        vec variance() const {
168                return diag ( R.to_mat() );
169        }
[299]170//      mlnorm<sq_T>* condition ( const RV &rvn ) const ; <=========== fails to cmpile. Why?
[737]171        shared_ptr<pdf> condition ( const RV &rvn ) const;
[504]172
[737]173        // target not typed to mlnorm<sq_T, enorm<sq_T> > &
174        // because that doesn't compile (perhaps because we
175        // haven't finished defining enorm yet), but the type
176        // is required
177        void condition ( const RV &rvn, pdf &target ) const;
[504]178
[737]179        shared_ptr<epdf> marginal ( const RV &rvn ) const;
180        void marginal ( const RV &rvn, enorm<sq_T> &target ) const;
181        //!@}
[270]182
[737]183        //! \name Access to attributes
184        //!@{
[270]185
[737]186        vec& _mu() {
187                return mu;
188        }
189        const vec& _mu() const {
190                return mu;
191        }
192        void set_mu ( const vec mu0 ) {
193                mu = mu0;
194        }
195        sq_T& _R() {
196                return R;
197        }
198        const sq_T& _R() const {
199                return R;
200        }
201        //!@}
[28]202
[488]203};
[737]204UIREGISTER2 ( enorm, chmat );
[529]205SHAREDPTR2 ( enorm, chmat );
[737]206UIREGISTER2 ( enorm, ldmat );
[529]207SHAREDPTR2 ( enorm, ldmat );
[737]208UIREGISTER2 ( enorm, fsqmat );
[529]209SHAREDPTR2 ( enorm, fsqmat );
[8]210
[388]211
[488]212/*!
213* \brief Gauss-inverse-Wishart density stored in LD form
[96]214
[488]215* For \f$p\f$-variate densities, given rv.count() should be \f$p\times\f$ V.rows().
216*
217*/
[737]218class egiw : public eEF {
219protected:
220        //! Extended information matrix of sufficient statistics
221        ldmat V;
222        //! Number of data records (degrees of freedom) of sufficient statistics
223        double nu;
224        //! Dimension of the output
225        int dimx;
226        //! Dimension of the regressor
227        int nPsi;
228public:
229        //!\name Constructors
230        //!@{
231        egiw() : eEF() {};
232        egiw ( int dimx0, ldmat V0, double nu0 = -1.0 ) : eEF() {
233                set_parameters ( dimx0, V0, nu0 );
234        };
[270]235
[737]236        void set_parameters ( int dimx0, ldmat V0, double nu0 = -1.0 );
237        //!@}
[96]238
[737]239        vec sample() const;
240        mat sample_mat ( int n ) const;
241        vec mean() const;
242        vec variance() const;
243        void sample_mat ( mat &Mi, chmat &Ri ) const;
[330]244
[737]245        void factorize ( mat &M, ldmat &Vz, ldmat &Lam ) const;
246        //! LS estimate of \f$\theta\f$
247        vec est_theta() const;
[330]248
[737]249        //! Covariance of the LS estimate
250        ldmat est_theta_cov() const;
[96]251
[737]252        //! expected values of the linear coefficient and the covariance matrix are written to \c M and \c R , respectively
253        void mean_mat ( mat &M, mat&R ) const;
254        //! In this instance, val= [theta, r]. For multivariate instances, it is stored columnwise val = [theta_1 theta_2 ... r_1 r_2 ]
255        double evallog_nn ( const vec &val ) const;
256        double lognc () const;
257        void pow ( double p ) {
258                V *= p;
259                nu *= p;
260        };
[270]261
[737]262        //! \name Access attributes
263        //!@{
264
265        ldmat& _V() {
266                return V;
267        }
268        const ldmat& _V() const {
269                return V;
270        }
271        double& _nu()  {
272                return nu;
273        }
274        const double& _nu() const {
275                return nu;
276        }
277        const int & _dimx() const {
278                return dimx;
279        }
280
281        /*! Create Gauss-inverse-Wishart density
282        \f[ f(rv) = GiW(V,\nu) \f]
283        from structure
284        \code
285        class = 'egiw';
286        V     = [];               // square matrix
287        dV    = [];               // vector of diagonal of V (when V not given)
288        nu    = [];               // scalar \nu ((almost) degrees of freedom)
289                                                          // when missing, it will be computed to obtain proper pdf
290        dimx  = [];               // dimension of the wishart part
291        rv = RV({'name'})         // description of RV
292        rvc = RV({'name'})        // description of RV in condition
293        \endcode
294        */
295
296        void from_setting ( const Setting &set ) {
297                epdf::from_setting ( set );
298                UI::get ( dimx, set, "dimx", UI::compulsory );
299                if ( !UI::get ( nu, set, "nu", UI::optional ) ) {
300                        nu = -1;
[488]301                }
[737]302                mat V;
303                if ( !UI::get ( V, set, "V", UI::optional ) ) {
304                        vec dV;
305                        UI::get ( dV, set, "dV", UI::compulsory );
306                        set_parameters ( dimx, ldmat ( dV ), nu );
307
308                } else {
309                        set_parameters ( dimx, V, nu );
[665]310                }
[737]311        }
312
313        void to_setting ( Setting& set ) const {
314                epdf::to_setting ( set );
315                string s ( "egiw" );
316                UI::save ( s, set, "class" );
317                UI::save ( dimx, set, "dimx" );
318                UI::save ( V.to_mat(), set, "V" );
319                UI::save ( nu, set, "nu" );
320        };
321
322        void validate() {
323                // check sizes, rvs etc.
324        }
[739]325        void log_register ( bdm::logger& L, const string& prefix );
[737]326
[739]327        void log_write() const;
[737]328        //!@}
[488]329};
[529]330UIREGISTER ( egiw );
331SHAREDPTR ( egiw );
[96]332
[488]333/*! \brief Dirichlet posterior density
[173]334
[488]335Continuous Dirichlet density of \f$n\f$-dimensional variable \f$x\f$
336\f[
337f(x|\beta) = \frac{\Gamma[\gamma]}{\prod_{i=1}^{n}\Gamma(\beta_i)} \prod_{i=1}^{n}x_i^{\beta_i-1}
338\f]
339where \f$\gamma=\sum_i \beta_i\f$.
340*/
[737]341class eDirich: public eEF {
342protected:
343        //!sufficient statistics
344        vec beta;
345public:
346        //!\name Constructors
347        //!@{
[270]348
[737]349        eDirich () : eEF () {};
350        eDirich ( const eDirich &D0 ) : eEF () {
351                set_parameters ( D0.beta );
352        };
353        eDirich ( const vec &beta0 ) {
354                set_parameters ( beta0 );
355        };
356        void set_parameters ( const vec &beta0 ) {
357                beta = beta0;
358                dim = beta.length();
359        }
360        //!@}
[270]361
[737]362        //! using sampling procedure from wikipedia
363        vec sample() const {
364                vec y ( beta.length() );
365                for ( int i = 0; i < beta.length(); i++ ) {
366                        GamRNG.setup ( beta ( i ), 1 );
367#pragma omp critical
368                        y ( i ) = GamRNG();
[565]369                }
[737]370                return y / sum ( y );
371        }
[565]372
[737]373        vec mean() const {
374                return beta / sum ( beta );
375        };
376        vec variance() const {
377                double gamma = sum ( beta );
378                return elem_mult ( beta, ( gamma - beta ) ) / ( gamma*gamma* ( gamma + 1 ) );
379        }
380        //! In this instance, val is ...
381        double evallog_nn ( const vec &val ) const {
382                double tmp;
383                tmp = ( beta - 1 ) * log ( val );
384                return tmp;
385        }
[565]386
[737]387        double lognc () const {
388                double tmp;
389                double gam = sum ( beta );
390                double lgb = 0.0;
391                for ( int i = 0; i < beta.length(); i++ ) {
392                        lgb += lgamma ( beta ( i ) );
[565]393                }
[737]394                tmp = lgb - lgamma ( gam );
395                return tmp;
396        }
[565]397
[737]398        //!access function
399        vec& _beta()  {
400                return beta;
401        }
402        /*! configuration structure
403        \code
404        class = 'eDirich';
405        beta  = [];           //parametr beta
406        \endcode
407        */
408        void from_setting ( const Setting &set ) {
409                epdf::from_setting ( set );
410                UI::get ( beta, set, "beta", UI::compulsory );
411                validate();
412        }
413        void validate() {
414                //check rv
415                dim = beta.length();
416        }
[746]417
418        void to_setting ( Setting &set ) const
419        {                       
420                eEF::to_setting( set );
421                UI::save( beta, set, "beta" );
422        } 
[488]423};
[737]424UIREGISTER ( eDirich );
[96]425
[637]426/*! Random Walk on Dirichlet
[737]427Using simple assignment
[637]428 \f[ \beta = rvc / k + \beta_c \f]
429 hence, mean value = rvc, variance = (k+1)*mean*mean;
[737]430
[637]431 The greater k is, the greater is the variance of the random walk;
[737]432
[637]433 \f$ \beta_c \f$ is used as regularizing element to avoid corner cases, i.e. when one element of rvc is zero.
434 By default is it set to 0.1;
435*/
436
[693]437class mDirich: public pdf_internal<eDirich> {
[737]438protected:
439        //! constant \f$ k \f$ of the random walk
440        double k;
441        //! cache of beta_i
442        vec &_beta;
443        //! stabilizing coefficient \f$ \beta_c \f$
444        vec betac;
445public:
446        mDirich() : pdf_internal<eDirich>(), _beta ( iepdf._beta() ) {};
447        void condition ( const vec &val ) {
448                _beta =  val / k + betac;
449        };
450        /*! Create Dirichlet random walk
451        \f[ f(rv|rvc) = Di(rvc*k) \f]
452        from structure
453        \code
454        class = 'mDirich';
455        k = 1;                      // multiplicative constant k
456        --- optional ---
457        rv = RV({'name'},size)      // description of RV
458        beta0 = [];                 // initial value of beta
459        betac = [];                 // initial value of beta
460        \endcode
461        */
462        void from_setting ( const Setting &set ) {
463                pdf::from_setting ( set ); // reads rv and rvc
464                if ( _rv()._dsize() > 0 ) {
465                        rvc = _rv().copy_t ( -1 );
[637]466                }
[737]467                vec beta0;
468                if ( !UI::get ( beta0, set, "beta0", UI::optional ) ) {
469                        beta0 = ones ( _rv()._dsize() );
470                }
471                if ( !UI::get ( betac, set, "betac", UI::optional ) ) {
472                        betac = 0.1 * ones ( _rv()._dsize() );
473                }
474                _beta = beta0;
475
476                UI::get ( k, set, "k", UI::compulsory );
477                validate();
478        }
479        void validate() {
480                pdf_internal<eDirich>::validate();
481                bdm_assert ( _beta.length() == betac.length(), "beta0 and betac are not compatible" );
482                if ( _rv()._dsize() > 0 ) {
483                        bdm_assert ( ( _rv()._dsize() == dimension() ) , "Size of rv does not match with beta" );
484                }
485                dimc = _beta.length();
486        };
[637]487};
[737]488UIREGISTER ( mDirich );
[637]489
[181]490//! \brief Estimator for Multinomial density
[737]491class multiBM : public BMEF {
492protected:
493        //! Conjugate prior and posterior
494        eDirich est;
495        //! Pointer inside est to sufficient statistics
496        vec &beta;
497public:
498        //!Default constructor
499        multiBM () : BMEF (), est (), beta ( est._beta() ) {
500                if ( beta.length() > 0 ) {
501                        last_lognc = est.lognc();
502                } else {
503                        last_lognc = 0.0;
[488]504                }
[737]505        }
506        //!Copy constructor
507        multiBM ( const multiBM &B ) : BMEF ( B ), est ( B.est ), beta ( est._beta() ) {}
508        //! Sets sufficient statistics to match that of givefrom mB0
509        void set_statistics ( const BM* mB0 ) {
510                const multiBM* mB = dynamic_cast<const multiBM*> ( mB0 );
511                beta = mB->beta;
512        }
[739]513        void bayes ( const vec &yt, const vec &cond = empty_vec );
[176]514
[739]515        double logpred ( const vec &yt ) const;
[170]516
[739]517        void flatten ( const BMEF* B );
518
[737]519        //! return correctly typed posterior (covariant return)
520        const eDirich& posterior() const {
521                return est;
522        };
523        //! constructor function
524        void set_parameters ( const vec &beta0 ) {
525                est.set_parameters ( beta0 );
[741]526                est.validate();
[737]527                if ( evalll ) {
528                        last_lognc = est.lognc();
[488]529                }
[737]530        }
[746]531
[737]532        void to_setting ( Setting &set ) const {
533                BMEF::to_setting ( set );
[746]534                UI::save( &est, set, "prior" );
[737]535        }
[488]536};
[746]537UIREGISTER( multiBM );
[170]538
[488]539/*!
540 \brief Gamma posterior density
[32]541
[488]542 Multivariate Gamma density as product of independent univariate densities.
543 \f[
544 f(x|\alpha,\beta) = \prod f(x_i|\alpha_i,\beta_i)
545 \f]
546*/
[32]547
[737]548class egamma : public eEF {
549protected:
550        //! Vector \f$\alpha\f$
551        vec alpha;
552        //! Vector \f$\beta\f$
553        vec beta;
554public :
555        //! \name Constructors
556        //!@{
557        egamma () : eEF (), alpha ( 0 ), beta ( 0 ) {};
558        egamma ( const vec &a, const vec &b ) {
559                set_parameters ( a, b );
560        };
561        void set_parameters ( const vec &a, const vec &b ) {
562                alpha = a, beta = b;
563                dim = alpha.length();
564        };
565        //!@}
[270]566
[737]567        vec sample() const;
568        double evallog ( const vec &val ) const;
569        double lognc () const;
570        //! Returns pointer to internal alpha. Potentially dengerous: use with care!
571        vec& _alpha() {
572                return alpha;
573        }
574        //! Returns pointer to internal beta. Potentially dengerous: use with care!
575        vec& _beta() {
576                return beta;
577        }
578        vec mean() const {
579                return elem_div ( alpha, beta );
580        }
581        vec variance() const {
582                return elem_div ( alpha, elem_mult ( beta, beta ) );
583        }
[225]584
[737]585        /*! Create Gamma density
586        \f[ f(rv|rvc) = \Gamma(\alpha, \beta) \f]
587        from structure
588        \code
589        class = 'egamma';
590        alpha = [...];         // vector of alpha
591        beta = [...];          // vector of beta
592        rv = RV({'name'})      // description of RV
593        \endcode
594        */
595        void from_setting ( const Setting &set ) {
596                epdf::from_setting ( set ); // reads rv
597                UI::get ( alpha, set, "alpha", UI::compulsory );
598                UI::get ( beta, set, "beta", UI::compulsory );
599                validate();
600        }
601        void validate() {
602                bdm_assert ( alpha.length() == beta.length(), "parameters do not match" );
603                dim = alpha.length();
604        }
[488]605};
[737]606UIREGISTER ( egamma );
[529]607SHAREDPTR ( egamma );
608
[488]609/*!
610 \brief Inverse-Gamma posterior density
[225]611
[488]612 Multivariate inverse-Gamma density as product of independent univariate densities.
613 \f[
614 f(x|\alpha,\beta) = \prod f(x_i|\alpha_i,\beta_i)
615 \f]
[283]616
[488]617Vector \f$\beta\f$ has different meaning (in fact it is 1/beta as used in definition of iG)
[225]618
[488]619 Inverse Gamma can be converted to Gamma using \f[
620 x\sim iG(a,b) => 1/x\sim G(a,1/b)
621\f]
622This relation is used in sampling.
623 */
[270]624
[737]625class eigamma : public egamma {
626protected:
627public :
628        //! \name Constructors
629        //! All constructors are inherited
630        //!@{
631        //!@}
[32]632
[737]633        vec sample() const {
634                return 1.0 / egamma::sample();
635        };
636        //! Returns poiter to alpha and beta. Potentially dangerous: use with care!
637        vec mean() const {
638                return elem_div ( beta, alpha - 1 );
639        }
640        vec variance() const {
641                vec mea = mean();
642                return elem_div ( elem_mult ( mea, mea ), alpha - 2 );
643        }
[488]644};
645/*
646//! Weighted mixture of epdfs with external owned components.
647class emix : public epdf {
648protected:
649        int n;
650        vec &w;
651        Array<epdf*> Coms;
652public:
653//! Default constructor
654        emix ( const RV &rv, vec &w0): epdf(rv), n(w0.length()), w(w0), Coms(n) {};
655        void set_parameters( int &i, double wi, epdf* ep){w(i)=wi;Coms(i)=ep;}
656        vec mean(){vec pom; for(int i=0;i<n;i++){pom+=Coms(i)->mean()*w(i);} return pom;};
657};
658*/
659
[32]660//!  Uniform distributed density on a rectangular support
661
[737]662class euni: public epdf {
663protected:
[32]664//! lower bound on support
[737]665        vec low;
[32]666//! upper bound on support
[737]667        vec high;
[32]668//! internal
[737]669        vec distance;
[32]670//! normalizing coefficients
[737]671        double nk;
[33]672//! cache of log( \c nk )
[737]673        double lnk;
674public:
675        //! \name Constructors
676        //!@{
677        euni () : epdf () {}
678        euni ( const vec &low0, const vec &high0 ) {
679                set_parameters ( low0, high0 );
680        }
681        void set_parameters ( const vec &low0, const vec &high0 ) {
682                distance = high0 - low0;
683                low = low0;
684                high = high0;
685                nk = prod ( 1.0 / distance );
686                lnk = log ( nk );
687                dim = low.length();
688        }
689        //!@}
[270]690
[737]691        double evallog ( const vec &val ) const  {
692                if ( any ( val < low ) && any ( val > high ) ) {
693                        return -inf;
694                } else return lnk;
695        }
696        vec sample() const {
697                vec smp ( dim );
[270]698#pragma omp critical
[737]699                UniRNG.sample_vector ( dim , smp );
700                return low + elem_mult ( distance, smp );
701        }
702        //! set values of \c low and \c high
703        vec mean() const {
704                return ( high - low ) / 2.0;
705        }
706        vec variance() const {
707                return ( pow ( high, 2 ) + pow ( low, 2 ) + elem_mult ( high, low ) ) / 3.0;
708        }
709        /*! Create Uniform density
710        \f[ f(rv) = U(low,high) \f]
711        from structure
712         \code
713         class = 'euni'
714         high = [...];          // vector of upper bounds
715         low = [...];           // vector of lower bounds
716         rv = RV({'name'});     // description of RV
717         \endcode
718         */
719        void from_setting ( const Setting &set ) {
720                epdf::from_setting ( set ); // reads rv and rvc
[471]721
[737]722                UI::get ( high, set, "high", UI::compulsory );
723                UI::get ( low, set, "low", UI::compulsory );
724                set_parameters ( low, high );
725                validate();
726        }
727        void validate() {
728                bdm_assert ( high.length() == low.length(), "Incompatible high and low vectors" );
729                dim = high.length();
730                bdm_assert ( min ( distance ) > 0.0, "bad support" );
731        }
[488]732};
[737]733UIREGISTER ( euni );
[32]734
[665]735//! Uniform density with conditional mean value
[737]736class mguni : public pdf_internal<euni> {
[665]737        //! function of the mean value
738        shared_ptr<fnc> mean;
739        //! distance from mean to both sides
740        vec delta;
[737]741public:
742        void condition ( const vec &cond ) {
743                vec mea = mean->eval ( cond );
744                iepdf.set_parameters ( mea - delta, mea + delta );
745        }
746        //! load from
747        void from_setting ( const Setting &set ) {
748                pdf::from_setting ( set ); //reads rv and rvc
749                UI::get ( delta, set, "delta", UI::compulsory );
750                mean = UI::build<fnc> ( set, "mean", UI::compulsory );
751
752                iepdf.set_parameters ( -delta, delta );
753                dimc = mean->dimensionc();
754                validate();
755        }
[665]756};
[737]757UIREGISTER ( mguni );
[488]758/*!
759 \brief Normal distributed linear function with linear function of mean value;
[32]760
[536]761 Mean value \f$ \mu=A*\mbox{rvc}+\mu_0 \f$.
[488]762*/
763template < class sq_T, template <typename> class TEpdf = enorm >
[737]764class mlnorm : public pdf_internal< TEpdf<sq_T> > {
765protected:
766        //! Internal epdf that arise by conditioning on \c rvc
767        mat A;
768        //! Constant additive term
769        vec mu_const;
[487]770//                      vec& _mu; //cached epdf.mu; !!!!!! WHY NOT?
[737]771public:
772        //! \name Constructors
773        //!@{
774        mlnorm() : pdf_internal< TEpdf<sq_T> >() {};
775        mlnorm ( const mat &A, const vec &mu0, const sq_T &R ) : pdf_internal< TEpdf<sq_T> >() {
776                set_parameters ( A, mu0, R );
777        }
[461]778
[737]779        //! Set \c A and \c R
780        void set_parameters ( const  mat &A0, const vec &mu0, const sq_T &R0 ) {
781                this->iepdf.set_parameters ( zeros ( A0.rows() ), R0 );
782                A = A0;
783                mu_const = mu0;
784                this->dimc = A0.cols();
785        }
786        //!@}
787        //! Set value of \c rvc . Result of this operation is stored in \c epdf use function \c _ep to access it.
788        void condition ( const vec &cond ) {
789                this->iepdf._mu() = A * cond + mu_const;
[487]790//R is already assigned;
[737]791        }
[198]792
[737]793        //!access function
794        const vec& _mu_const() const {
795                return mu_const;
796        }
797        //!access function
798        const mat& _A() const {
799                return A;
800        }
801        //!access function
802        mat _R() const {
803                return this->iepdf._R().to_mat();
804        }
805        //!access function
806        sq_T __R() const {
807                return this->iepdf._R();
808        }
[8]809
[737]810        //! Debug stream
811        template<typename sq_M>
812        friend std::ostream &operator<< ( std::ostream &os,  mlnorm<sq_M, enorm> &ml );
[488]813
[737]814        /*! Create Normal density with linear function of mean value
815         \f[ f(rv|rvc) = N(A*rvc+const, R) \f]
816        from structure
817        \code
818        class = 'mlnorm<ldmat>', (OR) 'mlnorm<chmat>', (OR) 'mlnorm<fsqmat>';
819        A     = [];                  // matrix or vector of appropriate dimension
820        const = [];                  // vector of constant term
821        R     = [];                  // square matrix of appropriate dimension
822        \endcode
823        */
824        void from_setting ( const Setting &set ) {
825                pdf::from_setting ( set );
826
827                UI::get ( A, set, "A", UI::compulsory );
828                UI::get ( mu_const, set, "const", UI::compulsory );
829                mat R0;
830                UI::get ( R0, set, "R", UI::compulsory );
831                set_parameters ( A, mu_const, R0 );
832                validate();
833        };
[763]834        void to_setting (Setting &set) const {
835                pdf::to_setting(set);
836                UI::save ( A, set, "A");
837                UI::save ( mu_const, set, "const");
838                UI::save ( _R(), set, "R");
839        }
[737]840        void validate() {
841                pdf_internal<TEpdf<sq_T> >::validate();
842                bdm_assert ( A.rows() == mu_const.length(), "mlnorm: A vs. mu mismatch" );
843                bdm_assert ( A.rows() == _R().rows(), "mlnorm: A vs. R mismatch" );
844
845        }
[488]846};
[737]847UIREGISTER2 ( mlnorm, ldmat );
[529]848SHAREDPTR2 ( mlnorm, ldmat );
[737]849UIREGISTER2 ( mlnorm, fsqmat );
[529]850SHAREDPTR2 ( mlnorm, fsqmat );
[737]851UIREGISTER2 ( mlnorm, chmat );
[529]852SHAREDPTR2 ( mlnorm, chmat );
[488]853
[693]854//! pdf with general function for mean value
[488]855template<class sq_T>
[737]856class mgnorm : public pdf_internal< enorm< sq_T > > {
857private:
[487]858//                      vec &mu; WHY NOT?
[737]859        shared_ptr<fnc> g;
[527]860
[737]861public:
862        //!default constructor
863        mgnorm() : pdf_internal<enorm<sq_T> >() { }
864        //!set mean function
865        inline void set_parameters ( const shared_ptr<fnc> &g0, const sq_T &R0 );
866        inline void condition ( const vec &cond );
[357]867
868
[737]869        /*! Create Normal density with given function of mean value
870        \f[ f(rv|rvc) = N( g(rvc), R) \f]
871        from structure
872        \code
873        class = 'mgnorm';
874        g.class =  'fnc';      // function for mean value evolution
875        g._fields_of_fnc = ...;
[357]876
[737]877        R = [1, 0;             // covariance matrix
878                0, 1];
879                --OR --
880        dR = [1, 1];           // diagonal of cavariance matrix
[357]881
[737]882        rv = RV({'name'})      // description of RV
883        rvc = RV({'name'})     // description of RV in condition
884        \endcode
885        */
[357]886
[737]887        void from_setting ( const Setting &set ) {
888                pdf::from_setting ( set );
889                shared_ptr<fnc> g = UI::build<fnc> ( set, "g", UI::compulsory );
[357]890
[737]891                mat R;
892                vec dR;
893                if ( UI::get ( dR, set, "dR" ) )
894                        R = diag ( dR );
895                else
896                        UI::get ( R, set, "R", UI::compulsory );
[280]897
[737]898                set_parameters ( g, R );
899                validate();
900        }
901        void validate() {
902                bdm_assert ( g->dimension() == this->dimension(), "incompatible function" );
903        }
[488]904};
[357]905
[737]906UIREGISTER2 ( mgnorm, chmat );
[529]907SHAREDPTR2 ( mgnorm, chmat );
[357]908
[262]909
[488]910/*! (Approximate) Student t density with linear function of mean value
[262]911
[488]912The internal epdf of this class is of the type of a Gaussian (enorm).
913However, each conditioning is trying to assure the best possible approximation by taking into account the zeta function. See [] for reference.
[270]914
[488]915Perhaps a moment-matching technique?
916*/
[737]917class mlstudent : public mlnorm<ldmat, enorm> {
918protected:
919        //! Variable \f$ \Lambda \f$ from theory
920        ldmat Lambda;
921        //! Reference to variable \f$ R \f$
922        ldmat &_R;
923        //! Variable \f$ R_e \f$
924        ldmat Re;
925public:
926        mlstudent () : mlnorm<ldmat, enorm> (),
927                        Lambda (),      _R ( iepdf._R() ) {}
928        //! constructor function
929        void set_parameters ( const mat &A0, const vec &mu0, const ldmat &R0, const ldmat& Lambda0 ) {
930                iepdf.set_parameters ( mu0, R0 );// was Lambda, why?
931                A = A0;
932                mu_const = mu0;
933                Re = R0;
934                Lambda = Lambda0;
935        }
[294]936
[739]937        void condition ( const vec &cond ); 
938
[737]939        void validate() {
940                bdm_assert ( A.rows() == mu_const.length(), "mlstudent: A vs. mu mismatch" );
941                bdm_assert ( _R.rows() == A.rows(), "mlstudent: A vs. R mismatch" );
942
943        }
[488]944};
945/*!
946\brief  Gamma random walk
[198]947
[488]948Mean value, \f$\mu\f$, of this density is given by \c rvc .
949Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
950This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
[32]951
[488]952The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
953*/
[737]954class mgamma : public pdf_internal<egamma> {
955protected:
[461]956
[737]957        //! Constant \f$k\f$
958        double k;
[461]959
[737]960        //! cache of iepdf.beta
961        vec &_beta;
[32]962
[737]963public:
964        //! Constructor
965        mgamma() : pdf_internal<egamma>(), k ( 0 ),
966                        _beta ( iepdf._beta() ) {
967        }
[461]968
[737]969        //! Set value of \c k
970        void set_parameters ( double k, const vec &beta0 );
[461]971
[737]972        void condition ( const vec &val ) {
973                _beta = k / val;
974        };
975        /*! Create Gamma density with conditional mean value
976        \f[ f(rv|rvc) = \Gamma(k, k/rvc) \f]
977        from structure
978        \code
979          class = 'mgamma';
980          beta = [...];          // vector of initial alpha
981          k = 1.1;               // multiplicative constant k
982          rv = RV({'name'})      // description of RV
983          rvc = RV({'name'})     // description of RV in condition
984         \endcode
985        */
986        void from_setting ( const Setting &set ) {
987                pdf::from_setting ( set ); // reads rv and rvc
988                vec betatmp; // ugly but necessary
989                UI::get ( betatmp, set, "beta", UI::compulsory );
990                UI::get ( k, set, "k", UI::compulsory );
991                set_parameters ( k, betatmp );
992                validate();
993        }
994        void validate() {
995                pdf_internal<egamma>::validate();
996
997                dim = _beta.length();
998                dimc = _beta.length();
999        }
[488]1000};
[737]1001UIREGISTER ( mgamma );
1002SHAREDPTR ( mgamma );
[32]1003
[488]1004/*!
1005\brief  Inverse-Gamma random walk
[225]1006
[488]1007Mean value, \f$ \mu \f$, of this density is given by \c rvc .
1008Standard deviation of the random walk is proportional to one \f$ k \f$-th the mean.
1009This is achieved by setting \f$ \alpha=\mu/k^2+2 \f$ and \f$ \beta=\mu(\alpha-1)\f$.
[461]1010
[488]1011The standard deviation of the walk is then: \f$ \mu/\sqrt(k)\f$.
1012 */
[737]1013class migamma : public pdf_internal<eigamma> {
1014protected:
1015        //! Constant \f$k\f$
1016        double k;
[461]1017
[737]1018        //! cache of iepdf.alpha
1019        vec &_alpha;
[225]1020
[737]1021        //! cache of iepdf.beta
1022        vec &_beta;
[461]1023
[737]1024public:
1025        //! \name Constructors
1026        //!@{
1027        migamma() : pdf_internal<eigamma>(),
1028                        k ( 0 ),
1029                        _alpha ( iepdf._alpha() ),
1030                        _beta ( iepdf._beta() ) {
1031        }
[225]1032
[737]1033        migamma ( const migamma &m ) : pdf_internal<eigamma>(),
1034                        k ( 0 ),
1035                        _alpha ( iepdf._alpha() ),
1036                        _beta ( iepdf._beta() ) {
1037        }
1038        //!@}
[225]1039
[737]1040        //! Set value of \c k
1041        void set_parameters ( int len, double k0 ) {
1042                k = k0;
1043                iepdf.set_parameters ( ( 1.0 / ( k*k ) + 2.0 ) *ones ( len ) /*alpha*/, ones ( len ) /*beta*/ );
1044                dimc = dimension();
1045        };
1046        void condition ( const vec &val ) {
1047                _beta = elem_mult ( val, ( _alpha - 1.0 ) );
1048        };
[488]1049};
[357]1050
[60]1051
[488]1052/*!
1053\brief  Gamma random walk around a fixed point
[60]1054
[488]1055Mean 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
1056\f[ \mu = \mu_{t-1} ^{l} p^{1-l}\f]
[60]1057
[488]1058Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
1059This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
[294]1060
[488]1061The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
1062*/
[737]1063class mgamma_fix : public mgamma {
1064protected:
1065        //! parameter l
1066        double l;
1067        //! reference vector
1068        vec refl;
1069public:
1070        //! Constructor
1071        mgamma_fix () : mgamma (), refl () {};
1072        //! Set value of \c k
1073        void set_parameters ( double k0 , vec ref0, double l0 ) {
1074                mgamma::set_parameters ( k0, ref0 );
1075                refl = pow ( ref0, 1.0 - l0 );
1076                l = l0;
1077                dimc = dimension();
1078        };
[60]1079
[737]1080        void condition ( const vec &val ) {
1081                vec mean = elem_mult ( refl, pow ( val, l ) );
1082                _beta = k / mean;
1083        };
[488]1084};
[60]1085
[225]1086
[488]1087/*!
1088\brief  Inverse-Gamma random walk around a fixed point
[225]1089
[488]1090Mean 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
1091\f[ \mu = \mu_{t-1} ^{l} p^{1-l}\f]
[225]1092
[488]1093==== Check == vv =
1094Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
1095This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
[225]1096
[488]1097The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
1098 */
[737]1099class migamma_ref : public migamma {
1100protected:
1101        //! parameter l
1102        double l;
1103        //! reference vector
1104        vec refl;
1105public:
1106        //! Constructor
1107        migamma_ref () : migamma (), refl () {};
[766]1108       
[737]1109        //! Set value of \c k
1110        void set_parameters ( double k0 , vec ref0, double l0 ) {
1111                migamma::set_parameters ( ref0.length(), k0 );
1112                refl = pow ( ref0, 1.0 - l0 );
1113                l = l0;
1114                dimc = dimension();
1115        };
[357]1116
[737]1117        void condition ( const vec &val ) {
1118                vec mean = elem_mult ( refl, pow ( val, l ) );
1119                migamma::condition ( mean );
1120        };
[357]1121
1122
[737]1123        /*! Create inverse-Gamma density with conditional mean value
1124        \f[ f(rv|rvc) = i\Gamma(k, k/(rvc^l \circ ref^{(1-l)}) \f]
1125        from structure
1126        \code
1127        class = 'migamma_ref';
1128        ref = [1e-5; 1e-5; 1e-2 1e-3];            // reference vector
1129        l = 0.999;                                // constant l
1130        k = 0.1;                                  // constant k
1131        rv = RV({'name'})                         // description of RV
1132        rvc = RV({'name'})                        // description of RV in condition
1133        \endcode
1134         */
1135        void from_setting ( const Setting &set );
[225]1136
[737]1137        // TODO dodelat void to_setting( Setting &set ) const;
[488]1138};
[357]1139
1140
[737]1141UIREGISTER ( migamma_ref );
1142SHAREDPTR ( migamma_ref );
[294]1143
[488]1144/*! Log-Normal probability density
1145 only allow diagonal covariances!
[294]1146
[488]1147Density of the form \f$ \log(x)\sim \mathcal{N}(\mu,\sigma^2) \f$ , i.e.
1148\f[
1149x \sim \frac{1}{x\sigma\sqrt{2\pi}}\exp{-\frac{1}{2\sigma^2}(\log(x)-\mu)}
1150\f]
[294]1151
[621]1152Function from_setting loads mu and R in the same way as it does for enorm<>!
[488]1153*/
[737]1154class elognorm: public enorm<ldmat> {
1155public:
1156        vec sample() const {
1157                return exp ( enorm<ldmat>::sample() );
1158        };
1159        vec mean() const {
1160                vec var = enorm<ldmat>::variance();
1161                return exp ( mu - 0.5*var );
1162        };
[285]1163
[488]1164};
[285]1165
[488]1166/*!
1167\brief  Log-Normal random walk
[285]1168
[488]1169Mean value, \f$\mu\f$, is...
[285]1170
[488]1171 */
[737]1172class mlognorm : public pdf_internal<elognorm> {
1173protected:
1174        //! parameter 1/2*sigma^2
1175        double sig2;
[461]1176
[737]1177        //! access
1178        vec &mu;
1179public:
1180        //! Constructor
1181        mlognorm() : pdf_internal<elognorm>(),
1182                        sig2 ( 0 ),
1183                        mu ( iepdf._mu() ) {
1184        }
[285]1185
[737]1186        //! Set value of \c k
1187        void set_parameters ( int size, double k ) {
1188                sig2 = 0.5 * log ( k * k + 1 );
1189                iepdf.set_parameters ( zeros ( size ), 2*sig2*eye ( size ) );
[285]1190
[737]1191                dimc = size;
1192        };
[357]1193
[737]1194        void condition ( const vec &val ) {
1195                mu = log ( val ) - sig2;//elem_mult ( refl,pow ( val,l ) );
1196        };
[357]1197
[737]1198        /*! Create logNormal random Walk
1199        \f[ f(rv|rvc) = log\mathcal{N}( \log(rvc)-0.5\log(k^2+1), k I) \f]
1200        from structure
1201        \code
1202        class = 'mlognorm';
1203        k   = 0.1;               // "variance" k
1204        mu0 = 0.1;               // Initial value of mean
1205        rv  = RV({'name'})       // description of RV
1206        rvc = RV({'name'})       // description of RV in condition
1207        \endcode
1208        */
1209        void from_setting ( const Setting &set );
[357]1210
[737]1211        // TODO dodelat void to_setting( Setting &set ) const;
[285]1212
[488]1213};
[294]1214
[737]1215UIREGISTER ( mlognorm );
1216SHAREDPTR ( mlognorm );
[294]1217
[488]1218/*! inverse Wishart density defined on Choleski decomposition
1219
1220*/
[737]1221class eWishartCh : public epdf {
1222protected:
1223        //! Upper-Triagle of Choleski decomposition of \f$ \Psi \f$
1224        chmat Y;
1225        //! dimension of matrix  \f$ \Psi \f$
1226        int p;
1227        //! degrees of freedom  \f$ \nu \f$
1228        double delta;
1229public:
1230        //! Set internal structures
1231        void set_parameters ( const mat &Y0, const double delta0 ) {
1232                Y = chmat ( Y0 );
1233                delta = delta0;
1234                p = Y.rows();
1235                dim = p * p;
1236        }
1237        //! Set internal structures
1238        void set_parameters ( const chmat &Y0, const double delta0 ) {
1239                Y = Y0;
1240                delta = delta0;
1241                p = Y.rows();
1242                dim = p * p;
1243        }
1244        //! Sample matrix argument
1245        mat sample_mat() const {
1246                mat X = zeros ( p, p );
[488]1247
[737]1248                //sample diagonal
1249                for ( int i = 0; i < p; i++ ) {
1250                        GamRNG.setup ( 0.5* ( delta - i ) , 0.5 );   // no +1 !! index if from 0
[294]1251#pragma omp critical
[737]1252                        X ( i, i ) = sqrt ( GamRNG() );
1253                }
1254                //do the rest
1255                for ( int i = 0; i < p; i++ ) {
1256                        for ( int j = i + 1; j < p; j++ ) {
[294]1257#pragma omp critical
[737]1258                                X ( i, j ) = NorRNG.sample();
[294]1259                        }
[488]1260                }
[737]1261                return X*Y._Ch();// return upper triangular part of the decomposition
1262        }
[766]1263
[737]1264        vec sample () const {
1265                return vec ( sample_mat()._data(), p*p );
1266        }
[766]1267
1268        virtual vec mean() const NOT_IMPLEMENTED(0);
1269
1270        //! return expected variance (not covariance!)
1271        virtual vec variance() const NOT_IMPLEMENTED(0);
1272
1273        virtual double evallog ( const vec &val ) const NOT_IMPLEMENTED(0);
1274
[737]1275        //! fast access function y0 will be copied into Y.Ch.
1276        void setY ( const mat &Ch0 ) {
1277                copy_vector ( dim, Ch0._data(), Y._Ch()._data() );
1278        }
[766]1279
[737]1280        //! fast access function y0 will be copied into Y.Ch.
1281        void _setY ( const vec &ch0 ) {
1282                copy_vector ( dim, ch0._data(), Y._Ch()._data() );
1283        }
[766]1284
[737]1285        //! access function
1286        const chmat& getY() const {
1287                return Y;
1288        }
[488]1289};
[294]1290
[536]1291//! Inverse Wishart on Choleski decomposition
1292/*! Being computed by conversion from `standard' Wishart
1293*/
[737]1294class eiWishartCh: public epdf {
1295protected:
1296        //! Internal instance of Wishart density
1297        eWishartCh W;
1298        //! size of Ch
1299        int p;
1300        //! parameter delta
1301        double delta;
1302public:
1303        //! constructor function
1304        void set_parameters ( const mat &Y0, const double delta0 ) {
1305                delta = delta0;
1306                W.set_parameters ( inv ( Y0 ), delta0 );
1307                p = Y0.rows();
1308        }
[750]1309       
1310        virtual void    validate (){
1311      dim = W.dimension();
1312        }
1313       
1314       
[737]1315        vec sample() const {
1316                mat iCh;
1317                iCh = inv ( W.sample_mat() );
1318                return vec ( iCh._data(), dim );
1319        }
1320        //! access function
1321        void _setY ( const vec &y0 ) {
1322                mat Ch ( p, p );
1323                mat iCh ( p, p );
1324                copy_vector ( dim, y0._data(), Ch._data() );
[488]1325
[737]1326                iCh = inv ( Ch );
1327                W.setY ( iCh );
1328        }
[766]1329
[737]1330        virtual double evallog ( const vec &val ) const {
1331                chmat X ( p );
1332                const chmat& Y = W.getY();
[488]1333
[737]1334                copy_vector ( p*p, val._data(), X._Ch()._data() );
1335                chmat iX ( p );
1336                X.inv ( iX );
1337                // compute
[294]1338//                              \frac{ |\Psi|^{m/2}|X|^{-(m+p+1)/2}e^{-tr(\Psi X^{-1})/2} }{ 2^{mp/2}\Gamma_p(m/2)},
[737]1339                mat M = Y.to_mat() * iX.to_mat();
[285]1340
[737]1341                double log1 = 0.5 * p * ( 2 * Y.logdet() ) - 0.5 * ( delta + p + 1 ) * ( 2 * X.logdet() ) - 0.5 * trace ( M );
1342                //Fixme! Multivariate gamma omitted!! it is ok for sampling, but not otherwise!!
[461]1343
[737]1344                /*                              if (0) {
1345                                                        mat XX=X.to_mat();
1346                                                        mat YY=Y.to_mat();
[461]1347
[737]1348                                                        double log2 = 0.5*p*log(det(YY))-0.5*(delta+p+1)*log(det(XX))-0.5*trace(YY*inv(XX));
1349                                                        cout << log1 << "," << log2 << endl;
1350                                                }*/
1351                return log1;
1352        };
[285]1353
[766]1354        virtual vec mean() const NOT_IMPLEMENTED(0);
1355
1356        //! return expected variance (not covariance!)
1357        virtual vec variance() const NOT_IMPLEMENTED(0);
[488]1358};
1359
[536]1360//! Random Walk on inverse Wishart
[737]1361class rwiWishartCh : public pdf_internal<eiWishartCh> {
1362protected:
1363        //!square root of \f$ \nu-p-1 \f$ - needed for computation of \f$ \Psi \f$ from conditions
1364        double sqd;
1365        //!reference point for diagonal
1366        vec refl;
1367        //! power of the reference
1368        double l;
1369        //! dimension
1370        int p;
[488]1371
[737]1372public:
1373        rwiWishartCh() : sqd ( 0 ), l ( 0 ), p ( 0 ) {}
1374        //! constructor function
1375        void set_parameters ( int p0, double k, vec ref0, double l0 ) {
1376                p = p0;
1377                double delta = 2 / ( k * k ) + p + 3;
1378                sqd = sqrt ( delta - p - 1 );
1379                l = l0;
1380                refl = pow ( ref0, 1 - l );
[488]1381
[737]1382                iepdf.set_parameters ( eye ( p ), delta );
1383                dimc = iepdf.dimension();
1384        }
1385        void condition ( const vec &c ) {
1386                vec z = c;
1387                int ri = 0;
1388                for ( int i = 0; i < p*p; i += ( p + 1 ) ) {//trace diagonal element
1389                        z ( i ) = pow ( z ( i ), l ) * refl ( ri );
1390                        ri++;
[488]1391                }
[285]1392
[737]1393                iepdf._setY ( sqd*z );
1394        }
[488]1395};
1396
[32]1397//! Switch between various resampling methods.
[488]1398enum RESAMPLING_METHOD { MULTINOMIAL = 0, STRATIFIED = 1, SYSTEMATIC = 3 };
1399/*!
1400\brief Weighted empirical density
[32]1401
[488]1402Used e.g. in particle filters.
1403*/
[737]1404class eEmp: public epdf {
1405protected :
1406        //! Number of particles
1407        int n;
1408        //! Sample weights \f$w\f$
1409        vec w;
1410        //! Samples \f$x^{(i)}, i=1..n\f$
1411        Array<vec> samples;
1412public:
1413        //! \name Constructors
1414        //!@{
1415        eEmp () : epdf (), w (), samples () {};
1416        //! copy constructor
1417        eEmp ( const eEmp &e ) : epdf ( e ), w ( e.w ), samples ( e.samples ) {};
1418        //!@}
[280]1419
[737]1420        //! Set samples and weights
1421        void set_statistics ( const vec &w0, const epdf &pdf0 );
1422        //! Set samples and weights
1423        void set_statistics ( const epdf &pdf0 , int n ) {
1424                set_statistics ( ones ( n ) / n, pdf0 );
1425        };
1426        //! Set sample
1427        void set_samples ( const epdf* pdf0 );
1428        //! Set sample
1429        void set_parameters ( int n0, bool copy = true ) {
1430                n = n0;
1431                w.set_size ( n0, copy );
1432                samples.set_size ( n0, copy );
1433        };
1434        //! Set samples
1435        void set_parameters ( const Array<vec> &Av ) {
1436                n = Av.size();
1437                w = 1 / n * ones ( n );
1438                samples = Av;
1439        };
[750]1440        virtual void    validate (){
[760]1441          bdm_assert (samples.length()==w.length(),"samples and weigths are of different lengths");
1442          n = w.length();
1443          if (n>0)
[795]1444                pdf::dim = samples ( 0 ).length();
[750]1445        }
[737]1446        //! Potentially dangerous, use with care.
1447        vec& _w()  {
1448                return w;
1449        };
1450        //! Potentially dangerous, use with care.
1451        const vec& _w() const {
1452                return w;
1453        };
1454        //! access function
1455        Array<vec>& _samples() {
1456                return samples;
1457        };
1458        //! access function
1459        const vec& _sample ( int i ) const {
1460                return samples ( i );
1461        };
1462        //! access function
1463        const Array<vec>& _samples() const {
1464                return samples;
1465        };
1466        //! 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.
1467        //! The vector with indeces of new samples is returned in variable \c index.
1468        void resample ( ivec &index, RESAMPLING_METHOD method = SYSTEMATIC );
[565]1469
[737]1470        //! Resampling without returning index of new particles.
1471        void resample ( RESAMPLING_METHOD method = SYSTEMATIC ) {
1472                ivec ind;
1473                resample ( ind, method );
1474        };
[565]1475
[737]1476        //! inherited operation : NOT implemented
[766]1477        vec sample() const NOT_IMPLEMENTED(0);
[565]1478
[737]1479        //! inherited operation : NOT implemented
[766]1480        double evallog ( const vec &val ) const NOT_IMPLEMENTED(0);
[737]1481
1482        vec mean() const {
1483                vec pom = zeros ( dim );
1484                for ( int i = 0; i < n; i++ ) {
1485                        pom += samples ( i ) * w ( i );
[488]1486                }
[737]1487                return pom;
1488        }
1489        vec variance() const {
1490                vec pom = zeros ( dim );
1491                for ( int i = 0; i < n; i++ ) {
1492                        pom += pow ( samples ( i ), 2 ) * w ( i );
[488]1493                }
[737]1494                return pom - pow ( mean(), 2 );
1495        }
1496        //! For this class, qbounds are minimum and maximum value of the population!
[739]1497        void qbounds ( vec &lb, vec &ub, double perc = 0.95 ) const;
[760]1498
1499        void to_setting ( Setting &set ) const {
1500                epdf::to_setting( set );
1501                UI::save ( samples, set, "samples" );
1502                UI::save ( w, set, "w" );
1503        }
1504
1505        void from_setting ( const Setting &set ) {
1506                epdf::from_setting( set );
1507               
1508                UI::get( samples, set, "samples", UI::compulsory );
1509                UI::get ( w, set, "w", UI::compulsory );
1510                validate();
1511        }
1512
[488]1513};
[760]1514UIREGISTER(eEmp);
[32]1515
1516
[8]1517////////////////////////
1518
[488]1519template<class sq_T>
[737]1520void enorm<sq_T>::set_parameters ( const vec &mu0, const sq_T &R0 ) {
[28]1521//Fixme test dimensions of mu0 and R0;
[488]1522        mu = mu0;
1523        R = R0;
1524        validate();
1525};
[8]1526
[488]1527template<class sq_T>
[737]1528void enorm<sq_T>::from_setting ( const Setting &set ) {
1529        epdf::from_setting ( set ); //reads rv
[384]1530
[737]1531        UI::get ( mu, set, "mu", UI::compulsory );
[488]1532        mat Rtmp;// necessary for conversion
[737]1533        UI::get ( Rtmp, set, "R", UI::compulsory );
[488]1534        R = Rtmp; // conversion
1535        validate();
1536}
[8]1537
[488]1538template<class sq_T>
[773]1539void enorm<sq_T>::to_setting ( Setting &set ) const {
1540        epdf::to_setting ( set ); //reads rv   
1541        UI::save ( mu, set, "mu");
1542        UI::save ( R.to_mat(), set, "R");
1543}
1544
1545template<class sq_T>
[737]1546void enorm<sq_T>::dupdate ( mat &v, double nu ) {
[488]1547        //
1548};
1549
[178]1550// template<class sq_T>
1551// void enorm<sq_T>::tupdate ( double phi, mat &vbar, double nubar ) {
1552//      //
1553// };
[8]1554
[488]1555template<class sq_T>
[737]1556vec enorm<sq_T>::sample() const {
1557        vec x ( dim );
[270]1558#pragma omp critical
[737]1559        NorRNG.sample_vector ( dim, x );
1560        vec smp = R.sqrt_mult ( x );
[12]1561
[488]1562        smp += mu;
1563        return smp;
1564};
[8]1565
[214]1566// template<class sq_T>
1567// double enorm<sq_T>::eval ( const vec &val ) const {
1568//      double pdfl,e;
1569//      pdfl = evallog ( val );
1570//      e = exp ( pdfl );
1571//      return e;
1572// };
[8]1573
[488]1574template<class sq_T>
[737]1575double enorm<sq_T>::evallog_nn ( const vec &val ) const {
[488]1576        // 1.83787706640935 = log(2pi)
[737]1577        double tmp = -0.5 * ( R.invqform ( mu - val ) );// - lognc();
[488]1578        return  tmp;
1579};
[28]1580
[488]1581template<class sq_T>
[737]1582inline double enorm<sq_T>::lognc () const {
[488]1583        // 1.83787706640935 = log(2pi)
[737]1584        double tmp = 0.5 * ( R.cols() * 1.83787706640935 + R.logdet() );
[488]1585        return tmp;
1586};
[28]1587
[8]1588
[192]1589// template<class sq_T>
1590// vec mlnorm<sq_T>::samplecond (const  vec &cond, double &lik ) {
1591//      this->condition ( cond );
1592//      vec smp = epdf.sample();
1593//      lik = epdf.eval ( smp );
1594//      return smp;
1595// }
[8]1596
[192]1597// template<class sq_T>
1598// mat mlnorm<sq_T>::samplecond (const vec &cond, vec &lik, int n ) {
1599//      int i;
1600//      int dim = rv.count();
1601//      mat Smp ( dim,n );
1602//      vec smp ( dim );
1603//      this->condition ( cond );
[198]1604//
[192]1605//      for ( i=0; i<n; i++ ) {
1606//              smp = epdf.sample();
1607//              lik ( i ) = epdf.eval ( smp );
1608//              Smp.set_col ( i ,smp );
1609//      }
[198]1610//
[192]1611//      return Smp;
1612// }
[28]1613
[8]1614
[488]1615template<class sq_T>
[737]1616shared_ptr<epdf> enorm<sq_T>::marginal ( const RV &rvn ) const {
[504]1617        enorm<sq_T> *tmp = new enorm<sq_T> ();
[737]1618        shared_ptr<epdf> narrow ( tmp );
[504]1619        marginal ( rvn, *tmp );
1620        return narrow;
1621}
1622
1623template<class sq_T>
[737]1624void enorm<sq_T>::marginal ( const RV &rvn, enorm<sq_T> &target ) const {
1625        bdm_assert ( isnamed(), "rv description is not assigned" );
1626        ivec irvn = rvn.dataind ( rv );
[178]1627
[737]1628        sq_T Rn ( R, irvn );  // select rows and columns of R
[280]1629
[504]1630        target.set_rv ( rvn );
[737]1631        target.set_parameters ( mu ( irvn ), Rn );
[488]1632}
[178]1633
[488]1634template<class sq_T>
[737]1635shared_ptr<pdf> enorm<sq_T>::condition ( const RV &rvn ) const {
[504]1636        mlnorm<sq_T> *tmp = new mlnorm<sq_T> ();
[737]1637        shared_ptr<pdf> narrow ( tmp );
[504]1638        condition ( rvn, *tmp );
1639        return narrow;
1640}
[178]1641
[504]1642template<class sq_T>
[737]1643void enorm<sq_T>::condition ( const RV &rvn, pdf &target ) const {
[504]1644        typedef mlnorm<sq_T> TMlnorm;
1645
[737]1646        bdm_assert ( isnamed(), "rvs are not assigned" );
1647        TMlnorm &uptarget = dynamic_cast<TMlnorm &> ( target );
[270]1648
[737]1649        RV rvc = rv.subt ( rvn );
1650        bdm_assert ( ( rvc._dsize() + rvn._dsize() == rv._dsize() ), "wrong rvn" );
[488]1651        //Permutation vector of the new R
[737]1652        ivec irvn = rvn.dataind ( rv );
1653        ivec irvc = rvc.dataind ( rv );
1654        ivec perm = concat ( irvn , irvc );
1655        sq_T Rn ( R, perm );
[178]1656
[488]1657        //fixme - could this be done in general for all sq_T?
1658        mat S = Rn.to_mat();
1659        //fixme
1660        int n = rvn._dsize() - 1;
1661        int end = R.rows() - 1;
[737]1662        mat S11 = S.get ( 0, n, 0, n );
1663        mat S12 = S.get ( 0, n , rvn._dsize(), end );
1664        mat S22 = S.get ( rvn._dsize(), end, rvn._dsize(), end );
[178]1665
[737]1666        vec mu1 = mu ( irvn );
1667        vec mu2 = mu ( irvc );
1668        mat A = S12 * inv ( S22 );
1669        sq_T R_n ( S11 - A *S12.T() );
[178]1670
[737]1671        uptarget.set_rv ( rvn );
1672        uptarget.set_rvc ( rvc );
1673        uptarget.set_parameters ( A, mu1 - A*mu2, R_n );
[488]1674}
[178]1675
[488]1676////
1677///////
1678template<class sq_T>
[737]1679void mgnorm<sq_T >::set_parameters ( const shared_ptr<fnc> &g0, const sq_T &R0 ) {
[527]1680        g = g0;
[737]1681        this->iepdf.set_parameters ( zeros ( g->dimension() ), R0 );
[527]1682}
1683
[488]1684template<class sq_T>
[737]1685void mgnorm<sq_T >::condition ( const vec &cond ) {
1686        this->iepdf._mu() = g->eval ( cond );
1687};
[28]1688
[536]1689//! \todo unify this stuff with to_string()
[488]1690template<class sq_T>
[737]1691std::ostream &operator<< ( std::ostream &os,  mlnorm<sq_T> &ml ) {
[488]1692        os << "A:" << ml.A << endl;
1693        os << "mu:" << ml.mu_const << endl;
1694        os << "R:" << ml._R() << endl;
1695        return os;
1696};
[28]1697
[254]1698}
[8]1699#endif //EF_H
Note: See TracBrowser for help on using the browser.