root/bdm/stat/emix.h @ 182

Revision 182, 7.9 kB (checked in by smidl, 17 years ago)

compilation error!

  • 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
20using namespace itpp;
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
34At present the only supported operation is evalcond().
35 */
36class mratio: public mpdf {
37        protected:
38        //! Nominator in the form of mpdf
39                const epdf* nom;
40        //!Denominator in the form of epdf
41                epdf* den;
42        //!flag for destructor
43                bool destroynom;
44        public:
45        //!Default constructor. By default, the given epdf is not copied!
46        //! It is assumed that this function will be used only temporarily.
47                mratio(const epdf* nom0, const RV &rv, bool copy=false):mpdf(rv,RV()){
48                        if (copy){
49//                      nom = nom0->_copy_();
50                                destroynom=true;
51                        } else {
52                                nom = nom0;
53                                destroynom = false;
54                        }
55                        rvc = nom->_rv().subt(rv);
56                        it_assert_debug(rvc.length()>0,"Makes no sense to use this object!");
57                        den = nom->marginal(rvc);
58                };
59                double evalcond(const vec &val, const vec &cond) const {
60                        return exp(nom->evalpdflog(concat(val,cond)) - den->evalpdflog(cond));
61                }
62        //! Object takes ownership of nom and will destroy it
63                void ownnom(){destroynom=true;}
64        //! Default destructor
65                ~mratio(){delete den; if (destroynom) {delete nom;}}
66};
67
[107]68/*!
69* \brief Mixture of epdfs
70
71Density function:
72\f[
73f(x) = \sum_{i=1}^{n} w_{i} f_i(x), \quad \sum_{i=1}^n w_i = 1.
74\f]
75where \f$f_i(x)\f$ is any density on random variable \f$x\f$, called \a component,
76
77*/
[145]78class emix : public epdf {
[162]79protected:
80        //! weights of the components
81        vec w;
82        //! Component (epdfs)
83        Array<epdf*> Coms;
[178]84        //!Flag if owning Coms
85        bool destroyComs;
[162]86public:
87        //!Default constructor
[181]88        emix ( const RV &rv ) : epdf ( rv ) {};
[182]89        //! Set weights \c w and components \c Coms
90        //!By default Coms are copied inside. \param copy can be set to false if Coms live externally. Use method ownComs() if Coms should be destroyed by the destructor.
[178]91        void set_parameters ( const vec &w, const Array<epdf*> &Coms, bool copy=true );
[107]92
[162]93        vec sample() const;
94        vec mean() const {
95                int i; vec mu = zeros ( rv.count() );
96                for ( i = 0;i < w.length();i++ ) {mu += w ( i ) * Coms ( i )->mean(); }
97                return mu;
98        }
99        double evalpdflog ( const vec &val ) const {
100                int i;
101                double sum = 0.0;
102                for ( i = 0;i < w.length();i++ ) {sum += w ( i ) * Coms ( i )->evalpdflog ( val );}
103                return log ( sum );
104        };
[182]105        vec evalpdflog_m ( const mat &Val ) const {
106                vec x=ones(Val.cols());
107                vec y(Val.cols());
108                for (int i = 0; i < w.length(); i++ ) {
109                        y = w ( i )*exp(Coms ( i )->evalpdflog_m ( Val ) );
110                        elem_mult_inplace(y,x); //result is in x
111                }
112                return log(x);
113        };
[107]114
[182]115        emix* marginal ( const RV &rv ) const;
116        mratio* condition ( const RV &rv ) const; //why not mratio!!
117
[107]118//Access methods
[162]119        //! returns a pointer to the internal mean value. Use with Care!
120        vec& _w() {return w;}
[181]121        virtual ~emix() {if ( destroyComs ) {for ( int i=0;i<Coms.length();i++ ) {delete Coms ( i );}}}
[178]122        //! Auxiliary function for taking ownership of the Coms()
[181]123        void ownComs() {destroyComs=true;}
[107]124};
125
[115]126/*! \brief Chain rule decomposition of epdf
127
[145]128Probability density in the form of Chain-rule decomposition:
129\[
130f(x_1,x_2,x_3) = f(x_1|x_2,x_3)f(x_2,x_3)f(x_3)
131\]
132Note that
[115]133*/
[175]134class mprod: public compositepdf, public mpdf {
[162]135protected:
[181]136        //! pointers to epdfs - shortcut to mpdfs()._epdf()
[162]137        Array<epdf*> epdfs;
138        //! Indeces of rvc in common rvc
[182]139        Array<ivec> irvcs_rvc;
[181]140        //! Indeces of common rvc in rvcs
[182]141        Array<ivec> irvc_rvcs;
[162]142public:
[168]143        /*!\brief Constructor from list of mFacs,
[165]144        */
[182]145        mprod ( Array<mpdf*> mFacs ) : compositepdf ( mFacs ), mpdf ( getrv ( true ),RV() ), epdfs ( n ), irvcs_rvc ( n ), irvc_rvcs ( n ) {
[181]146                setrvc ( rv,rvc );
147                setindices ( rv );
148                for ( int i = 0;i < n;i++ ) {
[182]149                        // establish link between rvc and rvcs
150                        rvc.dataind ( mpdfs ( i )->_rvc(), irvc_rvcs ( i ), irvcs_rvc ( i ) );
[181]151                }
152
153                for ( int i=0;i<n;i++ ) {
154                        epdfs ( i ) =& ( mpdfs ( i )->_epdf() );
155                }
[175]156        };
[124]157
[182]158        double evalcond ( const vec &val, const vec &cond ) {
[162]159                int i;
160                double res = 0.0;
[181]161                vec condi;
[182]162                for ( i = n - 1;i >= 0;i-- ) {
163                        if ( ( irvcs_rvc ( i ).length() > 0 ) || ( irvcs_rv ( i ).length() > 0 ) ) {
164                                condi = zeros ( irvcs_rvc ( i ).length() +irvcs_rv ( i ).length() );
[181]165                                //copy part of the rvc into condi
[182]166                                set_subvector ( condi, irvcs_rvc ( i ), get_vec ( cond,irvc_rvcs ( i ) ) );
[181]167                                //copy part of the rv into condi
[182]168                                set_subvector ( condi, irvcs_rv ( i ), get_vec ( val,irv_rvcs ( i ) ) );
[181]169                                mpdfs ( i )->condition ( condi );
170                        }
[162]171                        // add logarithms
[175]172                        res += epdfs ( i )->evalpdflog ( val ( rvsinrv ( i ) ) );
[145]173                }
[182]174                return exp ( res );
[162]175        }
176        vec samplecond ( const vec &cond, double &ll ) {
177                vec smp=zeros ( rv.count() );
178                vec condi;
[165]179                vec smpi;
180                ll = 0;
[162]181                for ( int i = ( n - 1 );i >= 0;i-- ) {
[182]182                        if ( ( irvcs_rvc ( i ).length() > 0 ) || ( irvcs_rv ( i ).length() > 0 ) ) {
183                                condi = zeros ( irvcs_rv ( i ).length() + irvcs_rvc ( i ).length() );
[162]184                                // copy data in condition
[182]185                                set_subvector ( condi,irvcs_rvc ( i ), get_vec ( cond, irvc_rvcs ( i ) ) );
[162]186                                // copy data in already generated sample
[182]187                                set_subvector ( condi,irvcs_rv ( i ), get_vec ( smp,irv_rvcs ( i ) ) );
[162]188
189                                mpdfs ( i )->condition ( condi );
[145]190                        }
[165]191                        smpi = epdfs ( i )->sample();
[162]192                        // copy contribution of this pdf into smp
[175]193                        set_subvector ( smp,rvsinrv ( i ), smpi );
[165]194                        // add ith likelihood contribution
[168]195                        ll+=epdfs ( i )->evalpdflog ( smpi );
[145]196                }
[162]197                return smp;
198        }
199        mat samplecond ( const vec &cond, vec &ll, int N ) {
[168]200                mat Smp ( rv.count(),N );
201                for ( int i=0;i<N;i++ ) {Smp.set_col ( i,samplecond ( cond,ll ( i ) ) );}
[162]202                return Smp;
203        }
204
205        ~mprod() {};
[107]206};
207
[168]208//! Product of independent epdfs. For dependent pdfs, use mprod.
209class eprod: public epdf {
210protected:
211        //! Components (epdfs)
[170]212        Array<const epdf*> epdfs;
[168]213        //! Array of indeces
214        Array<ivec> rvinds;
215public:
[170]216        eprod ( const Array<const epdf*> epdfs0 ) : epdf ( RV() ),epdfs ( epdfs0 ),rvinds ( epdfs.length() ) {
[168]217                bool independent=true;
218                for ( int i=0;i<epdfs.length();i++ ) {
219                        independent=rv.add ( epdfs ( i )->_rv() );
220                        it_assert_debug ( independent==true, "eprod:: given components are not independent ." );
221                        rvinds ( i ) = ( epdfs ( i )->_rv() ).dataind ( rv );
222                }
223        }
224
225        vec mean() const {
226                vec tmp ( rv.count() );
227                for ( int i=0;i<epdfs.length();i++ ) {
228                        vec pom = epdfs ( i )->mean();
229                        set_subvector ( tmp,rvinds ( i ), pom );
230                }
231                return tmp;
232        }
233        vec sample() const {
234                vec tmp ( rv.count() );
235                for ( int i=0;i<epdfs.length();i++ ) {
236                        vec pom = epdfs ( i )->sample();
237                        set_subvector ( tmp,rvinds ( i ), pom );
238                }
239                return tmp;
240        }
241        double evalpdflog ( const vec &val ) const {
242                double tmp=0;
243                for ( int i=0;i<epdfs.length();i++ ) {
[181]244                        tmp+=epdfs ( i )->evalpdflog ( val ( rvinds ( i ) ) );
[168]245                }
246                return tmp;
247        }
[170]248        //!access function
[181]249        const epdf* operator () ( int i ) const {it_assert_debug ( i<epdfs.length(),"wrong index" );return epdfs ( i );}
[168]250};
251
252
[145]253/*! \brief Mixture of mpdfs with constant weights, all mpdfs are of equal type
[124]254
255*/
[145]256class mmix : public mpdf {
[162]257protected:
258        //! Component (epdfs)
259        Array<mpdf*> Coms;
260        //!Internal epdf
261        emix Epdf;
262public:
263        //!Default constructor
264        mmix ( RV &rv, RV &rvc ) : mpdf ( rv, rvc ), Epdf ( rv ) {ep = &Epdf;};
265        //! Set weights \c w and components \c R
266        void set_parameters ( const vec &w, const Array<mpdf*> &Coms ) {
267                Array<epdf*> Eps ( Coms.length() );
[124]268
[162]269                for ( int i = 0;i < Coms.length();i++ ) {
270                        Eps ( i ) = & ( Coms ( i )->_epdf() );
271                }
272                Epdf.set_parameters ( w, Eps );
273        };
[124]274
[162]275        void condition ( const vec &cond ) {
276                for ( int i = 0;i < Coms.length();i++ ) {Coms ( i )->condition ( cond );}
277        };
[124]278};
[182]279
[107]280#endif //MX_H
Note: See TracBrowser for help on using the browser.