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

Revision 1068, 55.0 kB (checked in by mido, 14 years ago)

patch of documentation - all conditional pdfs revised

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