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

Revision 723, 40.3 kB (checked in by smidl, 15 years ago)

Big commit of LQG stuff

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