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

Revision 996, 44.7 kB (checked in by smidl, 14 years ago)

Scheduling of forgetting factor

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