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

Revision 504, 34.2 kB (checked in by vbarta, 15 years ago)

returning shared pointers from epdf::marginal & epdf::condition; testsuite run leaks down from 8402 to 6510 bytes

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