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

Revision 850, 45.5 kB (checked in by smidl, 14 years ago)

changes in Loggers!

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