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

Revision 1175, 56.5 kB (checked in by smidl, 14 years ago)

unit test for student - fake sampling in student

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