root/library/bdm/stat/emix.h @ 896

Revision 896, 9.1 kB (checked in by mido, 14 years ago)

cleanup of MemDS and its descendants
bdmtoolbox/CMakeLists.txt slightly changed to avoid unnecessary MEX condition
"indeces" replaced by "indices"

  • 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
[394]13#ifndef EMIX_H
14#define EMIX_H
[107]15
[477]16#define LOG2  0.69314718055995
[333]17
[461]18#include "../shared_ptr.h"
[384]19#include "exp_family.h"
[107]20
[286]21namespace bdm {
[107]22
[182]23//this comes first because it is used inside emix!
24
25/*! \brief Class representing ratio of two densities
26which arise e.g. by applying the Bayes rule.
27It represents density in the form:
28\f[
29f(rv|rvc) = \frac{f(rv,rvc)}{f(rvc)}
30\f]
31where \f$ f(rvc) = \int f(rv,rvc) d\ rv \f$.
32
33In particular this type of arise by conditioning of a mixture model.
34
[211]35At present the only supported operation is evallogcond().
[182]36 */
[693]37class mratio: public pdf {
[192]38protected:
[693]39        //! Nominator in the form of pdf
[192]40        const epdf* nom;
[504]41
[182]42        //!Denominator in the form of epdf
[504]43        shared_ptr<epdf> den;
44
[192]45        //!flag for destructor
46        bool destroynom;
[193]47        //!datalink between conditional and nom
48        datalink_m2e dl;
[192]49public:
50        //!Default constructor. By default, the given epdf is not copied!
[182]51        //! It is assumed that this function will be used only temporarily.
[693]52        mratio ( const epdf* nom0, const RV &rv, bool copy = false ) : pdf ( ), dl ( ) {
[286]53                // adjust rv and rvc
[675]54
[766]55                set_rv ( rv ); 
[675]56                dim = rv._dsize();
57
[286]58                rvc = nom0->_rv().subt ( rv );
59                dimc = rvc._dsize();
[737]60
[286]61                //prepare data structures
[477]62                if ( copy ) {
[565]63                        bdm_error ( "todo" );
64                        // destroynom = true;
[477]65                } else {
66                        nom = nom0;
67                        destroynom = false;
68                }
[565]69                bdm_assert_debug ( rvc.length() > 0, "Makes no sense to use this object!" );
[477]70
[286]71                // build denominator
[192]72                den = nom->marginal ( rvc );
[477]73                dl.set_connection ( rv, rvc, nom0->_rv() );
[192]74        };
[675]75
[211]76        double evallogcond ( const vec &val, const vec &cond ) {
[214]77                double tmp;
[487]78                vec nom_val ( dimension() + dimc );
[477]79                dl.pushup_cond ( nom_val, val, cond );
[214]80                tmp = exp ( nom->evallog ( nom_val ) - den->evallog ( cond ) );
81                return tmp;
[192]82        }
[766]83
84        //! Returns a sample from the density conditioned on \c cond, \f$x \sim epdf(rv|cond)\f$. \param cond is numeric value of \c rv
85        virtual vec samplecond ( const vec &cond ) NOT_IMPLEMENTED(0);
86
[182]87        //! Object takes ownership of nom and will destroy it
[477]88        void ownnom() {
89                destroynom = true;
90        }
[182]91        //! Default destructor
[477]92        ~mratio() {
93                if ( destroynom ) {
94                        delete nom;
95                }
96        }
[550]97
[766]98
[550]99private:
100        // not implemented
101        mratio ( const mratio & );
[737]102        mratio &operator= ( const mratio & );
[182]103};
104
[886]105class emix; //forward
106
107/*! Base class (Interface) for mixtures
108*/
109class emix_base : public epdf {
110        protected:
111        //! reference to vector of weights
112        vec &w;
113        //! function returning ith component
114        virtual const epdf * component(const int &i) const=0;
115       
116        virtual int no_coms() const=0;
117       
118        public:
119               
120                emix_base(vec &w0): w(w0){}
121               
122                void validate ();
123               
124                vec sample() const;
125               
126                vec mean() const;
127               
128                vec variance() const;
129               
130                double evallog ( const vec &val ) const;
131               
132                vec evallog_mat ( const mat &Val ) const;
133               
134                //! Auxiliary function that returns pdflog for each component
135                mat evallog_coms ( const mat &Val ) const;
136               
137                shared_ptr<epdf> marginal ( const RV &rv ) const;
138                //! Update already existing marginal density  \c target
139                void marginal ( const RV &rv, emix &target ) const;
140                shared_ptr<pdf> condition ( const RV &rv ) const;
141               
142                //Access methods       
143                //! returns a reference to the internal weights. Use with Care!
144                vec& _w() {
145                        return w;
146                }
147               
148                const vec& _w() const {
149                        return w;
150                }
151                //!access
152                const epdf* _com(int i) const {return component(i);}
153               
154};
155
[107]156/*!
157* \brief Mixture of epdfs
158
159Density function:
160\f[
161f(x) = \sum_{i=1}^{n} w_{i} f_i(x), \quad \sum_{i=1}^n w_i = 1.
162\f]
163where \f$f_i(x)\f$ is any density on random variable \f$x\f$, called \a component,
164
165*/
[886]166class emix : public emix_base {
[162]167protected:
168        //! weights of the components
[886]169        vec weights;
[559]170
[162]171        //! Component (epdfs)
[504]172        Array<shared_ptr<epdf> > Coms;
173
[162]174public:
[559]175        //! Default constructor
[886]176        emix ( ) : emix_base ( weights) { }
177       
178        const epdf* component(const int &i) const {return Coms(i).get();}
179        void validate();
180       
[559]181
[886]182        int no_coms() const {return Coms.length(); }
[107]183
[713]184        //! Load from structure with elements:
185        //!  \code
186        //! { class='emix';
187        //!   pdfs = (..., ...);     // list of pdfs in the mixture
188        //!   weights = ( 0.5, 0.5 ); // weights of pdfs in the mixture
189        //! }
190        //! \endcode
191        //!@}
[766]192        void from_setting ( const Setting &set );
[107]193
[477]194        void set_rv ( const RV &rv ) {
[886]195                epdf::set_rv ( rv );
196                for ( int i = 0; i < no_coms(); i++ ) {
197                        Coms( i )->set_rv ( rv );
[477]198                }
[333]199        }
[886]200       
201        Array<shared_ptr<epdf> >& _Coms ( ) {
202                        return Coms;
203                }
[333]204};
[886]205SHAREDPTR ( emix );
206UIREGISTER ( emix );
[333]207
[886]208
[115]209/*! \brief Chain rule decomposition of epdf
210
[145]211Probability density in the form of Chain-rule decomposition:
212\[
213f(x_1,x_2,x_3) = f(x_1|x_2,x_3)f(x_2,x_3)f(x_3)
214\]
215Note that
[115]216*/
[693]217class mprod: public pdf {
[507]218private:
[693]219        Array<shared_ptr<pdf> > pdfs;
[507]220
[693]221        //! Data link for each pdfs
[546]222        Array<shared_ptr<datalink_m2m> > dls;
[461]223
[162]224public:
[507]225        //! \brief Default constructor
226        mprod() { }
227
228        /*!\brief Constructor from list of mFacs
[165]229        */
[693]230        mprod ( const Array<shared_ptr<pdf> > &mFacs ) {
[477]231                set_elements ( mFacs );
[461]232        }
[693]233        //! Set internal \c pdfs from given values
[737]234        void set_elements ( const Array<shared_ptr<pdf> > &mFacs );
[477]235
[739]236        double evallogcond ( const vec &val, const vec &cond );
[395]237
[739]238        vec evallogcond_mat ( const mat &Dt, const vec &cond );
[395]239
[739]240        vec evallogcond_mat ( const Array<vec> &Dt, const vec &cond );
241
[270]242        //TODO smarter...
243        vec samplecond ( const vec &cond ) {
[477]244                //! Ugly hack to help to discover if mpfs are not in proper order. Correct solution = check that explicitely.
[487]245                vec smp = std::numeric_limits<double>::infinity() * ones ( dimension() );
[165]246                vec smpi;
[192]247                // Hard assumption here!!! We are going backwards, to assure that samples that are needed from smp are already generated!
[693]248                for ( int i = ( pdfs.length() - 1 ); i >= 0; i-- ) {
249                        // generate contribution of this pdf
[737]250                        smpi = pdfs ( i )->samplecond ( dls ( i )->get_cond ( smp , cond ) );
[162]251                        // copy contribution of this pdf into smp
[270]252                        dls ( i )->pushup ( smp, smpi );
[145]253                }
[162]254                return smp;
255        }
256
[395]257        //! Load from structure with elements:
258        //!  \code
259        //! { class='mprod';
[693]260        //!   pdfs = (..., ...);     // list of pdfs in the order of chain rule
[395]261        //! }
262        //! \endcode
263        //!@}
[477]264        void from_setting ( const Setting &set ) {
[766]265                Array<shared_ptr<pdf> > temp_array; 
266                UI::get ( temp_array, set, "pdfs", UI::compulsory );
267                set_elements ( temp_array );
[395]268        }
[107]269};
[477]270UIREGISTER ( mprod );
[529]271SHAREDPTR ( mprod );
[107]272
[886]273
[168]274//! Product of independent epdfs. For dependent pdfs, use mprod.
[886]275class eprod_base: public epdf {
[168]276protected:
[896]277        //! Array of indices
[270]278        Array<datalink*> dls;
[886]279        //! interface for a factor
280        virtual const epdf* factor(int i) const NOT_IMPLEMENTED(NULL); 
281        //!number of factors
282        virtual const int no_factors() const =0;
[168]283public:
[536]284        //! Default constructor
[886]285        eprod_base () :  dls (0) {};
[737]286        //! Set internal
[886]287        vec mean() const;
288
289        vec variance() const;
290
291        vec sample() const;
292
293        double evallog ( const vec &val ) const;
294
295        //!Destructor
296        ~eprod_base() {
297                for ( int i = 0; i < dls.length(); i++ ) {
298                        delete dls ( i );
[204]299                }
[886]300        }
301        void validate() {
302                dls.set_length ( no_factors() );
303               
304                bool independent = true;
305                dim = 0;
306                for ( int i = 0; i < no_factors(); i++ ) {
307                        independent = rv.add ( factor ( i )->_rv() );
308                        dim += factor ( i )->dimension();
309                        bdm_assert_debug ( independent, "eprod:: given components are not independent." );
310                };
311               
[286]312                //
[477]313                int cumdim = 0;
314                int dimi = 0;
[286]315                int i;
[886]316                for ( i = 0; i < no_factors(); i++ ) {
[286]317                        dls ( i ) = new datalink;
[886]318                        if ( isnamed() ) { // rvs are complete
319                                dls ( i )->set_connection ( factor ( i )->_rv() , rv );
320                        } else { //rvs are not reliable
321                                dimi = factor ( i )->dimension();
[477]322                                dls ( i )->set_connection ( dimi, dim, linspace ( cumdim, cumdim + dimi - 1 ) );
323                                cumdim += dimi;
[286]324                        }
325                }
[878]326       
[168]327        }
[886]328};
[168]329
[886]330class eprod: public eprod_base{
331        protected:
332                Array<shared_ptr<epdf> > factors;
333        public:
334                const epdf* factor(int i) const {return factors(i).get();}
335                const int no_factors() const {return factors.length();}
336        void set_parameters ( const Array<shared_ptr<epdf> > &epdfs0) {
337                factors = epdfs0;
[477]338        }
[886]339};
[204]340
[886]341//! similar to eprod but used only internally -- factors are external pointers
342class eprod_internal: public eprod_base{
343        protected:
344                Array<epdf* > factors;
345                const epdf* factor(int i) const {return factors(i);}
346                const int no_factors() const {return factors.length();}
347        public:
348                void set_parameters ( const Array<epdf *> &epdfs0) {
349                        factors = epdfs0;
[477]350                }
[168]351};
352
[693]353/*! \brief Mixture of pdfs with constant weights, all pdfs are of equal RV and RVC
[124]354
355*/
[693]356class mmix : public pdf {
[488]357protected:
[693]358        //! Component (pdfs)
359        Array<shared_ptr<pdf> > Coms;
[488]360        //!weights of the components
361        vec w;
362public:
363        //!Default constructor
[878]364        mmix() : Coms ( 0 ) { };
[461]365
[878]366
367
368
369
370       
[737]371        double evallogcond ( const vec &dt, const vec &cond ) {
372                double ll = 0.0;
373                for ( int i = 0; i < Coms.length(); i++ ) {
374                        ll += Coms ( i )->evallogcond ( dt, cond );
[488]375                }
376                return ll;
377        }
378
[737]379        vec samplecond ( const vec &cond );
[488]380
[711]381        //! Load from structure with elements:
382        //!  \code
383        //! { class='mmix';
384        //!   pdfs = (..., ...);     // list of pdfs in the mixture
385        //!   weights = ( 0.5, 0.5 ); // weights of pdfs in the mixture
386        //! }
387        //! \endcode
388        //!@}
[766]389        void from_setting ( const Setting &set );
[711]390
[766]391        virtual void validate();
[488]392};
[737]393SHAREDPTR ( mmix );
[711]394UIREGISTER ( mmix );
[488]395
[254]396}
[107]397#endif //MX_H
Note: See TracBrowser for help on using the browser.