root/bdm/stat/emix.h @ 192

Revision 192, 7.7 kB (checked in by smidl, 16 years ago)

modification of datalinks and switch mprod and merger to use them

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