root/bdm/stat/emix.h @ 211

Revision 211, 8.1 kB (checked in by smidl, 16 years ago)

prejmenovani evalpdflog a evalcond

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