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

Revision 878, 10.1 kB (checked in by sarka, 14 years ago)

dim ze set_parameters do validate

  • 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
99
100
[550]101private:
102        // not implemented
103        mratio ( const mratio & );
[737]104        mratio &operator= ( const mratio & );
[182]105};
106
[107]107/*!
108* \brief Mixture of epdfs
109
110Density function:
111\f[
112f(x) = \sum_{i=1}^{n} w_{i} f_i(x), \quad \sum_{i=1}^n w_i = 1.
113\f]
114where \f$f_i(x)\f$ is any density on random variable \f$x\f$, called \a component,
115
116*/
[145]117class emix : public epdf {
[162]118protected:
119        //! weights of the components
120        vec w;
[559]121
[162]122        //! Component (epdfs)
[504]123        Array<shared_ptr<epdf> > Coms;
124
[162]125public:
[559]126        //! Default constructor
127        emix ( ) : epdf ( ) { }
128
[750]129        virtual void validate ();
[107]130
[162]131        vec sample() const;
[715]132
[739]133        vec mean() const;
[715]134
[739]135        vec variance() const;
136
137        double evallog ( const vec &val ) const;
138
139        vec evallog_mat ( const mat &Val ) const;
140
[214]141        //! Auxiliary function that returns pdflog for each component
[739]142        mat evallog_coms ( const mat &Val ) const;
[107]143
[504]144        shared_ptr<epdf> marginal ( const RV &rv ) const;
[536]145        //! Update already existing marginal density  \c target
[504]146        void marginal ( const RV &rv, emix &target ) const;
[693]147        shared_ptr<pdf> condition ( const RV &rv ) const;
[182]148
[766]149        //Access methods       
150        //! returns a reference to the internal weights. Use with Care!
[477]151        vec& _w() {
152                return w;
153        }
[204]154
[766]155        /*!
156          \brief returns a reference to the internal array of components. Use with Care! Set components \c Coms
157
158          Shared pointers in Coms are kept inside this instance and
159          shouldn't be modified after being passed to this method.
160        */
[775]161        Array<shared_ptr<epdf> >& _Coms ( ) {
[766]162                return Coms;
163        }
164
165        //! returns a reference to the internal components specified by index i. Use with Care!
[504]166        shared_ptr<epdf> _Coms ( int i ) {
[477]167                return Coms ( i );
[286]168        }
[504]169
[477]170        void set_rv ( const RV &rv ) {
171                epdf::set_rv ( rv );
172                for ( int i = 0; i < Coms.length(); i++ ) {
173                        Coms ( i )->set_rv ( rv );
174                }
175        }
[713]176
177        //! Load from structure with elements:
178        //!  \code
179        //! { class='emix';
180        //!   pdfs = (..., ...);     // list of pdfs in the mixture
181        //!   weights = ( 0.5, 0.5 ); // weights of pdfs in the mixture
182        //! }
183        //! \endcode
184        //!@}
[766]185        void from_setting ( const Setting &set );
[107]186};
[737]187SHAREDPTR ( emix );
[713]188UIREGISTER ( emix );
[107]189
[333]190/*!
191* \brief Mixture of egiws
192
193*/
194class egiwmix : public egiw {
195protected:
196        //! weights of the components
197        vec w;
198        //! Component (epdfs)
199        Array<egiw*> Coms;
200        //!Flag if owning Coms
201        bool destroyComs;
202public:
203        //!Default constructor
204        egiwmix ( ) : egiw ( ) {};
205
206        //! Set weights \c w and components \c Coms
207        //!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.
[477]208        void set_parameters ( const vec &w, const Array<egiw*> &Coms, bool copy = false );
[878]209       
[333]210        //!return expected value
[878]211        void validate();
212       
[333]213        vec mean() const;
214
215        //!return a sample from the density
216        vec sample() const;
217
218        //!return the expected variance
[477]219        vec variance() const;
[333]220
221        // TODO!!! Defined to follow ANSI and/or for future development
222        void mean_mat ( mat &M, mat&R ) const {};
[477]223        double evallog_nn ( const vec &val ) const {
224                return 0;
225        };
226        double lognc () const {
227                return 0;
[504]228        }
[333]229
[504]230        shared_ptr<epdf> marginal ( const RV &rv ) const;
[660]231        //! marginal density update
[504]232        void marginal ( const RV &rv, emix &target ) const;
233
[333]234//Access methods
235        //! returns a pointer to the internal mean value. Use with Care!
[477]236        vec& _w() {
237                return w;
238        }
239        virtual ~egiwmix() {
240                if ( destroyComs ) {
241                        for ( int i = 0; i < Coms.length(); i++ ) {
242                                delete Coms ( i );
243                        }
244                }
245        }
[333]246        //! Auxiliary function for taking ownership of the Coms()
[477]247        void ownComs() {
248                destroyComs = true;
249        }
[333]250
251        //!access function
[477]252        egiw* _Coms ( int i ) {
253                return Coms ( i );
254        }
[333]255
[477]256        void set_rv ( const RV &rv ) {
257                egiw::set_rv ( rv );
258                for ( int i = 0; i < Coms.length(); i++ ) {
259                        Coms ( i )->set_rv ( rv );
260                }
[333]261        }
262
263        //! Approximation of a GiW mix by a single GiW pdf
264        egiw* approx();
265};
266
[115]267/*! \brief Chain rule decomposition of epdf
268
[145]269Probability density in the form of Chain-rule decomposition:
270\[
271f(x_1,x_2,x_3) = f(x_1|x_2,x_3)f(x_2,x_3)f(x_3)
272\]
273Note that
[115]274*/
[693]275class mprod: public pdf {
[507]276private:
[693]277        Array<shared_ptr<pdf> > pdfs;
[507]278
[693]279        //! Data link for each pdfs
[546]280        Array<shared_ptr<datalink_m2m> > dls;
[461]281
[162]282public:
[507]283        //! \brief Default constructor
284        mprod() { }
285
286        /*!\brief Constructor from list of mFacs
[165]287        */
[693]288        mprod ( const Array<shared_ptr<pdf> > &mFacs ) {
[477]289                set_elements ( mFacs );
[461]290        }
[693]291        //! Set internal \c pdfs from given values
[737]292        void set_elements ( const Array<shared_ptr<pdf> > &mFacs );
[477]293
[739]294        double evallogcond ( const vec &val, const vec &cond );
[395]295
[739]296        vec evallogcond_mat ( const mat &Dt, const vec &cond );
[395]297
[739]298        vec evallogcond_mat ( const Array<vec> &Dt, const vec &cond );
299
[270]300        //TODO smarter...
301        vec samplecond ( const vec &cond ) {
[477]302                //! Ugly hack to help to discover if mpfs are not in proper order. Correct solution = check that explicitely.
[487]303                vec smp = std::numeric_limits<double>::infinity() * ones ( dimension() );
[165]304                vec smpi;
[192]305                // Hard assumption here!!! We are going backwards, to assure that samples that are needed from smp are already generated!
[693]306                for ( int i = ( pdfs.length() - 1 ); i >= 0; i-- ) {
307                        // generate contribution of this pdf
[737]308                        smpi = pdfs ( i )->samplecond ( dls ( i )->get_cond ( smp , cond ) );
[162]309                        // copy contribution of this pdf into smp
[270]310                        dls ( i )->pushup ( smp, smpi );
[145]311                }
[162]312                return smp;
313        }
314
[395]315        //! Load from structure with elements:
316        //!  \code
317        //! { class='mprod';
[693]318        //!   pdfs = (..., ...);     // list of pdfs in the order of chain rule
[395]319        //! }
320        //! \endcode
321        //!@}
[477]322        void from_setting ( const Setting &set ) {
[766]323                Array<shared_ptr<pdf> > temp_array; 
324                UI::get ( temp_array, set, "pdfs", UI::compulsory );
325                set_elements ( temp_array );
[395]326        }
[107]327};
[477]328UIREGISTER ( mprod );
[529]329SHAREDPTR ( mprod );
[107]330
[168]331//! Product of independent epdfs. For dependent pdfs, use mprod.
332class eprod: public epdf {
333protected:
334        //! Components (epdfs)
[170]335        Array<const epdf*> epdfs;
[168]336        //! Array of indeces
[270]337        Array<datalink*> dls;
[168]338public:
[536]339        //! Default constructor
[477]340        eprod () : epdfs ( 0 ), dls ( 0 ) {};
[737]341        //! Set internal
[477]342        void set_parameters ( const Array<const epdf*> &epdfs0, bool named = true ) {
343                epdfs = epdfs0;//.set_length ( epdfs0.length() );
[286]344                dls.set_length ( epdfs.length() );
[477]345                bool independent = true;
[286]346                if ( named ) {
[477]347                        for ( int i = 0; i < epdfs.length(); i++ ) {
348                                independent = rv.add ( epdfs ( i )->_rv() );
[565]349                                bdm_assert_debug ( independent, "eprod:: given components are not independent." );
[286]350                        }
[477]351                        dim = rv._dsize();
[878]352                       
[477]353                } else {
354                        dim = 0;
355                        for ( int i = 0; i < epdfs.length(); i++ ) {
356                                dim += epdfs ( i )->dimension();
[286]357                        }
[204]358                }
[286]359                //
[477]360                int cumdim = 0;
361                int dimi = 0;
[286]362                int i;
[477]363                for ( i = 0; i < epdfs.length(); i++ ) {
[286]364                        dls ( i ) = new datalink;
[477]365                        if ( named ) {
366                                dls ( i )->set_connection ( epdfs ( i )->_rv() , rv );
367                        } else {
[286]368                                dimi = epdfs ( i )->dimension();
[477]369                                dls ( i )->set_connection ( dimi, dim, linspace ( cumdim, cumdim + dimi - 1 ) );
370                                cumdim += dimi;
[286]371                        }
372                }
[878]373       
[168]374        }
375
[878]376       
[739]377        vec mean() const;
378
379        vec variance() const;
380
381        vec sample() const;
382
383        double evallog ( const vec &val ) const;
384
[170]385        //!access function
[477]386        const epdf* operator () ( int i ) const {
[565]387                bdm_assert_debug ( i < epdfs.length(), "wrong index" );
[477]388                return epdfs ( i );
389        }
[204]390
[193]391        //!Destructor
[477]392        ~eprod() {
393                for ( int i = 0; i < epdfs.length(); i++ ) {
394                        delete dls ( i );
395                }
396        }
[168]397};
398
399
[693]400/*! \brief Mixture of pdfs with constant weights, all pdfs are of equal RV and RVC
[124]401
402*/
[693]403class mmix : public pdf {
[488]404protected:
[693]405        //! Component (pdfs)
406        Array<shared_ptr<pdf> > Coms;
[488]407        //!weights of the components
408        vec w;
409public:
410        //!Default constructor
[878]411        mmix() : Coms ( 0 ) { };
[461]412
[878]413
414
415
416
417       
[737]418        double evallogcond ( const vec &dt, const vec &cond ) {
419                double ll = 0.0;
420                for ( int i = 0; i < Coms.length(); i++ ) {
421                        ll += Coms ( i )->evallogcond ( dt, cond );
[488]422                }
423                return ll;
424        }
425
[737]426        vec samplecond ( const vec &cond );
[488]427
[711]428        //! Load from structure with elements:
429        //!  \code
430        //! { class='mmix';
431        //!   pdfs = (..., ...);     // list of pdfs in the mixture
432        //!   weights = ( 0.5, 0.5 ); // weights of pdfs in the mixture
433        //! }
434        //! \endcode
435        //!@}
[766]436        void from_setting ( const Setting &set );
[711]437
[766]438        virtual void validate();
[488]439};
[737]440SHAREDPTR ( mmix );
[711]441UIREGISTER ( mmix );
[488]442
[254]443}
[107]444#endif //MX_H
Note: See TracBrowser for help on using the browser.