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

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

new object discrete_support, merger adapted to accept this input as well

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