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

Revision 429, 34.7 kB (checked in by smidl, 15 years ago)

merger changes + corresponding fixes

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