root/bdm/stat/emix.h @ 271

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

Next major revision

  • 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
20namespace bdm{
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 ( ), dl ( rv,rvc,nom0->_rv() ) {
50                ep->set_rv(_rv());
51                set_rvc(nom0->_rv().subt ( rv ) );
52                if ( copy ) {
53//                      nom = nom0->_copy_();
54                        it_error ( "todo" );
55                        destroynom=true;
56                }
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        };
64        double evallogcond ( const vec &val, const vec &cond ) {
65                double tmp;
66                vec nom_val ( ep->dimension() + dimc );
67                dl.pushup_cond ( nom_val,val,cond );
68                tmp = exp ( nom->evallog ( nom_val ) - den->evallog ( cond ) );
69                it_assert_debug(std::isfinite(tmp),"Infinite value");
70                return tmp;
71        }
72        //! Object takes ownership of nom and will destroy it
73        void ownnom() {destroynom=true;}
74        //! Default destructor
75        ~mratio() {delete den; if ( destroynom ) {delete nom;}}
76};
77
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*/
88class emix : public epdf {
89protected:
90        //! weights of the components
91        vec w;
92        //! Component (epdfs)
93        Array<epdf*> Coms;
94        //!Flag if owning Coms
95        bool destroyComs;
96public:
97        //!Default constructor
98        emix (  ) : epdf ( ) {};
99        //! Set weights \c w and components \c Coms
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.
101        void set_parameters ( const vec &w, const Array<epdf*> &Coms, bool copy=false );
102
103        vec sample() const;
104        vec mean() const {
105                int i; vec mu = zeros ( dim);
106                for ( i = 0;i < w.length();i++ ) {mu += w ( i ) * Coms ( i )->mean(); }
107                return mu;
108        }
109        vec variance() const {
110                //non-central moment
111                vec mom2 = zeros(dim);
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        }
116        double evallog ( const vec &val ) const {
117                int i;
118                double sum = 0.0;
119                for ( i = 0;i < w.length();i++ ) {sum += w ( i ) * exp ( Coms ( i )->evallog ( val ) );}
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;
124        };
125        vec evallog_m ( const mat &Val ) const {
126                vec x=zeros ( Val.cols() );
127                for ( int i = 0; i < w.length(); i++ ) {
128                        x+= w ( i ) *exp ( Coms ( i )->evallog_m ( Val ) );
129                }
130                return log ( x );
131        };
132        //! Auxiliary function that returns pdflog for each component
133        mat evallog_M ( const mat &Val ) const {
134                mat X ( w.length(), Val.cols() );
135                for ( int i = 0; i < w.length(); i++ ) {
136                        X.set_row ( i, w ( i ) *exp ( Coms ( i )->evallog_m ( Val ) ) );
137                }
138                return X;
139        };
140
141        emix* marginal ( const RV &rv ) const;
142        mratio* condition ( const RV &rv ) const; //why not mratio!!
143
144//Access methods
145        //! returns a pointer to the internal mean value. Use with Care!
146        vec& _w() {return w;}
147        virtual ~emix() {if ( destroyComs ) {for ( int i=0;i<Coms.length();i++ ) {delete Coms ( i );}}}
148        //! Auxiliary function for taking ownership of the Coms()
149        void ownComs() {destroyComs=true;}
150
151        //!access function
152        epdf* _Coms ( int i ) {return Coms ( i );}
153};
154
155/*! \brief Chain rule decomposition of epdf
156
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
162*/
163class mprod: public compositepdf, public mpdf {
164protected:
165        //! pointers to epdfs - shortcut to mpdfs().posterior()
166        Array<epdf*> epdfs;
167        //! Data link for each mpdfs
168        Array<datalink_m2m*> dls;
169        //! dummy ep
170        epdf dummy;
171public:
172        /*!\brief Constructor from list of mFacs,
173        */
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 );
179                // rv and rvc established = > we can link them with mpdfs
180                for ( int i = 0;i < n;i++ ) {
181                        dls ( i ) = new datalink_m2m ( mpdfs ( i )->_rv(), mpdfs ( i )->_rvc(), _rv(), _rvc() );
182                }
183
184                for ( int i=0;i<n;i++ ) {
185                        epdfs ( i ) =& ( mpdfs ( i )->_epdf() );
186                }
187        };
188
189        double evallogcond ( const vec &val, const vec &cond ) {
190                int i;
191                double res = 0.0;
192                for ( i = n - 1;i >= 0;i-- ) {
193                        /*                      if ( mpdfs(i)->_rvc().count() >0) {
194                                                        mpdfs ( i )->condition ( dls ( i )->get_cond ( val,cond ) );
195                                                }
196                                                // add logarithms
197                                                res += epdfs ( i )->evallog ( dls ( i )->pushdown ( val ) );*/
198                        res += mpdfs ( i )->evallogcond (
199                                   dls ( i )->pushdown ( val ),
200                                   dls ( i )->get_cond ( val, cond )
201                               );
202                }
203                return res;
204        }
205        //TODO smarter...
206        vec samplecond ( const vec &cond ) {
207                //! Ugly hack to help to discover if mpfs are not in proper order. Correct solution = check that explicitely.
208                vec smp= std::numeric_limits<double>::infinity() * ones ( ep->dimension() );
209                vec smpi;
210                // Hard assumption here!!! We are going backwards, to assure that samples that are needed from smp are already generated!
211                for ( int i = ( n - 1 );i >= 0;i-- ) {
212                        if ( mpdfs ( i )->dimensionc() ) {
213                                mpdfs ( i )->condition ( dls ( i )->get_cond ( smp ,cond ) ); // smp is val here!!
214                        }
215                        smpi = epdfs ( i )->sample();
216                        // copy contribution of this pdf into smp
217                        dls ( i )->pushup ( smp, smpi );
218                        // add ith likelihood contribution
219                }
220                return smp;
221        }
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 ) );}
225                return Smp;
226        }
227
228        ~mprod() {};
229};
230
231//! Product of independent epdfs. For dependent pdfs, use mprod.
232class eprod: public epdf {
233protected:
234        //! Components (epdfs)
235        Array<const epdf*> epdfs;
236        //! Array of indeces
237        Array<datalink*> dls;
238public:
239        eprod ( const Array<const epdf*> epdfs0 ) : epdf (  ),epdfs ( epdfs0 ),dls ( epdfs.length() ) {
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                }
245                for ( int i=0;i<epdfs.length();i++ ) {
246                        dls ( i ) = new datalink ( epdfs ( i )->_rv() , rv );
247                }
248        }
249
250        vec mean() const {
251                vec tmp ( dim );
252                for ( int i=0;i<epdfs.length();i++ ) {
253                        vec pom = epdfs ( i )->mean();
254                        dls ( i )->pushup ( tmp, pom );
255                }
256                return tmp;
257        }
258        vec variance() const {
259                vec tmp ( dim ); //second moment
260                for ( int i=0;i<epdfs.length();i++ ) {
261                        vec pom = epdfs ( i )->mean();
262                        dls ( i )->pushup ( tmp, pow(pom,2) );
263                }
264                return tmp-pow(mean(),2);
265        }
266        vec sample() const {
267                vec tmp ( dim );
268                for ( int i=0;i<epdfs.length();i++ ) {
269                        vec pom = epdfs ( i )->sample();
270                        dls ( i )->pushup ( tmp, pom );
271                }
272                return tmp;
273        }
274        double evallog ( const vec &val ) const {
275                double tmp=0;
276                for ( int i=0;i<epdfs.length();i++ ) {
277                        tmp+=epdfs ( i )->evallog ( dls ( i )->pushdown ( val ) );
278                }
279                it_assert_debug(std::isfinite(tmp),"Infinite");
280                return tmp;
281        }
282        //!access function
283        const epdf* operator () ( int i ) const {it_assert_debug ( i<epdfs.length(),"wrong index" );return epdfs ( i );}
284
285        //!Destructor
286        ~eprod() {for ( int i=0;i<epdfs.length();i++ ) {delete dls ( i );}}
287};
288
289
290/*! \brief Mixture of mpdfs with constant weights, all mpdfs are of equal type
291
292*/
293class mmix : public mpdf {
294protected:
295        //! Component (epdfs)
296        Array<mpdf*> Coms;
297        //!Internal epdf
298        emix Epdf;
299public:
300        //!Default constructor
301        mmix ( ) : mpdf ( ), Epdf () {ep = &Epdf;};
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() );
305
306                for ( int i = 0;i < Coms.length();i++ ) {
307                        Eps ( i ) = & ( Coms ( i )->_epdf() );
308                }
309                Epdf.set_parameters ( w, Eps );
310        };
311
312        void condition ( const vec &cond ) {
313                for ( int i = 0;i < Coms.length();i++ ) {Coms ( i )->condition ( cond );}
314        };
315};
316
317}
318#endif //MX_H
Note: See TracBrowser for help on using the browser.