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

Revision 1015, 44.9 kB (checked in by smidl, 14 years ago)

UI for ldmat - use it in egiw

  • 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;
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        /*! configuration structure
542        \code
543        class = 'eDirich';
544        beta  = [];           //parametr beta
545        \endcode
546        */
547        void from_setting ( const Setting &set );
548        void validate();
549        void to_setting ( Setting &set ) const;
550};
551UIREGISTER ( eDirich );
552
553/*! Random Walk on Dirichlet
554Using simple assignment
555 \f[ \beta = rvc / k + \beta_c \f]
556 hence, mean value = rvc, variance = (k+1)*mean*mean;
557
558 The greater k is, the greater is the variance of the random walk;
559
560 \f$ \beta_c \f$ is used as regularizing element to avoid corner cases, i.e. when one element of rvc is zero.
561 By default is it set to 0.1;
562*/
563
564class mDirich: public pdf_internal<eDirich> {
565protected:
566        //! constant \f$ k \f$ of the random walk
567        double k;
568        //! cache of beta_i
569        vec &_beta;
570        //! stabilizing coefficient \f$ \beta_c \f$
571        vec betac;
572public:
573        mDirich() : pdf_internal<eDirich>(), _beta ( iepdf._beta() ) {};
574        void condition ( const vec &val ) {
575                _beta =  val / k + betac;
576        };
577        /*! Create Dirichlet random walk
578        \f[ f(rv|rvc) = Di(rvc*k) \f]
579        from structure
580        \code
581        class = 'mDirich';
582        k = 1;                      // multiplicative constant k
583        --- optional ---
584        rv = RV({'name'},size)      // description of RV
585        beta0 = [];                 // initial value of beta
586        betac = [];                 // initial value of beta
587        \endcode
588        */
589        void from_setting ( const Setting &set );
590        void    to_setting  (Setting  &set) const;
591        void validate();
592};
593UIREGISTER ( mDirich );
594
595
596//! \brief Estimator for Multinomial density
597class multiBM : public BMEF {
598protected:
599        //! Conjugate prior and posterior
600        eDirich est;
601        //! Pointer inside est to sufficient statistics
602        vec &beta;
603public:
604        //!Default constructor
605        multiBM () : BMEF (), est (), beta ( est._beta() ) {
606                if ( beta.length() > 0 ) {
607                        last_lognc = est.lognc();
608                } else {
609                        last_lognc = 0.0;
610                }
611        }
612        //!Copy constructor
613        multiBM ( const multiBM &B ) : BMEF ( B ), est ( B.est ), beta ( est._beta() ) {}
614        //! Sets sufficient statistics to match that of givefrom mB0
615        void set_statistics ( const BM* mB0 ) {
616                const multiBM* mB = dynamic_cast<const multiBM*> ( mB0 );
617                beta = mB->beta;
618        }
619        void bayes ( const vec &yt, const vec &cond = empty_vec );
620
621        double logpred ( const vec &yt ) const;
622
623        void flatten ( const BMEF* B , double weight);
624
625        //! return correctly typed posterior (covariant return)
626        const eDirich& posterior() const {
627                return est;
628        };
629        //! constructor function
630        void set_parameters ( const vec &beta0 ) {
631                est.set_parameters ( beta0 );
632                est.validate();
633                if ( evalll ) {
634                        last_lognc = est.lognc();
635                }
636        }
637
638        void to_setting ( Setting &set ) const {
639                BMEF::to_setting ( set );
640                UI::save( &est, set, "prior" );
641        }
642        void from_setting (const Setting &set )  {
643                BMEF::from_setting ( set );
644                UI::get( est, set, "prior" );
645        }
646};
647UIREGISTER( multiBM );
648
649/*!
650 \brief Gamma posterior density
651
652 Multivariate Gamma density as product of independent univariate densities.
653 \f[
654 f(x|\alpha,\beta) = \prod f(x_i|\alpha_i,\beta_i)
655 \f]
656*/
657
658class egamma : public eEF {
659protected:
660        //! Vector \f$\alpha\f$
661        vec alpha;
662        //! Vector \f$\beta\f$
663        vec beta;
664public :
665        //! \name Constructors
666        //!@{
667        egamma () : eEF (), alpha ( 0 ), beta ( 0 ) {};
668        egamma ( const vec &a, const vec &b ) {
669                set_parameters ( a, b );
670                validate();
671        };
672        void set_parameters ( const vec &a, const vec &b ) {
673                alpha = a, beta = b;
674        };
675        //!@}
676
677        vec sample() const;
678        double evallog ( const vec &val ) const;
679        double lognc () const;
680        //! Returns pointer to internal alpha. Potentially dengerous: use with care!
681        vec& _alpha() {
682                return alpha;
683        }
684        //! Returns pointer to internal beta. Potentially dengerous: use with care!
685        vec& _beta() {
686                return beta;
687        }
688        vec mean() const {
689                return elem_div ( alpha, beta );
690        }
691        vec variance() const {
692                return elem_div ( alpha, elem_mult ( beta, beta ) );
693        }
694
695        /*! Create Gamma density
696        \f[ f(rv|rvc) = \Gamma(\alpha, \beta) \f]
697        from structure
698        \code
699        class = 'egamma';
700        alpha = [...];         // vector of alpha
701        beta = [...];          // vector of beta
702        rv = RV({'name'})      // description of RV
703        \endcode
704        */
705        void from_setting ( const Setting &set );
706        void to_setting ( Setting &set ) const;
707        void validate(); 
708};
709UIREGISTER ( egamma );
710SHAREDPTR ( egamma );
711
712/*!
713 \brief Inverse-Gamma posterior density
714
715 Multivariate inverse-Gamma density as product of independent univariate densities.
716 \f[
717 f(x|\alpha,\beta) = \prod f(x_i|\alpha_i,\beta_i)
718 \f]
719
720Vector \f$\beta\f$ has different meaning (in fact it is 1/beta as used in definition of iG)
721
722 Inverse Gamma can be converted to Gamma using \f[
723 x\sim iG(a,b) => 1/x\sim G(a,1/b)
724\f]
725This relation is used in sampling.
726 */
727
728class eigamma : public egamma {
729protected:
730public :
731        //! \name Constructors
732        //! All constructors are inherited
733        //!@{
734        //!@}
735
736        vec sample() const {
737                return 1.0 / egamma::sample();
738        };
739        //! Returns poiter to alpha and beta. Potentially dangerous: use with care!
740        vec mean() const {
741                return elem_div ( beta, alpha - 1 );
742        }
743        vec variance() const {
744                vec mea = mean();
745                return elem_div ( elem_mult ( mea, mea ), alpha - 2 );
746        }
747};
748/*
749//! Weighted mixture of epdfs with external owned components.
750class emix : public epdf {
751protected:
752        int n;
753        vec &w;
754        Array<epdf*> Coms;
755public:
756//! Default constructor
757        emix ( const RV &rv, vec &w0): epdf(rv), n(w0.length()), w(w0), Coms(n) {};
758        void set_parameters( int &i, double wi, epdf* ep){w(i)=wi;Coms(i)=ep;}
759        vec mean(){vec pom; for(int i=0;i<n;i++){pom+=Coms(i)->mean()*w(i);} return pom;};
760};
761*/
762
763//!  Uniform distributed density on a rectangular support
764
765class euni: public epdf {
766protected:
767//! lower bound on support
768        vec low;
769//! upper bound on support
770        vec high;
771//! internal
772        vec distance;
773//! normalizing coefficients
774        double nk;
775//! cache of log( \c nk )
776        double lnk;
777public:
778        //! \name Constructors
779        //!@{
780        euni () : epdf () {}
781        euni ( const vec &low0, const vec &high0 ) {
782                set_parameters ( low0, high0 );
783        }
784        void set_parameters ( const vec &low0, const vec &high0 ) {
785                distance = high0 - low0;
786                low = low0;
787                high = high0;
788                nk = prod ( 1.0 / distance );
789                lnk = log ( nk );
790        }
791        //!@}
792
793        double evallog ( const vec &val ) const  {
794                if ( any ( val < low ) && any ( val > high ) ) {
795                        return -inf;
796                } else return lnk;
797        }
798        vec sample() const {
799                vec smp ( dim );
800#pragma omp critical
801                UniRNG.sample_vector ( dim , smp );
802                return low + elem_mult ( distance, smp );
803        }
804        //! set values of \c low and \c high
805        vec mean() const {
806                return ( high - low ) / 2.0;
807        }
808        vec variance() const {
809                return ( pow ( high, 2 ) + pow ( low, 2 ) + elem_mult ( high, low ) ) / 3.0;
810        }
811        /*! Create Uniform density
812        \f[ f(rv) = U(low,high) \f]
813        from structure
814         \code
815         class = 'euni'
816         high = [...];          // vector of upper bounds
817         low = [...];           // vector of lower bounds
818         rv = RV({'name'});     // description of RV
819         \endcode
820         */
821        void from_setting ( const Setting &set );
822        void    to_setting  (Setting  &set) const;
823        void validate();
824};
825UIREGISTER ( euni );
826
827//! Uniform density with conditional mean value
828class mguni : public pdf_internal<euni> {
829        //! function of the mean value
830        shared_ptr<fnc> mean;
831        //! distance from mean to both sides
832        vec delta;
833public:
834        void condition ( const vec &cond ) {
835                vec mea = mean->eval ( cond );
836                iepdf.set_parameters ( mea - delta, mea + delta );
837        }
838        //! load from
839        void from_setting ( const Setting &set ) {
840                pdf::from_setting ( set ); //reads rv and rvc
841                UI::get ( delta, set, "delta", UI::compulsory );
842                mean = UI::build<fnc> ( set, "mean", UI::compulsory );
843                iepdf.set_parameters ( -delta, delta );
844        }
845        void    to_setting  (Setting  &set) const {
846                pdf::to_setting ( set ); 
847                UI::save( iepdf.mean(), set, "delta");
848                UI::save(mean, set, "mean");
849        }
850        void validate(){
851                pdf_internal<euni>::validate();
852                dimc = mean->dimensionc();
853               
854        }
855
856};
857UIREGISTER ( mguni );
858/*!
859 \brief Normal distributed linear function with linear function of mean value;
860
861 Mean value \f$ \mu=A*\mbox{rvc}+\mu_0 \f$.
862*/
863template < class sq_T, template <typename> class TEpdf = enorm >
864class mlnorm : public pdf_internal< TEpdf<sq_T> > {
865protected:
866        //! Internal epdf that arise by conditioning on \c rvc
867        mat A;
868        //! Constant additive term
869        vec mu_const;
870//                      vec& _mu; //cached epdf.mu; !!!!!! WHY NOT?
871public:
872        //! \name Constructors
873        //!@{
874        mlnorm() : pdf_internal< TEpdf<sq_T> >() {};
875        mlnorm ( const mat &A, const vec &mu0, const sq_T &R ) : pdf_internal< TEpdf<sq_T> >() {
876                set_parameters ( A, mu0, R );
877                validate();
878        }
879
880        //! Set \c A and \c R
881        void set_parameters ( const  mat &A0, const vec &mu0, const sq_T &R0 ) {
882                this->iepdf.set_parameters ( zeros ( A0.rows() ), R0 );
883                A = A0;
884                mu_const = mu0;
885        }
886
887        //!@}
888        //! Set value of \c rvc . Result of this operation is stored in \c epdf use function \c _ep to access it.
889        void condition ( const vec &cond ) {
890                this->iepdf._mu() = A * cond + mu_const;
891//R is already assigned;
892        }
893
894        //!access function
895        const vec& _mu_const() const {
896                return mu_const;
897        }
898        //!access function
899        const mat& _A() const {
900                return A;
901        }
902        //!access function
903        mat _R() const {
904                return this->iepdf._R().to_mat();
905        }
906        //!access function
907        sq_T __R() const {
908                return this->iepdf._R();
909        }
910
911        //! Debug stream
912        template<typename sq_M>
913        friend std::ostream &operator<< ( std::ostream &os,  mlnorm<sq_M, enorm> &ml );
914
915        /*! Create Normal density with linear function of mean value
916         \f[ f(rv|rvc) = N(A*rvc+const, R) \f]
917        from structure
918        \code
919        class = 'mlnorm<ldmat>', (OR) 'mlnorm<chmat>', (OR) 'mlnorm<fsqmat>';
920        A     = [];                  // matrix or vector of appropriate dimension
921        R     = [];                  // square matrix of appropriate dimension
922        --- optional ---
923        const = zeros(A.rows);       // vector of constant term
924        \endcode
925        */
926        void from_setting ( const Setting &set ) {
927                pdf::from_setting ( set );
928
929                UI::get ( A, set, "A", UI::compulsory );
930                UI::get ( mu_const, set, "const", UI::optional);
931                mat R0;
932                UI::get ( R0, set, "R", UI::compulsory );
933                set_parameters ( A, mu_const, R0 );
934        }
935
936void to_setting (Setting &set) const {
937                pdf::to_setting(set);
938                UI::save ( A, set, "A");
939                UI::save ( mu_const, set, "const");
940                UI::save ( _R(), set, "R");
941        }
942
943void validate() {
944                pdf_internal<TEpdf<sq_T> >::validate();
945                if (mu_const.length()==0) { // default in from_setting
946                        mu_const=zeros(A.rows());
947                }
948                bdm_assert ( A.rows() == mu_const.length(), "mlnorm: A vs. mu mismatch" );
949                bdm_assert ( A.rows() == _R().rows(), "mlnorm: A vs. R mismatch" );
950                this->dimc = A.cols();
951
952        }
953};
954UIREGISTER2 ( mlnorm, ldmat );
955SHAREDPTR2 ( mlnorm, ldmat );
956UIREGISTER2 ( mlnorm, fsqmat );
957SHAREDPTR2 ( mlnorm, fsqmat );
958UIREGISTER2 ( mlnorm, chmat );
959SHAREDPTR2 ( mlnorm, chmat );
960
961//! \class mlgauss
962//!\brief Normal distribution with linear function of mean value. Same as mlnorm<fsqmat>.
963typedef mlnorm<fsqmat> mlgauss;
964UIREGISTER(mlgauss);
965
966//! pdf with general function for mean value
967template<class sq_T>
968class mgnorm : public pdf_internal< enorm< sq_T > > {
969private:
970//                      vec &mu; WHY NOT?
971        shared_ptr<fnc> g;
972
973public:
974        //!default constructor
975        mgnorm() : pdf_internal<enorm<sq_T> >() { }
976        //!set mean function
977        inline void set_parameters ( const shared_ptr<fnc> &g0, const sq_T &R0 );
978        inline void condition ( const vec &cond );
979
980
981        /*! Create Normal density with given function of mean value
982        \f[ f(rv|rvc) = N( g(rvc), R) \f]
983        from structure
984        \code
985        class = 'mgnorm';
986        g.class =  'fnc';      // function for mean value evolution
987        g._fields_of_fnc = ...;
988
989        R = [1, 0;             // covariance matrix
990                0, 1];
991                --OR --
992        dR = [1, 1];           // diagonal of cavariance matrix
993
994        rv = RV({'name'})      // description of RV
995        rvc = RV({'name'})     // description of RV in condition
996        \endcode
997        */
998
999
1000void from_setting ( const Setting &set ) {
1001                pdf::from_setting ( set );
1002                shared_ptr<fnc> g = UI::build<fnc> ( set, "g", UI::compulsory );
1003
1004                mat R;
1005                vec dR;
1006                if ( UI::get ( dR, set, "dR" ) )
1007                        R = diag ( dR );
1008                else
1009                        UI::get ( R, set, "R", UI::compulsory );
1010
1011                set_parameters ( g, R );
1012                //validate();
1013        }
1014       
1015
1016void to_setting  (Setting  &set) const {
1017                UI::save( g,set, "g");
1018                UI::save(this->iepdf._R().to_mat(),set, "R");
1019       
1020        }
1021
1022
1023
1024void validate() {
1025                this->iepdf.validate();
1026                bdm_assert ( g->dimension() == this->iepdf.dimension(), "incompatible function" );
1027                this->dim = g->dimension();
1028                this->dimc = g->dimensionc();
1029                this->iepdf.validate();
1030        }
1031
1032};
1033
1034UIREGISTER2 ( mgnorm, chmat );
1035UIREGISTER2 ( mgnorm, ldmat );
1036SHAREDPTR2 ( mgnorm, chmat );
1037
1038
1039/*! (Approximate) Student t density with linear function of mean value
1040
1041The internal epdf of this class is of the type of a Gaussian (enorm).
1042However, each conditioning is trying to assure the best possible approximation by taking into account the zeta function. See [] for reference.
1043
1044Perhaps a moment-matching technique?
1045*/
1046class mlstudent : public mlnorm<ldmat, enorm> {
1047protected:
1048        //! Variable \f$ \Lambda \f$ from theory
1049        ldmat Lambda;
1050        //! Reference to variable \f$ R \f$
1051        ldmat &_R;
1052        //! Variable \f$ R_e \f$
1053        ldmat Re;
1054public:
1055        mlstudent () : mlnorm<ldmat, enorm> (),
1056                        Lambda (),      _R ( iepdf._R() ) {}
1057        //! constructor function
1058        void set_parameters ( const mat &A0, const vec &mu0, const ldmat &R0, const ldmat& Lambda0 ) {
1059                iepdf.set_parameters ( mu0, R0 );// was Lambda, why?
1060                A = A0;
1061                mu_const = mu0;
1062                Re = R0;
1063                Lambda = Lambda0;
1064        }
1065
1066        void condition ( const vec &cond ); 
1067
1068        void validate() {
1069                mlnorm<ldmat, enorm>::validate();
1070                bdm_assert ( A.rows() == mu_const.length(), "mlstudent: A vs. mu mismatch" );
1071                bdm_assert ( _R.rows() == A.rows(), "mlstudent: A vs. R mismatch" );
1072
1073        }
1074};
1075
1076/*!
1077\brief  Gamma random walk
1078
1079Mean value, \f$\mu\f$, of this density is given by \c rvc .
1080Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
1081This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
1082
1083The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
1084*/
1085class mgamma : public pdf_internal<egamma> {
1086protected:
1087
1088        //! Constant \f$k\f$
1089        double k;
1090
1091        //! cache of iepdf.beta
1092        vec &_beta;
1093
1094public:
1095        //! Constructor
1096        mgamma() : pdf_internal<egamma>(), k ( 0 ),
1097                        _beta ( iepdf._beta() ) {
1098        }
1099
1100        //! Set value of \c k
1101        void set_parameters ( double k, const vec &beta0 );
1102
1103        void condition ( const vec &val ) {
1104                _beta = k / val;
1105        };
1106        /*! Create Gamma density with conditional mean value
1107        \f[ f(rv|rvc) = \Gamma(k, k/rvc) \f]
1108        from structure
1109        \code
1110          class = 'mgamma';
1111          beta = [...];          // vector of initial alpha
1112          k = 1.1;               // multiplicative constant k
1113          rv = RV({'name'})      // description of RV
1114          rvc = RV({'name'})     // description of RV in condition
1115         \endcode
1116        */
1117        void from_setting ( const Setting &set );
1118        void    to_setting  (Setting  &set) const;
1119        void validate();
1120};
1121UIREGISTER ( mgamma );
1122SHAREDPTR ( mgamma );
1123
1124/*!
1125\brief  Inverse-Gamma random walk
1126
1127Mean value, \f$ \mu \f$, of this density is given by \c rvc .
1128Standard deviation of the random walk is proportional to one \f$ k \f$-th the mean.
1129This is achieved by setting \f$ \alpha=\mu/k^2+2 \f$ and \f$ \beta=\mu(\alpha-1)\f$.
1130
1131The standard deviation of the walk is then: \f$ \mu/\sqrt(k)\f$.
1132 */
1133class migamma : public pdf_internal<eigamma> {
1134protected:
1135        //! Constant \f$k\f$
1136        double k;
1137
1138        //! cache of iepdf.alpha
1139        vec &_alpha;
1140
1141        //! cache of iepdf.beta
1142        vec &_beta;
1143
1144public:
1145        //! \name Constructors
1146        //!@{
1147        migamma() : pdf_internal<eigamma>(),
1148                        k ( 0 ),
1149                        _alpha ( iepdf._alpha() ),
1150                        _beta ( iepdf._beta() ) {
1151        }
1152
1153        migamma ( const migamma &m ) : pdf_internal<eigamma>(),
1154                        k ( 0 ),
1155                        _alpha ( iepdf._alpha() ),
1156                        _beta ( iepdf._beta() ) {
1157        }
1158        //!@}
1159
1160        //! Set value of \c k
1161        void set_parameters ( int len, double k0 ) {
1162                k = k0;
1163                iepdf.set_parameters ( ( 1.0 / ( k*k ) + 2.0 ) *ones ( len ) /*alpha*/, ones ( len ) /*beta*/ );               
1164        };
1165
1166        void    validate (){
1167                pdf_internal<eigamma>::validate();
1168                dimc = dimension();
1169};
1170
1171        void condition ( const vec &val ) {
1172                _beta = elem_mult ( val, ( _alpha - 1.0 ) );
1173        };
1174};
1175
1176
1177/*!
1178\brief  Gamma random walk around a fixed point
1179
1180Mean 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
1181\f[ \mu = \mu_{t-1} ^{l} p^{1-l}\f]
1182
1183Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
1184This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
1185
1186The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
1187*/
1188class mgamma_fix : public mgamma {
1189protected:
1190        //! parameter l
1191        double l;
1192        //! reference vector
1193        vec refl;
1194public:
1195        //! Constructor
1196        mgamma_fix () : mgamma (), refl () {};
1197        //! Set value of \c k
1198        void set_parameters ( double k0 , vec ref0, double l0 ) {
1199                mgamma::set_parameters ( k0, ref0 );
1200                refl = pow ( ref0, 1.0 - l0 );
1201                l = l0; 
1202        };
1203
1204        void    validate (){
1205                mgamma::validate();
1206                dimc = dimension();
1207        };
1208
1209        void condition ( const vec &val ) {
1210                vec mean = elem_mult ( refl, pow ( val, l ) );
1211                _beta = k / mean;
1212        };
1213};
1214
1215
1216/*!
1217\brief  Inverse-Gamma random walk around a fixed point
1218
1219Mean 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
1220\f[ \mu = \mu_{t-1} ^{l} p^{1-l}\f]
1221
1222==== Check == vv =
1223Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
1224This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
1225
1226The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
1227 */
1228class migamma_ref : public migamma {
1229protected:
1230        //! parameter l
1231        double l;
1232        //! reference vector
1233        vec refl;
1234public:
1235        //! Constructor
1236        migamma_ref () : migamma (), refl () {};
1237       
1238        //! Set value of \c k
1239        void set_parameters ( double k0 , vec ref0, double l0 ) {
1240                migamma::set_parameters ( ref0.length(), k0 );
1241                refl = pow ( ref0, 1.0 - l0 );
1242                l = l0;
1243        };
1244
1245        void validate(){
1246                migamma::validate();
1247                dimc = dimension();
1248        };
1249       
1250        void condition ( const vec &val ) {
1251                vec mean = elem_mult ( refl, pow ( val, l ) );
1252                migamma::condition ( mean );
1253        };
1254
1255
1256        /*! Create inverse-Gamma density with conditional mean value
1257        \f[ f(rv|rvc) = i\Gamma(k, k/(rvc^l \circ ref^{(1-l)}) \f]
1258        from structure
1259        \code
1260        class = 'migamma_ref';
1261        ref = [1e-5; 1e-5; 1e-2 1e-3];            // reference vector
1262        l = 0.999;                                // constant l
1263        k = 0.1;                                  // constant k
1264        rv = RV({'name'})                         // description of RV
1265        rvc = RV({'name'})                        // description of RV in condition
1266        \endcode
1267         */
1268        void from_setting ( const Setting &set );
1269
1270        void to_setting  (Setting  &set) const; 
1271};
1272
1273
1274UIREGISTER ( migamma_ref );
1275SHAREDPTR ( migamma_ref );
1276
1277/*! Log-Normal probability density
1278 only allow diagonal covariances!
1279
1280Density of the form \f$ \log(x)\sim \mathcal{N}(\mu,\sigma^2) \f$ , i.e.
1281\f[
1282x \sim \frac{1}{x\sigma\sqrt{2\pi}}\exp{-\frac{1}{2\sigma^2}(\log(x)-\mu)}
1283\f]
1284
1285Function from_setting loads mu and R in the same way as it does for enorm<>!
1286*/
1287class elognorm: public enorm<ldmat> {
1288public:
1289        vec sample() const {
1290                return exp ( enorm<ldmat>::sample() );
1291        };
1292        vec mean() const {
1293                vec var = enorm<ldmat>::variance();
1294                return exp ( mu - 0.5*var );
1295        };
1296
1297};
1298
1299/*!
1300\brief  Log-Normal random walk
1301
1302Mean value, \f$\mu\f$, is...
1303
1304 */
1305class mlognorm : public pdf_internal<elognorm> {
1306protected:
1307        //! parameter 1/2*sigma^2
1308        double sig2;
1309
1310        //! access
1311        vec &mu;
1312public:
1313        //! Constructor
1314        mlognorm() : pdf_internal<elognorm>(),
1315                        sig2 ( 0 ),
1316                        mu ( iepdf._mu() ) {
1317        }
1318
1319        //! Set value of \c k
1320        void set_parameters ( int size, double k ) {
1321                sig2 = 0.5 * log ( k * k + 1 );
1322                iepdf.set_parameters ( zeros ( size ), 2*sig2*eye ( size ) );
1323        };
1324       
1325        void validate(){
1326                pdf_internal<elognorm>::validate();
1327                dimc = iepdf.dimension();
1328        }
1329
1330        void condition ( const vec &val ) {
1331                mu = log ( val ) - sig2;//elem_mult ( refl,pow ( val,l ) );
1332        };
1333
1334        /*! Create logNormal random Walk
1335        \f[ f(rv|rvc) = log\mathcal{N}( \log(rvc)-0.5\log(k^2+1), k I) \f]
1336        from structure
1337        \code
1338        class = 'mlognorm';
1339        k   = 0.1;               // "variance" k
1340        mu0 = 0.1;               // Initial value of mean
1341        rv  = RV({'name'})       // description of RV
1342        rvc = RV({'name'})       // description of RV in condition
1343        \endcode
1344        */
1345        void from_setting ( const Setting &set );
1346       
1347        void to_setting  (Setting  &set) const; 
1348};
1349
1350UIREGISTER ( mlognorm );
1351SHAREDPTR ( mlognorm );
1352
1353/*! inverse Wishart density defined on Choleski decomposition
1354
1355*/
1356class eWishartCh : public epdf {
1357protected:
1358        //! Upper-Triagle of Choleski decomposition of \f$ \Psi \f$
1359        chmat Y;
1360        //! dimension of matrix  \f$ \Psi \f$
1361        int p;
1362        //! degrees of freedom  \f$ \nu \f$
1363        double delta;
1364public:
1365        //! Set internal structures
1366        void set_parameters ( const mat &Y0, const double delta0 ) {
1367                Y = chmat ( Y0 );
1368                delta = delta0;
1369                p = Y.rows();   
1370        }
1371        //! Set internal structures
1372        void set_parameters ( const chmat &Y0, const double delta0 ) {
1373                Y = Y0;
1374                delta = delta0;
1375                p = Y.rows();
1376                }
1377       
1378        virtual void validate (){
1379                epdf::validate();
1380                dim = p * p;
1381        }
1382
1383        //! Sample matrix argument
1384        mat sample_mat() const {
1385                mat X = zeros ( p, p );
1386
1387                //sample diagonal
1388                for ( int i = 0; i < p; i++ ) {
1389                        GamRNG.setup ( 0.5* ( delta - i ) , 0.5 );   // no +1 !! index if from 0
1390#pragma omp critical
1391                        X ( i, i ) = sqrt ( GamRNG() );
1392                }
1393                //do the rest
1394                for ( int i = 0; i < p; i++ ) {
1395                        for ( int j = i + 1; j < p; j++ ) {
1396#pragma omp critical
1397                                X ( i, j ) = NorRNG.sample();
1398                        }
1399                }
1400                return X*Y._Ch();// return upper triangular part of the decomposition
1401        }
1402
1403        vec sample () const {
1404                return vec ( sample_mat()._data(), p*p );
1405        }
1406
1407        virtual vec mean() const NOT_IMPLEMENTED(0);
1408
1409        //! return expected variance (not covariance!)
1410        virtual vec variance() const NOT_IMPLEMENTED(0);
1411
1412        virtual double evallog ( const vec &val ) const NOT_IMPLEMENTED(0);
1413
1414        //! fast access function y0 will be copied into Y.Ch.
1415        void setY ( const mat &Ch0 ) {
1416                copy_vector ( dim, Ch0._data(), Y._Ch()._data() );
1417        }
1418
1419        //! fast access function y0 will be copied into Y.Ch.
1420        void _setY ( const vec &ch0 ) {
1421                copy_vector ( dim, ch0._data(), Y._Ch()._data() );
1422        }
1423
1424        //! access function
1425        const chmat& getY() const {
1426                return Y;
1427        }
1428};
1429
1430//! Inverse Wishart on Choleski decomposition
1431/*! Being computed by conversion from `standard' Wishart
1432*/
1433class eiWishartCh: public epdf {
1434protected:
1435        //! Internal instance of Wishart density
1436        eWishartCh W;
1437        //! size of Ch
1438        int p;
1439        //! parameter delta
1440        double delta;
1441public:
1442        //! constructor function
1443        void set_parameters ( const mat &Y0, const double delta0 ) {
1444                delta = delta0;
1445                W.set_parameters ( inv ( Y0 ), delta0 );
1446                p = Y0.rows();
1447        }
1448       
1449        virtual void    validate (){
1450                epdf::validate();
1451                W.validate();
1452                dim = W.dimension();
1453        }
1454       
1455       
1456        vec sample() const {
1457                mat iCh;
1458                iCh = inv ( W.sample_mat() );
1459                return vec ( iCh._data(), dim );
1460        }
1461        //! access function
1462        void _setY ( const vec &y0 ) {
1463                mat Ch ( p, p );
1464                mat iCh ( p, p );
1465                copy_vector ( dim, y0._data(), Ch._data() );
1466
1467                iCh = inv ( Ch );
1468                W.setY ( iCh );
1469        }
1470
1471        virtual double evallog ( const vec &val ) const {
1472                chmat X ( p );
1473                const chmat& Y = W.getY();
1474
1475                copy_vector ( p*p, val._data(), X._Ch()._data() );
1476                chmat iX ( p );
1477                X.inv ( iX );
1478                // compute
1479//                              \frac{ |\Psi|^{m/2}|X|^{-(m+p+1)/2}e^{-tr(\Psi X^{-1})/2} }{ 2^{mp/2}\Gamma_p(m/2)},
1480                mat M = Y.to_mat() * iX.to_mat();
1481
1482                double log1 = 0.5 * p * ( 2 * Y.logdet() ) - 0.5 * ( delta + p + 1 ) * ( 2 * X.logdet() ) - 0.5 * trace ( M );
1483                //Fixme! Multivariate gamma omitted!! it is ok for sampling, but not otherwise!!
1484
1485                /*                              if (0) {
1486                                                        mat XX=X.to_mat();
1487                                                        mat YY=Y.to_mat();
1488
1489                                                        double log2 = 0.5*p*log(det(YY))-0.5*(delta+p+1)*log(det(XX))-0.5*trace(YY*inv(XX));
1490                                                        cout << log1 << "," << log2 << endl;
1491                                                }*/
1492                return log1;
1493        };
1494
1495        virtual vec mean() const NOT_IMPLEMENTED(0);
1496
1497        //! return expected variance (not covariance!)
1498        virtual vec variance() const NOT_IMPLEMENTED(0);
1499};
1500
1501//! Random Walk on inverse Wishart
1502class rwiWishartCh : public pdf_internal<eiWishartCh> {
1503protected:
1504        //!square root of \f$ \nu-p-1 \f$ - needed for computation of \f$ \Psi \f$ from conditions
1505        double sqd;
1506        //!reference point for diagonal
1507        vec refl;
1508        //! power of the reference
1509        double l;
1510        //! dimension
1511        int p;
1512
1513public:
1514        rwiWishartCh() : sqd ( 0 ), l ( 0 ), p ( 0 ) {}
1515        //! constructor function
1516        void set_parameters ( int p0, double k, vec ref0, double l0 ) {
1517                p = p0;
1518                double delta = 2 / ( k * k ) + p + 3;
1519                sqd = sqrt ( delta - p - 1 );
1520                l = l0;
1521                refl = pow ( ref0, 1 - l );
1522                iepdf.set_parameters ( eye ( p ), delta );
1523        };
1524       
1525        void validate(){
1526                pdf_internal<eiWishartCh>::validate();
1527                dimc = iepdf.dimension();
1528        }
1529       
1530        void condition ( const vec &c ) {
1531                vec z = c;
1532                int ri = 0;
1533                for ( int i = 0; i < p*p; i += ( p + 1 ) ) {//trace diagonal element
1534                        z ( i ) = pow ( z ( i ), l ) * refl ( ri );
1535                        ri++;
1536                }
1537
1538                iepdf._setY ( sqd*z );
1539        }
1540};
1541
1542//! Switch between various resampling methods.
1543enum RESAMPLING_METHOD { MULTINOMIAL = 0, STRATIFIED = 1, SYSTEMATIC = 3 };
1544
1545//! Shortcut for multinomial.sample(int n). Various simplifications are allowed see RESAMPLING_METHOD
1546void resample(const vec &w, ivec &ind, RESAMPLING_METHOD=SYSTEMATIC);
1547
1548/*!
1549\brief Weighted empirical density
1550
1551Used e.g. in particle filters.
1552*/
1553class eEmp: public epdf {
1554protected :
1555        //! Number of particles
1556        int n;
1557        //! Sample weights \f$w\f$
1558        vec w;
1559        //! Samples \f$x^{(i)}, i=1..n\f$
1560        Array<vec> samples;
1561public:
1562        //! \name Constructors
1563        //!@{
1564        eEmp () : epdf (), w (), samples () {};
1565        //! copy constructor
1566        eEmp ( const eEmp &e ) : epdf ( e ), w ( e.w ), samples ( e.samples ) {};
1567        //!@}
1568
1569        //! Set samples and weights
1570        void set_statistics ( const vec &w0, const epdf &pdf0 );
1571        //! Set samples and weights
1572        void set_statistics ( const epdf &pdf0 , int n ) {
1573                set_statistics ( ones ( n ) / n, pdf0 );
1574        };
1575        //! Set sample
1576        void set_samples ( const epdf* pdf0 );
1577        //! Set sample
1578        void set_parameters ( int n0, bool copy = true ) {
1579                n = n0;
1580                w.set_size ( n0, copy );
1581                samples.set_size ( n0, copy );
1582        };
1583        //! Set samples
1584        void set_parameters ( const Array<vec> &Av ) {
1585                n = Av.size();
1586                w = 1 / n * ones ( n );
1587                samples = Av;
1588        };
1589        virtual void    validate ();
1590        //! Potentially dangerous, use with care.
1591        vec& _w()  {
1592                return w;
1593        };
1594        //! Potentially dangerous, use with care.
1595        const vec& _w() const {
1596                return w;
1597        };
1598        //! access function
1599        Array<vec>& _samples() {
1600                return samples;
1601        };
1602        //! access function
1603        const vec& _sample ( int i ) const {
1604                return samples ( i );
1605        };
1606        //! access function
1607        const Array<vec>& _samples() const {
1608                return samples;
1609        };
1610        //! 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.
1611        void resample ( RESAMPLING_METHOD method = SYSTEMATIC );
1612
1613        //! inherited operation : NOT implemented
1614        vec sample() const NOT_IMPLEMENTED(0);
1615
1616        //! inherited operation : NOT implemented
1617        double evallog ( const vec &val ) const NOT_IMPLEMENTED(0);
1618
1619        vec mean() const {
1620                vec pom = zeros ( dim );
1621                for ( int i = 0; i < n; i++ ) {
1622                        pom += samples ( i ) * w ( i );
1623                }
1624                return pom;
1625        }
1626        vec variance() const {
1627                vec pom = zeros ( dim );
1628                for ( int i = 0; i < n; i++ ) {
1629                        pom += pow ( samples ( i ), 2 ) * w ( i );
1630                }
1631                return pom - pow ( mean(), 2 );
1632        }
1633        //! For this class, qbounds are minimum and maximum value of the population!
1634        void qbounds ( vec &lb, vec &ub, double perc = 0.95 ) const;
1635
1636        void to_setting ( Setting &set ) const;
1637        void from_setting ( const Setting &set );
1638
1639};
1640UIREGISTER(eEmp);
1641
1642
1643////////////////////////
1644
1645template<class sq_T>
1646void enorm<sq_T>::set_parameters ( const vec &mu0, const sq_T &R0 ) {
1647//Fixme test dimensions of mu0 and R0;
1648        mu = mu0;
1649        R = R0;
1650        validate();
1651};
1652
1653template<class sq_T>
1654void enorm<sq_T>::from_setting ( const Setting &set ) {
1655        epdf::from_setting ( set ); //reads rv
1656
1657        UI::get ( mu, set, "mu", UI::compulsory );
1658        mat Rtmp;// necessary for conversion
1659        UI::get ( Rtmp, set, "R", UI::compulsory );
1660        R = Rtmp; // conversion
1661}
1662
1663template<class sq_T>
1664void enorm<sq_T>::validate() {
1665                eEF::validate();
1666                bdm_assert ( mu.length() == R.rows(), "mu and R parameters do not match" );
1667                dim = mu.length();
1668        }
1669
1670template<class sq_T>
1671void enorm<sq_T>::to_setting ( Setting &set ) const {
1672        epdf::to_setting ( set ); //reads rv   
1673        UI::save ( mu, set, "mu");
1674        UI::save ( R.to_mat(), set, "R");
1675}
1676
1677
1678
1679template<class sq_T>
1680void enorm<sq_T>::dupdate ( mat &v, double nu ) {
1681        //
1682};
1683
1684// template<class sq_T>
1685// void enorm<sq_T>::tupdate ( double phi, mat &vbar, double nubar ) {
1686//      //
1687// };
1688
1689template<class sq_T>
1690vec enorm<sq_T>::sample() const {
1691        vec x ( dim );
1692#pragma omp critical
1693        NorRNG.sample_vector ( dim, x );
1694        vec smp = R.sqrt_mult ( x );
1695
1696        smp += mu;
1697        return smp;
1698};
1699
1700// template<class sq_T>
1701// double enorm<sq_T>::eval ( const vec &val ) const {
1702//      double pdfl,e;
1703//      pdfl = evallog ( val );
1704//      e = exp ( pdfl );
1705//      return e;
1706// };
1707
1708template<class sq_T>
1709double enorm<sq_T>::evallog_nn ( const vec &val ) const {
1710        // 1.83787706640935 = log(2pi)
1711        double tmp = -0.5 * ( R.invqform ( mu - val ) );// - lognc();
1712        return  tmp;
1713};
1714
1715template<class sq_T>
1716inline double enorm<sq_T>::lognc () const {
1717        // 1.83787706640935 = log(2pi)
1718        double tmp = 0.5 * ( R.cols() * 1.83787706640935 + R.logdet() );
1719        return tmp;
1720};
1721
1722
1723// template<class sq_T>
1724// vec mlnorm<sq_T>::samplecond (const  vec &cond, double &lik ) {
1725//      this->condition ( cond );
1726//      vec smp = epdf.sample();
1727//      lik = epdf.eval ( smp );
1728//      return smp;
1729// }
1730
1731// template<class sq_T>
1732// mat mlnorm<sq_T>::samplecond (const vec &cond, vec &lik, int n ) {
1733//      int i;
1734//      int dim = rv.count();
1735//      mat Smp ( dim,n );
1736//      vec smp ( dim );
1737//      this->condition ( cond );
1738//
1739//      for ( i=0; i<n; i++ ) {
1740//              smp = epdf.sample();
1741//              lik ( i ) = epdf.eval ( smp );
1742//              Smp.set_col ( i ,smp );
1743//      }
1744//
1745//      return Smp;
1746// }
1747
1748
1749template<class sq_T>
1750shared_ptr<epdf> enorm<sq_T>::marginal ( const RV &rvn ) const {
1751        enorm<sq_T> *tmp = new enorm<sq_T> ();
1752        shared_ptr<epdf> narrow ( tmp );
1753        marginal ( rvn, *tmp );
1754        return narrow;
1755}
1756
1757template<class sq_T>
1758void enorm<sq_T>::marginal ( const RV &rvn, enorm<sq_T> &target ) const {
1759        bdm_assert ( isnamed(), "rv description is not assigned" );
1760        ivec irvn = rvn.dataind ( rv );
1761
1762        sq_T Rn ( R, irvn );  // select rows and columns of R
1763
1764        target.set_rv ( rvn );
1765        target.set_parameters ( mu ( irvn ), Rn );
1766}
1767
1768template<class sq_T>
1769shared_ptr<pdf> enorm<sq_T>::condition ( const RV &rvn ) const {
1770        mlnorm<sq_T> *tmp = new mlnorm<sq_T> ();
1771        shared_ptr<pdf> narrow ( tmp );
1772        condition ( rvn, *tmp );
1773        return narrow;
1774}
1775
1776template<class sq_T>
1777void enorm<sq_T>::condition ( const RV &rvn, pdf &target ) const {
1778        typedef mlnorm<sq_T> TMlnorm;
1779
1780        bdm_assert ( isnamed(), "rvs are not assigned" );
1781        TMlnorm &uptarget = dynamic_cast<TMlnorm &> ( target );
1782
1783        RV rvc = rv.subt ( rvn );
1784        bdm_assert ( ( rvc._dsize() + rvn._dsize() == rv._dsize() ), "wrong rvn" );
1785        //Permutation vector of the new R
1786        ivec irvn = rvn.dataind ( rv );
1787        ivec irvc = rvc.dataind ( rv );
1788        ivec perm = concat ( irvn , irvc );
1789        sq_T Rn ( R, perm );
1790
1791        //fixme - could this be done in general for all sq_T?
1792        mat S = Rn.to_mat();
1793        //fixme
1794        int n = rvn._dsize() - 1;
1795        int end = R.rows() - 1;
1796        mat S11 = S.get ( 0, n, 0, n );
1797        mat S12 = S.get ( 0, n , rvn._dsize(), end );
1798        mat S22 = S.get ( rvn._dsize(), end, rvn._dsize(), end );
1799
1800        vec mu1 = mu ( irvn );
1801        vec mu2 = mu ( irvc );
1802        mat A = S12 * inv ( S22 );
1803        sq_T R_n ( S11 - A *S12.T() );
1804
1805        uptarget.set_rv ( rvn );
1806        uptarget.set_rvc ( rvc );
1807        uptarget.set_parameters ( A, mu1 - A*mu2, R_n );
1808        uptarget.validate();
1809}
1810
1811/*! Dirac delta function distribution */
1812class dirac: public epdf{
1813        public: 
1814                vec point;
1815        public:
1816                double evallog (const vec &dt) const {return -inf;}
1817                vec mean () const {return point;}
1818                vec variance () const {return zeros(point.length());}
1819                void qbounds ( vec &lb, vec &ub, double percentage = 0.95 ) const { lb = point; ub = point;}
1820                //! access
1821                const vec& _point() {return point;}
1822                void set_point(const vec& p){point =p; dim=p.length();}
1823                vec sample() const {return point;}
1824        };
1825
1826////
1827///////
1828template<class sq_T>
1829void mgnorm<sq_T >::set_parameters ( const shared_ptr<fnc> &g0, const sq_T &R0 ) {
1830        g = g0;
1831        this->iepdf.set_parameters ( zeros ( g->dimension() ), R0 );
1832}
1833
1834template<class sq_T>
1835void mgnorm<sq_T >::condition ( const vec &cond ) {
1836        this->iepdf._mu() = g->eval ( cond );
1837};
1838
1839//! \todo unify this stuff with to_string()
1840template<class sq_T>
1841std::ostream &operator<< ( std::ostream &os,  mlnorm<sq_T> &ml ) {
1842        os << "A:" << ml.A << endl;
1843        os << "mu:" << ml.mu_const << endl;
1844        os << "R:" << ml._R() << endl;
1845        return os;
1846};
1847
1848}
1849#endif //EF_H
Note: See TracBrowser for help on using the browser.