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

Revision 388, 32.5 kB (checked in by smidl, 15 years ago)

mergers

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