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

Revision 1077, 55.8 kB (checked in by mido, 14 years ago)

another update of doc - all bayesian models until bdm::MultiModel? finished
also MixEF::MixEF_options renamed just to MixEF::Options

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