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

Revision 1383, 57.6 kB (checked in by sindj, 13 years ago)

Program update, kontrola vypoctu provedena, integruje spravne v nedegenerovanem pripade. JS

  • 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
[1383]31
[488]32/*!
[1063]33* \brief Abstract class of general conjugate exponential family posterior density.
[8]34
[488]35* More?...
36*/
[737]37class eEF : public epdf {
38public:
[1066]39//    eEF() :epdf() {};
[1064]40    //! default constructor
41    eEF () : epdf () {};
42    //! logarithm of the normalizing constant, \f$\mathcal{I}\f$
43    virtual double lognc() const = 0;
[565]44
[1064]45    //!Evaluate normalized log-probability
46    virtual double evallog_nn ( const vec &val ) const NOT_IMPLEMENTED(0);
[565]47
[1064]48    //!Evaluate normalized log-probability
49    virtual double evallog ( const vec &val ) const {
50        double tmp;
51        tmp = evallog_nn ( val ) - lognc();
52        return tmp;
53    }
54    //!Evaluate normalized log-probability for many samples
55    virtual vec evallog_mat ( const mat &Val ) const {
56        vec x ( Val.cols() );
57        for ( int i = 0; i < Val.cols(); i++ ) {
58            x ( i ) = evallog_nn ( Val.get_col ( i ) ) ;
59        }
60        return x - lognc();
61    }
62    //!Evaluate normalized log-probability for many samples
63    virtual vec evallog_mat ( const Array<vec> &Val ) const {
64        vec x ( Val.length() );
65        for ( int i = 0; i < Val.length(); i++ ) {
66            x ( i ) = evallog_nn ( Val ( i ) ) ;
67        }
68        return x - lognc();
69    }
[565]70
[1064]71    //!Power of the density, used e.g. to flatten the density
72    virtual void pow ( double p ) NOT_IMPLEMENTED_VOID;
[488]73};
[8]74
[33]75
[170]76//! Estimator for Exponential family
[737]77class BMEF : public BM {
78public:
[1064]79    //! forgetting factor
80    double frg;
81protected:
82    //! cached value of lognc() in the previous step (used in evaluation of \c ll )
83    double last_lognc;
84    //! factor k = [0..1] for scheduling of forgetting factor: \f$ frg_t = (1-k) * frg_{t-1} + k \f$, default 0
85    double frg_sched_factor;
86public:
87    //! Default constructor (=empty constructor)
88    BMEF ( double frg0 = 1.0 ) : BM (), frg ( frg0 ), last_lognc(0.0),frg_sched_factor(0.0) {}
89    //! Copy constructor
90    BMEF ( const BMEF &B ) : BM ( B ), frg ( B.frg ), last_lognc ( B.last_lognc ),frg_sched_factor(B.frg_sched_factor) {}
91    //!get statistics from another model
92    virtual void set_statistics ( const BMEF* BM0 ) NOT_IMPLEMENTED_VOID;
[565]93
[1064]94    //! Weighted update of sufficient statistics (Bayes rule)
95    virtual void bayes_weighted ( const vec &data, const vec &cond = empty_vec, const double w = 1.0 ) {
96        if (frg_sched_factor>0) {
97            frg = frg*(1-frg_sched_factor)+frg_sched_factor;
98        }
99    };
100    //original Bayes
101    void bayes ( const vec &yt, const vec &cond = empty_vec );
[565]102
[1064]103    //!Flatten the posterior according to the given BMEF (of the same type!)
104    virtual void flatten ( const BMEF * B, double weight=1.0 ) NOT_IMPLEMENTED_VOID;;
[198]105
[746]106
[1064]107    void to_setting ( Setting &set ) const
108    {
109        BM::to_setting( set );
110        UI::save(frg, set, "frg");
111        UI::save( frg_sched_factor, set, "frg_sched_factor" );
112    }
[907]113
[1077]114   /*! Create object from the following structure
115
116    \code
117    class = 'BMEF';
118     --- optional fields ---
119    frg = [];                   % forgetting factor
120    frg_sched_factor = [];      % factor for scheduling of forgetting factor: a number from [0..1]
121    --- inherited fields ---
122    bdm::BM::from_setting
123    \endcode
124    If the optional fields are not given, they will be filled as follows:
125    \code
126    frg = 1;                    % default forgetting factor
127    frg_sched_factor = 0;
128    \endcode
129    */
[1064]130    void from_setting( const Setting &set) {
131        BM::from_setting(set);
132        if ( !UI::get ( frg, set, "frg" ) )
133            frg = 1.0;
[1169]134        if ( !UI::get ( frg_sched_factor, set, "frg_sched_factor" ) )
[1077]135            frg_sched_factor = 0.0;
[1064]136    }
[850]137
[1064]138    void validate() {
139        BM::validate();
140    }
[850]141
[488]142};
[170]143
[1068]144/*! \brief Dirac delta density with predefined transformation
[797]145
146Density of the type:\f[ f(x_t | y_t) = \delta (x_t - g(y_t)) \f]
147where \f$ x_t \f$ is the \c rv, \f$ y_t \f$ is the \c rvc and g is a deterministic transformation of class fn.
148*/
[1064]149class mgdirac: public pdf {
150protected:
151    shared_ptr<fnc> g;
152public:
153    vec samplecond(const vec &cond) {
154        bdm_assert_debug(cond.length()==g->dimensionc(),"given cond in not compatible with g");
155        vec tmp = g->eval(cond);
156        return tmp;
157    }
158    double evallogcond ( const vec &yt, const vec &cond ) {
159        return std::numeric_limits< double >::max();
160    }
[1068]161
162    /*! Create object from the following structure
163
164    \code
165    class = 'mgdirac';
166    g = function bdm::fnc;      % any offspring of fnc, bdm::fnc::from_setting
167    --- inherited fields ---
168    bdm::pdf::from_setting
169    \endcode
170    */
[1064]171    void from_setting(const Setting& set);
172    void to_setting(Setting &set) const;
173    void validate();
[797]174};
175UIREGISTER(mgdirac);
176
177
[504]178template<class sq_T, template <typename> class TEpdf>
[488]179class mlnorm;
[178]180
[488]181/*!
182* \brief Gaussian density with positive definite (decomposed) covariance matrix.
[8]183
[488]184* More?...
185*/
186template<class sq_T>
[737]187class enorm : public eEF {
188protected:
[1064]189    //! mean value
190    vec mu;
191    //! Covariance matrix in decomposed form
192    sq_T R;
[737]193public:
[1064]194    //!\name Constructors
195    //!@{
[270]196
[1064]197    enorm () : eEF (), mu (), R () {};
198    enorm ( const vec &mu, const sq_T &R ) {
199        set_parameters ( mu, R );
200    }
201    void set_parameters ( const vec &mu, const sq_T &R );
202    /*! Create Normal density
203    \f[ f(rv) = N(\mu, R) \f]
204    from structure
205    \code
206    class = 'enorm<ldmat>', (OR) 'enorm<chmat>', (OR) 'enorm<fsqmat>';
207    mu    = [];                  // mean value
208    R     = [];                  // variance, square matrix of appropriate dimension
209    \endcode
210    */
211    void from_setting ( const Setting &root );
212    void to_setting ( Setting &root ) const ;
[270]213
[1064]214    void validate();
215    //!@}
[270]216
[1064]217    //! \name Mathematical operations
218    //!@{
[28]219
[1064]220    //! dupdate in exponential form (not really handy)
221    void dupdate ( mat &v, double nu = 1.0 );
[450]222
[1064]223    //! evaluate bhattacharya distance
224    double bhattacharyya(const enorm<sq_T> &e2) {
225        bdm_assert(dim == e2.dimension(), "enorms of differnt dimensions");
226        sq_T P=R;
227        P.add(e2._R());
[504]228
[1064]229        double tmp = 0.125*P.invqform(mu - e2._mu()) + 0.5*(P.logdet() - 0.5*(R.logdet() + e2._R().logdet()));
230        return tmp;
231    }
[504]232
[1064]233    vec sample() const;
[270]234
[1064]235    double evallog_nn ( const vec &val ) const;
236    double lognc () const;
237    vec mean() const {
238        return mu;
239    }
240    vec variance() const {
241        return diag ( R.to_mat() );
242    }
243    mat covariance() const {
244        return R.to_mat();
245    }
[1066]246    //    mlnorm<sq_T>* condition ( const RV &rvn ) const ; <=========== fails to cmpile. Why?
[1064]247    shared_ptr<pdf> condition ( const RV &rvn ) const;
[270]248
[1064]249    // target not typed to mlnorm<sq_T, enorm<sq_T> > &
250    // because that doesn't compile (perhaps because we
251    // haven't finished defining enorm yet), but the type
252    // is required
253    void condition ( const RV &rvn, pdf &target ) const;
[28]254
[1064]255    shared_ptr<epdf> marginal ( const RV &rvn ) const;
256    void marginal ( const RV &rvn, enorm<sq_T> &target ) const;
257    //!@}
258
259    //! \name Access to attributes
260    //!@{
261
262    vec& _mu() {
263        return mu;
264    }
265    const vec& _mu() const {
266        return mu;
267    }
268    void set_mu ( const vec mu0 ) {
269        mu = mu0;
270    }
271    sq_T& _R() {
272        return R;
273    }
274    const sq_T& _R() const {
275        return R;
276    }
277    //!@}
278
[488]279};
[737]280UIREGISTER2 ( enorm, chmat );
[529]281SHAREDPTR2 ( enorm, chmat );
[737]282UIREGISTER2 ( enorm, ldmat );
[529]283SHAREDPTR2 ( enorm, ldmat );
[737]284UIREGISTER2 ( enorm, fsqmat );
[529]285SHAREDPTR2 ( enorm, fsqmat );
[8]286
[1064]287//! \class bdm::egauss
[948]288//!\brief Gaussian (Normal) distribution. Same as enorm<fsqmat>.
[887]289typedef enorm<ldmat> egauss;
290UIREGISTER(egauss);
291
292
[802]293//forward declaration
294class mstudent;
[388]295
[802]296/*! distribution of multivariate Student t density
297
[1064]298Based on article by Genest and Zidek,
[802]299*/
300template<class sq_T>
[1064]301class estudent : public eEF {
302protected:
303    //! mena value
304    vec mu;
305    //! matrix H
306    sq_T H;
307    //! degrees of freedom
308    double delta;
309public:
310    double evallog_nn(const vec &val) const {
311        double tmp = -0.5*H.logdet() - 0.5*(delta + dim) * log(1+ H.invqform(val - mu)/delta);
312        return tmp;
313    }
314    double lognc() const {
315        //log(pi) = 1.14472988584940
316        double tmp = -lgamma(0.5*(delta+dim))+lgamma(0.5*delta) + 0.5*dim*(log(delta) + 1.14472988584940);
317        return tmp;
318    }
319    void marginal (const RV &rvm, estudent<sq_T> &marg) const {
320        ivec ind = rvm.findself_ids(rv); // indices of rvm in rv
321        marg._mu() = mu(ind);
322        marg._H() = sq_T(H,ind);
323        marg._delta() = delta;
324        marg.validate();
325    }
326    shared_ptr<epdf> marginal(const RV &rvm) const {
327        shared_ptr<estudent<sq_T> > tmp = new estudent<sq_T>;
328        marginal(rvm, *tmp);
329        return tmp;
330    }
[1175]331    vec sample() const {
332                enorm<sq_T> en;
333                en._mu()=mu;
334                en._R()=H;
335                en._R()*=delta/(delta-2);
336                en.validate();
337                return en.sample(); 
338        }
[1064]339
340    vec mean() const {
341        return mu;
342    }
343    mat covariance() const {
344        return delta/(delta-2)*H.to_mat();
345    }
346    vec variance() const {
347        return diag(covariance());
348    }
349    //! \name access
350    //! @{
351    //! access function
352    vec& _mu() {
353        return mu;
354    }
355    //! access function
356    sq_T& _H() {
357        return H;
358    }
359    //! access function
360    double& _delta() {
361        return delta;
362    }
363    //!@}
364    //! todo
365    void from_setting(const Setting &set) {
366        epdf::from_setting(set);
367        mat H0;
368        UI::get(H0,set, "H");
369        H= H0; // conversion!!
370        UI::get(delta,set,"delta");
371        UI::get(mu,set,"mu");
372    }
373    void to_setting(Setting &set) const {
374        epdf::to_setting(set);
375        UI::save(H.to_mat(), set, "H");
376        UI::save(delta, set, "delta");
377        UI::save(mu, set, "mu");
378    }
379    void validate() {
380        eEF::validate();
381        dim = H.rows();
382    }
[802]383};
384UIREGISTER2(estudent,fsqmat);
385UIREGISTER2(estudent,ldmat);
386UIREGISTER2(estudent,chmat);
387
[1196]388// template < class sq_T, template <typename> class TEpdf = estudent >
389// class mstudent : public pdf_internal< TEpdf<sq_T> > {
390// protected:
391//      //! Internal epdf that arise by conditioning on \c rvc
392//      mat A;
393//      //! Constant additive term
394//      vec mu_const;
395//     
396// public:
397//      void condition( const vec &cond ) {
398//              iepdf._mu()=A*val*mu_const;
399//      }
400//             
401// };
402
[488]403/*!
404* \brief Gauss-inverse-Wishart density stored in LD form
[96]405
[1189]406* For \f$p\f$-variate densities,
407*
408* \f$ M,R \sim GiW( V_t, \nu_t) \propto |R|^{0.5\nu}\exp(-1/2 tr(R^{-1}[I,M] V_t [I;M'])) \f$
[488]409*
[1189]410* Factorizes as:
411* \f$ M|R \sim N( \hat{M}, R \otimes Vz^{-1}) \propto |R|^{-0.5dim(psi)}\exp(-1/2 tr((M-\hat{M})R^{-1}(M-\hat{M})Vz) \f$
412* \f$ R \sim iW( \Lambda,\delta) \propto |R|^{-0.5(\nu - dim(psi))} |\Lambda|^{}\exp(-1/2 tr(R^{-1}\Lambda) \f$
413* where in standard notation \f$ |R|^{-0.5(\delta + p +1)}\f$, i.e.
414* \f$ \delta = \nu-dim(psi) -p-1 \f$
[488]415*/
[737]416class egiw : public eEF {
[1064]417    //! \var log_level_enums logvartheta
418    //! Log variance of the theta part
[870]419
[1064]420    LOG_LEVEL(egiw,logvartheta);
[907]421
[737]422protected:
[1064]423    //! Extended information matrix of sufficient statistics
424    ldmat V;
425    //! Number of data records (degrees of freedom) of sufficient statistics
426    double nu;
427    //! Dimension of the output
428    int dimx;
429    //! Dimension of the regressor
430    int nPsi;
[737]431public:
[1064]432    //!\name Constructors
433    //!@{
434    egiw() : eEF(),dimx(0) {};
435    egiw ( int dimx0, ldmat V0, double nu0 = -1.0 ) : eEF(),dimx(0) {
436        set_parameters ( dimx0, V0, nu0 );
437        validate();
438    };
[270]439
[1064]440    void set_parameters ( int dimx0, ldmat V0, double nu0 = -1.0 );
441    //!@}
[96]442
[1064]443    vec sample() const;
444    mat sample_mat ( int n ) const;
445    vec mean() const;
446    vec variance() const;
447    //mat covariance() const;
448    void sample_mat ( mat &Mi, chmat &Ri ) const;
[330]449
[1064]450    void factorize ( mat &M, ldmat &Vz, ldmat &Lam ) const;
[1189]451    //! LS estimate of \f$\theta\f$
[1064]452    vec est_theta() const;
[330]453
[1064]454    //! Covariance of the LS estimate
455    ldmat est_theta_cov() const;
[96]456
[1064]457    //! expected values of the linear coefficient and the covariance matrix are written to \c M and \c R , respectively
458    void mean_mat ( mat &M, mat&R ) const;
459    //! In this instance, val= [theta, r]. For multivariate instances, it is stored columnwise val = [theta_1 theta_2 ... r_1 r_2 ]
460    double evallog_nn ( const vec &val ) const;
461    double lognc () const;
462    void pow ( double p ) {
463        V *= p;
464        nu *= p;
465    };
[270]466
[1064]467    //! marginal density (only student for now)
468    shared_ptr<epdf> marginal(const RV &rvm) const {
469        bdm_assert(dimx==1, "Not supported");
470        //TODO - this is too trivial!!!
471        ivec ind = rvm.findself_ids(rv);
472        if (min(ind)==0) { //assume it si
473            shared_ptr<estudent<ldmat> > tmp = new estudent<ldmat>;
474            mat M;
475            ldmat Vz;
476            ldmat Lam;
477            factorize(M,Vz,Lam);
[737]478
[1064]479            tmp->_mu() = M.get_col(0);
480            ldmat H;
481            Vz.inv(H);
482            H *=Lam._D()(0)/nu;
483            tmp->_H() = H;
484            tmp->_delta() = nu;
485            tmp->validate();
486            return tmp;
487        }
488        return NULL;
489    }
490    //! \name Access attributes
491    //!@{
[737]492
[1064]493    ldmat& _V() {
494        return V;
495    }
496    const ldmat& _V() const {
497        return V;
498    }
499    double& _nu()  {
500        return nu;
501    }
502    const double& _nu() const {
503        return nu;
504    }
505    const int & _dimx() const {
506        return dimx;
507    }
[889]508
[1066]509    /*! Create object from the following structure
[1064]510    \code
[1066]511
[1064]512    class = 'egiw';
[1066]513    dimx    = [...];       % dimension of the wishart part
514    V.L     = [...];       % L part of matrix V
515    V.D     = [...];       % D part of matrix V
[1079]516    -or- fV = [...];       % full matrix V
[1066]517    -or- dV = [...];       % vector of diagonal of V (when V not given)
518
519    rv = RV({'names',...},[sizes,...],[times,...]);   % description of RV
520    rvc = RV({'names',...},[sizes,...],[times,...]);  % description of RV in condition
521
522    --- optional fields ---
523    nu      = [];             % scalar \nu ((almost) degrees of freedom)
524    --- inherited fields ---
525    bdm::eEF::from_setting
[1064]526    \endcode
[737]527
[1066]528    fulfilling formula \f[ f(rv) = GiW(V,\nu) \f]
529
530    If \nu is not given, it will be computed to obtain proper pdf.
531
[1064]532    \sa log_level_enums
533    */
534    void from_setting ( const Setting &set );
535    //! see egiw::from_setting
536    void to_setting ( Setting& set ) const;
537    void validate();
538    void log_register ( bdm::logger& L, const string& prefix );
539
540    void log_write() const;
541    //!@}
[488]542};
[529]543UIREGISTER ( egiw );
544SHAREDPTR ( egiw );
[96]545
[1121]546//! \brief Gauss-Wishart with recursion on moments
547//! Using precision as parameter
548//! following notation of [Karny Andrysek 2009], precision
549template<class sq_T>
550class egw_ls: public eEF{
551        public:
552                vec theta;
553                sq_T P;
554                double omega;
555                double nu;
556               
557                vec mean() const{
558                        return concat(theta, omega);
559                }
560                mat covariance() const {
561                        sq_T tmp=P;
562                        tmp*=nu/((nu-2)*omega);
563                        return tmp.to_mat();//<======= error - missing omega
564                }
565                vec variance() const {
566                        return diag(covariance());//<======= error - missing omega
567                }
568                vec sample() const NOT_IMPLEMENTED(vec(0));
569                double lognc() const {return 0.0;} //TODO
570};
571
[488]572/*! \brief Dirichlet posterior density
[173]573
[488]574Continuous Dirichlet density of \f$n\f$-dimensional variable \f$x\f$
575\f[
576f(x|\beta) = \frac{\Gamma[\gamma]}{\prod_{i=1}^{n}\Gamma(\beta_i)} \prod_{i=1}^{n}x_i^{\beta_i-1}
577\f]
578where \f$\gamma=\sum_i \beta_i\f$.
579*/
[737]580class eDirich: public eEF {
581protected:
[1064]582    //!sufficient statistics
583    vec beta;
[737]584public:
[1064]585    //!\name Constructors
586    //!@{
[270]587
[1064]588    eDirich () : eEF () {};
589    eDirich ( const eDirich &D0 ) : eEF () {
590        set_parameters ( D0.beta );
591        validate();
592    };
593    eDirich ( const vec &beta0 ) {
594        set_parameters ( beta0 );
595        validate();
596    };
597    void set_parameters ( const vec &beta0 ) {
598        beta = beta0;
599        dim = beta.length();
600    }
601    //!@}
[270]602
[1064]603    //! using sampling procedure from wikipedia
604    vec sample() const {
605        vec y ( beta.length() );
606        for ( int i = 0; i < beta.length(); i++ ) {
607            GamRNG.setup ( beta ( i ), 1 );
[737]608#pragma omp critical
[1064]609            y ( i ) = GamRNG();
610        }
611        return y / sum ( y );
612    }
[565]613
[1064]614    vec mean() const {
615        return beta / sum ( beta );
616    };
617    vec variance() const {
618        double gamma = sum ( beta );
619        return elem_mult ( beta, ( gamma - beta ) ) / ( gamma*gamma* ( gamma + 1 ) );
620    }
621    //! In this instance, val is ...
622    double evallog_nn ( const vec &val ) const {
623        double tmp;
624        tmp = ( beta - 1 ) * log ( val );
625        return tmp;
626    }
[565]627
[1064]628    double lognc () const {
629        double tmp;
630        double gam = sum ( beta );
631        double lgb = 0.0;
632        for ( int i = 0; i < beta.length(); i++ ) {
633            lgb += lgamma ( beta ( i ) );
634        }
635        tmp = lgb - lgamma ( gam );
636        return tmp;
637    }
[565]638
[1064]639    //!access function
640    vec& _beta()  {
641        return beta;
642    }
[1063]643
[1064]644    /*! Create object from the following structure
645    \code
646    class = 'eDirich';
647    beta  = [...];           % vector parameter beta
648    --- inherited fields ---
649    bdm::eEF::from_setting
650    \endcode
651    */
652    void from_setting ( const Setting &set );
[1063]653
[1064]654    void validate();
[1063]655
[1064]656    void to_setting ( Setting &set ) const;
[488]657};
[737]658UIREGISTER ( eDirich );
[96]659
[1063]660/*! \brief Product of Beta distributions
[1033]661
662Continuous Dirichlet density of \f$n\f$-dimensional variable \f$x\f$
663\f[
[1064]664f(x|\alpha,\beta)  = \frac{\Gamma(\alpha+\beta)}{\Gamma(\alpha)\Gamma(\beta)}\, x^{\alpha-1}(1-x)^{\beta-1}
[1033]665\f]
666is a simplification of Dirichlet to univariate case.
667*/
668class eBeta: public eEF {
[1064]669public:
670    //!sufficient statistics
671    vec alpha;
672    //!sufficient statistics
673    vec beta;
674public:
675    //!\name Constructors
676    //!@{
[1063]677
[1064]678    eBeta () : eEF () {};
679    eBeta ( const eBeta &B0 ) : eEF (), alpha(B0.alpha),beta(B0.beta) {
680        validate();
681    };
682    //!@}
[1063]683
[1064]684    //! using sampling procedure from wikipedia
685    vec sample() const {
686        vec y ( beta.length() ); // all vectors
687        for ( int i = 0; i < beta.length(); i++ ) {
688            GamRNG.setup ( alpha ( i ), 1 );
689#pragma omp critical
690            double Ga = GamRNG();
[1063]691
[1064]692            GamRNG.setup ( beta ( i ), 1 );
693#pragma omp critical
694            double Gb = GamRNG();
695
696            y ( i ) = Ga/(Ga+Gb);
697        }
698        return y;
699    }
700
701    vec mean() const {
702        return elem_div(alpha, alpha + beta); // dot-division
703    };
704    vec variance() const {
705        vec apb=alpha+beta;
706        return elem_div (elem_mult ( alpha, beta) ,
707                         elem_mult ( elem_mult(apb,apb), apb+1 ) );
708    }
709    //! In this instance, val is ...
710    double evallog_nn ( const vec &val ) const {
711        double tmp;
712        tmp = ( alpha - 1 ) * log ( val ) + (beta-1)*log(1-val);
713        return tmp;
714    }
715
716    double lognc () const {
717        double lgb = 0.0;
718        for ( int i = 0; i < beta.length(); i++ ) {
719            lgb += -lgamma ( alpha(i)+beta(i) ) + lgamma(alpha(i)) + lgamma(beta(i));
720        }
721        return lgb;
722    }
723
724    /*! Create object from the following structure
725
726    \code
727    class = 'eBeta';
728    alpha = [...];           % vector parameter alpha
729    beta  = [...];           % vector parameter beta of the same length as alpha
730    \endcode
731
732    Class does not call bdm::eEF::from_setting
733    */
734    void from_setting ( const Setting &set ) {
735        UI::get(alpha, set, "alpha", UI::compulsory);
736        UI::get(beta, set, "beta", UI::compulsory);
737    }
738
739    void validate() {
740        bdm_assert(alpha.length()==beta.length(), "eBeta:: alpha and beta length do not match");
741        dim = alpha.length();
742    }
743
744    void to_setting ( Setting &set ) const {
745        UI::save(alpha, set, "alpha");
746        UI::save(beta, set, "beta");
747    }
[1033]748};
749UIREGISTER ( eBeta );
750
[1068]751/*! \brief Random Walk on Dirichlet
752
[737]753Using simple assignment
[637]754 \f[ \beta = rvc / k + \beta_c \f]
755 hence, mean value = rvc, variance = (k+1)*mean*mean;
[737]756
[637]757 The greater k is, the greater is the variance of the random walk;
[737]758
[637]759 \f$ \beta_c \f$ is used as regularizing element to avoid corner cases, i.e. when one element of rvc is zero.
760 By default is it set to 0.1;
761*/
[693]762class mDirich: public pdf_internal<eDirich> {
[737]763protected:
[1064]764    //! constant \f$ k \f$ of the random walk
765    double k;
766    //! cache of beta_i
767    vec &_beta;
768    //! stabilizing coefficient \f$ \beta_c \f$
769    vec betac;
[737]770public:
[1064]771    mDirich() : pdf_internal<eDirich>(), _beta ( iepdf._beta() ) {};
772    void condition ( const vec &val ) {
773        _beta =  val / k + betac;
774    };
[1068]775
776    /*! Create object from the following structure
[1064]777    \code
778    class = 'mDirich';
[1068]779    k = 1;                      % multiplicative constant k
[1064]780    --- optional ---
[1068]781    beta0 = [...];              % initial values of beta
782    betac = [...];              % initial values of beta stabilizing coefficients
783    --- inherited fields ---
784    bdm::pdf::from_setting
[1064]785    \endcode
[1068]786    fulfilling form  \f[ f(rv|rvc) = Di(rvc*k) \f]
787
788    If the optional fields are not given, they will be filled as follows:
789    \code
790    beta0 = [1,1,1,...];               
791    betac = 0.1 * [1,1,1,...];
792    \endcode
[1064]793    */
794    void from_setting ( const Setting &set );
[1066]795    void     to_setting  (Setting  &set) const;
[1064]796    void validate();
[637]797};
[737]798UIREGISTER ( mDirich );
[637]799
[1033]800/*! \brief Random Walk with vector Beta distribution
[1068]801
[1033]802Using simple assignment
[1064]803\f{eqnarray*}
[1063]804\alpha & = & rvc / k + \beta_c \\
805\beta & = &(1-rvc) / k + \beta_c \\
806\f}
[1033]807for each element of alpha and beta, mean value = rvc, variance = (k+1)*mean*mean;
[977]808
[1033]809The greater \f$ k \f$ is, the greater is the variance of the random walk;
810
811\f$ \beta_c \f$ is used as regularizing element to avoid corner cases, i.e. when one element of rvc is zero.
812By default is it set to 0.1;
813*/
[1064]814class mBeta: public pdf_internal<eBeta> {
815    //! vector of constants \f$ k \f$ of the random walk
816    vec k;
817    //! stabilizing coefficient \f$ \beta_c \f$
818    vec betac;
[1033]819
[1064]820public:
821    void condition ( const vec &val ) {
822        this->iepdf.alpha =  elem_div(val , k) + betac;
823        this->iepdf.beta =  elem_div (1-val , k) + betac;
824    };
[1063]825
[1068]826    /*! Create object from the following structure
[1064]827    \code
828    class = 'mBeta';
[1068]829    k = [...];          % vector of multiplicative constants k
830    --- optional fields ---
831    beta  = [...];      % initial values of beta
832    betac = [...];      % initial values of beta stabilizing constants
833    --- inherited fields ---
834    bdm::pdf::from_setting
[1064]835    \endcode
[1068]836    fulfilling form \f[ f(rv|rvc) = \prod Beta(rvc,k) \f]
837
838    If the optional fields are not given, they will be filled as follows:
839    \code
840    beta  = [1,1,1,...];
841    betac = 0.1 * [1,1,1,...];
842    \endcode
843   
[1064]844    */
845    void from_setting ( const Setting &set );
[1063]846
[1064]847    void to_setting  (Setting  &set) const;
848
849    void validate() {
850        pdf_internal<eBeta>::validate();
851        bdm_assert(betac.length()==dimension(),"Incomaptible betac");
852        bdm_assert(k.length()==dimension(),"Incomaptible k");
853        dimc = iepdf.dimension();
854    }
855    //!
[1033]856};
857UIREGISTER(mBeta);
858
[181]859//! \brief Estimator for Multinomial density
[737]860class multiBM : public BMEF {
861protected:
[1064]862    //! Conjugate prior and posterior
863    eDirich est;
864    //! Pointer inside est to sufficient statistics
865    vec &beta;
[737]866public:
[1064]867    //!Default constructor
868    multiBM () : BMEF (), est (), beta ( est._beta() ) {
869        if ( beta.length() > 0 ) {
870            last_lognc = est.lognc();
871        } else {
872            last_lognc = 0.0;
873        }
874    }
875    //!Copy constructor
876    multiBM ( const multiBM &B ) : BMEF ( B ), est ( B.est ), beta ( est._beta() ) {}
877    //! Sets sufficient statistics to match that of givefrom mB0
878    void set_statistics ( const BM* mB0 ) {
879        const multiBM* mB = dynamic_cast<const multiBM*> ( mB0 );
880        beta = mB->beta;
881    }
882    void bayes ( const vec &yt, const vec &cond = empty_vec );
[176]883
[1064]884    double logpred ( const vec &yt ) const;
[170]885
[1064]886    void flatten ( const BMEF* B , double weight);
[739]887
[1064]888    //! return correctly typed posterior (covariant return)
889    const eDirich& posterior() const {
890        return est;
891    };
892    //! constructor function
893    void set_parameters ( const vec &beta0 ) {
894        est.set_parameters ( beta0 );
895        est.validate();
896        if ( evalll ) {
897            last_lognc = est.lognc();
898        }
899    }
[746]900
[1064]901    void to_setting ( Setting &set ) const {
902        BMEF::to_setting ( set );
903        UI::save( &est, set, "prior" );
904    }
[1077]905
906    /*! Create object from the following structure
907
908    \code
909    class = 'MultiBM';
910    prior = configuration of bdm::eDirich;       % any offspring of eDirich, bdm::eDirich::from_setting
911    --- inherited fields ---
912    bdm::BMEF::from_setting
913    \endcode
914    */
[1064]915    void from_setting (const Setting &set )  {
916        BMEF::from_setting ( set );
917        UI::get( est, set, "prior" );
918    }
[488]919};
[746]920UIREGISTER( multiBM );
[170]921
[488]922/*!
923 \brief Gamma posterior density
[32]924
[488]925 Multivariate Gamma density as product of independent univariate densities.
926 \f[
927 f(x|\alpha,\beta) = \prod f(x_i|\alpha_i,\beta_i)
928 \f]
929*/
[32]930
[737]931class egamma : public eEF {
932protected:
[1064]933    //! Vector \f$\alpha\f$
934    vec alpha;
935    //! Vector \f$\beta\f$
936    vec beta;
[737]937public :
[1064]938    //! \name Constructors
939    //!@{
940    egamma () : eEF (), alpha ( 0 ), beta ( 0 ) {};
941    egamma ( const vec &a, const vec &b ) {
942        set_parameters ( a, b );
943        validate();
944    };
945    void set_parameters ( const vec &a, const vec &b ) {
946        alpha = a, beta = b;
947    };
948    //!@}
[270]949
[1064]950    vec sample() const;
[1083]951        double evallog_nn ( const vec &val ) const;
952        double lognc () const;
[1064]953    //! Returns pointer to internal alpha. Potentially dengerous: use with care!
954    vec& _alpha() {
955        return alpha;
956    }
957    //! Returns pointer to internal beta. Potentially dengerous: use with care!
958    vec& _beta() {
959        return beta;
960    }
961    vec mean() const {
962        return elem_div ( alpha, beta );
963    }
964    vec variance() const {
965        return elem_div ( alpha, elem_mult ( beta, beta ) );
966    }
[225]967
[1064]968    /*! Create object from the following structure
[1063]969
[1064]970    \code
971    class = 'egamma';
[1066]972    alpha = [...];         % vector alpha
973    beta = [...];          % vector beta
[1064]974    --- inherited fields ---
975    bdm::eEF::from_setting
976    \endcode
977     fulfilling formula \f[ f(rv|rvc) = \Gamma(\alpha, \beta) \f]
978    */
979    void from_setting ( const Setting &set );
[1063]980
[1064]981    void to_setting ( Setting &set ) const;
982    void validate();
[488]983};
[737]984UIREGISTER ( egamma );
[529]985SHAREDPTR ( egamma );
986
[488]987/*!
988 \brief Inverse-Gamma posterior density
[225]989
[488]990 Multivariate inverse-Gamma density as product of independent univariate densities.
991 \f[
992 f(x|\alpha,\beta) = \prod f(x_i|\alpha_i,\beta_i)
993 \f]
[283]994
[488]995Vector \f$\beta\f$ has different meaning (in fact it is 1/beta as used in definition of iG)
[225]996
[488]997 Inverse Gamma can be converted to Gamma using \f[
998 x\sim iG(a,b) => 1/x\sim G(a,1/b)
999\f]
1000This relation is used in sampling.
1001 */
[270]1002
[737]1003class eigamma : public egamma {
1004protected:
1005public :
[1064]1006    //! \name Constructors
1007    //! All constructors are inherited
1008    //!@{
1009    //!@}
[32]1010
[1064]1011    vec sample() const {
1012        return 1.0 / egamma::sample();
1013    };
1014    //! Returns poiter to alpha and beta. Potentially dangerous: use with care!
1015    vec mean() const {
1016        return elem_div ( beta, alpha - 1 );
1017    }
1018    vec variance() const {
1019        vec mea = mean();
1020        return elem_div ( elem_mult ( mea, mea ), alpha - 2 );
1021    }
[488]1022};
1023/*
1024//! Weighted mixture of epdfs with external owned components.
1025class emix : public epdf {
1026protected:
[1066]1027    int n;
1028    vec &w;
1029    Array<epdf*> Coms;
[488]1030public:
1031//! Default constructor
[1066]1032    emix ( const RV &rv, vec &w0): epdf(rv), n(w0.length()), w(w0), Coms(n) {};
1033    void set_parameters( int &i, double wi, epdf* ep){w(i)=wi;Coms(i)=ep;}
1034    vec mean(){vec pom; for(int i=0;i<n;i++){pom+=Coms(i)->mean()*w(i);} return pom;};
[488]1035};
1036*/
1037
[1068]1038//! \brief Uniform distributed density on a rectangular support
[737]1039class euni: public epdf {
1040protected:
[32]1041//! lower bound on support
[1064]1042    vec low;
[32]1043//! upper bound on support
[1064]1044    vec high;
[32]1045//! internal
[1064]1046    vec distance;
[32]1047//! normalizing coefficients
[1064]1048    double nk;
[33]1049//! cache of log( \c nk )
[1064]1050    double lnk;
[737]1051public:
[1064]1052    //! \name Constructors
1053    //!@{
1054    euni () : epdf () {}
1055    euni ( const vec &low0, const vec &high0 ) {
1056        set_parameters ( low0, high0 );
1057    }
1058    void set_parameters ( const vec &low0, const vec &high0 ) {
1059        distance = high0 - low0;
1060        low = low0;
1061        high = high0;
1062        nk = prod ( 1.0 / distance );
1063        lnk = log ( nk );
1064    }
1065    //!@}
[270]1066
[1064]1067    double evallog ( const vec &val ) const  {
1068        if ( any ( val < low ) && any ( val > high ) ) {
1069            return -inf;
1070        } else return lnk;
1071    }
1072    vec sample() const {
1073        vec smp ( dim );
[270]1074#pragma omp critical
[1064]1075        UniRNG.sample_vector ( dim , smp );
1076        return low + elem_mult ( distance, smp );
1077    }
1078    //! set values of \c low and \c high
1079    vec mean() const {
1080        return ( high - low ) / 2.0;
1081    }
1082    vec variance() const {
1083        return ( pow ( high, 2 ) + pow ( low, 2 ) + elem_mult ( high, low ) ) / 3.0;
1084    }
[1068]1085
1086
1087     /*! Create object from the following structure
[1064]1088     \code
[1068]1089   
[1064]1090     class = 'euni'
[1068]1091     high = [...];          % vector of upper bounds
1092     low = [...];           % vector of lower bounds     
1093      rv = RV({'names',...},[sizes,...],[times,...]);   % description of RV
1094     --- inherited fields ---
1095     bdm::epdf::from_setting
[1064]1096     \endcode
[1068]1097
1098     fulfilling form \f[ f(rv) = U(low,high) \f]
[1064]1099     */
1100    void from_setting ( const Setting &set );
[1066]1101    void     to_setting  (Setting  &set) const;
[1064]1102    void validate();
[488]1103};
[737]1104UIREGISTER ( euni );
[32]1105
[665]1106//! Uniform density with conditional mean value
[737]1107class mguni : public pdf_internal<euni> {
[1064]1108    //! function of the mean value
1109    shared_ptr<fnc> mean;
1110    //! distance from mean to both sides
1111    vec delta;
[737]1112public:
[1064]1113    void condition ( const vec &cond ) {
1114        vec mea = mean->eval ( cond );
1115        iepdf.set_parameters ( mea - delta, mea + delta );
1116    }
[1068]1117
1118    /*! Create object from the following structure
1119    \code
1120    class = 'mguni';
1121    mean = function bdm::fnc;       % any offspring of fnc, bdm::fnc::from_setting
1122    delta = [...];                  % distance from mean to both sides
1123    --- inherited fields ---
1124    bdm::pdf::from_setting
1125    \endcode
1126    */
[1064]1127    void from_setting ( const Setting &set ) {
1128        pdf::from_setting ( set ); //reads rv and rvc
1129        UI::get ( delta, set, "delta", UI::compulsory );
1130        mean = UI::build<fnc> ( set, "mean", UI::compulsory );
1131        iepdf.set_parameters ( -delta, delta );
1132    }
[1066]1133    void     to_setting  (Setting  &set) const {
[1064]1134        pdf::to_setting ( set );
1135        UI::save( iepdf.mean(), set, "delta");
1136        UI::save(mean, set, "mean");
1137    }
1138    void validate() {
1139        pdf_internal<euni>::validate();
1140        dimc = mean->dimensionc();
[878]1141
[1064]1142    }
1143
[665]1144};
[737]1145UIREGISTER ( mguni );
[488]1146/*!
1147 \brief Normal distributed linear function with linear function of mean value;
[32]1148
[536]1149 Mean value \f$ \mu=A*\mbox{rvc}+\mu_0 \f$.
[488]1150*/
1151template < class sq_T, template <typename> class TEpdf = enorm >
[737]1152class mlnorm : public pdf_internal< TEpdf<sq_T> > {
1153protected:
[1196]1154        //! Internal epdf that arise by conditioning on \c rvc
1155        mat A;
1156        //! Constant additive term
1157        vec mu_const;
1158        //            vec& _mu; //cached epdf.mu; !!!!!! WHY NOT?
[737]1159public:
[1064]1160    //! \name Constructors
1161    //!@{
1162    mlnorm() : pdf_internal< TEpdf<sq_T> >() {};
1163    mlnorm ( const mat &A, const vec &mu0, const sq_T &R ) : pdf_internal< TEpdf<sq_T> >() {
1164        set_parameters ( A, mu0, R );
1165        validate();
1166    }
[461]1167
[1064]1168    //! Set \c A and \c R
1169    void set_parameters ( const  mat &A0, const vec &mu0, const sq_T &R0 ) {
1170        this->iepdf.set_parameters ( zeros ( A0.rows() ), R0 );
1171        A = A0;
1172        mu_const = mu0;
1173    }
[878]1174
[1064]1175    //!@}
1176    //! Set value of \c rvc . Result of this operation is stored in \c epdf use function \c _ep to access it.
1177    void condition ( const vec &cond ) {
1178        this->iepdf._mu() = A * cond + mu_const;
[487]1179//R is already assigned;
[1064]1180    }
[198]1181
[1064]1182    //!access function
1183    const vec& _mu_const() const {
1184        return mu_const;
1185    }
1186    //!access function
1187    const mat& _A() const {
1188        return A;
1189    }
1190    //!access function
1191    mat _R() const {
1192        return this->iepdf._R().to_mat();
1193    }
1194    //!access function
1195    sq_T __R() const {
1196        return this->iepdf._R();
1197    }
[8]1198
[1064]1199    //! Debug stream
1200    template<typename sq_M>
1201    friend std::ostream &operator<< ( std::ostream &os,  mlnorm<sq_M, enorm> &ml );
[488]1202
[1064]1203    /*! Create Normal density with linear function of mean value
1204     \f[ f(rv|rvc) = N(A*rvc+const, R) \f]
1205    from structure
1206    \code
1207    class = 'mlnorm<ldmat>', (OR) 'mlnorm<chmat>', (OR) 'mlnorm<fsqmat>';
1208    A     = [];                  // matrix or vector of appropriate dimension
1209    R     = [];                  // square matrix of appropriate dimension
1210    --- optional ---
1211    const = zeros(A.rows);       // vector of constant term
1212    \endcode
1213    */
1214    void from_setting ( const Setting &set ) {
1215        pdf::from_setting ( set );
[737]1216
[1064]1217        UI::get ( A, set, "A", UI::compulsory );
1218        UI::get ( mu_const, set, "const", UI::optional);
1219        mat R0;
1220        UI::get ( R0, set, "R", UI::compulsory );
1221        set_parameters ( A, mu_const, R0 );
1222    }
[956]1223
[1064]1224    void to_setting (Setting &set) const {
1225        pdf::to_setting(set);
1226        UI::save ( A, set, "A");
1227        UI::save ( mu_const, set, "const");
1228        UI::save ( _R(), set, "R");
1229    }
[956]1230
[1064]1231    void validate() {
1232        pdf_internal<TEpdf<sq_T> >::validate();
1233        if (mu_const.length()==0) { // default in from_setting
1234            mu_const=zeros(A.rows());
1235        }
1236        bdm_assert ( A.rows() == mu_const.length(), "mlnorm: A vs. mu mismatch" );
1237        bdm_assert ( A.rows() == _R().rows(), "mlnorm: A vs. R mismatch" );
1238        this->dimc = A.cols();
[737]1239
[1064]1240    }
[488]1241};
[737]1242UIREGISTER2 ( mlnorm, ldmat );
[529]1243SHAREDPTR2 ( mlnorm, ldmat );
[737]1244UIREGISTER2 ( mlnorm, fsqmat );
[529]1245SHAREDPTR2 ( mlnorm, fsqmat );
[737]1246UIREGISTER2 ( mlnorm, chmat );
[529]1247SHAREDPTR2 ( mlnorm, chmat );
[488]1248
[1064]1249//! \class mlgauss
[948]1250//!\brief Normal distribution with linear function of mean value. Same as mlnorm<fsqmat>.
1251typedef mlnorm<fsqmat> mlgauss;
1252UIREGISTER(mlgauss);
1253
[693]1254//! pdf with general function for mean value
[488]1255template<class sq_T>
[737]1256class mgnorm : public pdf_internal< enorm< sq_T > > {
1257private:
[1066]1258//            vec &mu; WHY NOT?
[1064]1259    shared_ptr<fnc> g;
[527]1260
[737]1261public:
[1064]1262    //!default constructor
1263    mgnorm() : pdf_internal<enorm<sq_T> >() { }
1264    //!set mean function
1265    inline void set_parameters ( const shared_ptr<fnc> &g0, const sq_T &R0 );
1266    inline void condition ( const vec &cond );
[357]1267
1268
[1064]1269    /*! Create Normal density with given function of mean value
1270    \f[ f(rv|rvc) = N( g(rvc), R) \f]
1271    from structure
1272    \code
1273    class = 'mgnorm';
1274    g.class =  'fnc';      // function for mean value evolution
1275    g._fields_of_fnc = ...;
[357]1276
[1064]1277    R = [1, 0;             // covariance matrix
[1066]1278        0, 1];
1279        --OR --
[1064]1280    dR = [1, 1];           // diagonal of cavariance matrix
[357]1281
[1064]1282    rv = RV({'name'})      // description of RV
1283    rvc = RV({'name'})     // description of RV in condition
1284    \endcode
1285    */
[357]1286
[956]1287
[1064]1288    void from_setting ( const Setting &set ) {
1289        pdf::from_setting ( set );
1290        shared_ptr<fnc> g = UI::build<fnc> ( set, "g", UI::compulsory );
[357]1291
[1064]1292        mat R;
1293        vec dR;
1294        if ( UI::get ( dR, set, "dR" ) )
1295            R = diag ( dR );
1296        else
1297            UI::get ( R, set, "R", UI::compulsory );
[280]1298
[1064]1299        set_parameters ( g, R );
1300        //validate();
1301    }
[956]1302
1303
[1064]1304    void to_setting  (Setting  &set) const {
1305        UI::save( g,set, "g");
1306        UI::save(this->iepdf._R().to_mat(),set, "R");
[956]1307
[1064]1308    }
[956]1309
1310
[1064]1311
1312    void validate() {
1313        this->iepdf.validate();
1314        bdm_assert ( g->dimension() == this->iepdf.dimension(), "incompatible function" );
1315        this->dim = g->dimension();
1316        this->dimc = g->dimensionc();
1317        this->iepdf.validate();
1318    }
1319
[488]1320};
[357]1321
[737]1322UIREGISTER2 ( mgnorm, chmat );
[944]1323UIREGISTER2 ( mgnorm, ldmat );
[529]1324SHAREDPTR2 ( mgnorm, chmat );
[357]1325
[262]1326
[1068]1327/*! \brief (Approximate) Student t density with linear function of mean value
[262]1328
[488]1329The internal epdf of this class is of the type of a Gaussian (enorm).
1330However, each conditioning is trying to assure the best possible approximation by taking into account the zeta function. See [] for reference.
[270]1331
[488]1332Perhaps a moment-matching technique?
1333*/
[737]1334class mlstudent : public mlnorm<ldmat, enorm> {
1335protected:
[1064]1336    //! Variable \f$ \Lambda \f$ from theory
1337    ldmat Lambda;
1338    //! Reference to variable \f$ R \f$
1339    ldmat &_R;
1340    //! Variable \f$ R_e \f$
1341    ldmat Re;
[737]1342public:
[1064]1343    mlstudent () : mlnorm<ldmat, enorm> (),
[1066]1344        Lambda (),    _R ( iepdf._R() ) {}
[1064]1345    //! constructor function
1346    void set_parameters ( const mat &A0, const vec &mu0, const ldmat &R0, const ldmat& Lambda0 ) {
1347        iepdf.set_parameters ( mu0, R0 );// was Lambda, why?
1348        A = A0;
1349        mu_const = mu0;
1350        Re = R0;
1351        Lambda = Lambda0;
1352    }
[294]1353
[1064]1354    void condition ( const vec &cond );
[739]1355
[1064]1356    void validate() {
1357        mlnorm<ldmat, enorm>::validate();
1358        bdm_assert ( A.rows() == mu_const.length(), "mlstudent: A vs. mu mismatch" );
1359        bdm_assert ( _R.rows() == A.rows(), "mlstudent: A vs. R mismatch" );
[737]1360
[1064]1361    }
[488]1362};
[811]1363
[488]1364/*!
1365\brief  Gamma random walk
[198]1366
[488]1367Mean value, \f$\mu\f$, of this density is given by \c rvc .
1368Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
1369This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
[32]1370
[488]1371The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
1372*/
[737]1373class mgamma : public pdf_internal<egamma> {
1374protected:
[461]1375
[1064]1376    //! Constant \f$k\f$
1377    double k;
[461]1378
[1064]1379    //! cache of iepdf.beta
1380    vec &_beta;
[32]1381
[737]1382public:
[1064]1383    //! Constructor
1384    mgamma() : pdf_internal<egamma>(), k ( 0 ),
1385        _beta ( iepdf._beta() ) {
1386    }
[461]1387
[1064]1388    //! Set value of \c k
1389    void set_parameters ( double k, const vec &beta0 );
[461]1390
[1064]1391    void condition ( const vec &val ) {
1392        _beta = k / val;
1393    };
[1068]1394
1395    /*! Create object from the following structure
[1064]1396    \code
[1068]1397    class = 'mgamma';   
1398    beta = [...];      % vector of initial beta
1399    k = x;             %  multiplicative scalar constant k
1400    --- inherited fields ---
1401    bdm::pdf::from_setting
1402    \endcode
1403    fulfilling form \f[ f(rv|rvc) = \Gamma(k, k/rvc) \f]
[1064]1404    */
1405    void from_setting ( const Setting &set );
[1066]1406    void     to_setting  (Setting  &set) const;
[1064]1407    void validate();
[488]1408};
[737]1409UIREGISTER ( mgamma );
1410SHAREDPTR ( mgamma );
[32]1411
[488]1412/*!
1413\brief  Inverse-Gamma random walk
[225]1414
[488]1415Mean value, \f$ \mu \f$, of this density is given by \c rvc .
1416Standard deviation of the random walk is proportional to one \f$ k \f$-th the mean.
1417This is achieved by setting \f$ \alpha=\mu/k^2+2 \f$ and \f$ \beta=\mu(\alpha-1)\f$.
[461]1418
[488]1419The standard deviation of the walk is then: \f$ \mu/\sqrt(k)\f$.
1420 */
[737]1421class migamma : public pdf_internal<eigamma> {
1422protected:
[1064]1423    //! Constant \f$k\f$
1424    double k;
[461]1425
[1064]1426    //! cache of iepdf.alpha
1427    vec &_alpha;
[225]1428
[1064]1429    //! cache of iepdf.beta
1430    vec &_beta;
[461]1431
[737]1432public:
[1064]1433    //! \name Constructors
1434    //!@{
1435    migamma() : pdf_internal<eigamma>(),
1436        k ( 0 ),
1437        _alpha ( iepdf._alpha() ),
1438        _beta ( iepdf._beta() ) {
1439    }
[225]1440
[1064]1441    migamma ( const migamma &m ) : pdf_internal<eigamma>(),
1442        k ( 0 ),
1443        _alpha ( iepdf._alpha() ),
1444        _beta ( iepdf._beta() ) {
1445    }
1446    //!@}
[225]1447
[1064]1448    //! Set value of \c k
1449    void set_parameters ( int len, double k0 ) {
1450        k = k0;
1451        iepdf.set_parameters ( ( 1.0 / ( k*k ) + 2.0 ) *ones ( len ) /*alpha*/, ones ( len ) /*beta*/ );
1452    };
[878]1453
[1066]1454    void     validate () {
[1064]1455        pdf_internal<eigamma>::validate();
1456        dimc = dimension();
1457    };
[878]1458
[1064]1459    void condition ( const vec &val ) {
1460        _beta = elem_mult ( val, ( _alpha - 1.0 ) );
1461    };
[488]1462};
[357]1463
[488]1464/*!
1465\brief  Gamma random walk around a fixed point
[60]1466
[488]1467Mean 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
1468\f[ \mu = \mu_{t-1} ^{l} p^{1-l}\f]
[60]1469
[488]1470Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
1471This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
[294]1472
[488]1473The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
1474*/
[737]1475class mgamma_fix : public mgamma {
1476protected:
[1064]1477    //! parameter l
1478    double l;
1479    //! reference vector
1480    vec refl;
[737]1481public:
[1064]1482    //! Constructor
1483    mgamma_fix () : mgamma (), refl () {};
1484    //! Set value of \c k
1485    void set_parameters ( double k0 , vec ref0, double l0 ) {
1486        mgamma::set_parameters ( k0, ref0 );
1487        refl = pow ( ref0, 1.0 - l0 );
1488        l = l0;
1489    };
[878]1490
[1068]1491    void validate () {
[1064]1492        mgamma::validate();
1493        dimc = dimension();
1494    };
[60]1495
[1064]1496    void condition ( const vec &val ) {
1497        vec mean = elem_mult ( refl, pow ( val, l ) );
1498        _beta = k / mean;
1499    };
[488]1500};
[60]1501
[225]1502
[488]1503/*!
1504\brief  Inverse-Gamma random walk around a fixed point
[225]1505
[488]1506Mean 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
1507\f[ \mu = \mu_{t-1} ^{l} p^{1-l}\f]
[225]1508
[488]1509==== Check == vv =
1510Standard deviation of the random walk is proportional to one \f$k\f$-th the mean.
1511This is achieved by setting \f$\alpha=k\f$ and \f$\beta=k/\mu\f$.
[225]1512
[488]1513The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
1514 */
[737]1515class migamma_ref : public migamma {
1516protected:
[1064]1517    //! parameter l
1518    double l;
1519    //! reference vector
1520    vec refl;
[737]1521public:
[1064]1522    //! Constructor
1523    migamma_ref () : migamma (), refl () {};
[878]1524
[1064]1525    //! Set value of \c k
1526    void set_parameters ( double k0 , vec ref0, double l0 ) {
1527        migamma::set_parameters ( ref0.length(), k0 );
1528        refl = pow ( ref0, 1.0 - l0 );
1529        l = l0;
1530    };
[357]1531
[1064]1532    void validate() {
1533        migamma::validate();
1534        dimc = dimension();
1535    };
[357]1536
[1064]1537    void condition ( const vec &val ) {
1538        vec mean = elem_mult ( refl, pow ( val, l ) );
1539        migamma::condition ( mean );
1540    };
[957]1541
[1068]1542    /*! Create object from the following structure
[1064]1543    \code
1544    class = 'migamma_ref';
[1068]1545    ref = [...];           % reference vector
1546    l = [];                % constant scalar l
1547    k = [];                % constant scalar k   
1548    --- inherited fields ---
1549    bdm::migamma::from_setting
[1064]1550    \endcode
[1068]1551    fulfilling form \f[ f(rv|rvc) = i\Gamma(k, k/(rvc^l \circ ref^{(1-l)}) \f]
[1064]1552     */
1553    void from_setting ( const Setting &set );
1554
1555    void to_setting  (Setting  &set) const;
[488]1556};
[357]1557
1558
[737]1559UIREGISTER ( migamma_ref );
1560SHAREDPTR ( migamma_ref );
[294]1561
[1068]1562/*! \brief Log-Normal probability density - it allows only diagonal covariances!
[294]1563
[488]1564Density of the form \f$ \log(x)\sim \mathcal{N}(\mu,\sigma^2) \f$ , i.e.
1565\f[
1566x \sim \frac{1}{x\sigma\sqrt{2\pi}}\exp{-\frac{1}{2\sigma^2}(\log(x)-\mu)}
1567\f]
[294]1568
[621]1569Function from_setting loads mu and R in the same way as it does for enorm<>!
[488]1570*/
[737]1571class elognorm: public enorm<ldmat> {
1572public:
[1064]1573    vec sample() const {
1574        return exp ( enorm<ldmat>::sample() );
1575    };
1576    vec mean() const {
1577        vec var = enorm<ldmat>::variance();
1578        return exp ( mu - 0.5*var );
1579    };
[285]1580
[488]1581};
[285]1582
[488]1583/*!
1584\brief  Log-Normal random walk
[285]1585
[488]1586Mean value, \f$\mu\f$, is...
[285]1587
[488]1588 */
[737]1589class mlognorm : public pdf_internal<elognorm> {
1590protected:
[1064]1591    //! parameter 1/2*sigma^2
1592    double sig2;
[461]1593
[1064]1594    //! access
1595    vec &mu;
[737]1596public:
[1064]1597    //! Constructor
1598    mlognorm() : pdf_internal<elognorm>(),
1599        sig2 ( 0 ),
1600        mu ( iepdf._mu() ) {
1601    }
[285]1602
[1064]1603    //! Set value of \c k
1604    void set_parameters ( int size, double k ) {
1605        sig2 = 0.5 * log ( k * k + 1 );
1606        iepdf.set_parameters ( zeros ( size ), 2*sig2*eye ( size ) );
1607    };
[357]1608
[1064]1609    void validate() {
1610        pdf_internal<elognorm>::validate();
1611        dimc = iepdf.dimension();
1612    }
[357]1613
[1064]1614    void condition ( const vec &val ) {
1615        mu = log ( val ) - sig2;//elem_mult ( refl,pow ( val,l ) );
1616    };
1617
[1068]1618    /*! Create object from the following structure
[1064]1619    \code
1620    class = 'mlognorm';
[1068]1621    k   = [];               % "variance" k
1622    mu0 = [];               % initial value of mean
1623    --- inherited fields ---
1624    bdm::pdf_internal<elognorm>::from_setting
[1064]1625    \endcode
[1068]1626    fulfilling form \f[ f(rv|rvc) = log\mathcal{N}( \log(rvc)-0.5\log(k^2+1), k I) \f]
[1064]1627    */
1628    void from_setting ( const Setting &set );
1629
1630    void to_setting  (Setting  &set) const;
[488]1631};
[294]1632
[737]1633UIREGISTER ( mlognorm );
1634SHAREDPTR ( mlognorm );
[294]1635
[1068]1636/*! \brief Inverse Wishart density defined on Choleski decomposition
[1189]1637 *
1638 * here \f$\Omega \sim |\Sigma|^{-0.5(\delta}|\Omega|^{0.5(\delta -p -1)} \exp(-1/2 tr(\Omega\Sigma^{-1}))\$f
[488]1639*/
[737]1640class eWishartCh : public epdf {
1641protected:
[1064]1642    //! Upper-Triagle of Choleski decomposition of \f$ \Psi \f$
[1189]1643    chmat Sigma;
[1064]1644    //! dimension of matrix  \f$ \Psi \f$
1645    int p;
1646    //! degrees of freedom  \f$ \nu \f$
1647    double delta;
[737]1648public:
[1064]1649    //! Set internal structures
1650    void set_parameters ( const mat &Y0, const double delta0 ) {
[1189]1651        Sigma = chmat ( Y0 );
[1064]1652        delta = delta0;
[1189]1653        p = Sigma.rows();
[1064]1654    }
1655    //! Set internal structures
1656    void set_parameters ( const chmat &Y0, const double delta0 ) {
[1189]1657        Sigma = Y0;
[1064]1658        delta = delta0;
[1189]1659        p = Sigma.rows();
[1064]1660    }
[878]1661
[1064]1662    virtual void validate () {
1663        epdf::validate();
1664        dim = p * p;
1665    }
[488]1666
[1189]1667    //! Sample matrix argument - lower
1668    //! Using Bartlet decomposition: W=L A A^T L^T where A is lower triag and L is choleski factor of Sigma.
1669    chmat sample_mat() const {
1670        mat A_T = zeros ( p, p ); // A transpose
[1064]1671
1672        //sample diagonal
1673        for ( int i = 0; i < p; i++ ) {
1674            GamRNG.setup ( 0.5* ( delta - i ) , 0.5 );   // no +1 !! index if from 0
[294]1675#pragma omp critical
[1189]1676            A_T ( i, i ) = sqrt ( GamRNG() );
[1064]1677        }
1678        //do the rest
1679        for ( int i = 0; i < p; i++ ) {
1680            for ( int j = i + 1; j < p; j++ ) {
[294]1681#pragma omp critical
[1189]1682                A_T ( i, j ) = NorRNG.sample();
[1064]1683            }
1684        }
[1189]1685        chmat tmp;
1686                tmp._Ch()=A_T*Sigma._Ch();
1687        return tmp;// return upper triangular part of the decomposition
[1064]1688    }
[766]1689
[1064]1690    vec sample () const {
[1189]1691        return vec ( sample_mat().to_mat()._data(), p*p );
[1064]1692    }
[766]1693
[1064]1694    virtual vec mean() const NOT_IMPLEMENTED(0);
[766]1695
[1064]1696    //! return expected variance (not covariance!)
1697    virtual vec variance() const NOT_IMPLEMENTED(0);
[766]1698
[1064]1699    virtual double evallog ( const vec &val ) const NOT_IMPLEMENTED(0);
[766]1700
[1064]1701    //! fast access function y0 will be copied into Y.Ch.
1702    void setY ( const mat &Ch0 ) {
[1189]1703        copy_vector ( dim, Ch0._data(), Sigma._Ch()._data() );
[1064]1704    }
[766]1705
[1064]1706    //! fast access function y0 will be copied into Y.Ch.
1707    void _setY ( const vec &ch0 ) {
[1189]1708        copy_vector ( dim, ch0._data(), Sigma._Ch()._data() );
[1064]1709    }
[766]1710
[1064]1711    //! access function
1712    const chmat& getY() const {
[1189]1713        return Sigma;
[1064]1714    }
[488]1715};
[294]1716
[536]1717//! Inverse Wishart on Choleski decomposition
1718/*! Being computed by conversion from `standard' Wishart
1719*/
[737]1720class eiWishartCh: public epdf {
1721protected:
[1064]1722    //! Internal instance of Wishart density
1723    eWishartCh W;
1724    //! size of Ch
1725    int p;
1726    //! parameter delta
1727    double delta;
[737]1728public:
[1064]1729    //! constructor function
1730    void set_parameters ( const mat &Y0, const double delta0 ) {
1731        delta = delta0;
1732        W.set_parameters ( inv ( Y0 ), delta0 );
1733        p = Y0.rows();
1734    }
[488]1735
[1066]1736    virtual void     validate () {
[1064]1737        epdf::validate();
1738        W.validate();
1739        dim = W.dimension();
1740    }
[766]1741
[488]1742
[1064]1743    vec sample() const {
1744        mat iCh;
[1189]1745        iCh = inv ( W.sample_mat()._Ch() );
[1064]1746        return vec ( iCh._data(), dim );
1747    }
1748    //! access function
1749    void _setY ( const vec &y0 ) {
1750        mat Ch ( p, p );
1751        mat iCh ( p, p );
1752        copy_vector ( dim, y0._data(), Ch._data() );
1753
1754        iCh = inv ( Ch );
1755        W.setY ( iCh );
1756    }
1757
1758    virtual double evallog ( const vec &val ) const {
1759        chmat X ( p );
1760        const chmat& Y = W.getY();
1761
1762        copy_vector ( p*p, val._data(), X._Ch()._data() );
1763        chmat iX ( p );
1764        X.inv ( iX );
1765        // compute
[1066]1766//                 \frac{ |\Psi|^{m/2}|X|^{-(m+p+1)/2}e^{-tr(\Psi X^{-1})/2} }{ 2^{mp/2}\Gamma_p(m/2)},
[1064]1767        mat M = Y.to_mat() * iX.to_mat();
[285]1768
[1064]1769        double log1 = 0.5 * p * ( 2 * Y.logdet() ) - 0.5 * ( delta + p + 1 ) * ( 2 * X.logdet() ) - 0.5 * trace ( M );
1770        //Fixme! Multivariate gamma omitted!! it is ok for sampling, but not otherwise!!
[461]1771
[1066]1772        /*                if (0) {
1773                            mat XX=X.to_mat();
1774                            mat YY=Y.to_mat();
[461]1775
[1066]1776                            double log2 = 0.5*p*log(det(YY))-0.5*(delta+p+1)*log(det(XX))-0.5*trace(YY*inv(XX));
1777                            cout << log1 << "," << log2 << endl;
1778                        }*/
[1064]1779        return log1;
1780    };
[285]1781
[1064]1782    virtual vec mean() const NOT_IMPLEMENTED(0);
[766]1783
[1064]1784    //! return expected variance (not covariance!)
1785    virtual vec variance() const NOT_IMPLEMENTED(0);
[488]1786};
1787
[536]1788//! Random Walk on inverse Wishart
[737]1789class rwiWishartCh : public pdf_internal<eiWishartCh> {
1790protected:
[1064]1791    //!square root of \f$ \nu-p-1 \f$ - needed for computation of \f$ \Psi \f$ from conditions
1792    double sqd;
1793    //!reference point for diagonal
1794    vec refl;
1795    //! power of the reference
1796    double l;
1797    //! dimension
1798    int p;
[488]1799
[737]1800public:
[1064]1801    rwiWishartCh() : sqd ( 0 ), l ( 0 ), p ( 0 ) {}
1802    //! constructor function
1803    void set_parameters ( int p0, double k, vec ref0, double l0 ) {
1804        p = p0;
1805        double delta = 2 / ( k * k ) + p + 3;
1806        sqd = sqrt ( delta - p - 1 );
1807        l = l0;
1808        refl = pow ( ref0, 1 - l );
1809        iepdf.set_parameters ( eye ( p ), delta );
1810    };
[285]1811
[1064]1812    void validate() {
1813        pdf_internal<eiWishartCh>::validate();
1814        dimc = iepdf.dimension();
1815    }
1816
1817    void condition ( const vec &c ) {
1818        vec z = c;
1819        int ri = 0;
1820        for ( int i = 0; i < p*p; i += ( p + 1 ) ) {//trace diagonal element
1821            z ( i ) = pow ( z ( i ), l ) * refl ( ri );
1822            ri++;
1823        }
1824
1825        iepdf._setY ( sqd*z );
1826    }
[488]1827};
1828
[32]1829//! Switch between various resampling methods.
[488]1830enum RESAMPLING_METHOD { MULTINOMIAL = 0, STRATIFIED = 1, SYSTEMATIC = 3 };
[887]1831
[1064]1832//! Shortcut for multinomial.sample(int n). Various simplifications are allowed see RESAMPLING_METHOD
[887]1833void resample(const vec &w, ivec &ind, RESAMPLING_METHOD=SYSTEMATIC);
1834
[1063]1835/*! \brief Weighted empirical density
[32]1836
[488]1837Used e.g. in particle filters.
1838*/
[737]1839class eEmp: public epdf {
1840protected :
[1064]1841    //! Number of particles
1842    int n;
1843    //! Sample weights \f$w\f$
1844    vec w;
1845    //! Samples \f$x^{(i)}, i=1..n\f$
1846    Array<vec> samples;
[737]1847public:
[1064]1848    //! \name Constructors
1849    //!@{
1850    eEmp () : epdf (), w (), samples () {};
1851    //! copy constructor
1852    eEmp ( const eEmp &e ) : epdf ( e ), w ( e.w ), samples ( e.samples ) {};
1853    //!@}
[280]1854
[1064]1855    //! Set samples and weights
1856    void set_statistics ( const vec &w0, const epdf &pdf0 );
1857    //! Set samples and weights
1858    void set_statistics ( const epdf &pdf0 , int n ) {
1859        set_statistics ( ones ( n ) / n, pdf0 );
1860    };
1861    //! Set sample
1862    void set_samples ( const epdf* pdf0 );
1863    //! Set sample
1864    void set_parameters ( int n0, bool copy = true ) {
1865        n = n0;
1866        w.set_size ( n0, copy );
1867        samples.set_size ( n0, copy );
1868    };
1869    //! Set samples
1870    void set_parameters ( const Array<vec> &Av ) {
1871        n = Av.size();
1872        w = 1 / n * ones ( n );
1873        samples = Av;
1874    };
[1066]1875    virtual void     validate ();
[1064]1876    //! Potentially dangerous, use with care.
1877    vec& _w()  {
1878        return w;
1879    };
1880    //! Potentially dangerous, use with care.
1881    const vec& _w() const {
1882        return w;
1883    };
1884    //! access function
1885    Array<vec>& _samples() {
1886        return samples;
1887    };
1888    //! access function
1889    const vec& _sample ( int i ) const {
1890        return samples ( i );
1891    };
1892    //! access function
1893    const Array<vec>& _samples() const {
1894        return samples;
1895    };
1896    //! 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.
1897    void resample ( RESAMPLING_METHOD method = SYSTEMATIC );
[565]1898
[1064]1899    //! inherited operation : NOT implemented
1900    vec sample() const NOT_IMPLEMENTED(0);
[565]1901
[1064]1902    //! inherited operation : NOT implemented
1903    double evallog ( const vec &val ) const NOT_IMPLEMENTED(0);
[737]1904
[1064]1905    vec mean() const {
1906        vec pom = zeros ( dim );
1907        for ( int i = 0; i < n; i++ ) {
1908            pom += samples ( i ) * w ( i );
1909        }
1910        return pom;
1911    }
1912    vec variance() const {
1913        vec pom = zeros ( dim );
1914        for ( int i = 0; i < n; i++ ) {
1915            pom += pow ( samples ( i ), 2 ) * w ( i );
1916        }
1917        return pom - pow ( mean(), 2 );
1918    }
1919    //! For this class, qbounds are minimum and maximum value of the population!
1920    void qbounds ( vec &lb, vec &ub, double perc = 0.95 ) const;
[760]1921
[1064]1922    void to_setting ( Setting &set ) const;
[1063]1923
[1064]1924    /*! Create object from the following structure
1925
1926    \code
1927    class = 'eEmp';
[1066]1928    samples = [...];  % array of samples
1929    w = [...];        % weights of samples stored in vector
[1064]1930    --- inherited fields ---
1931    bdm::epdf::from_setting
1932    \endcode
1933    */
1934    void from_setting ( const Setting &set );
[488]1935};
[760]1936UIREGISTER(eEmp);
[32]1937
1938
[8]1939////////////////////////
1940
[488]1941template<class sq_T>
[737]1942void enorm<sq_T>::set_parameters ( const vec &mu0, const sq_T &R0 ) {
[28]1943//Fixme test dimensions of mu0 and R0;
[1064]1944    mu = mu0;
1945    R = R0;
1946    validate();
[488]1947};
[8]1948
[488]1949template<class sq_T>
[737]1950void enorm<sq_T>::from_setting ( const Setting &set ) {
[1064]1951    epdf::from_setting ( set ); //reads rv
[384]1952
[1064]1953    UI::get ( mu, set, "mu", UI::compulsory );
1954    mat Rtmp;// necessary for conversion
1955    UI::get ( Rtmp, set, "R", UI::compulsory );
1956    R = Rtmp; // conversion
[488]1957}
[8]1958
[488]1959template<class sq_T>
[956]1960void enorm<sq_T>::validate() {
[1064]1961    eEF::validate();
1962    bdm_assert ( mu.length() == R.rows(), "mu and R parameters do not match" );
1963    dim = mu.length();
1964}
[956]1965
1966template<class sq_T>
[773]1967void enorm<sq_T>::to_setting ( Setting &set ) const {
[1064]1968    epdf::to_setting ( set ); //reads rv
1969    UI::save ( mu, set, "mu");
1970    UI::save ( R.to_mat(), set, "R");
[773]1971}
1972
[956]1973
1974
[773]1975template<class sq_T>
[737]1976void enorm<sq_T>::dupdate ( mat &v, double nu ) {
[1064]1977    //
[488]1978};
1979
[178]1980// template<class sq_T>
1981// void enorm<sq_T>::tupdate ( double phi, mat &vbar, double nubar ) {
[1066]1982//     //
[178]1983// };
[8]1984
[488]1985template<class sq_T>
[737]1986vec enorm<sq_T>::sample() const {
[1064]1987    vec x ( dim );
[270]1988#pragma omp critical
[1064]1989    NorRNG.sample_vector ( dim, x );
1990    vec smp = R.sqrt_mult ( x );
[12]1991
[1064]1992    smp += mu;
1993    return smp;
[488]1994};
[8]1995
[214]1996// template<class sq_T>
1997// double enorm<sq_T>::eval ( const vec &val ) const {
[1066]1998//     double pdfl,e;
1999//     pdfl = evallog ( val );
2000//     e = exp ( pdfl );
2001//     return e;
[214]2002// };
[8]2003
[488]2004template<class sq_T>
[737]2005double enorm<sq_T>::evallog_nn ( const vec &val ) const {
[1064]2006    // 1.83787706640935 = log(2pi)
2007    double tmp = -0.5 * ( R.invqform ( mu - val ) );// - lognc();
2008    return  tmp;
[488]2009};
[28]2010
[488]2011template<class sq_T>
[737]2012inline double enorm<sq_T>::lognc () const {
[1064]2013    // 1.83787706640935 = log(2pi)
2014    double tmp = 0.5 * ( R.cols() * 1.83787706640935 + R.logdet() );
2015    return tmp;
[488]2016};
[28]2017
[8]2018
[192]2019// template<class sq_T>
2020// vec mlnorm<sq_T>::samplecond (const  vec &cond, double &lik ) {
[1066]2021//     this->condition ( cond );
2022//     vec smp = epdf.sample();
2023//     lik = epdf.eval ( smp );
2024//     return smp;
[192]2025// }
[8]2026
[192]2027// template<class sq_T>
2028// mat mlnorm<sq_T>::samplecond (const vec &cond, vec &lik, int n ) {
[1066]2029//     int i;
2030//     int dim = rv.count();
2031//     mat Smp ( dim,n );
2032//     vec smp ( dim );
2033//     this->condition ( cond );
[198]2034//
[1066]2035//     for ( i=0; i<n; i++ ) {
2036//         smp = epdf.sample();
2037//         lik ( i ) = epdf.eval ( smp );
2038//         Smp.set_col ( i ,smp );
2039//     }
[198]2040//
[1066]2041//     return Smp;
[192]2042// }
[28]2043
[8]2044
[488]2045template<class sq_T>
[737]2046shared_ptr<epdf> enorm<sq_T>::marginal ( const RV &rvn ) const {
[1064]2047    enorm<sq_T> *tmp = new enorm<sq_T> ();
2048    shared_ptr<epdf> narrow ( tmp );
2049    marginal ( rvn, *tmp );
2050    return narrow;
[504]2051}
2052
2053template<class sq_T>
[737]2054void enorm<sq_T>::marginal ( const RV &rvn, enorm<sq_T> &target ) const {
[1064]2055    bdm_assert ( isnamed(), "rv description is not assigned" );
2056    ivec irvn = rvn.dataind ( rv );
[178]2057
[1064]2058    sq_T Rn ( R, irvn );  // select rows and columns of R
[280]2059
[1064]2060    target.set_rv ( rvn );
2061    target.set_parameters ( mu ( irvn ), Rn );
[488]2062}
[178]2063
[488]2064template<class sq_T>
[737]2065shared_ptr<pdf> enorm<sq_T>::condition ( const RV &rvn ) const {
[1064]2066    mlnorm<sq_T> *tmp = new mlnorm<sq_T> ();
2067    shared_ptr<pdf> narrow ( tmp );
2068    condition ( rvn, *tmp );
2069    return narrow;
[504]2070}
[178]2071
[504]2072template<class sq_T>
[737]2073void enorm<sq_T>::condition ( const RV &rvn, pdf &target ) const {
[1064]2074    typedef mlnorm<sq_T> TMlnorm;
[504]2075
[1064]2076    bdm_assert ( isnamed(), "rvs are not assigned" );
2077    TMlnorm &uptarget = dynamic_cast<TMlnorm &> ( target );
[270]2078
[1064]2079    RV rvc = rv.subt ( rvn );
2080    bdm_assert ( ( rvc._dsize() + rvn._dsize() == rv._dsize() ), "wrong rvn" );
2081    //Permutation vector of the new R
2082    ivec irvn = rvn.dataind ( rv );
2083    ivec irvc = rvc.dataind ( rv );
2084    ivec perm = concat ( irvn , irvc );
2085    sq_T Rn ( R, perm );
[178]2086
[1064]2087    //fixme - could this be done in general for all sq_T?
2088    mat S = Rn.to_mat();
2089    //fixme
2090    int n = rvn._dsize() - 1;
2091    int end = R.rows() - 1;
2092    mat S11 = S.get ( 0, n, 0, n );
2093    mat S12 = S.get ( 0, n , rvn._dsize(), end );
2094    mat S22 = S.get ( rvn._dsize(), end, rvn._dsize(), end );
[178]2095
[1064]2096    vec mu1 = mu ( irvn );
2097    vec mu2 = mu ( irvc );
2098    mat A = S12 * inv ( S22 );
2099    sq_T R_n ( S11 - A *S12.T() );
[178]2100
[1064]2101    uptarget.set_rv ( rvn );
2102    uptarget.set_rvc ( rvc );
2103    uptarget.set_parameters ( A, mu1 - A*mu2, R_n );
2104    uptarget.validate();
[488]2105}
[178]2106
[1063]2107/*! \brief Dirac delta function distribution */
[1064]2108class dirac: public epdf {
2109public:
2110    vec point;
2111public:
2112    double evallog (const vec &dt) const {
2113        return -inf;
2114    }
2115    vec mean () const {
2116        return point;
2117    }
2118    vec variance () const {
2119        return zeros(point.length());
2120    }
2121    void qbounds ( vec &lb, vec &ub, double percentage = 0.95 ) const {
2122        lb = point;
2123        ub = point;
2124    }
2125    //! access
2126    const vec& _point() {
2127        return point;
2128    }
2129    void set_point(const vec& p) {
2130        point =p;
2131        dim=p.length();
2132    }
2133    vec sample() const {
2134        return point;
2135    }
2136};
[887]2137
[1063]2138
2139///////////
2140
[488]2141template<class sq_T>
[737]2142void mgnorm<sq_T >::set_parameters ( const shared_ptr<fnc> &g0, const sq_T &R0 ) {
[1064]2143    g = g0;
2144    this->iepdf.set_parameters ( zeros ( g->dimension() ), R0 );
[527]2145}
2146
[488]2147template<class sq_T>
[737]2148void mgnorm<sq_T >::condition ( const vec &cond ) {
[1064]2149    this->iepdf._mu() = g->eval ( cond );
[737]2150};
[28]2151
[1077]2152//!     odo unify this stuff with to_string()
[488]2153template<class sq_T>
[737]2154std::ostream &operator<< ( std::ostream &os,  mlnorm<sq_T> &ml ) {
[1064]2155    os << "A:" << ml.A << endl;
2156    os << "mu:" << ml.mu_const << endl;
2157    os << "R:" << ml._R() << endl;
2158    return os;
[488]2159};
[28]2160
[254]2161}
[8]2162#endif //EF_H
Note: See TracBrowser for help on using the browser.