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

Revision 1121, 56.4 kB (checked in by smidl, 14 years ago)

Preparation for ARX with linear forgetting

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