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

Revision 1033, 48.5 kB (checked in by smidl, 14 years ago)

New ebeta distribution + tests

  • 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 "../shared_ptr.h"
18#include "../base/bdmbase.h"
19#include "../math/chmat.h"
20
21namespace bdm {
22
23
24//! Global Uniform_RNG
25extern Uniform_RNG UniRNG;
26//! Global Normal_RNG
27extern Normal_RNG NorRNG;
28//! Global Gamma_RNG
29extern Gamma_RNG GamRNG;
30
31/*!
32* \brief General conjugate exponential family posterior density.
33
34* More?...
35*/
36
37class eEF : public epdf {
38public:
39//      eEF() :epdf() {};
40        //! default constructor
41        eEF () : epdf () {};
42        //! logarithm of the normalizing constant, \f$\mathcal{I}\f$
43        virtual double lognc() const = 0;
44
45        //!Evaluate normalized log-probability
46        virtual double evallog_nn ( const vec &val ) const NOT_IMPLEMENTED(0);
47
48        //!Evaluate normalized log-probability
49        virtual double evallog ( const vec &val ) const {
50                double tmp;
51                tmp = evallog_nn ( val ) - lognc();
52                return tmp;
53        }
54        //!Evaluate normalized log-probability for many samples
55        virtual vec evallog_mat ( const mat &Val ) const {
56                vec x ( Val.cols() );
57                for ( int i = 0; i < Val.cols(); i++ ) {
58                        x ( i ) = evallog_nn ( Val.get_col ( i ) ) ;
59                }
60                return x - lognc();
61        }
62        //!Evaluate normalized log-probability for many samples
63        virtual vec evallog_mat ( const Array<vec> &Val ) const {
64                vec x ( Val.length() );
65                for ( int i = 0; i < Val.length(); i++ ) {
66                        x ( i ) = evallog_nn ( Val ( i ) ) ;
67                }
68                return x - lognc();
69        }
70
71        //!Power of the density, used e.g. to flatten the density
72        virtual void pow ( double p ) NOT_IMPLEMENTED_VOID;
73};
74
75
76//! Estimator for Exponential family
77class BMEF : public BM {
78        public:
79        //! forgetting factor
80        double frg;
81        protected:
82        //! cached value of lognc() in the previous step (used in evaluation of \c ll )
83        double last_lognc;
84        //! factor k = [0..1] for scheduling of forgetting factor: \f$ frg_t = (1-k) * frg_{t-1} + k \f$, default 0
85        double frg_sched_factor;
86public:
87        //! Default constructor (=empty constructor)
88        BMEF ( double frg0 = 1.0 ) : BM (), frg ( frg0 ), last_lognc(0.0),frg_sched_factor(0.0) {}
89        //! Copy constructor
90        BMEF ( const BMEF &B ) : BM ( B ), frg ( B.frg ), last_lognc ( B.last_lognc ),frg_sched_factor(B.frg_sched_factor) {}
91        //!get statistics from another model
92        virtual void set_statistics ( const BMEF* BM0 ) NOT_IMPLEMENTED_VOID;
93
94        //! Weighted update of sufficient statistics (Bayes rule)
95        virtual void bayes_weighted ( const vec &data, const vec &cond = empty_vec, const double w = 1.0 ) {
96                if (frg_sched_factor>0) {frg = frg*(1-frg_sched_factor)+frg_sched_factor;}
97        };
98        //original Bayes
99        void bayes ( const vec &yt, const vec &cond = empty_vec );
100
101        //!Flatten the posterior according to the given BMEF (of the same type!)
102        virtual void flatten ( const BMEF * B, double weight=1.0 ) NOT_IMPLEMENTED_VOID;;
103
104
105        void to_setting ( Setting &set ) const
106        {                       
107                BM::to_setting( set );
108                UI::save(frg, set, "frg");
109                UI::save( frg_sched_factor, set, "frg_sched_factor" );
110        } 
111
112        void from_setting( const Setting &set) {
113                BM::from_setting(set);
114                if ( !UI::get ( frg, set, "frg" ) )
115                        frg = 1.0;
116                UI::get ( frg_sched_factor, set, "frg_sched_factor",UI::optional );
117        }
118
119        void validate() {
120                BM::validate(); 
121        }
122
123};
124
125/*! Dirac delta density with predefined transformation
126
127Density of the type:\f[ f(x_t | y_t) = \delta (x_t - g(y_t)) \f]
128where \f$ x_t \f$ is the \c rv, \f$ y_t \f$ is the \c rvc and g is a deterministic transformation of class fn.
129*/
130class mgdirac: public pdf{
131        protected:
132        shared_ptr<fnc> g;
133        public:
134                vec samplecond(const vec &cond) {
135                        bdm_assert_debug(cond.length()==g->dimensionc(),"given cond in not compatible with g");
136                        vec tmp = g->eval(cond);
137                        return tmp;
138                } 
139                double evallogcond ( const vec &yt, const vec &cond ){
140                        return std::numeric_limits< double >::max();
141                }
142                void from_setting(const Setting& set);
143                void to_setting(Setting &set) const;
144                void validate();
145};
146UIREGISTER(mgdirac);
147
148
149template<class sq_T, template <typename> class TEpdf>
150class mlnorm;
151
152/*!
153* \brief Gaussian density with positive definite (decomposed) covariance matrix.
154
155* More?...
156*/
157template<class sq_T>
158class enorm : public eEF {
159protected:
160        //! mean value
161        vec mu;
162        //! Covariance matrix in decomposed form
163        sq_T R;
164public:
165        //!\name Constructors
166        //!@{
167
168        enorm () : eEF (), mu (), R () {};
169        enorm ( const vec &mu, const sq_T &R ) {
170                set_parameters ( mu, R );
171        }
172        void set_parameters ( const vec &mu, const sq_T &R );
173        /*! Create Normal density
174        \f[ f(rv) = N(\mu, R) \f]
175        from structure
176        \code
177        class = 'enorm<ldmat>', (OR) 'enorm<chmat>', (OR) 'enorm<fsqmat>';
178        mu    = [];                  // mean value
179        R     = [];                  // variance, square matrix of appropriate dimension
180        \endcode
181        */
182        void from_setting ( const Setting &root );
183        void to_setting ( Setting &root ) const ;
184       
185        void validate();
186        //!@}
187
188        //! \name Mathematical operations
189        //!@{
190
191        //! dupdate in exponential form (not really handy)
192        void dupdate ( mat &v, double nu = 1.0 );
193
194        //! evaluate bhattacharya distance
195        double bhattacharyya(const enorm<sq_T> &e2){
196                bdm_assert(dim == e2.dimension(), "enorms of differnt dimensions");
197                sq_T P=R;
198                P.add(e2._R());
199               
200                double tmp = 0.125*P.invqform(mu - e2._mu()) + 0.5*(P.logdet() - 0.5*(R.logdet() + e2._R().logdet()));
201                return tmp;
202        }
203       
204        vec sample() const;
205
206        double evallog_nn ( const vec &val ) const;
207        double lognc () const;
208        vec mean() const {
209                return mu;
210        }
211        vec variance() const {
212                return diag ( R.to_mat() );
213        }
214        mat covariance() const {
215                return R.to_mat();
216        }
217        //      mlnorm<sq_T>* condition ( const RV &rvn ) const ; <=========== fails to cmpile. Why?
218        shared_ptr<pdf> condition ( const RV &rvn ) const;
219
220        // target not typed to mlnorm<sq_T, enorm<sq_T> > &
221        // because that doesn't compile (perhaps because we
222        // haven't finished defining enorm yet), but the type
223        // is required
224        void condition ( const RV &rvn, pdf &target ) const;
225
226        shared_ptr<epdf> marginal ( const RV &rvn ) const;
227        void marginal ( const RV &rvn, enorm<sq_T> &target ) const;
228        //!@}
229
230        //! \name Access to attributes
231        //!@{
232
233        vec& _mu() {
234                return mu;
235        }
236        const vec& _mu() const {
237                return mu;
238        }
239        void set_mu ( const vec mu0 ) {
240                mu = mu0;
241        }
242        sq_T& _R() {
243                return R;
244        }
245        const sq_T& _R() const {
246                return R;
247        }
248        //!@}
249
250};
251UIREGISTER2 ( enorm, chmat );
252SHAREDPTR2 ( enorm, chmat );
253UIREGISTER2 ( enorm, ldmat );
254SHAREDPTR2 ( enorm, ldmat );
255UIREGISTER2 ( enorm, fsqmat );
256SHAREDPTR2 ( enorm, fsqmat );
257
258//! \class bdm::egauss
259//!\brief Gaussian (Normal) distribution. Same as enorm<fsqmat>.
260typedef enorm<ldmat> egauss;
261UIREGISTER(egauss);
262
263
264//forward declaration
265class mstudent;
266
267/*! distribution of multivariate Student t density
268
269Based on article by Genest and Zidek,
270*/
271template<class sq_T>
272class estudent : public eEF{
273        protected:
274                //! mena value
275                vec mu;
276                //! matrix H
277                sq_T H;
278                //! degrees of freedom
279                double delta;
280        public:
281                double evallog_nn(const vec &val) const{
282                        double tmp = -0.5*H.logdet() - 0.5*(delta + dim) * log(1+ H.invqform(val - mu)/delta);
283                        return tmp;
284                }
285                double lognc() const {
286                        //log(pi) = 1.14472988584940
287                        double tmp = -lgamma(0.5*(delta+dim))+lgamma(0.5*delta) + 0.5*dim*(log(delta) + 1.14472988584940);
288                        return tmp;
289                }
290                void marginal (const RV &rvm, estudent<sq_T> &marg) const {
291                        ivec ind = rvm.findself_ids(rv); // indices of rvm in rv
292                        marg._mu() = mu(ind);
293                        marg._H() = sq_T(H,ind);
294                        marg._delta() = delta;
295                        marg.validate();
296                }
297                shared_ptr<epdf> marginal(const RV &rvm) const {
298                        shared_ptr<estudent<sq_T> > tmp = new estudent<sq_T>;
299                        marginal(rvm, *tmp);
300                        return tmp;
301                }
302                vec sample() const NOT_IMPLEMENTED(vec(0))
303               
304                vec mean() const {return mu;}
305                mat covariance() const {
306                        return delta/(delta-2)*H.to_mat();
307                }
308                vec variance() const {return diag(covariance());}
309                        //! \name access
310                //! @{
311                        //! access function
312                        vec& _mu() {return mu;}
313                        //! access function
314                        sq_T& _H() {return H;}
315                        //! access function
316                        double& _delta() {return delta;}
317                        //!@}
318                        //! todo
319                        void from_setting(const Setting &set){
320                                epdf::from_setting(set);
321                                mat H0;
322                                UI::get(H0,set, "H");
323                                H= H0; // conversion!!
324                                UI::get(delta,set,"delta");
325                                UI::get(mu,set,"mu");
326                        }
327                        void to_setting(Setting &set) const{
328                                epdf::to_setting(set);
329                                UI::save(H.to_mat(), set, "H");
330                                UI::save(delta, set, "delta");
331                                UI::save(mu, set, "mu");
332                        }
333                        void validate() {
334                                eEF::validate();
335                                dim = H.rows();
336                        }
337};
338UIREGISTER2(estudent,fsqmat);
339UIREGISTER2(estudent,ldmat);
340UIREGISTER2(estudent,chmat);
341
342/*!
343* \brief Gauss-inverse-Wishart density stored in LD form
344
345* For \f$p\f$-variate densities, given rv.count() should be \f$p\times\f$ V.rows().
346*
347*/
348class egiw : public eEF {
349        //! \var log_level_enums logvartheta
350        //! Log variance of the theta part
351
352        LOG_LEVEL(egiw,logvartheta);
353
354protected:
355        //! Extended information matrix of sufficient statistics
356        ldmat V;
357        //! Number of data records (degrees of freedom) of sufficient statistics
358        double nu;
359        //! Dimension of the output
360        int dimx;
361        //! Dimension of the regressor
362        int nPsi;
363public:
364        //!\name Constructors
365        //!@{
366        egiw() : eEF(),dimx(0) {};
367        egiw ( int dimx0, ldmat V0, double nu0 = -1.0 ) : eEF(),dimx(0) {
368                set_parameters ( dimx0, V0, nu0 );
369                validate();
370        };
371
372        void set_parameters ( int dimx0, ldmat V0, double nu0 = -1.0 );
373        //!@}
374
375        vec sample() const;
376        mat sample_mat ( int n ) const;
377        vec mean() const;
378        vec variance() const;
379        //mat covariance() const;
380        void sample_mat ( mat &Mi, chmat &Ri ) const;
381
382        void factorize ( mat &M, ldmat &Vz, ldmat &Lam ) const;
383        //! LS estimate of \f$\theta\f$
384        vec est_theta() const;
385
386        //! Covariance of the LS estimate
387        ldmat est_theta_cov() const;
388
389        //! expected values of the linear coefficient and the covariance matrix are written to \c M and \c R , respectively
390        void mean_mat ( mat &M, mat&R ) const;
391        //! In this instance, val= [theta, r]. For multivariate instances, it is stored columnwise val = [theta_1 theta_2 ... r_1 r_2 ]
392        double evallog_nn ( const vec &val ) const;
393        double lognc () const;
394        void pow ( double p ) {
395                V *= p;
396                nu *= p;
397        };
398
399        //! marginal density (only student for now)
400        shared_ptr<epdf> marginal(const RV &rvm) const {
401                bdm_assert(dimx==1, "Not supported");
402                //TODO - this is too trivial!!!
403                ivec ind = rvm.findself_ids(rv);
404                if (min(ind)==0) { //assume it si
405                        shared_ptr<estudent<ldmat> > tmp = new estudent<ldmat>;
406                        mat M;
407                        ldmat Vz;
408                        ldmat Lam;
409                        factorize(M,Vz,Lam);
410                       
411                        tmp->_mu() = M.get_col(0);
412                        ldmat H;
413                        Vz.inv(H);
414                        H *=Lam._D()(0)/nu;
415                        tmp->_H() = H;
416                        tmp->_delta() = nu;
417                        tmp->validate();
418                        return tmp;
419                }
420                return NULL;
421        }
422        //! \name Access attributes
423        //!@{
424
425        ldmat& _V() {
426                return V;
427        }
428        const ldmat& _V() const {
429                return V;
430        }
431        double& _nu()  {
432                return nu;
433        }
434        const double& _nu() const {
435                return nu;
436        }
437        const int & _dimx() const {
438                return dimx;
439        }
440
441        /*! Create Gauss-inverse-Wishart density
442        \f[ f(rv) = GiW(V,\nu) \f]
443        from structure
444        \code
445        class = 'egiw';
446        V.L     = [];             // L part of matrix V
447        V.D     = [];             // D part of matrix V
448        -or- V  = []              // full matrix V
449        -or- dV = [];               // vector of diagonal of V (when V not given)
450        nu      = [];               // scalar \nu ((almost) degrees of freedom)
451                                                          // when missing, it will be computed to obtain proper pdf
452        dimx    = [];               // dimension of the wishart part
453        rv = RV({'name'})         // description of RV
454        rvc = RV({'name'})        // description of RV in condition
455        \endcode
456
457        \sa log_level_enums
458        */
459        void from_setting ( const Setting &set );
460        //! see egiw::from_setting
461        void to_setting ( Setting& set ) const;
462        void validate();
463        void log_register ( bdm::logger& L, const string& prefix );
464
465        void log_write() const;
466        //!@}
467};
468UIREGISTER ( egiw );
469SHAREDPTR ( egiw );
470
471/*! \brief Dirichlet posterior density
472
473Continuous Dirichlet density of \f$n\f$-dimensional variable \f$x\f$
474\f[
475f(x|\beta) = \frac{\Gamma[\gamma]}{\prod_{i=1}^{n}\Gamma(\beta_i)} \prod_{i=1}^{n}x_i^{\beta_i-1}
476\f]
477where \f$\gamma=\sum_i \beta_i\f$.
478*/
479class eDirich: public eEF {
480protected:
481        //!sufficient statistics
482        vec beta;
483public:
484        //!\name Constructors
485        //!@{
486
487        eDirich () : eEF () {};
488        eDirich ( const eDirich &D0 ) : eEF () {
489                set_parameters ( D0.beta );
490                validate();
491        };
492        eDirich ( const vec &beta0 ) {
493                set_parameters ( beta0 );
494                validate();
495        };
496        void set_parameters ( const vec &beta0 ) {
497                beta = beta0;
498                dim = beta.length();
499        }
500        //!@}
501
502        //! using sampling procedure from wikipedia
503        vec sample() const {
504                vec y ( beta.length() );
505                for ( int i = 0; i < beta.length(); i++ ) {
506                        GamRNG.setup ( beta ( i ), 1 );
507#pragma omp critical
508                        y ( i ) = GamRNG();
509                }
510                return y / sum ( y );
511        }
512
513        vec mean() const {
514                return beta / sum ( beta );
515        };
516        vec variance() const {
517                double gamma = sum ( beta );
518                return elem_mult ( beta, ( gamma - beta ) ) / ( gamma*gamma* ( gamma + 1 ) );
519        }
520        //! In this instance, val is ...
521        double evallog_nn ( const vec &val ) const {
522                double tmp;
523                tmp = ( beta - 1 ) * log ( val );
524                return tmp;
525        }
526
527        double lognc () const {
528                double tmp;
529                double gam = sum ( beta );
530                double lgb = 0.0;
531                for ( int i = 0; i < beta.length(); i++ ) {
532                        lgb += lgamma ( beta ( i ) );
533                }
534                tmp = lgb - lgamma ( gam );
535                return tmp;
536        }
537
538        //!access function
539        vec& _beta()  {
540                return beta;
541        }
542        /*! configuration structure
543        \code
544        class = 'eDirich';
545        beta  = [];           //parametr beta
546        \endcode
547        */
548        void from_setting ( const Setting &set );
549        void validate();
550        void to_setting ( Setting &set ) const;
551};
552UIREGISTER ( eDirich );
553
554/*! Product of Beta distributions
555
556Continuous Dirichlet density of \f$n\f$-dimensional variable \f$x\f$
557\f[
558f(x|\alpha,\beta)  = \frac{\Gamma(\alpha+\beta)}{\Gamma(\alpha)\Gamma(\beta)}\, x^{\alpha-1}(1-x)^{\beta-1}
559\f]
560is a simplification of Dirichlet to univariate case.
561*/
562class eBeta: public eEF {
563        public:
564                //!sufficient statistics
565                vec alpha;
566                //!sufficient statistics
567                vec beta;
568        public:
569                //!\name Constructors
570                //!@{
571                       
572                        eBeta () : eEF () {};
573                        eBeta ( const eBeta &B0 ) : eEF (), alpha(B0.alpha),beta(B0.beta) {
574                                validate();
575                        };
576                        //!@}
577                       
578                        //! using sampling procedure from wikipedia
579                        vec sample() const {
580                                vec y ( beta.length() ); // all vectors
581                                for ( int i = 0; i < beta.length(); i++ ) {
582                                        GamRNG.setup ( alpha ( i ), 1 );
583                                        #pragma omp critical
584                                        double Ga = GamRNG();
585                                       
586                                        GamRNG.setup ( beta ( i ), 1 );
587                                        #pragma omp critical
588                                        double Gb = GamRNG();
589                                       
590                                        y ( i ) = Ga/(Ga+Gb);
591                                }
592                                return y;
593                        }
594                       
595                        vec mean() const {
596                                return elem_div(alpha, alpha + beta); // dot-division
597                        };
598                        vec variance() const {
599                                vec apb=alpha+beta;
600                                return elem_div (elem_mult ( alpha, beta) ,
601                                                                 elem_mult ( elem_mult(apb,apb), apb+1 ) );
602                        }
603                        //! In this instance, val is ...
604                        double evallog_nn ( const vec &val ) const {
605                                double tmp;
606                                tmp = ( alpha - 1 ) * log ( val ) + (beta-1)*log(1-val);
607                                return tmp;
608                        }
609                       
610                        double lognc () const {
611                                double lgb = 0.0;
612                                for ( int i = 0; i < beta.length(); i++ ) {
613                                        lgb += -lgamma ( alpha(i)+beta(i) ) + lgamma(alpha(i)) + lgamma(beta(i));
614                                }
615                                return lgb;
616                        }
617                       
618                        /*! configuration structure
619                        \code
620                        class = 'eBeta';
621                        beta  = [];           //parametr beta
622                        alpha = [];           //parametr alpha
623                        \endcode
624                        */
625                        void from_setting ( const Setting &set ){
626                                UI::get(alpha, set, "alpha", UI::compulsory);
627                                UI::get(beta, set, "beta", UI::compulsory);
628                        }
629                        void validate(){
630                                bdm_assert(alpha.length()==beta.length(), "eBeta:: alpha and beta length do not match");
631                                dim = alpha.length();
632                        };
633                        void to_setting ( Setting &set ) const{
634                                UI::save(alpha, set, "alpha");
635                                UI::save(beta, set, "beta");
636                        }
637};
638UIREGISTER ( eBeta );
639
640/*! Random Walk on Dirichlet
641Using simple assignment
642 \f[ \beta = rvc / k + \beta_c \f]
643 hence, mean value = rvc, variance = (k+1)*mean*mean;
644
645 The greater k is, the greater is the variance of the random walk;
646
647 \f$ \beta_c \f$ is used as regularizing element to avoid corner cases, i.e. when one element of rvc is zero.
648 By default is it set to 0.1;
649*/
650
651class mDirich: public pdf_internal<eDirich> {
652protected:
653        //! constant \f$ k \f$ of the random walk
654        double k;
655        //! cache of beta_i
656        vec &_beta;
657        //! stabilizing coefficient \f$ \beta_c \f$
658        vec betac;
659public:
660        mDirich() : pdf_internal<eDirich>(), _beta ( iepdf._beta() ) {};
661        void condition ( const vec &val ) {
662                _beta =  val / k + betac;
663        };
664        /*! Create Dirichlet random walk
665        \f[ f(rv|rvc) = Di(rvc*k) \f]
666        from structure
667        \code
668        class = 'mDirich';
669        k = 1;                      // multiplicative constant k
670        --- optional ---
671        rv = RV({'name'},size)      // description of RV
672        beta0 = [];                 // initial value of beta
673        betac = [];                 // initial value of beta
674        \endcode
675        */
676        void from_setting ( const Setting &set );
677        void    to_setting  (Setting  &set) const;
678        void validate();
679};
680UIREGISTER ( mDirich );
681
682/*! \brief Random Walk with vector Beta distribution
683Using simple assignment
684\f{align}
685\alpha &= rvc / k + \beta_c \\
686\beta &= (1-rvc) / k + \beta_c \\
687\f{align}
688for each element of alpha and beta, mean value = rvc, variance = (k+1)*mean*mean;
689
690The greater \f$ k \f$ is, the greater is the variance of the random walk;
691
692\f$ \beta_c \f$ is used as regularizing element to avoid corner cases, i.e. when one element of rvc is zero.
693By default is it set to 0.1;
694*/
695
696class mBeta: public pdf_internal<eBeta>{
697        //! vector of constants \f$ k \f$ of the random walk
698        vec k;
699        //! stabilizing coefficient \f$ \beta_c \f$
700        vec betac;
701
702        public:
703                void condition ( const vec &val ) {
704                        this->iepdf.alpha =  elem_div(val , k) + betac;
705                        this->iepdf.beta =  elem_div (1-val , k) + betac;
706                };
707                /*! Create Beta random walk
708                \f[ f(rv|rvc) = \prod Beta(rvc,k) \f]
709                from structure
710                \code
711                class = 'mBeta';
712                k = 1;                      // multiplicative constant k
713                --- optional ---
714                rv = RV({'name'},size)      // description of RV
715                beta  = [];                 // initial value of beta
716                betac = [];                 // initial value of beta stabilizing constant
717                \endcode
718                */
719                void from_setting ( const Setting &set );
720                void    to_setting  (Setting  &set) const;
721                void validate(){
722                       
723                        pdf_internal<eBeta>::validate();
724                        bdm_assert(betac.length()==dimension(),"Incomaptible betac");
725                        bdm_assert(k.length()==dimension(),"Incomaptible k");
726                        dimc = iepdf.dimension();
727                }
728                //!
729};
730UIREGISTER(mBeta);
731
732//! \brief Estimator for Multinomial density
733class multiBM : public BMEF {
734protected:
735        //! Conjugate prior and posterior
736        eDirich est;
737        //! Pointer inside est to sufficient statistics
738        vec &beta;
739public:
740        //!Default constructor
741        multiBM () : BMEF (), est (), beta ( est._beta() ) {
742                if ( beta.length() > 0 ) {
743                        last_lognc = est.lognc();
744                } else {
745                        last_lognc = 0.0;
746                }
747        }
748        //!Copy constructor
749        multiBM ( const multiBM &B ) : BMEF ( B ), est ( B.est ), beta ( est._beta() ) {}
750        //! Sets sufficient statistics to match that of givefrom mB0
751        void set_statistics ( const BM* mB0 ) {
752                const multiBM* mB = dynamic_cast<const multiBM*> ( mB0 );
753                beta = mB->beta;
754        }
755        void bayes ( const vec &yt, const vec &cond = empty_vec );
756
757        double logpred ( const vec &yt ) const;
758
759        void flatten ( const BMEF* B , double weight);
760
761        //! return correctly typed posterior (covariant return)
762        const eDirich& posterior() const {
763                return est;
764        };
765        //! constructor function
766        void set_parameters ( const vec &beta0 ) {
767                est.set_parameters ( beta0 );
768                est.validate();
769                if ( evalll ) {
770                        last_lognc = est.lognc();
771                }
772        }
773
774        void to_setting ( Setting &set ) const {
775                BMEF::to_setting ( set );
776                UI::save( &est, set, "prior" );
777        }
778        void from_setting (const Setting &set )  {
779                BMEF::from_setting ( set );
780                UI::get( est, set, "prior" );
781        }
782};
783UIREGISTER( multiBM );
784
785/*!
786 \brief Gamma posterior density
787
788 Multivariate Gamma density as product of independent univariate densities.
789 \f[
790 f(x|\alpha,\beta) = \prod f(x_i|\alpha_i,\beta_i)
791 \f]
792*/
793
794class egamma : public eEF {
795protected:
796        //! Vector \f$\alpha\f$
797        vec alpha;
798        //! Vector \f$\beta\f$
799        vec beta;
800public :
801        //! \name Constructors
802        //!@{
803        egamma () : eEF (), alpha ( 0 ), beta ( 0 ) {};
804        egamma ( const vec &a, const vec &b ) {
805                set_parameters ( a, b );
806                validate();
807        };
808        void set_parameters ( const vec &a, const vec &b ) {
809                alpha = a, beta = b;
810        };
811        //!@}
812
813        vec sample() const;
814        double evallog ( const vec &val ) const;
815        double lognc () const;
816        //! Returns pointer to internal alpha. Potentially dengerous: use with care!
817        vec& _alpha() {
818                return alpha;
819        }
820        //! Returns pointer to internal beta. Potentially dengerous: use with care!
821        vec& _beta() {
822                return beta;
823        }
824        vec mean() const {
825                return elem_div ( alpha, beta );
826        }
827        vec variance() const {
828                return elem_div ( alpha, elem_mult ( beta, beta ) );
829        }
830
831        /*! Create Gamma density
832        \f[ f(rv|rvc) = \Gamma(\alpha, \beta) \f]
833        from structure
834        \code
835        class = 'egamma';
836        alpha = [...];         // vector of alpha
837        beta = [...];          // vector of beta
838        rv = RV({'name'})      // description of RV
839        \endcode
840        */
841        void from_setting ( const Setting &set );
842        void to_setting ( Setting &set ) const;
843        void validate(); 
844};
845UIREGISTER ( egamma );
846SHAREDPTR ( egamma );
847
848/*!
849 \brief Inverse-Gamma posterior density
850
851 Multivariate inverse-Gamma density as product of independent univariate densities.
852 \f[
853 f(x|\alpha,\beta) = \prod f(x_i|\alpha_i,\beta_i)
854 \f]
855
856Vector \f$\beta\f$ has different meaning (in fact it is 1/beta as used in definition of iG)
857
858 Inverse Gamma can be converted to Gamma using \f[
859 x\sim iG(a,b) => 1/x\sim G(a,1/b)
860\f]
861This relation is used in sampling.
862 */
863
864class eigamma : public egamma {
865protected:
866public :
867        //! \name Constructors
868        //! All constructors are inherited
869        //!@{
870        //!@}
871
872        vec sample() const {
873                return 1.0 / egamma::sample();
874        };
875        //! Returns poiter to alpha and beta. Potentially dangerous: use with care!
876        vec mean() const {
877                return elem_div ( beta, alpha - 1 );
878        }
879        vec variance() const {
880                vec mea = mean();
881                return elem_div ( elem_mult ( mea, mea ), alpha - 2 );
882        }
883};
884/*
885//! Weighted mixture of epdfs with external owned components.
886class emix : public epdf {
887protected:
888        int n;
889        vec &w;
890        Array<epdf*> Coms;
891public:
892//! Default constructor
893        emix ( const RV &rv, vec &w0): epdf(rv), n(w0.length()), w(w0), Coms(n) {};
894        void set_parameters( int &i, double wi, epdf* ep){w(i)=wi;Coms(i)=ep;}
895        vec mean(){vec pom; for(int i=0;i<n;i++){pom+=Coms(i)->mean()*w(i);} return pom;};
896};
897*/
898
899//!  Uniform distributed density on a rectangular support
900
901class euni: public epdf {
902protected:
903//! lower bound on support
904        vec low;
905//! upper bound on support
906        vec high;
907//! internal
908        vec distance;
909//! normalizing coefficients
910        double nk;
911//! cache of log( \c nk )
912        double lnk;
913public:
914        //! \name Constructors
915        //!@{
916        euni () : epdf () {}
917        euni ( const vec &low0, const vec &high0 ) {
918                set_parameters ( low0, high0 );
919        }
920        void set_parameters ( const vec &low0, const vec &high0 ) {
921                distance = high0 - low0;
922                low = low0;
923                high = high0;
924                nk = prod ( 1.0 / distance );
925                lnk = log ( nk );
926        }
927        //!@}
928
929        double evallog ( const vec &val ) const  {
930                if ( any ( val < low ) && any ( val > high ) ) {
931                        return -inf;
932                } else return lnk;
933        }
934        vec sample() const {
935                vec smp ( dim );
936#pragma omp critical
937                UniRNG.sample_vector ( dim , smp );
938                return low + elem_mult ( distance, smp );
939        }
940        //! set values of \c low and \c high
941        vec mean() const {
942                return ( high - low ) / 2.0;
943        }
944        vec variance() const {
945                return ( pow ( high, 2 ) + pow ( low, 2 ) + elem_mult ( high, low ) ) / 3.0;
946        }
947        /*! Create Uniform density
948        \f[ f(rv) = U(low,high) \f]
949        from structure
950         \code
951         class = 'euni'
952         high = [...];          // vector of upper bounds
953         low = [...];           // vector of lower bounds
954         rv = RV({'name'});     // description of RV
955         \endcode
956         */
957        void from_setting ( const Setting &set );
958        void    to_setting  (Setting  &set) const;
959        void validate();
960};
961UIREGISTER ( euni );
962
963//! Uniform density with conditional mean value
964class mguni : public pdf_internal<euni> {
965        //! function of the mean value
966        shared_ptr<fnc> mean;
967        //! distance from mean to both sides
968        vec delta;
969public:
970        void condition ( const vec &cond ) {
971                vec mea = mean->eval ( cond );
972                iepdf.set_parameters ( mea - delta, mea + delta );
973        }
974        //! load from
975        void from_setting ( const Setting &set ) {
976                pdf::from_setting ( set ); //reads rv and rvc
977                UI::get ( delta, set, "delta", UI::compulsory );
978                mean = UI::build<fnc> ( set, "mean", UI::compulsory );
979                iepdf.set_parameters ( -delta, delta );
980        }
981        void    to_setting  (Setting  &set) const {
982                pdf::to_setting ( set ); 
983                UI::save( iepdf.mean(), set, "delta");
984                UI::save(mean, set, "mean");
985        }
986        void validate(){
987                pdf_internal<euni>::validate();
988                dimc = mean->dimensionc();
989               
990        }
991
992};
993UIREGISTER ( mguni );
994/*!
995 \brief Normal distributed linear function with linear function of mean value;
996
997 Mean value \f$ \mu=A*\mbox{rvc}+\mu_0 \f$.
998*/
999template < class sq_T, template <typename> class TEpdf = enorm >
1000class mlnorm : public pdf_internal< TEpdf<sq_T> > {
1001protected:
1002        //! Internal epdf that arise by conditioning on \c rvc
1003        mat A;
1004        //! Constant additive term
1005        vec mu_const;
1006//                      vec& _mu; //cached epdf.mu; !!!!!! WHY NOT?
1007public:
1008        //! \name Constructors
1009        //!@{
1010        mlnorm() : pdf_internal< TEpdf<sq_T> >() {};
1011        mlnorm ( const mat &A, const vec &mu0, const sq_T &R ) : pdf_internal< TEpdf<sq_T> >() {
1012                set_parameters ( A, mu0, R );
1013                validate();
1014        }
1015
1016        //! Set \c A and \c R
1017        void set_parameters ( const  mat &A0, const vec &mu0, const sq_T &R0 ) {
1018                this->iepdf.set_parameters ( zeros ( A0.rows() ), R0 );
1019                A = A0;
1020                mu_const = mu0;
1021        }
1022
1023        //!@}
1024        //! Set value of \c rvc . Result of this operation is stored in \c epdf use function \c _ep to access it.
1025        void condition ( const vec &cond ) {
1026                this->iepdf._mu() = A * cond + mu_const;
1027//R is already assigned;
1028        }
1029
1030        //!access function
1031        const vec& _mu_const() const {
1032                return mu_const;
1033        }
1034        //!access function
1035        const mat& _A() const {
1036                return A;
1037        }
1038        //!access function
1039        mat _R() const {
1040                return this->iepdf._R().to_mat();
1041        }
1042        //!access function
1043        sq_T __R() const {
1044                return this->iepdf._R();
1045        }
1046
1047        //! Debug stream
1048        template<typename sq_M>
1049        friend std::ostream &operator<< ( std::ostream &os,  mlnorm<sq_M, enorm> &ml );
1050
1051        /*! Create Normal density with linear function of mean value
1052         \f[ f(rv|rvc) = N(A*rvc+const, R) \f]
1053        from structure
1054        \code
1055        class = 'mlnorm<ldmat>', (OR) 'mlnorm<chmat>', (OR) 'mlnorm<fsqmat>';
1056        A     = [];                  // matrix or vector of appropriate dimension
1057        R     = [];                  // square matrix of appropriate dimension
1058        --- optional ---
1059        const = zeros(A.rows);       // vector of constant term
1060        \endcode
1061        */
1062        void from_setting ( const Setting &set ) {
1063                pdf::from_setting ( set );
1064
1065                UI::get ( A, set, "A", UI::compulsory );
1066                UI::get ( mu_const, set, "const", UI::optional);
1067                mat R0;
1068                UI::get ( R0, set, "R", UI::compulsory );
1069                set_parameters ( A, mu_const, R0 );
1070        }
1071
1072void to_setting (Setting &set) const {
1073                pdf::to_setting(set);
1074                UI::save ( A, set, "A");
1075                UI::save ( mu_const, set, "const");
1076                UI::save ( _R(), set, "R");
1077        }
1078
1079void validate() {
1080                pdf_internal<TEpdf<sq_T> >::validate();
1081                if (mu_const.length()==0) { // default in from_setting
1082                        mu_const=zeros(A.rows());
1083                }
1084                bdm_assert ( A.rows() == mu_const.length(), "mlnorm: A vs. mu mismatch" );
1085                bdm_assert ( A.rows() == _R().rows(), "mlnorm: A vs. R mismatch" );
1086                this->dimc = A.cols();
1087
1088        }
1089};
1090UIREGISTER2 ( mlnorm, ldmat );
1091SHAREDPTR2 ( mlnorm, ldmat );
1092UIREGISTER2 ( mlnorm, fsqmat );
1093SHAREDPTR2 ( mlnorm, fsqmat );
1094UIREGISTER2 ( mlnorm, chmat );
1095SHAREDPTR2 ( mlnorm, chmat );
1096
1097//! \class mlgauss
1098//!\brief Normal distribution with linear function of mean value. Same as mlnorm<fsqmat>.
1099typedef mlnorm<fsqmat> mlgauss;
1100UIREGISTER(mlgauss);
1101
1102//! pdf with general function for mean value
1103template<class sq_T>
1104class mgnorm : public pdf_internal< enorm< sq_T > > {
1105private:
1106//                      vec &mu; WHY NOT?
1107        shared_ptr<fnc> g;
1108
1109public:
1110        //!default constructor
1111        mgnorm() : pdf_internal<enorm<sq_T> >() { }
1112        //!set mean function
1113        inline void set_parameters ( const shared_ptr<fnc> &g0, const sq_T &R0 );
1114        inline void condition ( const vec &cond );
1115
1116
1117        /*! Create Normal density with given function of mean value
1118        \f[ f(rv|rvc) = N( g(rvc), R) \f]
1119        from structure
1120        \code
1121        class = 'mgnorm';
1122        g.class =  'fnc';      // function for mean value evolution
1123        g._fields_of_fnc = ...;
1124
1125        R = [1, 0;             // covariance matrix
1126                0, 1];
1127                --OR --
1128        dR = [1, 1];           // diagonal of cavariance matrix
1129
1130        rv = RV({'name'})      // description of RV
1131        rvc = RV({'name'})     // description of RV in condition
1132        \endcode
1133        */
1134
1135
1136void from_setting ( const Setting &set ) {
1137                pdf::from_setting ( set );
1138                shared_ptr<fnc> g = UI::build<fnc> ( set, "g", UI::compulsory );
1139
1140                mat R;
1141                vec dR;
1142                if ( UI::get ( dR, set, "dR" ) )
1143                        R = diag ( dR );
1144                else
1145                        UI::get ( R, set, "R", UI::compulsory );
1146
1147                set_parameters ( g, R );
1148                //validate();
1149        }
1150       
1151
1152void to_setting  (Setting  &set) const {
1153                UI::save( g,set, "g");
1154                UI::save(this->iepdf._R().to_mat(),set, "R");
1155       
1156        }
1157
1158
1159
1160void validate() {
1161                this->iepdf.validate();
1162                bdm_assert ( g->dimension() == this->iepdf.dimension(), "incompatible function" );
1163                this->dim = g->dimension();
1164                this->dimc = g->dimensionc();
1165                this->iepdf.validate();
1166        }
1167
1168};
1169
1170UIREGISTER2 ( mgnorm, chmat );
1171UIREGISTER2 ( mgnorm, ldmat );
1172SHAREDPTR2 ( mgnorm, chmat );
1173
1174
1175/*! (Approximate) Student t density with linear function of mean value
1176
1177The internal epdf of this class is of the type of a Gaussian (enorm).
1178However, each conditioning is trying to assure the best possible approximation by taking into account the zeta function. See [] for reference.
1179
1180Perhaps a moment-matching technique?
1181*/
1182class mlstudent : public mlnorm<ldmat, enorm> {
1183protected:
1184        //! Variable \f$ \Lambda \f$ from theory
1185        ldmat Lambda;
1186        //! Reference to variable \f$ R \f$
1187        ldmat &_R;
1188        //! Variable \f$ R_e \f$
1189        ldmat Re;
1190public:
1191        mlstudent () : mlnorm<ldmat, enorm> (),
1192                        Lambda (),      _R ( iepdf._R() ) {}
1193        //! constructor function
1194        void set_parameters ( const mat &A0, const vec &mu0, const ldmat &R0, const ldmat& Lambda0 ) {
1195                iepdf.set_parameters ( mu0, R0 );// was Lambda, why?
1196                A = A0;
1197                mu_const = mu0;
1198                Re = R0;
1199                Lambda = Lambda0;
1200        }
1201
1202        void condition ( const vec &cond ); 
1203
1204        void validate() {
1205                mlnorm<ldmat, enorm>::validate();
1206                bdm_assert ( A.rows() == mu_const.length(), "mlstudent: A vs. mu mismatch" );
1207                bdm_assert ( _R.rows() == A.rows(), "mlstudent: A vs. R mismatch" );
1208
1209        }
1210};
1211
1212/*!
1213\brief  Gamma random walk
1214
1215Mean value, \f$\mu\f$, of this density is given by \c rvc .
1216Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
1217This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
1218
1219The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
1220*/
1221class mgamma : public pdf_internal<egamma> {
1222protected:
1223
1224        //! Constant \f$k\f$
1225        double k;
1226
1227        //! cache of iepdf.beta
1228        vec &_beta;
1229
1230public:
1231        //! Constructor
1232        mgamma() : pdf_internal<egamma>(), k ( 0 ),
1233                        _beta ( iepdf._beta() ) {
1234        }
1235
1236        //! Set value of \c k
1237        void set_parameters ( double k, const vec &beta0 );
1238
1239        void condition ( const vec &val ) {
1240                _beta = k / val;
1241        };
1242        /*! Create Gamma density with conditional mean value
1243        \f[ f(rv|rvc) = \Gamma(k, k/rvc) \f]
1244        from structure
1245        \code
1246          class = 'mgamma';
1247          beta = [...];          // vector of initial alpha
1248          k = 1.1;               // multiplicative constant k
1249          rv = RV({'name'})      // description of RV
1250          rvc = RV({'name'})     // description of RV in condition
1251         \endcode
1252        */
1253        void from_setting ( const Setting &set );
1254        void    to_setting  (Setting  &set) const;
1255        void validate();
1256};
1257UIREGISTER ( mgamma );
1258SHAREDPTR ( mgamma );
1259
1260/*!
1261\brief  Inverse-Gamma random walk
1262
1263Mean value, \f$ \mu \f$, of this density is given by \c rvc .
1264Standard deviation of the random walk is proportional to one \f$ k \f$-th the mean.
1265This is achieved by setting \f$ \alpha=\mu/k^2+2 \f$ and \f$ \beta=\mu(\alpha-1)\f$.
1266
1267The standard deviation of the walk is then: \f$ \mu/\sqrt(k)\f$.
1268 */
1269class migamma : public pdf_internal<eigamma> {
1270protected:
1271        //! Constant \f$k\f$
1272        double k;
1273
1274        //! cache of iepdf.alpha
1275        vec &_alpha;
1276
1277        //! cache of iepdf.beta
1278        vec &_beta;
1279
1280public:
1281        //! \name Constructors
1282        //!@{
1283        migamma() : pdf_internal<eigamma>(),
1284                        k ( 0 ),
1285                        _alpha ( iepdf._alpha() ),
1286                        _beta ( iepdf._beta() ) {
1287        }
1288
1289        migamma ( const migamma &m ) : pdf_internal<eigamma>(),
1290                        k ( 0 ),
1291                        _alpha ( iepdf._alpha() ),
1292                        _beta ( iepdf._beta() ) {
1293        }
1294        //!@}
1295
1296        //! Set value of \c k
1297        void set_parameters ( int len, double k0 ) {
1298                k = k0;
1299                iepdf.set_parameters ( ( 1.0 / ( k*k ) + 2.0 ) *ones ( len ) /*alpha*/, ones ( len ) /*beta*/ );               
1300        };
1301
1302        void    validate (){
1303                pdf_internal<eigamma>::validate();
1304                dimc = dimension();
1305};
1306
1307        void condition ( const vec &val ) {
1308                _beta = elem_mult ( val, ( _alpha - 1.0 ) );
1309        };
1310};
1311
1312
1313/*!
1314\brief  Gamma random walk around a fixed point
1315
1316Mean 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
1317\f[ \mu = \mu_{t-1} ^{l} p^{1-l}\f]
1318
1319Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
1320This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
1321
1322The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
1323*/
1324class mgamma_fix : public mgamma {
1325protected:
1326        //! parameter l
1327        double l;
1328        //! reference vector
1329        vec refl;
1330public:
1331        //! Constructor
1332        mgamma_fix () : mgamma (), refl () {};
1333        //! Set value of \c k
1334        void set_parameters ( double k0 , vec ref0, double l0 ) {
1335                mgamma::set_parameters ( k0, ref0 );
1336                refl = pow ( ref0, 1.0 - l0 );
1337                l = l0; 
1338        };
1339
1340        void    validate (){
1341                mgamma::validate();
1342                dimc = dimension();
1343        };
1344
1345        void condition ( const vec &val ) {
1346                vec mean = elem_mult ( refl, pow ( val, l ) );
1347                _beta = k / mean;
1348        };
1349};
1350
1351
1352/*!
1353\brief  Inverse-Gamma random walk around a fixed point
1354
1355Mean 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
1356\f[ \mu = \mu_{t-1} ^{l} p^{1-l}\f]
1357
1358==== Check == vv =
1359Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
1360This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
1361
1362The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
1363 */
1364class migamma_ref : public migamma {
1365protected:
1366        //! parameter l
1367        double l;
1368        //! reference vector
1369        vec refl;
1370public:
1371        //! Constructor
1372        migamma_ref () : migamma (), refl () {};
1373       
1374        //! Set value of \c k
1375        void set_parameters ( double k0 , vec ref0, double l0 ) {
1376                migamma::set_parameters ( ref0.length(), k0 );
1377                refl = pow ( ref0, 1.0 - l0 );
1378                l = l0;
1379        };
1380
1381        void validate(){
1382                migamma::validate();
1383                dimc = dimension();
1384        };
1385       
1386        void condition ( const vec &val ) {
1387                vec mean = elem_mult ( refl, pow ( val, l ) );
1388                migamma::condition ( mean );
1389        };
1390
1391
1392        /*! Create inverse-Gamma density with conditional mean value
1393        \f[ f(rv|rvc) = i\Gamma(k, k/(rvc^l \circ ref^{(1-l)}) \f]
1394        from structure
1395        \code
1396        class = 'migamma_ref';
1397        ref = [1e-5; 1e-5; 1e-2 1e-3];            // reference vector
1398        l = 0.999;                                // constant l
1399        k = 0.1;                                  // constant k
1400        rv = RV({'name'})                         // description of RV
1401        rvc = RV({'name'})                        // description of RV in condition
1402        \endcode
1403         */
1404        void from_setting ( const Setting &set );
1405
1406        void to_setting  (Setting  &set) const; 
1407};
1408
1409
1410UIREGISTER ( migamma_ref );
1411SHAREDPTR ( migamma_ref );
1412
1413/*! Log-Normal probability density
1414 only allow diagonal covariances!
1415
1416Density of the form \f$ \log(x)\sim \mathcal{N}(\mu,\sigma^2) \f$ , i.e.
1417\f[
1418x \sim \frac{1}{x\sigma\sqrt{2\pi}}\exp{-\frac{1}{2\sigma^2}(\log(x)-\mu)}
1419\f]
1420
1421Function from_setting loads mu and R in the same way as it does for enorm<>!
1422*/
1423class elognorm: public enorm<ldmat> {
1424public:
1425        vec sample() const {
1426                return exp ( enorm<ldmat>::sample() );
1427        };
1428        vec mean() const {
1429                vec var = enorm<ldmat>::variance();
1430                return exp ( mu - 0.5*var );
1431        };
1432
1433};
1434
1435/*!
1436\brief  Log-Normal random walk
1437
1438Mean value, \f$\mu\f$, is...
1439
1440 */
1441class mlognorm : public pdf_internal<elognorm> {
1442protected:
1443        //! parameter 1/2*sigma^2
1444        double sig2;
1445
1446        //! access
1447        vec &mu;
1448public:
1449        //! Constructor
1450        mlognorm() : pdf_internal<elognorm>(),
1451                        sig2 ( 0 ),
1452                        mu ( iepdf._mu() ) {
1453        }
1454
1455        //! Set value of \c k
1456        void set_parameters ( int size, double k ) {
1457                sig2 = 0.5 * log ( k * k + 1 );
1458                iepdf.set_parameters ( zeros ( size ), 2*sig2*eye ( size ) );
1459        };
1460       
1461        void validate(){
1462                pdf_internal<elognorm>::validate();
1463                dimc = iepdf.dimension();
1464        }
1465
1466        void condition ( const vec &val ) {
1467                mu = log ( val ) - sig2;//elem_mult ( refl,pow ( val,l ) );
1468        };
1469
1470        /*! Create logNormal random Walk
1471        \f[ f(rv|rvc) = log\mathcal{N}( \log(rvc)-0.5\log(k^2+1), k I) \f]
1472        from structure
1473        \code
1474        class = 'mlognorm';
1475        k   = 0.1;               // "variance" k
1476        mu0 = 0.1;               // Initial value of mean
1477        rv  = RV({'name'})       // description of RV
1478        rvc = RV({'name'})       // description of RV in condition
1479        \endcode
1480        */
1481        void from_setting ( const Setting &set );
1482       
1483        void to_setting  (Setting  &set) const; 
1484};
1485
1486UIREGISTER ( mlognorm );
1487SHAREDPTR ( mlognorm );
1488
1489/*! inverse Wishart density defined on Choleski decomposition
1490
1491*/
1492class eWishartCh : public epdf {
1493protected:
1494        //! Upper-Triagle of Choleski decomposition of \f$ \Psi \f$
1495        chmat Y;
1496        //! dimension of matrix  \f$ \Psi \f$
1497        int p;
1498        //! degrees of freedom  \f$ \nu \f$
1499        double delta;
1500public:
1501        //! Set internal structures
1502        void set_parameters ( const mat &Y0, const double delta0 ) {
1503                Y = chmat ( Y0 );
1504                delta = delta0;
1505                p = Y.rows();   
1506        }
1507        //! Set internal structures
1508        void set_parameters ( const chmat &Y0, const double delta0 ) {
1509                Y = Y0;
1510                delta = delta0;
1511                p = Y.rows();
1512                }
1513       
1514        virtual void validate (){
1515                epdf::validate();
1516                dim = p * p;
1517        }
1518
1519        //! Sample matrix argument
1520        mat sample_mat() const {
1521                mat X = zeros ( p, p );
1522
1523                //sample diagonal
1524                for ( int i = 0; i < p; i++ ) {
1525                        GamRNG.setup ( 0.5* ( delta - i ) , 0.5 );   // no +1 !! index if from 0
1526#pragma omp critical
1527                        X ( i, i ) = sqrt ( GamRNG() );
1528                }
1529                //do the rest
1530                for ( int i = 0; i < p; i++ ) {
1531                        for ( int j = i + 1; j < p; j++ ) {
1532#pragma omp critical
1533                                X ( i, j ) = NorRNG.sample();
1534                        }
1535                }
1536                return X*Y._Ch();// return upper triangular part of the decomposition
1537        }
1538
1539        vec sample () const {
1540                return vec ( sample_mat()._data(), p*p );
1541        }
1542
1543        virtual vec mean() const NOT_IMPLEMENTED(0);
1544
1545        //! return expected variance (not covariance!)
1546        virtual vec variance() const NOT_IMPLEMENTED(0);
1547
1548        virtual double evallog ( const vec &val ) const NOT_IMPLEMENTED(0);
1549
1550        //! fast access function y0 will be copied into Y.Ch.
1551        void setY ( const mat &Ch0 ) {
1552                copy_vector ( dim, Ch0._data(), Y._Ch()._data() );
1553        }
1554
1555        //! fast access function y0 will be copied into Y.Ch.
1556        void _setY ( const vec &ch0 ) {
1557                copy_vector ( dim, ch0._data(), Y._Ch()._data() );
1558        }
1559
1560        //! access function
1561        const chmat& getY() const {
1562                return Y;
1563        }
1564};
1565
1566//! Inverse Wishart on Choleski decomposition
1567/*! Being computed by conversion from `standard' Wishart
1568*/
1569class eiWishartCh: public epdf {
1570protected:
1571        //! Internal instance of Wishart density
1572        eWishartCh W;
1573        //! size of Ch
1574        int p;
1575        //! parameter delta
1576        double delta;
1577public:
1578        //! constructor function
1579        void set_parameters ( const mat &Y0, const double delta0 ) {
1580                delta = delta0;
1581                W.set_parameters ( inv ( Y0 ), delta0 );
1582                p = Y0.rows();
1583        }
1584       
1585        virtual void    validate (){
1586                epdf::validate();
1587                W.validate();
1588                dim = W.dimension();
1589        }
1590       
1591       
1592        vec sample() const {
1593                mat iCh;
1594                iCh = inv ( W.sample_mat() );
1595                return vec ( iCh._data(), dim );
1596        }
1597        //! access function
1598        void _setY ( const vec &y0 ) {
1599                mat Ch ( p, p );
1600                mat iCh ( p, p );
1601                copy_vector ( dim, y0._data(), Ch._data() );
1602
1603                iCh = inv ( Ch );
1604                W.setY ( iCh );
1605        }
1606
1607        virtual double evallog ( const vec &val ) const {
1608                chmat X ( p );
1609                const chmat& Y = W.getY();
1610
1611                copy_vector ( p*p, val._data(), X._Ch()._data() );
1612                chmat iX ( p );
1613                X.inv ( iX );
1614                // compute
1615//                              \frac{ |\Psi|^{m/2}|X|^{-(m+p+1)/2}e^{-tr(\Psi X^{-1})/2} }{ 2^{mp/2}\Gamma_p(m/2)},
1616                mat M = Y.to_mat() * iX.to_mat();
1617
1618                double log1 = 0.5 * p * ( 2 * Y.logdet() ) - 0.5 * ( delta + p + 1 ) * ( 2 * X.logdet() ) - 0.5 * trace ( M );
1619                //Fixme! Multivariate gamma omitted!! it is ok for sampling, but not otherwise!!
1620
1621                /*                              if (0) {
1622                                                        mat XX=X.to_mat();
1623                                                        mat YY=Y.to_mat();
1624
1625                                                        double log2 = 0.5*p*log(det(YY))-0.5*(delta+p+1)*log(det(XX))-0.5*trace(YY*inv(XX));
1626                                                        cout << log1 << "," << log2 << endl;
1627                                                }*/
1628                return log1;
1629        };
1630
1631        virtual vec mean() const NOT_IMPLEMENTED(0);
1632
1633        //! return expected variance (not covariance!)
1634        virtual vec variance() const NOT_IMPLEMENTED(0);
1635};
1636
1637//! Random Walk on inverse Wishart
1638class rwiWishartCh : public pdf_internal<eiWishartCh> {
1639protected:
1640        //!square root of \f$ \nu-p-1 \f$ - needed for computation of \f$ \Psi \f$ from conditions
1641        double sqd;
1642        //!reference point for diagonal
1643        vec refl;
1644        //! power of the reference
1645        double l;
1646        //! dimension
1647        int p;
1648
1649public:
1650        rwiWishartCh() : sqd ( 0 ), l ( 0 ), p ( 0 ) {}
1651        //! constructor function
1652        void set_parameters ( int p0, double k, vec ref0, double l0 ) {
1653                p = p0;
1654                double delta = 2 / ( k * k ) + p + 3;
1655                sqd = sqrt ( delta - p - 1 );
1656                l = l0;
1657                refl = pow ( ref0, 1 - l );
1658                iepdf.set_parameters ( eye ( p ), delta );
1659        };
1660       
1661        void validate(){
1662                pdf_internal<eiWishartCh>::validate();
1663                dimc = iepdf.dimension();
1664        }
1665       
1666        void condition ( const vec &c ) {
1667                vec z = c;
1668                int ri = 0;
1669                for ( int i = 0; i < p*p; i += ( p + 1 ) ) {//trace diagonal element
1670                        z ( i ) = pow ( z ( i ), l ) * refl ( ri );
1671                        ri++;
1672                }
1673
1674                iepdf._setY ( sqd*z );
1675        }
1676};
1677
1678//! Switch between various resampling methods.
1679enum RESAMPLING_METHOD { MULTINOMIAL = 0, STRATIFIED = 1, SYSTEMATIC = 3 };
1680
1681//! Shortcut for multinomial.sample(int n). Various simplifications are allowed see RESAMPLING_METHOD
1682void resample(const vec &w, ivec &ind, RESAMPLING_METHOD=SYSTEMATIC);
1683
1684/*!
1685\brief Weighted empirical density
1686
1687Used e.g. in particle filters.
1688*/
1689class eEmp: public epdf {
1690protected :
1691        //! Number of particles
1692        int n;
1693        //! Sample weights \f$w\f$
1694        vec w;
1695        //! Samples \f$x^{(i)}, i=1..n\f$
1696        Array<vec> samples;
1697public:
1698        //! \name Constructors
1699        //!@{
1700        eEmp () : epdf (), w (), samples () {};
1701        //! copy constructor
1702        eEmp ( const eEmp &e ) : epdf ( e ), w ( e.w ), samples ( e.samples ) {};
1703        //!@}
1704
1705        //! Set samples and weights
1706        void set_statistics ( const vec &w0, const epdf &pdf0 );
1707        //! Set samples and weights
1708        void set_statistics ( const epdf &pdf0 , int n ) {
1709                set_statistics ( ones ( n ) / n, pdf0 );
1710        };
1711        //! Set sample
1712        void set_samples ( const epdf* pdf0 );
1713        //! Set sample
1714        void set_parameters ( int n0, bool copy = true ) {
1715                n = n0;
1716                w.set_size ( n0, copy );
1717                samples.set_size ( n0, copy );
1718        };
1719        //! Set samples
1720        void set_parameters ( const Array<vec> &Av ) {
1721                n = Av.size();
1722                w = 1 / n * ones ( n );
1723                samples = Av;
1724        };
1725        virtual void    validate ();
1726        //! Potentially dangerous, use with care.
1727        vec& _w()  {
1728                return w;
1729        };
1730        //! Potentially dangerous, use with care.
1731        const vec& _w() const {
1732                return w;
1733        };
1734        //! access function
1735        Array<vec>& _samples() {
1736                return samples;
1737        };
1738        //! access function
1739        const vec& _sample ( int i ) const {
1740                return samples ( i );
1741        };
1742        //! access function
1743        const Array<vec>& _samples() const {
1744                return samples;
1745        };
1746        //! 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.
1747        void resample ( RESAMPLING_METHOD method = SYSTEMATIC );
1748
1749        //! inherited operation : NOT implemented
1750        vec sample() const NOT_IMPLEMENTED(0);
1751
1752        //! inherited operation : NOT implemented
1753        double evallog ( const vec &val ) const NOT_IMPLEMENTED(0);
1754
1755        vec mean() const {
1756                vec pom = zeros ( dim );
1757                for ( int i = 0; i < n; i++ ) {
1758                        pom += samples ( i ) * w ( i );
1759                }
1760                return pom;
1761        }
1762        vec variance() const {
1763                vec pom = zeros ( dim );
1764                for ( int i = 0; i < n; i++ ) {
1765                        pom += pow ( samples ( i ), 2 ) * w ( i );
1766                }
1767                return pom - pow ( mean(), 2 );
1768        }
1769        //! For this class, qbounds are minimum and maximum value of the population!
1770        void qbounds ( vec &lb, vec &ub, double perc = 0.95 ) const;
1771
1772        void to_setting ( Setting &set ) const;
1773        void from_setting ( const Setting &set );
1774
1775};
1776UIREGISTER(eEmp);
1777
1778
1779////////////////////////
1780
1781template<class sq_T>
1782void enorm<sq_T>::set_parameters ( const vec &mu0, const sq_T &R0 ) {
1783//Fixme test dimensions of mu0 and R0;
1784        mu = mu0;
1785        R = R0;
1786        validate();
1787};
1788
1789template<class sq_T>
1790void enorm<sq_T>::from_setting ( const Setting &set ) {
1791        epdf::from_setting ( set ); //reads rv
1792
1793        UI::get ( mu, set, "mu", UI::compulsory );
1794        mat Rtmp;// necessary for conversion
1795        UI::get ( Rtmp, set, "R", UI::compulsory );
1796        R = Rtmp; // conversion
1797}
1798
1799template<class sq_T>
1800void enorm<sq_T>::validate() {
1801                eEF::validate();
1802                bdm_assert ( mu.length() == R.rows(), "mu and R parameters do not match" );
1803                dim = mu.length();
1804        }
1805
1806template<class sq_T>
1807void enorm<sq_T>::to_setting ( Setting &set ) const {
1808        epdf::to_setting ( set ); //reads rv   
1809        UI::save ( mu, set, "mu");
1810        UI::save ( R.to_mat(), set, "R");
1811}
1812
1813
1814
1815template<class sq_T>
1816void enorm<sq_T>::dupdate ( mat &v, double nu ) {
1817        //
1818};
1819
1820// template<class sq_T>
1821// void enorm<sq_T>::tupdate ( double phi, mat &vbar, double nubar ) {
1822//      //
1823// };
1824
1825template<class sq_T>
1826vec enorm<sq_T>::sample() const {
1827        vec x ( dim );
1828#pragma omp critical
1829        NorRNG.sample_vector ( dim, x );
1830        vec smp = R.sqrt_mult ( x );
1831
1832        smp += mu;
1833        return smp;
1834};
1835
1836// template<class sq_T>
1837// double enorm<sq_T>::eval ( const vec &val ) const {
1838//      double pdfl,e;
1839//      pdfl = evallog ( val );
1840//      e = exp ( pdfl );
1841//      return e;
1842// };
1843
1844template<class sq_T>
1845double enorm<sq_T>::evallog_nn ( const vec &val ) const {
1846        // 1.83787706640935 = log(2pi)
1847        double tmp = -0.5 * ( R.invqform ( mu - val ) );// - lognc();
1848        return  tmp;
1849};
1850
1851template<class sq_T>
1852inline double enorm<sq_T>::lognc () const {
1853        // 1.83787706640935 = log(2pi)
1854        double tmp = 0.5 * ( R.cols() * 1.83787706640935 + R.logdet() );
1855        return tmp;
1856};
1857
1858
1859// template<class sq_T>
1860// vec mlnorm<sq_T>::samplecond (const  vec &cond, double &lik ) {
1861//      this->condition ( cond );
1862//      vec smp = epdf.sample();
1863//      lik = epdf.eval ( smp );
1864//      return smp;
1865// }
1866
1867// template<class sq_T>
1868// mat mlnorm<sq_T>::samplecond (const vec &cond, vec &lik, int n ) {
1869//      int i;
1870//      int dim = rv.count();
1871//      mat Smp ( dim,n );
1872//      vec smp ( dim );
1873//      this->condition ( cond );
1874//
1875//      for ( i=0; i<n; i++ ) {
1876//              smp = epdf.sample();
1877//              lik ( i ) = epdf.eval ( smp );
1878//              Smp.set_col ( i ,smp );
1879//      }
1880//
1881//      return Smp;
1882// }
1883
1884
1885template<class sq_T>
1886shared_ptr<epdf> enorm<sq_T>::marginal ( const RV &rvn ) const {
1887        enorm<sq_T> *tmp = new enorm<sq_T> ();
1888        shared_ptr<epdf> narrow ( tmp );
1889        marginal ( rvn, *tmp );
1890        return narrow;
1891}
1892
1893template<class sq_T>
1894void enorm<sq_T>::marginal ( const RV &rvn, enorm<sq_T> &target ) const {
1895        bdm_assert ( isnamed(), "rv description is not assigned" );
1896        ivec irvn = rvn.dataind ( rv );
1897
1898        sq_T Rn ( R, irvn );  // select rows and columns of R
1899
1900        target.set_rv ( rvn );
1901        target.set_parameters ( mu ( irvn ), Rn );
1902}
1903
1904template<class sq_T>
1905shared_ptr<pdf> enorm<sq_T>::condition ( const RV &rvn ) const {
1906        mlnorm<sq_T> *tmp = new mlnorm<sq_T> ();
1907        shared_ptr<pdf> narrow ( tmp );
1908        condition ( rvn, *tmp );
1909        return narrow;
1910}
1911
1912template<class sq_T>
1913void enorm<sq_T>::condition ( const RV &rvn, pdf &target ) const {
1914        typedef mlnorm<sq_T> TMlnorm;
1915
1916        bdm_assert ( isnamed(), "rvs are not assigned" );
1917        TMlnorm &uptarget = dynamic_cast<TMlnorm &> ( target );
1918
1919        RV rvc = rv.subt ( rvn );
1920        bdm_assert ( ( rvc._dsize() + rvn._dsize() == rv._dsize() ), "wrong rvn" );
1921        //Permutation vector of the new R
1922        ivec irvn = rvn.dataind ( rv );
1923        ivec irvc = rvc.dataind ( rv );
1924        ivec perm = concat ( irvn , irvc );
1925        sq_T Rn ( R, perm );
1926
1927        //fixme - could this be done in general for all sq_T?
1928        mat S = Rn.to_mat();
1929        //fixme
1930        int n = rvn._dsize() - 1;
1931        int end = R.rows() - 1;
1932        mat S11 = S.get ( 0, n, 0, n );
1933        mat S12 = S.get ( 0, n , rvn._dsize(), end );
1934        mat S22 = S.get ( rvn._dsize(), end, rvn._dsize(), end );
1935
1936        vec mu1 = mu ( irvn );
1937        vec mu2 = mu ( irvc );
1938        mat A = S12 * inv ( S22 );
1939        sq_T R_n ( S11 - A *S12.T() );
1940
1941        uptarget.set_rv ( rvn );
1942        uptarget.set_rvc ( rvc );
1943        uptarget.set_parameters ( A, mu1 - A*mu2, R_n );
1944        uptarget.validate();
1945}
1946
1947/*! Dirac delta function distribution */
1948class dirac: public epdf{
1949        public: 
1950                vec point;
1951        public:
1952                double evallog (const vec &dt) const {return -inf;}
1953                vec mean () const {return point;}
1954                vec variance () const {return zeros(point.length());}
1955                void qbounds ( vec &lb, vec &ub, double percentage = 0.95 ) const { lb = point; ub = point;}
1956                //! access
1957                const vec& _point() {return point;}
1958                void set_point(const vec& p){point =p; dim=p.length();}
1959                vec sample() const {return point;}
1960        };
1961
1962////
1963///////
1964template<class sq_T>
1965void mgnorm<sq_T >::set_parameters ( const shared_ptr<fnc> &g0, const sq_T &R0 ) {
1966        g = g0;
1967        this->iepdf.set_parameters ( zeros ( g->dimension() ), R0 );
1968}
1969
1970template<class sq_T>
1971void mgnorm<sq_T >::condition ( const vec &cond ) {
1972        this->iepdf._mu() = g->eval ( cond );
1973};
1974
1975//! \todo unify this stuff with to_string()
1976template<class sq_T>
1977std::ostream &operator<< ( std::ostream &os,  mlnorm<sq_T> &ml ) {
1978        os << "A:" << ml.A << endl;
1979        os << "mu:" << ml.mu_const << endl;
1980        os << "R:" << ml._R() << endl;
1981        return os;
1982};
1983
1984}
1985#endif //EF_H
Note: See TracBrowser for help on using the browser.