root/bdm/stat/libEF.h @ 378

Revision 378, 32.4 kB (checked in by smidl, 15 years ago)

details and compositepdf changes

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