root/bdm/stat/libEF.h @ 312

Revision 310, 29.8 kB (checked in by smidl, 15 years ago)

Published example 2d

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