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

Revision 644, 39.0 kB (checked in by smidl, 15 years ago)

win32 compilation fixes - does not compile yet...

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