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
Line 
1/*!
2  \file
3  \brief Probability distributions for Exponential Family models.
4  \author Vaclav Smidl.
5
6  -----------------------------------
7  BDM++ - C++ library for Bayesian Decision Making under Uncertainty
8
9  Using IT++ for numerical operations
10  -----------------------------------
11*/
12
13#ifndef EF_H
14#define EF_H
15
16
17#include "../shared_ptr.h"
18#include "../base/bdmbase.h"
19#include "../math/chmat.h"
20
21namespace bdm {
22
23
24//! Global Uniform_RNG
25extern Uniform_RNG UniRNG;
26//! Global Normal_RNG
27extern Normal_RNG NorRNG;
28//! Global Gamma_RNG
29extern Gamma_RNG GamRNG;
30
31
32/*!
33* \brief Abstract class of general conjugate exponential family posterior density.
34
35* More?...
36*/
37class eEF : public epdf {
38public:
39//    eEF() :epdf() {};
40    //! default constructor
41    eEF () : epdf () {};
42    //! logarithm of the normalizing constant, \f$\mathcal{I}\f$
43    virtual double lognc() const = 0;
44
45    //!Evaluate normalized log-probability
46    virtual double evallog_nn ( const vec &val ) const NOT_IMPLEMENTED(0);
47
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    }
70
71    //!Power of the density, used e.g. to flatten the density
72    virtual void pow ( double p ) NOT_IMPLEMENTED_VOID;
73};
74
75
76//! Estimator for Exponential family
77class BMEF : public BM {
78public:
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;
93
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 );
102
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;;
105
106
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    }
113
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    */
130    void from_setting( const Setting &set) {
131        BM::from_setting(set);
132        if ( !UI::get ( frg, set, "frg" ) )
133            frg = 1.0;
134        if ( !UI::get ( frg_sched_factor, set, "frg_sched_factor" ) )
135            frg_sched_factor = 0.0;
136    }
137
138    void validate() {
139        BM::validate();
140    }
141
142};
143
144/*! \brief Dirac delta density with predefined transformation
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*/
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    }
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    */
171    void from_setting(const Setting& set);
172    void to_setting(Setting &set) const;
173    void validate();
174};
175UIREGISTER(mgdirac);
176
177
178template<class sq_T, template <typename> class TEpdf>
179class mlnorm;
180
181/*!
182* \brief Gaussian density with positive definite (decomposed) covariance matrix.
183
184* More?...
185*/
186template<class sq_T>
187class enorm : public eEF {
188protected:
189    //! mean value
190    vec mu;
191    //! Covariance matrix in decomposed form
192    sq_T R;
193public:
194    //!\name Constructors
195    //!@{
196
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 ;
213
214    void validate();
215    //!@}
216
217    //! \name Mathematical operations
218    //!@{
219
220    //! dupdate in exponential form (not really handy)
221    void dupdate ( mat &v, double nu = 1.0 );
222
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());
228
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    }
232
233    vec sample() const;
234
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    }
246    //    mlnorm<sq_T>* condition ( const RV &rvn ) const ; <=========== fails to cmpile. Why?
247    shared_ptr<pdf> condition ( const RV &rvn ) const;
248
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;
254
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
279};
280UIREGISTER2 ( enorm, chmat );
281SHAREDPTR2 ( enorm, chmat );
282UIREGISTER2 ( enorm, ldmat );
283SHAREDPTR2 ( enorm, ldmat );
284UIREGISTER2 ( enorm, fsqmat );
285SHAREDPTR2 ( enorm, fsqmat );
286
287//! \class bdm::egauss
288//!\brief Gaussian (Normal) distribution. Same as enorm<fsqmat>.
289typedef enorm<ldmat> egauss;
290UIREGISTER(egauss);
291
292
293//forward declaration
294class mstudent;
295
296/*! distribution of multivariate Student t density
297
298Based on article by Genest and Zidek,
299*/
300template<class sq_T>
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    }
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        }
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    }
383};
384UIREGISTER2(estudent,fsqmat);
385UIREGISTER2(estudent,ldmat);
386UIREGISTER2(estudent,chmat);
387
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
403/*!
404* \brief Gauss-inverse-Wishart density stored in LD form
405
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$
409*
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$
415*/
416class egiw : public eEF {
417    //! \var log_level_enums logvartheta
418    //! Log variance of the theta part
419
420    LOG_LEVEL(egiw,logvartheta);
421
422protected:
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;
431public:
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    };
439
440    void set_parameters ( int dimx0, ldmat V0, double nu0 = -1.0 );
441    //!@}
442
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;
449
450    void factorize ( mat &M, ldmat &Vz, ldmat &Lam ) const;
451    //! LS estimate of \f$\theta\f$
452    vec est_theta() const;
453
454    //! Covariance of the LS estimate
455    ldmat est_theta_cov() const;
456
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    };
466
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);
478
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    //!@{
492
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    }
508
509    /*! Create object from the following structure
510    \code
511
512    class = 'egiw';
513    dimx    = [...];       % dimension of the wishart part
514    V.L     = [...];       % L part of matrix V
515    V.D     = [...];       % D part of matrix V
516    -or- fV = [...];       % full matrix V
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
526    \endcode
527
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
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    //!@}
542};
543UIREGISTER ( egiw );
544SHAREDPTR ( egiw );
545
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
572/*! \brief Dirichlet posterior density
573
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*/
580class eDirich: public eEF {
581protected:
582    //!sufficient statistics
583    vec beta;
584public:
585    //!\name Constructors
586    //!@{
587
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    //!@}
602
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 );
608#pragma omp critical
609            y ( i ) = GamRNG();
610        }
611        return y / sum ( y );
612    }
613
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    }
627
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    }
638
639    //!access function
640    vec& _beta()  {
641        return beta;
642    }
643
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 );
653
654    void validate();
655
656    void to_setting ( Setting &set ) const;
657};
658UIREGISTER ( eDirich );
659
660/*! \brief Product of Beta distributions
661
662Continuous Dirichlet density of \f$n\f$-dimensional variable \f$x\f$
663\f[
664f(x|\alpha,\beta)  = \frac{\Gamma(\alpha+\beta)}{\Gamma(\alpha)\Gamma(\beta)}\, x^{\alpha-1}(1-x)^{\beta-1}
665\f]
666is a simplification of Dirichlet to univariate case.
667*/
668class eBeta: public eEF {
669public:
670    //!sufficient statistics
671    vec alpha;
672    //!sufficient statistics
673    vec beta;
674public:
675    //!\name Constructors
676    //!@{
677
678    eBeta () : eEF () {};
679    eBeta ( const eBeta &B0 ) : eEF (), alpha(B0.alpha),beta(B0.beta) {
680        validate();
681    };
682    //!@}
683
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();
691
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    }
748};
749UIREGISTER ( eBeta );
750
751/*! \brief Random Walk on Dirichlet
752
753Using simple assignment
754 \f[ \beta = rvc / k + \beta_c \f]
755 hence, mean value = rvc, variance = (k+1)*mean*mean;
756
757 The greater k is, the greater is the variance of the random walk;
758
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*/
762class mDirich: public pdf_internal<eDirich> {
763protected:
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;
770public:
771    mDirich() : pdf_internal<eDirich>(), _beta ( iepdf._beta() ) {};
772    void condition ( const vec &val ) {
773        _beta =  val / k + betac;
774    };
775
776    /*! Create object from the following structure
777    \code
778    class = 'mDirich';
779    k = 1;                      % multiplicative constant k
780    --- optional ---
781    beta0 = [...];              % initial values of beta
782    betac = [...];              % initial values of beta stabilizing coefficients
783    --- inherited fields ---
784    bdm::pdf::from_setting
785    \endcode
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
793    */
794    void from_setting ( const Setting &set );
795    void     to_setting  (Setting  &set) const;
796    void validate();
797};
798UIREGISTER ( mDirich );
799
800/*! \brief Random Walk with vector Beta distribution
801
802Using simple assignment
803\f{eqnarray*}
804\alpha & = & rvc / k + \beta_c \\
805\beta & = &(1-rvc) / k + \beta_c \\
806\f}
807for each element of alpha and beta, mean value = rvc, variance = (k+1)*mean*mean;
808
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*/
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;
819
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    };
825
826    /*! Create object from the following structure
827    \code
828    class = 'mBeta';
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
835    \endcode
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   
844    */
845    void from_setting ( const Setting &set );
846
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    //!
856};
857UIREGISTER(mBeta);
858
859//! \brief Estimator for Multinomial density
860class multiBM : public BMEF {
861protected:
862    //! Conjugate prior and posterior
863    eDirich est;
864    //! Pointer inside est to sufficient statistics
865    vec &beta;
866public:
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 );
883
884    double logpred ( const vec &yt ) const;
885
886    void flatten ( const BMEF* B , double weight);
887
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    }
900
901    void to_setting ( Setting &set ) const {
902        BMEF::to_setting ( set );
903        UI::save( &est, set, "prior" );
904    }
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    */
915    void from_setting (const Setting &set )  {
916        BMEF::from_setting ( set );
917        UI::get( est, set, "prior" );
918    }
919};
920UIREGISTER( multiBM );
921
922/*!
923 \brief Gamma posterior density
924
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*/
930
931class egamma : public eEF {
932protected:
933    //! Vector \f$\alpha\f$
934    vec alpha;
935    //! Vector \f$\beta\f$
936    vec beta;
937public :
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    //!@}
949
950    vec sample() const;
951        double evallog_nn ( const vec &val ) const;
952        double lognc () const;
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    }
967
968    /*! Create object from the following structure
969
970    \code
971    class = 'egamma';
972    alpha = [...];         % vector alpha
973    beta = [...];          % vector beta
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 );
980
981    void to_setting ( Setting &set ) const;
982    void validate();
983};
984UIREGISTER ( egamma );
985SHAREDPTR ( egamma );
986
987/*!
988 \brief Inverse-Gamma posterior density
989
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]
994
995Vector \f$\beta\f$ has different meaning (in fact it is 1/beta as used in definition of iG)
996
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 */
1002
1003class eigamma : public egamma {
1004protected:
1005public :
1006    //! \name Constructors
1007    //! All constructors are inherited
1008    //!@{
1009    //!@}
1010
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    }
1022};
1023/*
1024//! Weighted mixture of epdfs with external owned components.
1025class emix : public epdf {
1026protected:
1027    int n;
1028    vec &w;
1029    Array<epdf*> Coms;
1030public:
1031//! Default constructor
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;};
1035};
1036*/
1037
1038//! \brief Uniform distributed density on a rectangular support
1039class euni: public epdf {
1040protected:
1041//! lower bound on support
1042    vec low;
1043//! upper bound on support
1044    vec high;
1045//! internal
1046    vec distance;
1047//! normalizing coefficients
1048    double nk;
1049//! cache of log( \c nk )
1050    double lnk;
1051public:
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    //!@}
1066
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 );
1074#pragma omp critical
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    }
1085
1086
1087     /*! Create object from the following structure
1088     \code
1089   
1090     class = 'euni'
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
1096     \endcode
1097
1098     fulfilling form \f[ f(rv) = U(low,high) \f]
1099     */
1100    void from_setting ( const Setting &set );
1101    void     to_setting  (Setting  &set) const;
1102    void validate();
1103};
1104UIREGISTER ( euni );
1105
1106//! Uniform density with conditional mean value
1107class mguni : public pdf_internal<euni> {
1108    //! function of the mean value
1109    shared_ptr<fnc> mean;
1110    //! distance from mean to both sides
1111    vec delta;
1112public:
1113    void condition ( const vec &cond ) {
1114        vec mea = mean->eval ( cond );
1115        iepdf.set_parameters ( mea - delta, mea + delta );
1116    }
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    */
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    }
1133    void     to_setting  (Setting  &set) const {
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();
1141
1142    }
1143
1144};
1145UIREGISTER ( mguni );
1146/*!
1147 \brief Normal distributed linear function with linear function of mean value;
1148
1149 Mean value \f$ \mu=A*\mbox{rvc}+\mu_0 \f$.
1150*/
1151template < class sq_T, template <typename> class TEpdf = enorm >
1152class mlnorm : public pdf_internal< TEpdf<sq_T> > {
1153protected:
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?
1159public:
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    }
1167
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    }
1174
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;
1179//R is already assigned;
1180    }
1181
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    }
1198
1199    //! Debug stream
1200    template<typename sq_M>
1201    friend std::ostream &operator<< ( std::ostream &os,  mlnorm<sq_M, enorm> &ml );
1202
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 );
1216
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    }
1223
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    }
1230
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();
1239
1240    }
1241};
1242UIREGISTER2 ( mlnorm, ldmat );
1243SHAREDPTR2 ( mlnorm, ldmat );
1244UIREGISTER2 ( mlnorm, fsqmat );
1245SHAREDPTR2 ( mlnorm, fsqmat );
1246UIREGISTER2 ( mlnorm, chmat );
1247SHAREDPTR2 ( mlnorm, chmat );
1248
1249//! \class mlgauss
1250//!\brief Normal distribution with linear function of mean value. Same as mlnorm<fsqmat>.
1251typedef mlnorm<fsqmat> mlgauss;
1252UIREGISTER(mlgauss);
1253
1254//! pdf with general function for mean value
1255template<class sq_T>
1256class mgnorm : public pdf_internal< enorm< sq_T > > {
1257private:
1258//            vec &mu; WHY NOT?
1259    shared_ptr<fnc> g;
1260
1261public:
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 );
1267
1268
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 = ...;
1276
1277    R = [1, 0;             // covariance matrix
1278        0, 1];
1279        --OR --
1280    dR = [1, 1];           // diagonal of cavariance matrix
1281
1282    rv = RV({'name'})      // description of RV
1283    rvc = RV({'name'})     // description of RV in condition
1284    \endcode
1285    */
1286
1287
1288    void from_setting ( const Setting &set ) {
1289        pdf::from_setting ( set );
1290        shared_ptr<fnc> g = UI::build<fnc> ( set, "g", UI::compulsory );
1291
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 );
1298
1299        set_parameters ( g, R );
1300        //validate();
1301    }
1302
1303
1304    void to_setting  (Setting  &set) const {
1305        UI::save( g,set, "g");
1306        UI::save(this->iepdf._R().to_mat(),set, "R");
1307
1308    }
1309
1310
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
1320};
1321
1322UIREGISTER2 ( mgnorm, chmat );
1323UIREGISTER2 ( mgnorm, ldmat );
1324SHAREDPTR2 ( mgnorm, chmat );
1325
1326
1327/*! \brief (Approximate) Student t density with linear function of mean value
1328
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.
1331
1332Perhaps a moment-matching technique?
1333*/
1334class mlstudent : public mlnorm<ldmat, enorm> {
1335protected:
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;
1342public:
1343    mlstudent () : mlnorm<ldmat, enorm> (),
1344        Lambda (),    _R ( iepdf._R() ) {}
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    }
1353
1354    void condition ( const vec &cond );
1355
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" );
1360
1361    }
1362};
1363
1364/*!
1365\brief  Gamma random walk
1366
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$.
1370
1371The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
1372*/
1373class mgamma : public pdf_internal<egamma> {
1374protected:
1375
1376    //! Constant \f$k\f$
1377    double k;
1378
1379    //! cache of iepdf.beta
1380    vec &_beta;
1381
1382public:
1383    //! Constructor
1384    mgamma() : pdf_internal<egamma>(), k ( 0 ),
1385        _beta ( iepdf._beta() ) {
1386    }
1387
1388    //! Set value of \c k
1389    void set_parameters ( double k, const vec &beta0 );
1390
1391    void condition ( const vec &val ) {
1392        _beta = k / val;
1393    };
1394
1395    /*! Create object from the following structure
1396    \code
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]
1404    */
1405    void from_setting ( const Setting &set );
1406    void     to_setting  (Setting  &set) const;
1407    void validate();
1408};
1409UIREGISTER ( mgamma );
1410SHAREDPTR ( mgamma );
1411
1412/*!
1413\brief  Inverse-Gamma random walk
1414
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$.
1418
1419The standard deviation of the walk is then: \f$ \mu/\sqrt(k)\f$.
1420 */
1421class migamma : public pdf_internal<eigamma> {
1422protected:
1423    //! Constant \f$k\f$
1424    double k;
1425
1426    //! cache of iepdf.alpha
1427    vec &_alpha;
1428
1429    //! cache of iepdf.beta
1430    vec &_beta;
1431
1432public:
1433    //! \name Constructors
1434    //!@{
1435    migamma() : pdf_internal<eigamma>(),
1436        k ( 0 ),
1437        _alpha ( iepdf._alpha() ),
1438        _beta ( iepdf._beta() ) {
1439    }
1440
1441    migamma ( const migamma &m ) : pdf_internal<eigamma>(),
1442        k ( 0 ),
1443        _alpha ( iepdf._alpha() ),
1444        _beta ( iepdf._beta() ) {
1445    }
1446    //!@}
1447
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    };
1453
1454    void     validate () {
1455        pdf_internal<eigamma>::validate();
1456        dimc = dimension();
1457    };
1458
1459    void condition ( const vec &val ) {
1460        _beta = elem_mult ( val, ( _alpha - 1.0 ) );
1461    };
1462};
1463
1464/*!
1465\brief  Gamma random walk around a fixed point
1466
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]
1469
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$.
1472
1473The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
1474*/
1475class mgamma_fix : public mgamma {
1476protected:
1477    //! parameter l
1478    double l;
1479    //! reference vector
1480    vec refl;
1481public:
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    };
1490
1491    void validate () {
1492        mgamma::validate();
1493        dimc = dimension();
1494    };
1495
1496    void condition ( const vec &val ) {
1497        vec mean = elem_mult ( refl, pow ( val, l ) );
1498        _beta = k / mean;
1499    };
1500};
1501
1502
1503/*!
1504\brief  Inverse-Gamma random walk around a fixed point
1505
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]
1508
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$.
1512
1513The standard deviation of the walk is then: \f$\mu/\sqrt(k)\f$.
1514 */
1515class migamma_ref : public migamma {
1516protected:
1517    //! parameter l
1518    double l;
1519    //! reference vector
1520    vec refl;
1521public:
1522    //! Constructor
1523    migamma_ref () : migamma (), refl () {};
1524
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    };
1531
1532    void validate() {
1533        migamma::validate();
1534        dimc = dimension();
1535    };
1536
1537    void condition ( const vec &val ) {
1538        vec mean = elem_mult ( refl, pow ( val, l ) );
1539        migamma::condition ( mean );
1540    };
1541
1542    /*! Create object from the following structure
1543    \code
1544    class = 'migamma_ref';
1545    ref = [...];           % reference vector
1546    l = [];                % constant scalar l
1547    k = [];                % constant scalar k   
1548    --- inherited fields ---
1549    bdm::migamma::from_setting
1550    \endcode
1551    fulfilling form \f[ f(rv|rvc) = i\Gamma(k, k/(rvc^l \circ ref^{(1-l)}) \f]
1552     */
1553    void from_setting ( const Setting &set );
1554
1555    void to_setting  (Setting  &set) const;
1556};
1557
1558
1559UIREGISTER ( migamma_ref );
1560SHAREDPTR ( migamma_ref );
1561
1562/*! \brief Log-Normal probability density - it allows only diagonal covariances!
1563
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]
1568
1569Function from_setting loads mu and R in the same way as it does for enorm<>!
1570*/
1571class elognorm: public enorm<ldmat> {
1572public:
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    };
1580
1581};
1582
1583/*!
1584\brief  Log-Normal random walk
1585
1586Mean value, \f$\mu\f$, is...
1587
1588 */
1589class mlognorm : public pdf_internal<elognorm> {
1590protected:
1591    //! parameter 1/2*sigma^2
1592    double sig2;
1593
1594    //! access
1595    vec &mu;
1596public:
1597    //! Constructor
1598    mlognorm() : pdf_internal<elognorm>(),
1599        sig2 ( 0 ),
1600        mu ( iepdf._mu() ) {
1601    }
1602
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    };
1608
1609    void validate() {
1610        pdf_internal<elognorm>::validate();
1611        dimc = iepdf.dimension();
1612    }
1613
1614    void condition ( const vec &val ) {
1615        mu = log ( val ) - sig2;//elem_mult ( refl,pow ( val,l ) );
1616    };
1617
1618    /*! Create object from the following structure
1619    \code
1620    class = 'mlognorm';
1621    k   = [];               % "variance" k
1622    mu0 = [];               % initial value of mean
1623    --- inherited fields ---
1624    bdm::pdf_internal<elognorm>::from_setting
1625    \endcode
1626    fulfilling form \f[ f(rv|rvc) = log\mathcal{N}( \log(rvc)-0.5\log(k^2+1), k I) \f]
1627    */
1628    void from_setting ( const Setting &set );
1629
1630    void to_setting  (Setting  &set) const;
1631};
1632
1633UIREGISTER ( mlognorm );
1634SHAREDPTR ( mlognorm );
1635
1636/*! \brief Inverse Wishart density defined on Choleski decomposition
1637 *
1638 * here \f$\Omega \sim |\Sigma|^{-0.5(\delta}|\Omega|^{0.5(\delta -p -1)} \exp(-1/2 tr(\Omega\Sigma^{-1}))\$f
1639*/
1640class eWishartCh : public epdf {
1641protected:
1642    //! Upper-Triagle of Choleski decomposition of \f$ \Psi \f$
1643    chmat Sigma;
1644    //! dimension of matrix  \f$ \Psi \f$
1645    int p;
1646    //! degrees of freedom  \f$ \nu \f$
1647    double delta;
1648public:
1649    //! Set internal structures
1650    void set_parameters ( const mat &Y0, const double delta0 ) {
1651        Sigma = chmat ( Y0 );
1652        delta = delta0;
1653        p = Sigma.rows();
1654    }
1655    //! Set internal structures
1656    void set_parameters ( const chmat &Y0, const double delta0 ) {
1657        Sigma = Y0;
1658        delta = delta0;
1659        p = Sigma.rows();
1660    }
1661
1662    virtual void validate () {
1663        epdf::validate();
1664        dim = p * p;
1665    }
1666
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
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
1675#pragma omp critical
1676            A_T ( i, i ) = sqrt ( GamRNG() );
1677        }
1678        //do the rest
1679        for ( int i = 0; i < p; i++ ) {
1680            for ( int j = i + 1; j < p; j++ ) {
1681#pragma omp critical
1682                A_T ( i, j ) = NorRNG.sample();
1683            }
1684        }
1685        chmat tmp;
1686                tmp._Ch()=A_T*Sigma._Ch();
1687        return tmp;// return upper triangular part of the decomposition
1688    }
1689
1690    vec sample () const {
1691        return vec ( sample_mat().to_mat()._data(), p*p );
1692    }
1693
1694    virtual vec mean() const NOT_IMPLEMENTED(0);
1695
1696    //! return expected variance (not covariance!)
1697    virtual vec variance() const NOT_IMPLEMENTED(0);
1698
1699    virtual double evallog ( const vec &val ) const NOT_IMPLEMENTED(0);
1700
1701    //! fast access function y0 will be copied into Y.Ch.
1702    void setY ( const mat &Ch0 ) {
1703        copy_vector ( dim, Ch0._data(), Sigma._Ch()._data() );
1704    }
1705
1706    //! fast access function y0 will be copied into Y.Ch.
1707    void _setY ( const vec &ch0 ) {
1708        copy_vector ( dim, ch0._data(), Sigma._Ch()._data() );
1709    }
1710
1711    //! access function
1712    const chmat& getY() const {
1713        return Sigma;
1714    }
1715};
1716
1717//! Inverse Wishart on Choleski decomposition
1718/*! Being computed by conversion from `standard' Wishart
1719*/
1720class eiWishartCh: public epdf {
1721protected:
1722    //! Internal instance of Wishart density
1723    eWishartCh W;
1724    //! size of Ch
1725    int p;
1726    //! parameter delta
1727    double delta;
1728public:
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    }
1735
1736    virtual void     validate () {
1737        epdf::validate();
1738        W.validate();
1739        dim = W.dimension();
1740    }
1741
1742
1743    vec sample() const {
1744        mat iCh;
1745        iCh = inv ( W.sample_mat()._Ch() );
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
1766//                 \frac{ |\Psi|^{m/2}|X|^{-(m+p+1)/2}e^{-tr(\Psi X^{-1})/2} }{ 2^{mp/2}\Gamma_p(m/2)},
1767        mat M = Y.to_mat() * iX.to_mat();
1768
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!!
1771
1772        /*                if (0) {
1773                            mat XX=X.to_mat();
1774                            mat YY=Y.to_mat();
1775
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                        }*/
1779        return log1;
1780    };
1781
1782    virtual vec mean() const NOT_IMPLEMENTED(0);
1783
1784    //! return expected variance (not covariance!)
1785    virtual vec variance() const NOT_IMPLEMENTED(0);
1786};
1787
1788//! Random Walk on inverse Wishart
1789class rwiWishartCh : public pdf_internal<eiWishartCh> {
1790protected:
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;
1799
1800public:
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    };
1811
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    }
1827};
1828
1829//! Switch between various resampling methods.
1830enum RESAMPLING_METHOD { MULTINOMIAL = 0, STRATIFIED = 1, SYSTEMATIC = 3 };
1831
1832//! Shortcut for multinomial.sample(int n). Various simplifications are allowed see RESAMPLING_METHOD
1833void resample(const vec &w, ivec &ind, RESAMPLING_METHOD=SYSTEMATIC);
1834
1835/*! \brief Weighted empirical density
1836
1837Used e.g. in particle filters.
1838*/
1839class eEmp: public epdf {
1840protected :
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;
1847public:
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    //!@}
1854
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    };
1875    virtual void     validate ();
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 );
1898
1899    //! inherited operation : NOT implemented
1900    vec sample() const NOT_IMPLEMENTED(0);
1901
1902    //! inherited operation : NOT implemented
1903    double evallog ( const vec &val ) const NOT_IMPLEMENTED(0);
1904
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;
1921
1922    void to_setting ( Setting &set ) const;
1923
1924    /*! Create object from the following structure
1925
1926    \code
1927    class = 'eEmp';
1928    samples = [...];  % array of samples
1929    w = [...];        % weights of samples stored in vector
1930    --- inherited fields ---
1931    bdm::epdf::from_setting
1932    \endcode
1933    */
1934    void from_setting ( const Setting &set );
1935};
1936UIREGISTER(eEmp);
1937
1938
1939////////////////////////
1940
1941template<class sq_T>
1942void enorm<sq_T>::set_parameters ( const vec &mu0, const sq_T &R0 ) {
1943//Fixme test dimensions of mu0 and R0;
1944    mu = mu0;
1945    R = R0;
1946    validate();
1947};
1948
1949template<class sq_T>
1950void enorm<sq_T>::from_setting ( const Setting &set ) {
1951    epdf::from_setting ( set ); //reads rv
1952
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
1957}
1958
1959template<class sq_T>
1960void enorm<sq_T>::validate() {
1961    eEF::validate();
1962    bdm_assert ( mu.length() == R.rows(), "mu and R parameters do not match" );
1963    dim = mu.length();
1964}
1965
1966template<class sq_T>
1967void enorm<sq_T>::to_setting ( Setting &set ) const {
1968    epdf::to_setting ( set ); //reads rv
1969    UI::save ( mu, set, "mu");
1970    UI::save ( R.to_mat(), set, "R");
1971}
1972
1973
1974
1975template<class sq_T>
1976void enorm<sq_T>::dupdate ( mat &v, double nu ) {
1977    //
1978};
1979
1980// template<class sq_T>
1981// void enorm<sq_T>::tupdate ( double phi, mat &vbar, double nubar ) {
1982//     //
1983// };
1984
1985template<class sq_T>
1986vec enorm<sq_T>::sample() const {
1987    vec x ( dim );
1988#pragma omp critical
1989    NorRNG.sample_vector ( dim, x );
1990    vec smp = R.sqrt_mult ( x );
1991
1992    smp += mu;
1993    return smp;
1994};
1995
1996// template<class sq_T>
1997// double enorm<sq_T>::eval ( const vec &val ) const {
1998//     double pdfl,e;
1999//     pdfl = evallog ( val );
2000//     e = exp ( pdfl );
2001//     return e;
2002// };
2003
2004template<class sq_T>
2005double enorm<sq_T>::evallog_nn ( const vec &val ) const {
2006    // 1.83787706640935 = log(2pi)
2007    double tmp = -0.5 * ( R.invqform ( mu - val ) );// - lognc();
2008    return  tmp;
2009};
2010
2011template<class sq_T>
2012inline double enorm<sq_T>::lognc () const {
2013    // 1.83787706640935 = log(2pi)
2014    double tmp = 0.5 * ( R.cols() * 1.83787706640935 + R.logdet() );
2015    return tmp;
2016};
2017
2018
2019// template<class sq_T>
2020// vec mlnorm<sq_T>::samplecond (const  vec &cond, double &lik ) {
2021//     this->condition ( cond );
2022//     vec smp = epdf.sample();
2023//     lik = epdf.eval ( smp );
2024//     return smp;
2025// }
2026
2027// template<class sq_T>
2028// mat mlnorm<sq_T>::samplecond (const vec &cond, vec &lik, int n ) {
2029//     int i;
2030//     int dim = rv.count();
2031//     mat Smp ( dim,n );
2032//     vec smp ( dim );
2033//     this->condition ( cond );
2034//
2035//     for ( i=0; i<n; i++ ) {
2036//         smp = epdf.sample();
2037//         lik ( i ) = epdf.eval ( smp );
2038//         Smp.set_col ( i ,smp );
2039//     }
2040//
2041//     return Smp;
2042// }
2043
2044
2045template<class sq_T>
2046shared_ptr<epdf> enorm<sq_T>::marginal ( const RV &rvn ) const {
2047    enorm<sq_T> *tmp = new enorm<sq_T> ();
2048    shared_ptr<epdf> narrow ( tmp );
2049    marginal ( rvn, *tmp );
2050    return narrow;
2051}
2052
2053template<class sq_T>
2054void enorm<sq_T>::marginal ( const RV &rvn, enorm<sq_T> &target ) const {
2055    bdm_assert ( isnamed(), "rv description is not assigned" );
2056    ivec irvn = rvn.dataind ( rv );
2057
2058    sq_T Rn ( R, irvn );  // select rows and columns of R
2059
2060    target.set_rv ( rvn );
2061    target.set_parameters ( mu ( irvn ), Rn );
2062}
2063
2064template<class sq_T>
2065shared_ptr<pdf> enorm<sq_T>::condition ( const RV &rvn ) const {
2066    mlnorm<sq_T> *tmp = new mlnorm<sq_T> ();
2067    shared_ptr<pdf> narrow ( tmp );
2068    condition ( rvn, *tmp );
2069    return narrow;
2070}
2071
2072template<class sq_T>
2073void enorm<sq_T>::condition ( const RV &rvn, pdf &target ) const {
2074    typedef mlnorm<sq_T> TMlnorm;
2075
2076    bdm_assert ( isnamed(), "rvs are not assigned" );
2077    TMlnorm &uptarget = dynamic_cast<TMlnorm &> ( target );
2078
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 );
2086
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 );
2095
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() );
2100
2101    uptarget.set_rv ( rvn );
2102    uptarget.set_rvc ( rvc );
2103    uptarget.set_parameters ( A, mu1 - A*mu2, R_n );
2104    uptarget.validate();
2105}
2106
2107/*! \brief Dirac delta function distribution */
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};
2137
2138
2139///////////
2140
2141template<class sq_T>
2142void mgnorm<sq_T >::set_parameters ( const shared_ptr<fnc> &g0, const sq_T &R0 ) {
2143    g = g0;
2144    this->iepdf.set_parameters ( zeros ( g->dimension() ), R0 );
2145}
2146
2147template<class sq_T>
2148void mgnorm<sq_T >::condition ( const vec &cond ) {
2149    this->iepdf._mu() = g->eval ( cond );
2150};
2151
2152//!     odo unify this stuff with to_string()
2153template<class sq_T>
2154std::ostream &operator<< ( std::ostream &os,  mlnorm<sq_T> &ml ) {
2155    os << "A:" << ml.A << endl;
2156    os << "mu:" << ml.mu_const << endl;
2157    os << "R:" << ml._R() << endl;
2158    return os;
2159};
2160
2161}
2162#endif //EF_H
Note: See TracBrowser for help on using the browser.