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

Revision 1003, 44.8 kB (checked in by smidl, 14 years ago)

corrections in ARX

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