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

Revision 536, 35.2 kB (checked in by smidl, 15 years ago)

removal of unused functions _e() and samplecond(,) and added documentation lines

  • 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
25//! Global Uniform_RNG
26extern Uniform_RNG UniRNG;
27//! Global Normal_RNG
28extern Normal_RNG NorRNG;
29//! Global Gamma_RNG
30extern Gamma_RNG GamRNG;
31
32/*!
33* \brief General conjugate exponential family posterior density.
34
35* More?...
36*/
37
38class eEF : public epdf
39{
40        public:
41//      eEF() :epdf() {};
42                //! default constructor
43                eEF () : epdf () {};
44                //! logarithm of the normalizing constant, \f$\mathcal{I}\f$
45                virtual double lognc() const = 0;
46                //!Evaluate normalized log-probability
47                virtual double evallog_nn (const vec &val) const{it_error ("Not implemented");return 0.0;};
48                //!Evaluate normalized log-probability
49                virtual double evallog (const vec &val) const {
50                        double tmp;
51                        tmp = evallog_nn (val) - lognc();
52//                              it_assert_debug ( std::isfinite ( tmp ),"Infinite value" );
53                        return tmp;
54                }
55                //!Evaluate normalized log-probability for many samples
56                virtual vec evallog_m (const mat &Val) const {
57                        vec x (Val.cols());
58                        for (int i = 0;i < Val.cols();i++) {x (i) = evallog_nn (Val.get_col (i)) ;}
59                        return x -lognc();
60                }
61                //!Evaluate normalized log-probability for many samples
62                virtual vec evallog_m (const Array<vec> &Val) const {
63                        vec x (Val.length());
64                        for (int i = 0;i < Val.length();i++) {x (i) = evallog_nn (Val (i)) ;}
65                        return x -lognc();
66                }
67                //!Power of the density, used e.g. to flatten the density
68                virtual void pow (double p) {it_error ("Not implemented");};
69};
70
71
72//! Estimator for Exponential family
73class BMEF : public BM
74{
75        protected:
76                //! forgetting factor
77                double frg;
78                //! cached value of lognc() in the previous step (used in evaluation of \c ll )
79                double last_lognc;
80        public:
81                //! Default constructor (=empty constructor)
82                BMEF (double frg0 = 1.0) : BM (), frg (frg0) {}
83                //! Copy constructor
84                BMEF (const BMEF &B) : BM (B), frg (B.frg), last_lognc (B.last_lognc) {}
85                //!get statistics from another model
86                virtual void set_statistics (const BMEF* BM0) {it_error ("Not implemented");};
87                //! Weighted update of sufficient statistics (Bayes rule)
88                virtual void bayes (const vec &data, const double w) {};
89                //original Bayes
90                void bayes (const vec &dt);
91                //!Flatten the posterior according to the given BMEF (of the same type!)
92                virtual void flatten (const BMEF * B) {it_error ("Not implemented");}
93                //!Flatten the posterior as if to keep nu0 data
94//      virtual void flatten ( double nu0 ) {it_error ( "Not implemented" );}
95
96                BMEF* _copy_ () const {it_error ("function _copy_ not implemented for this BM"); return NULL;};
97};
98
99template<class sq_T, template <typename> class TEpdf>
100class mlnorm;
101
102/*!
103* \brief Gaussian density with positive definite (decomposed) covariance matrix.
104
105* More?...
106*/
107template<class sq_T>
108class enorm : public eEF
109{
110        protected:
111                //! mean value
112                vec mu;
113                //! Covariance matrix in decomposed form
114                sq_T R;
115        public:
116                //!\name Constructors
117                //!@{
118
119                enorm () : eEF (), mu (), R () {};
120                enorm (const vec &mu, const sq_T &R) {set_parameters (mu, R);}
121                void set_parameters (const vec &mu, const sq_T &R);
122                void from_setting (const Setting &root);
123                void validate() {
124                        it_assert (mu.length() == R.rows(), "parameters mismatch");
125                        dim = mu.length();
126                }
127                //!@}
128
129                //! \name Mathematical operations
130                //!@{
131
132                //! dupdate in exponential form (not really handy)
133                void dupdate (mat &v, double nu = 1.0);
134
135                vec sample() const;
136
137                double evallog_nn (const vec &val) const;
138                double lognc () const;
139                vec mean() const {return mu;}
140                vec variance() const {return diag (R.to_mat());}
141//      mlnorm<sq_T>* condition ( const RV &rvn ) const ; <=========== fails to cmpile. Why?
142                shared_ptr<mpdf> condition ( const RV &rvn ) const;
143
144                // target not typed to mlnorm<sq_T, enorm<sq_T> > &
145                // because that doesn't compile (perhaps because we
146                // haven't finished defining enorm yet), but the type
147                // is required
148                void condition ( const RV &rvn, mpdf &target ) const;
149
150                shared_ptr<epdf> marginal (const RV &rvn ) const;
151                void marginal ( const RV &rvn, enorm<sq_T> &target ) const;
152                //!@}
153
154                //! \name Access to attributes
155                //!@{
156
157                vec& _mu() {return mu;}
158                void set_mu (const vec mu0) { mu = mu0;}
159                sq_T& _R() {return R;}
160                const sq_T& _R() const {return R;}
161                //!@}
162
163};
164UIREGISTER2 (enorm, chmat);
165SHAREDPTR2 ( enorm, chmat );
166UIREGISTER2 (enorm, ldmat);
167SHAREDPTR2 ( enorm, ldmat );
168UIREGISTER2 (enorm, fsqmat);
169SHAREDPTR2 ( enorm, fsqmat );
170
171
172/*!
173* \brief Gauss-inverse-Wishart density stored in LD form
174
175* For \f$p\f$-variate densities, given rv.count() should be \f$p\times\f$ V.rows().
176*
177*/
178class egiw : public eEF
179{
180        protected:
181                //! Extended information matrix of sufficient statistics
182                ldmat V;
183                //! Number of data records (degrees of freedom) of sufficient statistics
184                double nu;
185                //! Dimension of the output
186                int dimx;
187                //! Dimension of the regressor
188                int nPsi;
189        public:
190                //!\name Constructors
191                //!@{
192                egiw() : eEF() {};
193                egiw (int dimx0, ldmat V0, double nu0 = -1.0) : eEF() {set_parameters (dimx0, V0, nu0);};
194
195                void set_parameters (int dimx0, ldmat V0, double nu0 = -1.0) {
196                        dimx = dimx0;
197                        nPsi = V0.rows() - dimx;
198                        dim = dimx * (dimx + nPsi); // size(R) + size(Theta)
199
200                        V = V0;
201                        if (nu0 < 0) {
202                                nu = 0.1 + nPsi + 2 * dimx + 2; // +2 assures finite expected value of R
203                                // terms before that are sufficient for finite normalization
204                        } else {
205                                nu = nu0;
206                        }
207                }
208                //!@}
209
210                vec sample() const;
211                vec mean() const;
212                vec variance() const;
213
214                //! LS estimate of \f$\theta\f$
215                vec est_theta() const;
216
217                //! Covariance of the LS estimate
218                ldmat est_theta_cov() const;
219
220                //! expected values of the linear coefficient and the covariance matrix are written to \c M and \c R , respectively
221                void mean_mat (mat &M, mat&R) const;
222                //! In this instance, val= [theta, r]. For multivariate instances, it is stored columnwise val = [theta_1 theta_2 ... r_1 r_2 ]
223                double evallog_nn (const vec &val) const;
224                double lognc () const;
225                void pow (double p) {V *= p;nu *= p;};
226
227                //! \name Access attributes
228                //!@{
229
230                ldmat& _V() {return V;}
231                const ldmat& _V() const {return V;}
232                double& _nu()  {return nu;}
233                const double& _nu() const {return nu;}
234                void from_setting (const Setting &set) {
235                        UI::get (nu, set, "nu", UI::compulsory);
236                        UI::get (dimx, set, "dimx", UI::compulsory);
237                        mat V;
238                        UI::get (V, set, "V", UI::compulsory);
239                        set_parameters (dimx, V, nu);
240                        shared_ptr<RV> rv = UI::build<RV> (set, "rv", UI::compulsory);
241                        set_rv (*rv);
242                }
243                //!@}
244};
245UIREGISTER ( egiw );
246SHAREDPTR ( egiw );
247
248/*! \brief Dirichlet posterior density
249
250Continuous Dirichlet density of \f$n\f$-dimensional variable \f$x\f$
251\f[
252f(x|\beta) = \frac{\Gamma[\gamma]}{\prod_{i=1}^{n}\Gamma(\beta_i)} \prod_{i=1}^{n}x_i^{\beta_i-1}
253\f]
254where \f$\gamma=\sum_i \beta_i\f$.
255*/
256class eDirich: public eEF
257{
258        protected:
259                //!sufficient statistics
260                vec beta;
261        public:
262                //!\name Constructors
263                //!@{
264
265                eDirich () : eEF () {};
266                eDirich (const eDirich &D0) : eEF () {set_parameters (D0.beta);};
267                eDirich (const vec &beta0) {set_parameters (beta0);};
268                void set_parameters (const vec &beta0) {
269                        beta = beta0;
270                        dim = beta.length();
271                }
272                //!@}
273
274                vec sample() const {it_error ("Not implemented");return vec_1 (0.0);};
275                vec mean() const {return beta / sum (beta);};
276                vec variance() const {double gamma = sum (beta); return elem_mult (beta, (beta + 1)) / (gamma* (gamma + 1));}
277                //! In this instance, val is ...
278                double evallog_nn (const vec &val) const {
279                        double tmp; tmp = (beta - 1) * log (val);
280//                              it_assert_debug ( std::isfinite ( tmp ),"Infinite value" );
281                        return tmp;
282                };
283                double lognc () const {
284                        double tmp;
285                        double gam = sum (beta);
286                        double lgb = 0.0;
287                        for (int i = 0;i < beta.length();i++) {lgb += lgamma (beta (i));}
288                        tmp = lgb - lgamma (gam);
289//                              it_assert_debug ( std::isfinite ( tmp ),"Infinite value" );
290                        return tmp;
291                };
292                //!access function
293                vec& _beta()  {return beta;}
294                //!Set internal parameters
295};
296
297//! \brief Estimator for Multinomial density
298class multiBM : public BMEF
299{
300        protected:
301                //! Conjugate prior and posterior
302                eDirich est;
303                //! Pointer inside est to sufficient statistics
304                vec &beta;
305        public:
306                //!Default constructor
307                multiBM () : BMEF (), est (), beta (est._beta()) {
308                        if (beta.length() > 0) {last_lognc = est.lognc();}
309                        else{last_lognc = 0.0;}
310                }
311                //!Copy constructor
312                multiBM (const multiBM &B) : BMEF (B), est (B.est), beta (est._beta()) {}
313                //! Sets sufficient statistics to match that of givefrom mB0
314                void set_statistics (const BM* mB0) {const multiBM* mB = dynamic_cast<const multiBM*> (mB0); beta = mB->beta;}
315                void bayes (const vec &dt) {
316                        if (frg < 1.0) {beta *= frg;last_lognc = est.lognc();}
317                        beta += dt;
318                        if (evalll) {ll = est.lognc() - last_lognc;}
319                }
320                double logpred (const vec &dt) const {
321                        eDirich pred (est);
322                        vec &beta = pred._beta();
323
324                        double lll;
325                        if (frg < 1.0)
326                                {beta *= frg;lll = pred.lognc();}
327                        else
328                                if (evalll) {lll = last_lognc;}
329                                else{lll = pred.lognc();}
330
331                        beta += dt;
332                        return pred.lognc() - lll;
333                }
334                void flatten (const BMEF* B) {
335                        const multiBM* E = dynamic_cast<const multiBM*> (B);
336                        // sum(beta) should be equal to sum(B.beta)
337                        const vec &Eb = E->beta;//const_cast<multiBM*> ( E )->_beta();
338                        beta *= (sum (Eb) / sum (beta));
339                        if (evalll) {last_lognc = est.lognc();}
340                }
341                //! reimplemnetation of BM::posterior()
342                const eDirich& posterior() const {return est;};
343                //! constructor function               
344                void set_parameters (const vec &beta0) {
345                        est.set_parameters (beta0);
346                        if (evalll) {last_lognc = est.lognc();}
347                }
348};
349
350/*!
351 \brief Gamma posterior density
352
353 Multivariate Gamma density as product of independent univariate densities.
354 \f[
355 f(x|\alpha,\beta) = \prod f(x_i|\alpha_i,\beta_i)
356 \f]
357*/
358
359class egamma : public eEF
360{
361        protected:
362                //! Vector \f$\alpha\f$
363                vec alpha;
364                //! Vector \f$\beta\f$
365                vec beta;
366        public :
367                //! \name Constructors
368                //!@{
369                egamma () : eEF (), alpha (0), beta (0) {};
370                egamma (const vec &a, const vec &b) {set_parameters (a, b);};
371                void set_parameters (const vec &a, const vec &b) {alpha = a, beta = b;dim = alpha.length();};
372                //!@}
373
374                vec sample() const;
375                double evallog (const vec &val) const;
376                double lognc () const;
377                //! Returns pointer to internal alpha. Potentially dengerous: use with care!
378                vec& _alpha() {return alpha;}
379                //! Returns pointer to internal beta. Potentially dengerous: use with care!
380                vec& _beta() {return beta;}
381                vec mean() const {return elem_div (alpha, beta);}
382                vec variance() const {return elem_div (alpha, elem_mult (beta, beta)); }
383
384                //! Load from structure with elements:
385                //!  \code
386                //! { alpha = [...];         // vector of alpha
387                //!   beta = [...];          // vector of beta
388                //!   rv = {class="RV",...}  // description
389                //! }
390                //! \endcode
391                //!@}
392                void from_setting (const Setting &set) {
393                        epdf::from_setting (set); // reads rv
394                        UI::get (alpha, set, "alpha", UI::compulsory);
395                        UI::get (beta, set, "beta", UI::compulsory);
396                        validate();
397                }
398                void validate() {
399                        it_assert (alpha.length() == beta.length(), "parameters do not match");
400                        dim = alpha.length();
401                }
402};
403UIREGISTER (egamma);
404SHAREDPTR ( egamma );
405
406/*!
407 \brief Inverse-Gamma posterior density
408
409 Multivariate inverse-Gamma density as product of independent univariate densities.
410 \f[
411 f(x|\alpha,\beta) = \prod f(x_i|\alpha_i,\beta_i)
412 \f]
413
414Vector \f$\beta\f$ has different meaning (in fact it is 1/beta as used in definition of iG)
415
416 Inverse Gamma can be converted to Gamma using \f[
417 x\sim iG(a,b) => 1/x\sim G(a,1/b)
418\f]
419This relation is used in sampling.
420 */
421
422class eigamma : public egamma
423{
424        protected:
425        public :
426                //! \name Constructors
427                //! All constructors are inherited
428                //!@{
429                //!@}
430
431                vec sample() const {return 1.0 / egamma::sample();};
432                //! Returns poiter to alpha and beta. Potentially dangerous: use with care!
433                vec mean() const {return elem_div (beta, alpha - 1);}
434                vec variance() const {vec mea = mean(); return elem_div (elem_mult (mea, mea), alpha - 2);}
435};
436/*
437//! Weighted mixture of epdfs with external owned components.
438class emix : public epdf {
439protected:
440        int n;
441        vec &w;
442        Array<epdf*> Coms;
443public:
444//! Default constructor
445        emix ( const RV &rv, vec &w0): epdf(rv), n(w0.length()), w(w0), Coms(n) {};
446        void set_parameters( int &i, double wi, epdf* ep){w(i)=wi;Coms(i)=ep;}
447        vec mean(){vec pom; for(int i=0;i<n;i++){pom+=Coms(i)->mean()*w(i);} return pom;};
448        vec sample() {it_error ( "Not implemented" );return 0;}
449};
450*/
451
452//!  Uniform distributed density on a rectangular support
453
454class euni: public epdf
455{
456        protected:
457//! lower bound on support
458                vec low;
459//! upper bound on support
460                vec high;
461//! internal
462                vec distance;
463//! normalizing coefficients
464                double nk;
465//! cache of log( \c nk )
466                double lnk;
467        public:
468                //! \name Constructors
469                //!@{
470                euni () : epdf () {}
471                euni (const vec &low0, const vec &high0) {set_parameters (low0, high0);}
472                void set_parameters (const vec &low0, const vec &high0) {
473                        distance = high0 - low0;
474                        it_assert_debug (min (distance) > 0.0, "bad support");
475                        low = low0;
476                        high = high0;
477                        nk = prod (1.0 / distance);
478                        lnk = log (nk);
479                        dim = low.length();
480                }
481                //!@}
482
483                double evallog (const vec &val) const  {
484                        if (any (val < low) && any (val > high)) {return inf;}
485                        else return lnk;
486                }
487                vec sample() const {
488                        vec smp (dim);
489#pragma omp critical
490                        UniRNG.sample_vector (dim , smp);
491                        return low + elem_mult (distance, smp);
492                }
493                //! set values of \c low and \c high
494                vec mean() const {return (high -low) / 2.0;}
495                vec variance() const {return (pow (high, 2) + pow (low, 2) + elem_mult (high, low)) / 3.0;}
496                //! Load from structure with elements:
497                //!  \code
498                //! { high = [...];          // vector of upper bounds
499                //!   low = [...];           // vector of lower bounds
500                //!   rv = {class="RV",...}  // description of RV
501                //! }
502                //! \endcode
503                //!@}
504                void from_setting (const Setting &set) {
505                        epdf::from_setting (set); // reads rv and rvc
506
507                        UI::get (high, set, "high", UI::compulsory);
508                        UI::get (low, set, "low", UI::compulsory);
509                }
510};
511
512
513/*!
514 \brief Normal distributed linear function with linear function of mean value;
515
516 Mean value \f$ \mu=A*\mbox{rvc}+\mu_0 \f$.
517*/
518template < class sq_T, template <typename> class TEpdf = enorm >
519class mlnorm : public mpdf_internal< TEpdf<sq_T> >
520{
521        protected:
522                //! Internal epdf that arise by conditioning on \c rvc
523                mat A;
524                //! Constant additive term
525                vec mu_const;
526//                      vec& _mu; //cached epdf.mu; !!!!!! WHY NOT?
527        public:
528                //! \name Constructors
529                //!@{
530                mlnorm() : mpdf_internal< TEpdf<sq_T> >() {};
531                mlnorm (const mat &A, const vec &mu0, const sq_T &R) : mpdf_internal< TEpdf<sq_T> >() {
532                        set_parameters (A, mu0, R);
533                }
534
535                //! Set \c A and \c R
536                void set_parameters (const  mat &A0, const vec &mu0, const sq_T &R0) {
537                        it_assert_debug (A0.rows() == mu0.length(), "");
538                        it_assert_debug (A0.rows() == R0.rows(), "");
539
540                        this->iepdf.set_parameters (zeros (A0.rows()), R0);
541                        A = A0;
542                        mu_const = mu0;
543                        this->dimc = A0.cols();
544                }
545                //!@}
546                //! Set value of \c rvc . Result of this operation is stored in \c epdf use function \c _ep to access it.
547                void condition (const vec &cond) {
548                        this->iepdf._mu() = A * cond + mu_const;
549//R is already assigned;
550                }
551
552                //!access function
553                vec& _mu_const() {return mu_const;}
554                //!access function
555                mat& _A() {return A;}
556                //!access function
557                mat _R() { return this->iepdf._R().to_mat(); }
558
559                //! Debug stream
560                template<typename sq_M>
561                friend std::ostream &operator<< (std::ostream &os,  mlnorm<sq_M, enorm> &ml);
562
563                void from_setting (const Setting &set) {
564                        mpdf::from_setting (set);
565
566                        UI::get (A, set, "A", UI::compulsory);
567                        UI::get (mu_const, set, "const", UI::compulsory);
568                        mat R0;
569                        UI::get (R0, set, "R", UI::compulsory);
570                        set_parameters (A, mu_const, R0);
571                };
572};
573UIREGISTER2 (mlnorm,ldmat);
574SHAREDPTR2 ( mlnorm, ldmat );
575UIREGISTER2 (mlnorm,fsqmat);
576SHAREDPTR2 ( mlnorm, fsqmat );
577UIREGISTER2 (mlnorm, chmat);
578SHAREDPTR2 ( mlnorm, chmat );
579
580//! Mpdf with general function for mean value
581template<class sq_T>
582class mgnorm : public mpdf_internal< enorm< sq_T > >
583{
584        private:
585//                      vec &mu; WHY NOT?
586                shared_ptr<fnc> g;
587
588        public:
589                //!default constructor
590                mgnorm() : mpdf_internal<enorm<sq_T> >() { }
591                //!set mean function
592                inline void set_parameters (const shared_ptr<fnc> &g0, const sq_T &R0);
593                inline void condition (const vec &cond);
594
595
596                /*! UI for mgnorm
597
598                The mgnorm is constructed from a structure with fields:
599                \code
600                system = {
601                        type = "mgnorm";
602                        // function for mean value evolution
603                        g = {type="fnc"; ... }
604
605                        // variance
606                        R = [1, 0,
607                                 0, 1];
608                        // --OR --
609                        dR = [1, 1];
610
611                        // == OPTIONAL ==
612
613                        // description of y variables
614                        y = {type="rv"; names=["y", "u"];};
615                        // description of u variable
616                        u = {type="rv"; names=[];}
617                };
618                \endcode
619
620                Result if
621                */
622
623                void from_setting (const Setting &set) {
624                        shared_ptr<fnc> g = UI::build<fnc> (set, "g", UI::compulsory);
625
626                        mat R;
627                        vec dR;
628                        if (UI::get (dR, set, "dR"))
629                                R = diag (dR);
630                        else
631                                UI::get (R, set, "R", UI::compulsory);
632
633                        set_parameters (g, R);
634                }
635};
636
637UIREGISTER2 (mgnorm, chmat);
638SHAREDPTR2 ( mgnorm, chmat );
639
640
641/*! (Approximate) Student t density with linear function of mean value
642
643The internal epdf of this class is of the type of a Gaussian (enorm).
644However, each conditioning is trying to assure the best possible approximation by taking into account the zeta function. See [] for reference.
645
646Perhaps a moment-matching technique?
647*/
648class mlstudent : public mlnorm<ldmat, enorm>
649{
650        protected:
651                //! Variable \f$ \Lambda \f$ from theory
652                ldmat Lambda;
653                //! Reference to variable \f$ R \f$
654                ldmat &_R;
655                //! Variable \f$ R_e \f$
656                ldmat Re;
657        public:
658                mlstudent () : mlnorm<ldmat, enorm> (),
659                                Lambda (),      _R (iepdf._R()) {}
660                //! constructor function
661                void set_parameters (const mat &A0, const vec &mu0, const ldmat &R0, const ldmat& Lambda0) {
662                        it_assert_debug (A0.rows() == mu0.length(), "");
663                        it_assert_debug (R0.rows() == A0.rows(), "");
664
665                        iepdf.set_parameters (mu0, Lambda);  //
666                        A = A0;
667                        mu_const = mu0;
668                        Re = R0;
669                        Lambda = Lambda0;
670                }
671                void condition (const vec &cond) {
672                        iepdf._mu() = A * cond + mu_const;
673                        double zeta;
674                        //ugly hack!
675                        if ( (cond.length() + 1) == Lambda.rows()) {
676                                zeta = Lambda.invqform (concat (cond, vec_1 (1.0)));
677                        } else {
678                                zeta = Lambda.invqform (cond);
679                        }
680                        _R = Re;
681                        _R *= (1 + zeta);// / ( nu ); << nu is in Re!!!!!!
682                };
683
684};
685/*!
686\brief  Gamma random walk
687
688Mean value, \f$\mu\f$, of this density is given by \c rvc .
689Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
690This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
691
692The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
693*/
694class mgamma : public mpdf_internal<egamma>
695{
696        protected:
697
698                //! Constant \f$k\f$
699                double k;
700
701                //! cache of iepdf.beta
702                vec &_beta;
703
704        public:
705                //! Constructor
706                mgamma() : mpdf_internal<egamma>(), k (0),
707                                _beta (iepdf._beta()) {
708                }
709
710                //! Set value of \c k
711                void set_parameters (double k, const vec &beta0);
712
713                void condition (const vec &val) {_beta = k / val;};
714                //! Load from structure with elements:
715                //!  \code
716                //! { alpha = [...];         // vector of alpha
717                //!   k = 1.1;               // multiplicative constant k
718                //!   rv = {class="RV",...}  // description of RV
719                //!   rvc = {class="RV",...} // description of RV in condition
720                //! }
721                //! \endcode
722                //!@}
723                void from_setting (const Setting &set) {
724                        mpdf::from_setting (set); // reads rv and rvc
725                        vec betatmp; // ugly but necessary
726                        UI::get (betatmp, set, "beta", UI::compulsory);
727                        UI::get (k, set, "k", UI::compulsory);
728                        set_parameters (k, betatmp);
729                }
730};
731UIREGISTER (mgamma);
732SHAREDPTR (mgamma);
733
734/*!
735\brief  Inverse-Gamma random walk
736
737Mean value, \f$ \mu \f$, of this density is given by \c rvc .
738Standard deviation of the random walk is proportional to one \f$ k \f$-th the mean.
739This is achieved by setting \f$ \alpha=\mu/k^2+2 \f$ and \f$ \beta=\mu(\alpha-1)\f$.
740
741The standard deviation of the walk is then: \f$ \mu/\sqrt(k)\f$.
742 */
743class migamma : public mpdf_internal<eigamma>
744{
745        protected:
746                //! Constant \f$k\f$
747                double k;
748
749                //! cache of iepdf.alpha
750                vec &_alpha;
751
752                //! cache of iepdf.beta
753                vec &_beta;
754
755        public:
756                //! \name Constructors
757                //!@{
758                migamma() : mpdf_internal<eigamma>(),
759                                k (0),
760                                _alpha (iepdf._alpha()),
761                                _beta (iepdf._beta()) {
762                }
763
764                migamma (const migamma &m) : mpdf_internal<eigamma>(),
765                                k (0),
766                                _alpha (iepdf._alpha()),
767                                _beta (iepdf._beta()) {
768                }
769                //!@}
770
771                //! Set value of \c k
772                void set_parameters (int len, double k0) {
773                        k = k0;
774                        iepdf.set_parameters ( (1.0 / (k*k) + 2.0) *ones (len) /*alpha*/, ones (len) /*beta*/);
775                        dimc = dimension();
776                };
777                void condition (const vec &val) {
778                        _beta = elem_mult (val, (_alpha - 1.0));
779                };
780};
781
782
783/*!
784\brief  Gamma random walk around a fixed point
785
786Mean 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
787\f[ \mu = \mu_{t-1} ^{l} p^{1-l}\f]
788
789Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
790This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
791
792The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
793*/
794class mgamma_fix : public mgamma
795{
796        protected:
797                //! parameter l
798                double l;
799                //! reference vector
800                vec refl;
801        public:
802                //! Constructor
803                mgamma_fix () : mgamma (), refl () {};
804                //! Set value of \c k
805                void set_parameters (double k0 , vec ref0, double l0) {
806                        mgamma::set_parameters (k0, ref0);
807                        refl = pow (ref0, 1.0 - l0);l = l0;
808                        dimc = dimension();
809                };
810
811                void condition (const vec &val) {vec mean = elem_mult (refl, pow (val, l)); _beta = k / mean;};
812};
813
814
815/*!
816\brief  Inverse-Gamma random walk around a fixed point
817
818Mean 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
819\f[ \mu = \mu_{t-1} ^{l} p^{1-l}\f]
820
821==== Check == vv =
822Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
823This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
824
825The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
826 */
827class migamma_ref : public migamma
828{
829        protected:
830                //! parameter l
831                double l;
832                //! reference vector
833                vec refl;
834        public:
835                //! Constructor
836                migamma_ref () : migamma (), refl () {};
837                //! Set value of \c k
838                void set_parameters (double k0 , vec ref0, double l0) {
839                        migamma::set_parameters (ref0.length(), k0);
840                        refl = pow (ref0, 1.0 - l0);
841                        l = l0;
842                        dimc = dimension();
843                };
844
845                void condition (const vec &val) {
846                        vec mean = elem_mult (refl, pow (val, l));
847                        migamma::condition (mean);
848                };
849
850                /*! UI for migamma_ref
851
852                The migamma_ref is constructed from a structure with fields:
853                \code
854                system = {
855                        type = "migamma_ref";
856                        ref = [1e-5; 1e-5; 1e-2 1e-3];            // reference vector
857                        l = 0.999;                                // constant l
858                        k = 0.1;                                  // constant k
859                       
860                        // == OPTIONAL ==
861                        // description of y variables
862                        y = {type="rv"; names=["y", "u"];};
863                        // description of u variable
864                        u = {type="rv"; names=[];}
865                };
866                \endcode
867
868                Result if
869                 */
870                void from_setting (const Setting &set);
871
872                // TODO dodelat void to_setting( Setting &set ) const;
873};
874
875
876UIREGISTER (migamma_ref);
877SHAREDPTR (migamma_ref);
878
879/*! Log-Normal probability density
880 only allow diagonal covariances!
881
882Density of the form \f$ \log(x)\sim \mathcal{N}(\mu,\sigma^2) \f$ , i.e.
883\f[
884x \sim \frac{1}{x\sigma\sqrt{2\pi}}\exp{-\frac{1}{2\sigma^2}(\log(x)-\mu)}
885\f]
886
887*/
888class elognorm: public enorm<ldmat>
889{
890        public:
891                vec sample() const {return exp (enorm<ldmat>::sample());};
892                vec mean() const {vec var = enorm<ldmat>::variance();return exp (mu - 0.5*var);};
893
894};
895
896/*!
897\brief  Log-Normal random walk
898
899Mean value, \f$\mu\f$, is...
900
901==== Check == vv =
902Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
903This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
904
905The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
906 */
907class mlognorm : public mpdf_internal<elognorm>
908{
909        protected:
910                //! parameter 1/2*sigma^2
911                double sig2;
912
913                //! access
914                vec &mu;
915        public:
916                //! Constructor
917                mlognorm() : mpdf_internal<elognorm>(),
918                                sig2 (0),
919                                mu (iepdf._mu()) {
920                }
921
922                //! Set value of \c k
923                void set_parameters (int size, double k) {
924                        sig2 = 0.5 * log (k * k + 1);
925                        iepdf.set_parameters (zeros (size), 2*sig2*eye (size));
926
927                        dimc = size;
928                };
929
930                void condition (const vec &val) {
931                        mu = log (val) - sig2;//elem_mult ( refl,pow ( val,l ) );
932                };
933
934                /*! UI for mlognorm
935
936                The mlognorm is constructed from a structure with fields:
937                \code
938                system = {
939                        type = "mlognorm";
940                        k = 0.1;                                  // constant k
941                        mu0 = [1., 1.];
942                       
943                        // == OPTIONAL ==
944                        // description of y variables
945                        y = {type="rv"; names=["y", "u"];};
946                        // description of u variable
947                        u = {type="rv"; names=[];}
948                };
949                \endcode
950
951                 */
952                void from_setting (const Setting &set);
953
954                // TODO dodelat void to_setting( Setting &set ) const;
955
956};
957
958UIREGISTER (mlognorm);
959SHAREDPTR (mlognorm);
960
961/*! inverse Wishart density defined on Choleski decomposition
962
963*/
964class eWishartCh : public epdf
965{
966        protected:
967                //! Upper-Triagle of Choleski decomposition of \f$ \Psi \f$
968                chmat Y;
969                //! dimension of matrix  \f$ \Psi \f$
970                int p;
971                //! degrees of freedom  \f$ \nu \f$
972                double delta;
973        public:
974                //! Set internal structures
975                void set_parameters (const mat &Y0, const double delta0) {Y = chmat (Y0);delta = delta0; p = Y.rows(); dim = p * p; }
976                //! Sample matrix argument
977                mat sample_mat() const {
978                        mat X = zeros (p, p);
979
980                        //sample diagonal
981                        for (int i = 0;i < p;i++) {
982                                GamRNG.setup (0.5* (delta - i) , 0.5);   // no +1 !! index if from 0
983#pragma omp critical
984                                X (i, i) = sqrt (GamRNG());
985                        }
986                        //do the rest
987                        for (int i = 0;i < p;i++) {
988                                for (int j = i + 1;j < p;j++) {
989#pragma omp critical
990                                        X (i, j) = NorRNG.sample();
991                                }
992                        }
993                        return X*Y._Ch();// return upper triangular part of the decomposition
994                }
995                vec sample () const {
996                        return vec (sample_mat()._data(), p*p);
997                }
998                //! fast access function y0 will be copied into Y.Ch.
999                void setY (const mat &Ch0) {copy_vector (dim, Ch0._data(), Y._Ch()._data());}
1000                //! fast access function y0 will be copied into Y.Ch.
1001                void _setY (const vec &ch0) {copy_vector (dim, ch0._data(), Y._Ch()._data()); }
1002                //! access function
1003                const chmat& getY() const {return Y;}
1004};
1005
1006//! Inverse Wishart on Choleski decomposition
1007/*! Being computed by conversion from `standard' Wishart
1008*/
1009class eiWishartCh: public epdf
1010{
1011        protected:
1012                //! Internal instance of Wishart density
1013                eWishartCh W;
1014                //! size of Ch
1015                int p;
1016                //! parameter delta
1017                double delta;
1018        public:
1019                //! constructor function
1020                void set_parameters (const mat &Y0, const double delta0) {
1021                        delta = delta0;
1022                        W.set_parameters (inv (Y0), delta0);
1023                        dim = W.dimension(); p = Y0.rows();
1024                }
1025                vec sample() const {mat iCh; iCh = inv (W.sample_mat()); return vec (iCh._data(), dim);}
1026                //! access function
1027                void _setY (const vec &y0) {
1028                        mat Ch (p, p);
1029                        mat iCh (p, p);
1030                        copy_vector (dim, y0._data(), Ch._data());
1031
1032                        iCh = inv (Ch);
1033                        W.setY (iCh);
1034                }
1035                virtual double evallog (const vec &val) const {
1036                        chmat X (p);
1037                        const chmat& Y = W.getY();
1038
1039                        copy_vector (p*p, val._data(), X._Ch()._data());
1040                        chmat iX (p);X.inv (iX);
1041                        // compute
1042//                              \frac{ |\Psi|^{m/2}|X|^{-(m+p+1)/2}e^{-tr(\Psi X^{-1})/2} }{ 2^{mp/2}\Gamma_p(m/2)},
1043                        mat M = Y.to_mat() * iX.to_mat();
1044
1045                        double log1 = 0.5 * p * (2 * Y.logdet()) - 0.5 * (delta + p + 1) * (2 * X.logdet()) - 0.5 * trace (M);
1046                        //Fixme! Multivariate gamma omitted!! it is ok for sampling, but not otherwise!!
1047
1048                        /*                              if (0) {
1049                                                                mat XX=X.to_mat();
1050                                                                mat YY=Y.to_mat();
1051
1052                                                                double log2 = 0.5*p*log(det(YY))-0.5*(delta+p+1)*log(det(XX))-0.5*trace(YY*inv(XX));
1053                                                                cout << log1 << "," << log2 << endl;
1054                                                        }*/
1055                        return log1;
1056                };
1057
1058};
1059
1060//! Random Walk on inverse Wishart
1061class rwiWishartCh : public mpdf_internal<eiWishartCh>
1062{
1063        protected:
1064                //!square root of \f$ \nu-p-1 \f$ - needed for computation of \f$ \Psi \f$ from conditions
1065                double sqd;
1066                //!reference point for diagonal
1067                vec refl;
1068                //! power of the reference
1069                double l;
1070                //! dimension
1071                int p;
1072
1073        public:
1074                rwiWishartCh() : sqd (0), l (0), p (0) {}
1075                //! constructor function
1076                void set_parameters (int p0, double k, vec ref0, double l0) {
1077                        p = p0;
1078                        double delta = 2 / (k * k) + p + 3;
1079                        sqd = sqrt (delta - p - 1);
1080                        l = l0;
1081                        refl = pow (ref0, 1 - l);
1082
1083                        iepdf.set_parameters (eye (p), delta);
1084                        dimc = iepdf.dimension();
1085                }
1086                void condition (const vec &c) {
1087                        vec z = c;
1088                        int ri = 0;
1089                        for (int i = 0;i < p*p;i += (p + 1)) {//trace diagonal element
1090                                z (i) = pow (z (i), l) * refl (ri);
1091                                ri++;
1092                        }
1093
1094                        iepdf._setY (sqd*z);
1095                }
1096};
1097
1098//! Switch between various resampling methods.
1099enum RESAMPLING_METHOD { MULTINOMIAL = 0, STRATIFIED = 1, SYSTEMATIC = 3 };
1100/*!
1101\brief Weighted empirical density
1102
1103Used e.g. in particle filters.
1104*/
1105class eEmp: public epdf
1106{
1107        protected :
1108                //! Number of particles
1109                int n;
1110                //! Sample weights \f$w\f$
1111                vec w;
1112                //! Samples \f$x^{(i)}, i=1..n\f$
1113                Array<vec> samples;
1114        public:
1115                //! \name Constructors
1116                //!@{
1117                eEmp () : epdf (), w (), samples () {};
1118                //! copy constructor
1119                eEmp (const eEmp &e) : epdf (e), w (e.w), samples (e.samples) {};
1120                //!@}
1121
1122                //! Set samples and weights
1123                void set_statistics (const vec &w0, const epdf &pdf0);
1124                //! Set samples and weights
1125                void set_statistics (const epdf &pdf0 , int n) {set_statistics (ones (n) / n, pdf0);};
1126                //! Set sample
1127                void set_samples (const epdf* pdf0);
1128                //! Set sample
1129                void set_parameters (int n0, bool copy = true) {n = n0; w.set_size (n0, copy);samples.set_size (n0, copy);};
1130                //! Potentially dangerous, use with care.
1131                vec& _w()  {return w;};
1132                //! Potentially dangerous, use with care.
1133                const vec& _w() const {return w;};
1134                //! access function
1135                Array<vec>& _samples() {return samples;};
1136                //! access function
1137                const Array<vec>& _samples() const {return samples;};
1138                //! 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.
1139                ivec resample (RESAMPLING_METHOD method = SYSTEMATIC);
1140                //! inherited operation : NOT implemneted
1141                vec sample() const {it_error ("Not implemented");return 0;}
1142                //! inherited operation : NOT implemneted
1143                double evallog (const vec &val) const {it_error ("Not implemented");return 0.0;}
1144                vec mean() const {
1145                        vec pom = zeros (dim);
1146                        for (int i = 0;i < n;i++) {pom += samples (i) * w (i);}
1147                        return pom;
1148                }
1149                vec variance() const {
1150                        vec pom = zeros (dim);
1151                        for (int i = 0;i < n;i++) {pom += pow (samples (i), 2) * w (i);}
1152                        return pom -pow (mean(), 2);
1153                }
1154                //! For this class, qbounds are minimum and maximum value of the population!
1155                void qbounds (vec &lb, vec &ub, double perc = 0.95) const {
1156                        // lb in inf so than it will be pushed below;
1157                        lb.set_size (dim);
1158                        ub.set_size (dim);
1159                        lb = std::numeric_limits<double>::infinity();
1160                        ub = -std::numeric_limits<double>::infinity();
1161                        int j;
1162                        for (int i = 0;i < n;i++) {
1163                                for (j = 0;j < dim; j++) {
1164                                        if (samples (i) (j) < lb (j)) {lb (j) = samples (i) (j);}
1165                                        if (samples (i) (j) > ub (j)) {ub (j) = samples (i) (j);}
1166                                }
1167                        }
1168                }
1169};
1170
1171
1172////////////////////////
1173
1174template<class sq_T>
1175void enorm<sq_T>::set_parameters (const vec &mu0, const sq_T &R0)
1176{
1177//Fixme test dimensions of mu0 and R0;
1178        mu = mu0;
1179        R = R0;
1180        validate();
1181};
1182
1183template<class sq_T>
1184void enorm<sq_T>::from_setting (const Setting &set)
1185{
1186        epdf::from_setting (set); //reads rv
1187
1188        UI::get (mu, set, "mu", UI::compulsory);
1189        mat Rtmp;// necessary for conversion
1190        UI::get (Rtmp, set, "R", UI::compulsory);
1191        R = Rtmp; // conversion
1192        validate();
1193}
1194
1195template<class sq_T>
1196void enorm<sq_T>::dupdate (mat &v, double nu)
1197{
1198        //
1199};
1200
1201// template<class sq_T>
1202// void enorm<sq_T>::tupdate ( double phi, mat &vbar, double nubar ) {
1203//      //
1204// };
1205
1206template<class sq_T>
1207vec enorm<sq_T>::sample() const
1208{
1209        vec x (dim);
1210#pragma omp critical
1211        NorRNG.sample_vector (dim, x);
1212        vec smp = R.sqrt_mult (x);
1213
1214        smp += mu;
1215        return smp;
1216};
1217
1218// template<class sq_T>
1219// double enorm<sq_T>::eval ( const vec &val ) const {
1220//      double pdfl,e;
1221//      pdfl = evallog ( val );
1222//      e = exp ( pdfl );
1223//      return e;
1224// };
1225
1226template<class sq_T>
1227double enorm<sq_T>::evallog_nn (const vec &val) const
1228{
1229        // 1.83787706640935 = log(2pi)
1230        double tmp = -0.5 * (R.invqform (mu - val));// - lognc();
1231        return  tmp;
1232};
1233
1234template<class sq_T>
1235inline double enorm<sq_T>::lognc () const
1236{
1237        // 1.83787706640935 = log(2pi)
1238        double tmp = 0.5 * (R.cols() * 1.83787706640935 + R.logdet());
1239        return tmp;
1240};
1241
1242
1243// template<class sq_T>
1244// vec mlnorm<sq_T>::samplecond (const  vec &cond, double &lik ) {
1245//      this->condition ( cond );
1246//      vec smp = epdf.sample();
1247//      lik = epdf.eval ( smp );
1248//      return smp;
1249// }
1250
1251// template<class sq_T>
1252// mat mlnorm<sq_T>::samplecond (const vec &cond, vec &lik, int n ) {
1253//      int i;
1254//      int dim = rv.count();
1255//      mat Smp ( dim,n );
1256//      vec smp ( dim );
1257//      this->condition ( cond );
1258//
1259//      for ( i=0; i<n; i++ ) {
1260//              smp = epdf.sample();
1261//              lik ( i ) = epdf.eval ( smp );
1262//              Smp.set_col ( i ,smp );
1263//      }
1264//
1265//      return Smp;
1266// }
1267
1268
1269template<class sq_T>
1270shared_ptr<epdf> enorm<sq_T>::marginal ( const RV &rvn ) const
1271{
1272        enorm<sq_T> *tmp = new enorm<sq_T> ();
1273        shared_ptr<epdf> narrow(tmp);
1274        marginal ( rvn, *tmp );
1275        return narrow;
1276}
1277
1278template<class sq_T>
1279void enorm<sq_T>::marginal ( const RV &rvn, enorm<sq_T> &target ) const
1280{
1281        it_assert_debug (isnamed(), "rv description is not assigned");
1282        ivec irvn = rvn.dataind (rv);
1283
1284        sq_T Rn (R, irvn);  // select rows and columns of R
1285
1286        target.set_rv ( rvn );
1287        target.set_parameters (mu (irvn), Rn);
1288}
1289
1290template<class sq_T>
1291shared_ptr<mpdf> enorm<sq_T>::condition ( const RV &rvn ) const
1292{
1293        mlnorm<sq_T> *tmp = new mlnorm<sq_T> ();
1294        shared_ptr<mpdf> narrow(tmp);
1295        condition ( rvn, *tmp );
1296        return narrow;
1297}
1298
1299template<class sq_T>
1300void enorm<sq_T>::condition ( const RV &rvn, mpdf &target ) const
1301{
1302        typedef mlnorm<sq_T> TMlnorm;
1303
1304        it_assert_debug (isnamed(), "rvs are not assigned");
1305        TMlnorm &uptarget = dynamic_cast<TMlnorm &>(target);
1306
1307        RV rvc = rv.subt (rvn);
1308        it_assert_debug ( (rvc._dsize() + rvn._dsize() == rv._dsize()), "wrong rvn");
1309        //Permutation vector of the new R
1310        ivec irvn = rvn.dataind (rv);
1311        ivec irvc = rvc.dataind (rv);
1312        ivec perm = concat (irvn , irvc);
1313        sq_T Rn (R, perm);
1314
1315        //fixme - could this be done in general for all sq_T?
1316        mat S = Rn.to_mat();
1317        //fixme
1318        int n = rvn._dsize() - 1;
1319        int end = R.rows() - 1;
1320        mat S11 = S.get (0, n, 0, n);
1321        mat S12 = S.get (0, n , rvn._dsize(), end);
1322        mat S22 = S.get (rvn._dsize(), end, rvn._dsize(), end);
1323
1324        vec mu1 = mu (irvn);
1325        vec mu2 = mu (irvc);
1326        mat A = S12 * inv (S22);
1327        sq_T R_n (S11 - A *S12.T());
1328
1329        uptarget.set_rv (rvn);
1330        uptarget.set_rvc (rvc);
1331        uptarget.set_parameters (A, mu1 - A*mu2, R_n);
1332}
1333
1334////
1335///////
1336template<class sq_T>
1337void mgnorm<sq_T >::set_parameters (const shared_ptr<fnc> &g0, const sq_T &R0) {
1338        g = g0;
1339        this->iepdf.set_parameters (zeros (g->dimension()), R0);
1340}
1341
1342template<class sq_T>
1343void mgnorm<sq_T >::condition (const vec &cond) {this->iepdf._mu() = g->eval (cond);};
1344
1345//! \todo unify this stuff with to_string()
1346template<class sq_T>
1347std::ostream &operator<< (std::ostream &os,  mlnorm<sq_T> &ml)
1348{
1349        os << "A:" << ml.A << endl;
1350        os << "mu:" << ml.mu_const << endl;
1351        os << "R:" << ml._R() << endl;
1352        return os;
1353};
1354
1355}
1356#endif //EF_H
Note: See TracBrowser for help on using the browser.