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

Revision 1196, 57.6 kB (checked in by smidl, 14 years ago)

monitor Neff + test enorm

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