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

Revision 529, 34.5 kB (checked in by vbarta, 15 years ago)

defined *_ptr wrappers of shared pointers

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