root/bdm/stat/emix.h @ 270

Revision 270, 8.8 kB (checked in by smidl, 15 years ago)

Changes in the very root classes!
* rv and rvc are no longer compulsory,
* samplecond does not return ll
* BM has drv

  • Property svn:eol-style set to native
RevLine 
[107]1/*!
2  \file
3  \brief Probability distributions for Mixtures of pdfs
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 MX_H
14#define MX_H
15
16#include "libBM.h"
17#include "libEF.h"
18//#include <std>
19
[254]20namespace bdm{
[107]21
[182]22//this comes first because it is used inside emix!
23
24/*! \brief Class representing ratio of two densities
25which arise e.g. by applying the Bayes rule.
26It represents density in the form:
27\f[
28f(rv|rvc) = \frac{f(rv,rvc)}{f(rvc)}
29\f]
30where \f$ f(rvc) = \int f(rv,rvc) d\ rv \f$.
31
32In particular this type of arise by conditioning of a mixture model.
33
[211]34At present the only supported operation is evallogcond().
[182]35 */
36class mratio: public mpdf {
[192]37protected:
[182]38        //! Nominator in the form of mpdf
[192]39        const epdf* nom;
[182]40        //!Denominator in the form of epdf
[192]41        epdf* den;
42        //!flag for destructor
43        bool destroynom;
[193]44        //!datalink between conditional and nom
45        datalink_m2e dl;
[192]46public:
47        //!Default constructor. By default, the given epdf is not copied!
[182]48        //! It is assumed that this function will be used only temporarily.
[270]49        mratio ( const epdf* nom0, const RV &rv, bool copy=false ) :mpdf ( ), dl ( rv,rvc,nom0->_rv() ) {
50                ep->set_rv(_rv());
51                set_rvc(nom0->_rv().subt ( rv ) );
[192]52                if ( copy ) {
[182]53//                      nom = nom0->_copy_();
[204]54                        it_error ( "todo" );
[192]55                        destroynom=true;
[182]56                }
[192]57                else {
58                        nom = nom0;
59                        destroynom = false;
60                }
61                it_assert_debug ( rvc.length() >0,"Makes no sense to use this object!" );
62                den = nom->marginal ( rvc );
63        };
[211]64        double evallogcond ( const vec &val, const vec &cond ) {
[214]65                double tmp;
[270]66                vec nom_val ( ep->dimension() + dimc );
67                dl.pushup_cond ( nom_val,val,cond );
[214]68                tmp = exp ( nom->evallog ( nom_val ) - den->evallog ( cond ) );
69                it_assert_debug(std::isfinite(tmp),"Infinite value");
70                return tmp;
[192]71        }
[182]72        //! Object takes ownership of nom and will destroy it
[192]73        void ownnom() {destroynom=true;}
[182]74        //! Default destructor
[192]75        ~mratio() {delete den; if ( destroynom ) {delete nom;}}
[182]76};
77
[107]78/*!
79* \brief Mixture of epdfs
80
81Density function:
82\f[
83f(x) = \sum_{i=1}^{n} w_{i} f_i(x), \quad \sum_{i=1}^n w_i = 1.
84\f]
85where \f$f_i(x)\f$ is any density on random variable \f$x\f$, called \a component,
86
87*/
[145]88class emix : public epdf {
[162]89protected:
90        //! weights of the components
91        vec w;
92        //! Component (epdfs)
93        Array<epdf*> Coms;
[178]94        //!Flag if owning Coms
95        bool destroyComs;
[162]96public:
97        //!Default constructor
[270]98        emix (  ) : epdf ( ) {};
[182]99        //! Set weights \c w and components \c Coms
[224]100        //!By default Coms are copied inside. Parameter \c copy can be set to false if Coms live externally. Use method ownComs() if Coms should be destroyed by the destructor.
[270]101        void set_parameters ( const vec &w, const Array<epdf*> &Coms, bool copy=false );
[107]102
[162]103        vec sample() const;
104        vec mean() const {
[270]105                int i; vec mu = zeros ( dim);
[162]106                for ( i = 0;i < w.length();i++ ) {mu += w ( i ) * Coms ( i )->mean(); }
107                return mu;
108        }
[229]109        vec variance() const {
110                //non-central moment
[270]111                vec mom2 = zeros(dim);
[229]112                for ( int i = 0;i < w.length();i++ ) {mom2 += w ( i ) * pow(Coms ( i )->mean(),2); }
113                //central moment
114                return mom2-pow(mean(),2);
115        }
[211]116        double evallog ( const vec &val ) const {
[162]117                int i;
118                double sum = 0.0;
[211]119                for ( i = 0;i < w.length();i++ ) {sum += w ( i ) * exp ( Coms ( i )->evallog ( val ) );}
[214]120                if (sum==0.0){sum=std::numeric_limits<double>::epsilon();}
121                double tmp=log ( sum );
122                it_assert_debug(std::isfinite(tmp),"Infinite");
123                return tmp;
[162]124        };
[211]125        vec evallog_m ( const mat &Val ) const {
[193]126                vec x=zeros ( Val.cols() );
[192]127                for ( int i = 0; i < w.length(); i++ ) {
[211]128                        x+= w ( i ) *exp ( Coms ( i )->evallog_m ( Val ) );
[182]129                }
[192]130                return log ( x );
[182]131        };
[214]132        //! Auxiliary function that returns pdflog for each component
[211]133        mat evallog_M ( const mat &Val ) const {
[192]134                mat X ( w.length(), Val.cols() );
135                for ( int i = 0; i < w.length(); i++ ) {
[211]136                        X.set_row ( i, w ( i ) *exp ( Coms ( i )->evallog_m ( Val ) ) );
[189]137                }
138                return X;
139        };
[107]140
[182]141        emix* marginal ( const RV &rv ) const;
142        mratio* condition ( const RV &rv ) const; //why not mratio!!
143
[107]144//Access methods
[162]145        //! returns a pointer to the internal mean value. Use with Care!
146        vec& _w() {return w;}
[181]147        virtual ~emix() {if ( destroyComs ) {for ( int i=0;i<Coms.length();i++ ) {delete Coms ( i );}}}
[178]148        //! Auxiliary function for taking ownership of the Coms()
[181]149        void ownComs() {destroyComs=true;}
[204]150
[193]151        //!access function
[204]152        epdf* _Coms ( int i ) {return Coms ( i );}
[107]153};
154
[115]155/*! \brief Chain rule decomposition of epdf
156
[145]157Probability density in the form of Chain-rule decomposition:
158\[
159f(x_1,x_2,x_3) = f(x_1|x_2,x_3)f(x_2,x_3)f(x_3)
160\]
161Note that
[115]162*/
[175]163class mprod: public compositepdf, public mpdf {
[162]164protected:
[181]165        //! pointers to epdfs - shortcut to mpdfs()._epdf()
[162]166        Array<epdf*> epdfs;
[192]167        //! Data link for each mpdfs
168        Array<datalink_m2m*> dls;
[270]169        //! dummy ep
170        epdf dummy;
[162]171public:
[168]172        /*!\brief Constructor from list of mFacs,
[165]173        */
[270]174        mprod ( Array<mpdf*> mFacs ) : compositepdf ( mFacs ), mpdf (), epdfs ( n ), dls ( n ) {
175                ep=&dummy;
176                RV rv=getrv(true);
177                set_rv(rv);dummy.set_parameters(rv._dsize());
178                setrvc ( ep->_rv(),rvc );
[192]179                // rv and rvc established = > we can link them with mpdfs
[181]180                for ( int i = 0;i < n;i++ ) {
[270]181                        dls ( i ) = new datalink_m2m ( mpdfs ( i )->_rv(), mpdfs ( i )->_rvc(), _rv(), _rvc() );
[181]182                }
183
184                for ( int i=0;i<n;i++ ) {
185                        epdfs ( i ) =& ( mpdfs ( i )->_epdf() );
186                }
[175]187        };
[124]188
[211]189        double evallogcond ( const vec &val, const vec &cond ) {
[162]190                int i;
[270]191                double res = 0.0;
[182]192                for ( i = n - 1;i >= 0;i-- ) {
[193]193                        /*                      if ( mpdfs(i)->_rvc().count() >0) {
194                                                        mpdfs ( i )->condition ( dls ( i )->get_cond ( val,cond ) );
195                                                }
196                                                // add logarithms
[270]197                                                res += epdfs ( i )->evallog ( dls ( i )->pushdown ( val ) );*/
198                        res += mpdfs ( i )->evallogcond (
199                                   dls ( i )->pushdown ( val ),
[204]200                                   dls ( i )->get_cond ( val, cond )
201                               );
[145]202                }
[193]203                return res;
[162]204        }
[270]205        //TODO smarter...
206        vec samplecond ( const vec &cond ) {
[192]207                //! Ugly hack to help to discover if mpfs are not in proper order. Correct solution = check that explicitely.
[270]208                vec smp= std::numeric_limits<double>::infinity() * ones ( ep->dimension() );
[165]209                vec smpi;
[192]210                // Hard assumption here!!! We are going backwards, to assure that samples that are needed from smp are already generated!
[162]211                for ( int i = ( n - 1 );i >= 0;i-- ) {
[270]212                        if ( mpdfs ( i )->dimensionc() ) {
[192]213                                mpdfs ( i )->condition ( dls ( i )->get_cond ( smp ,cond ) ); // smp is val here!!
[145]214                        }
[165]215                        smpi = epdfs ( i )->sample();
[162]216                        // copy contribution of this pdf into smp
[270]217                        dls ( i )->pushup ( smp, smpi );
[165]218                        // add ith likelihood contribution
[145]219                }
[162]220                return smp;
221        }
[270]222        mat samplecond ( const vec &cond,  int N ) {
223                mat Smp ( dimension(),N );
224                for ( int i=0;i<N;i++ ) {Smp.set_col ( i,samplecond ( cond ) );}
[162]225                return Smp;
226        }
227
228        ~mprod() {};
[107]229};
230
[168]231//! Product of independent epdfs. For dependent pdfs, use mprod.
232class eprod: public epdf {
233protected:
234        //! Components (epdfs)
[170]235        Array<const epdf*> epdfs;
[168]236        //! Array of indeces
[270]237        Array<datalink*> dls;
[168]238public:
[270]239        eprod ( const Array<const epdf*> epdfs0 ) : epdf (  ),epdfs ( epdfs0 ),dls ( epdfs.length() ) {
[168]240                bool independent=true;
241                for ( int i=0;i<epdfs.length();i++ ) {
242                        independent=rv.add ( epdfs ( i )->_rv() );
243                        it_assert_debug ( independent==true, "eprod:: given components are not independent ." );
244                }
[204]245                for ( int i=0;i<epdfs.length();i++ ) {
[270]246                        dls ( i ) = new datalink ( epdfs ( i )->_rv() , rv );
[204]247                }
[168]248        }
249
250        vec mean() const {
[270]251                vec tmp ( dim );
[168]252                for ( int i=0;i<epdfs.length();i++ ) {
253                        vec pom = epdfs ( i )->mean();
[270]254                        dls ( i )->pushup ( tmp, pom );
[168]255                }
256                return tmp;
257        }
[229]258        vec variance() const {
[270]259                vec tmp ( dim ); //second moment
[229]260                for ( int i=0;i<epdfs.length();i++ ) {
261                        vec pom = epdfs ( i )->mean();
[270]262                        dls ( i )->pushup ( tmp, pow(pom,2) );
[229]263                }
264                return tmp-pow(mean(),2);
265        }
[168]266        vec sample() const {
[270]267                vec tmp ( dim );
[168]268                for ( int i=0;i<epdfs.length();i++ ) {
269                        vec pom = epdfs ( i )->sample();
[270]270                        dls ( i )->pushup ( tmp, pom );
[168]271                }
272                return tmp;
273        }
[211]274        double evallog ( const vec &val ) const {
[168]275                double tmp=0;
276                for ( int i=0;i<epdfs.length();i++ ) {
[270]277                        tmp+=epdfs ( i )->evallog ( dls ( i )->pushdown ( val ) );
[168]278                }
[214]279                it_assert_debug(std::isfinite(tmp),"Infinite");
[168]280                return tmp;
281        }
[170]282        //!access function
[181]283        const epdf* operator () ( int i ) const {it_assert_debug ( i<epdfs.length(),"wrong index" );return epdfs ( i );}
[204]284
[193]285        //!Destructor
[204]286        ~eprod() {for ( int i=0;i<epdfs.length();i++ ) {delete dls ( i );}}
[168]287};
288
289
[145]290/*! \brief Mixture of mpdfs with constant weights, all mpdfs are of equal type
[124]291
292*/
[145]293class mmix : public mpdf {
[162]294protected:
295        //! Component (epdfs)
296        Array<mpdf*> Coms;
297        //!Internal epdf
298        emix Epdf;
299public:
300        //!Default constructor
[270]301        mmix ( ) : mpdf ( ), Epdf () {ep = &Epdf;};
[162]302        //! Set weights \c w and components \c R
303        void set_parameters ( const vec &w, const Array<mpdf*> &Coms ) {
304                Array<epdf*> Eps ( Coms.length() );
[124]305
[162]306                for ( int i = 0;i < Coms.length();i++ ) {
307                        Eps ( i ) = & ( Coms ( i )->_epdf() );
308                }
309                Epdf.set_parameters ( w, Eps );
310        };
[124]311
[162]312        void condition ( const vec &cond ) {
313                for ( int i = 0;i < Coms.length();i++ ) {Coms ( i )->condition ( cond );}
314        };
[124]315};
[182]316
[254]317}
[107]318#endif //MX_H
Note: See TracBrowser for help on using the browser.