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

Revision 766, 10.1 kB (checked in by mido, 14 years ago)

abstract methods restored wherever they are meaningful
macros NOT_IMPLEMENTED and NOT_IMPLEMENTED_VOID defined to make sources shorter
emix::set_parameters and mmix::set_parameters removed, corresponding acces methods created and the corresponding validate methods improved appropriately
some compilator warnings were avoided
and also a few other things cleaned up

  • 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        */
161        Array<shared_ptr<epdf>>& _Coms ( ) {
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 );
[333]209
210        //!return expected value
211        vec mean() const;
212
213        //!return a sample from the density
214        vec sample() const;
215
216        //!return the expected variance
[477]217        vec variance() const;
[333]218
219        // TODO!!! Defined to follow ANSI and/or for future development
220        void mean_mat ( mat &M, mat&R ) const {};
[477]221        double evallog_nn ( const vec &val ) const {
222                return 0;
223        };
224        double lognc () const {
225                return 0;
[504]226        }
[333]227
[504]228        shared_ptr<epdf> marginal ( const RV &rv ) const;
[660]229        //! marginal density update
[504]230        void marginal ( const RV &rv, emix &target ) const;
231
[333]232//Access methods
233        //! returns a pointer to the internal mean value. Use with Care!
[477]234        vec& _w() {
235                return w;
236        }
237        virtual ~egiwmix() {
238                if ( destroyComs ) {
239                        for ( int i = 0; i < Coms.length(); i++ ) {
240                                delete Coms ( i );
241                        }
242                }
243        }
[333]244        //! Auxiliary function for taking ownership of the Coms()
[477]245        void ownComs() {
246                destroyComs = true;
247        }
[333]248
249        //!access function
[477]250        egiw* _Coms ( int i ) {
251                return Coms ( i );
252        }
[333]253
[477]254        void set_rv ( const RV &rv ) {
255                egiw::set_rv ( rv );
256                for ( int i = 0; i < Coms.length(); i++ ) {
257                        Coms ( i )->set_rv ( rv );
258                }
[333]259        }
260
261        //! Approximation of a GiW mix by a single GiW pdf
262        egiw* approx();
263};
264
[115]265/*! \brief Chain rule decomposition of epdf
266
[145]267Probability density in the form of Chain-rule decomposition:
268\[
269f(x_1,x_2,x_3) = f(x_1|x_2,x_3)f(x_2,x_3)f(x_3)
270\]
271Note that
[115]272*/
[693]273class mprod: public pdf {
[507]274private:
[693]275        Array<shared_ptr<pdf> > pdfs;
[507]276
[693]277        //! Data link for each pdfs
[546]278        Array<shared_ptr<datalink_m2m> > dls;
[461]279
[162]280public:
[507]281        //! \brief Default constructor
282        mprod() { }
283
284        /*!\brief Constructor from list of mFacs
[165]285        */
[693]286        mprod ( const Array<shared_ptr<pdf> > &mFacs ) {
[477]287                set_elements ( mFacs );
[461]288        }
[693]289        //! Set internal \c pdfs from given values
[737]290        void set_elements ( const Array<shared_ptr<pdf> > &mFacs );
[477]291
[739]292        double evallogcond ( const vec &val, const vec &cond );
[395]293
[739]294        vec evallogcond_mat ( const mat &Dt, const vec &cond );
[395]295
[739]296        vec evallogcond_mat ( const Array<vec> &Dt, const vec &cond );
297
[270]298        //TODO smarter...
299        vec samplecond ( const vec &cond ) {
[477]300                //! Ugly hack to help to discover if mpfs are not in proper order. Correct solution = check that explicitely.
[487]301                vec smp = std::numeric_limits<double>::infinity() * ones ( dimension() );
[165]302                vec smpi;
[192]303                // Hard assumption here!!! We are going backwards, to assure that samples that are needed from smp are already generated!
[693]304                for ( int i = ( pdfs.length() - 1 ); i >= 0; i-- ) {
305                        // generate contribution of this pdf
[737]306                        smpi = pdfs ( i )->samplecond ( dls ( i )->get_cond ( smp , cond ) );
[162]307                        // copy contribution of this pdf into smp
[270]308                        dls ( i )->pushup ( smp, smpi );
[145]309                }
[162]310                return smp;
311        }
312
[395]313        //! Load from structure with elements:
314        //!  \code
315        //! { class='mprod';
[693]316        //!   pdfs = (..., ...);     // list of pdfs in the order of chain rule
[395]317        //! }
318        //! \endcode
319        //!@}
[477]320        void from_setting ( const Setting &set ) {
[766]321                Array<shared_ptr<pdf> > temp_array; 
322                UI::get ( temp_array, set, "pdfs", UI::compulsory );
323                set_elements ( temp_array );
[395]324        }
[107]325};
[477]326UIREGISTER ( mprod );
[529]327SHAREDPTR ( mprod );
[107]328
[168]329//! Product of independent epdfs. For dependent pdfs, use mprod.
330class eprod: public epdf {
331protected:
332        //! Components (epdfs)
[170]333        Array<const epdf*> epdfs;
[168]334        //! Array of indeces
[270]335        Array<datalink*> dls;
[168]336public:
[536]337        //! Default constructor
[477]338        eprod () : epdfs ( 0 ), dls ( 0 ) {};
[737]339        //! Set internal
[477]340        void set_parameters ( const Array<const epdf*> &epdfs0, bool named = true ) {
341                epdfs = epdfs0;//.set_length ( epdfs0.length() );
[286]342                dls.set_length ( epdfs.length() );
343
[477]344                bool independent = true;
[286]345                if ( named ) {
[477]346                        for ( int i = 0; i < epdfs.length(); i++ ) {
347                                independent = rv.add ( epdfs ( i )->_rv() );
[565]348                                bdm_assert_debug ( independent, "eprod:: given components are not independent." );
[286]349                        }
[477]350                        dim = rv._dsize();
351                } else {
352                        dim = 0;
353                        for ( int i = 0; i < epdfs.length(); i++ ) {
354                                dim += epdfs ( i )->dimension();
[286]355                        }
[204]356                }
[286]357                //
[477]358                int cumdim = 0;
359                int dimi = 0;
[286]360                int i;
[477]361                for ( i = 0; i < epdfs.length(); i++ ) {
[286]362                        dls ( i ) = new datalink;
[477]363                        if ( named ) {
364                                dls ( i )->set_connection ( epdfs ( i )->_rv() , rv );
365                        } else {
[286]366                                dimi = epdfs ( i )->dimension();
[477]367                                dls ( i )->set_connection ( dimi, dim, linspace ( cumdim, cumdim + dimi - 1 ) );
368                                cumdim += dimi;
[286]369                        }
370                }
[168]371        }
372
[739]373        vec mean() const;
374
375        vec variance() const;
376
377        vec sample() const;
378
379        double evallog ( const vec &val ) const;
380
[170]381        //!access function
[477]382        const epdf* operator () ( int i ) const {
[565]383                bdm_assert_debug ( i < epdfs.length(), "wrong index" );
[477]384                return epdfs ( i );
385        }
[204]386
[193]387        //!Destructor
[477]388        ~eprod() {
389                for ( int i = 0; i < epdfs.length(); i++ ) {
390                        delete dls ( i );
391                }
392        }
[168]393};
394
395
[693]396/*! \brief Mixture of pdfs with constant weights, all pdfs are of equal RV and RVC
[124]397
398*/
[693]399class mmix : public pdf {
[488]400protected:
[693]401        //! Component (pdfs)
402        Array<shared_ptr<pdf> > Coms;
[488]403        //!weights of the components
404        vec w;
405public:
406        //!Default constructor
[737]407        mmix() : Coms ( 0 ) { }
[461]408
[737]409        double evallogcond ( const vec &dt, const vec &cond ) {
410                double ll = 0.0;
411                for ( int i = 0; i < Coms.length(); i++ ) {
412                        ll += Coms ( i )->evallogcond ( dt, cond );
[488]413                }
414                return ll;
415        }
416
[737]417        vec samplecond ( const vec &cond );
[488]418
[711]419        //! Load from structure with elements:
420        //!  \code
421        //! { class='mmix';
422        //!   pdfs = (..., ...);     // list of pdfs in the mixture
423        //!   weights = ( 0.5, 0.5 ); // weights of pdfs in the mixture
424        //! }
425        //! \endcode
426        //!@}
[766]427        void from_setting ( const Setting &set );
[711]428
[766]429        virtual void validate();
[488]430};
[737]431SHAREDPTR ( mmix );
[711]432UIREGISTER ( mmix );
[488]433
[254]434}
[107]435#endif //MX_H
Note: See TracBrowser for help on using the browser.