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

Revision 1064, 53.9 kB (checked in by mido, 14 years ago)

astyle applied all over the library

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