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

Revision 1175, 56.5 kB (checked in by smidl, 14 years ago)

unit test for student - fake sampling in student

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