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

Revision 750, 40.4 kB (checked in by sarka, 15 years ago)

dimc ze set_parameters do validate

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