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

Revision 1063, 48.8 kB (checked in by mido, 14 years ago)

a small patch of documentation, to be contiuned..

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