root/bdm/stat/libEF.h @ 357

Revision 357, 32.1 kB (checked in by mido, 15 years ago)

mnoho zmen:
1) presun FindXXX modulu do \system
2) zalozeni dokumentace \doc\local\library_structure.dox
3) presun obsahu \tests\UI primo do \tests
4) namisto \INSTALL zalozen \install.html, je to vhodnejsi pro uzivatele WINDOWS, a snad i obecne
5) snaha o predelani veskerych UI podle nove koncepce, soubory pmsm_ui.h, arx_ui.h, KF_ui.h, libDS_ui.h, libEF_ui.h a loggers_ui.h ponechavam
jen zdokumentacnich duvodu, nic by na nich jiz nemelo zaviset, a po zkontrolovani spravnosti provedenych uprav by mely byt smazany
6) predelani estimatoru tak, aby fungoval s novym UI konceptem
7) vytazeni tridy bdmroot do samostatneho souboru \bdm\bdmroot.h
8) pridana dokumentace pro zacleneni programu ASTYLE do Visual studia, ASTYLE pridan do instalacniho balicku pro Windows

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