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

Revision 775, 10.1 kB (checked in by smidl, 14 years ago)

compilation fix

  • 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 EMIX_H
14#define EMIX_H
15
16#define LOG2  0.69314718055995
17
18#include "../shared_ptr.h"
19#include "exp_family.h"
20
21namespace bdm {
22
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
35At present the only supported operation is evallogcond().
36 */
37class mratio: public pdf {
38protected:
39        //! Nominator in the form of pdf
40        const epdf* nom;
41
42        //!Denominator in the form of epdf
43        shared_ptr<epdf> den;
44
45        //!flag for destructor
46        bool destroynom;
47        //!datalink between conditional and nom
48        datalink_m2e dl;
49public:
50        //!Default constructor. By default, the given epdf is not copied!
51        //! It is assumed that this function will be used only temporarily.
52        mratio ( const epdf* nom0, const RV &rv, bool copy = false ) : pdf ( ), dl ( ) {
53                // adjust rv and rvc
54
55                set_rv ( rv ); 
56                dim = rv._dsize();
57
58                rvc = nom0->_rv().subt ( rv );
59                dimc = rvc._dsize();
60
61                //prepare data structures
62                if ( copy ) {
63                        bdm_error ( "todo" );
64                        // destroynom = true;
65                } else {
66                        nom = nom0;
67                        destroynom = false;
68                }
69                bdm_assert_debug ( rvc.length() > 0, "Makes no sense to use this object!" );
70
71                // build denominator
72                den = nom->marginal ( rvc );
73                dl.set_connection ( rv, rvc, nom0->_rv() );
74        };
75
76        double evallogcond ( const vec &val, const vec &cond ) {
77                double tmp;
78                vec nom_val ( dimension() + dimc );
79                dl.pushup_cond ( nom_val, val, cond );
80                tmp = exp ( nom->evallog ( nom_val ) - den->evallog ( cond ) );
81                return tmp;
82        }
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
87        //! Object takes ownership of nom and will destroy it
88        void ownnom() {
89                destroynom = true;
90        }
91        //! Default destructor
92        ~mratio() {
93                if ( destroynom ) {
94                        delete nom;
95                }
96        }
97
98
99
100
101private:
102        // not implemented
103        mratio ( const mratio & );
104        mratio &operator= ( const mratio & );
105};
106
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*/
117class emix : public epdf {
118protected:
119        //! weights of the components
120        vec w;
121
122        //! Component (epdfs)
123        Array<shared_ptr<epdf> > Coms;
124
125public:
126        //! Default constructor
127        emix ( ) : epdf ( ) { }
128
129        virtual void validate ();
130
131        vec sample() const;
132
133        vec mean() const;
134
135        vec variance() const;
136
137        double evallog ( const vec &val ) const;
138
139        vec evallog_mat ( const mat &Val ) const;
140
141        //! Auxiliary function that returns pdflog for each component
142        mat evallog_coms ( const mat &Val ) const;
143
144        shared_ptr<epdf> marginal ( const RV &rv ) const;
145        //! Update already existing marginal density  \c target
146        void marginal ( const RV &rv, emix &target ) const;
147        shared_ptr<pdf> condition ( const RV &rv ) const;
148
149        //Access methods       
150        //! returns a reference to the internal weights. Use with Care!
151        vec& _w() {
152                return w;
153        }
154
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!
166        shared_ptr<epdf> _Coms ( int i ) {
167                return Coms ( i );
168        }
169
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        }
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        //!@}
185        void from_setting ( const Setting &set );
186};
187SHAREDPTR ( emix );
188UIREGISTER ( emix );
189
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.
208        void set_parameters ( const vec &w, const Array<egiw*> &Coms, bool copy = false );
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
217        vec variance() const;
218
219        // TODO!!! Defined to follow ANSI and/or for future development
220        void mean_mat ( mat &M, mat&R ) const {};
221        double evallog_nn ( const vec &val ) const {
222                return 0;
223        };
224        double lognc () const {
225                return 0;
226        }
227
228        shared_ptr<epdf> marginal ( const RV &rv ) const;
229        //! marginal density update
230        void marginal ( const RV &rv, emix &target ) const;
231
232//Access methods
233        //! returns a pointer to the internal mean value. Use with Care!
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        }
244        //! Auxiliary function for taking ownership of the Coms()
245        void ownComs() {
246                destroyComs = true;
247        }
248
249        //!access function
250        egiw* _Coms ( int i ) {
251                return Coms ( i );
252        }
253
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                }
259        }
260
261        //! Approximation of a GiW mix by a single GiW pdf
262        egiw* approx();
263};
264
265/*! \brief Chain rule decomposition of epdf
266
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
272*/
273class mprod: public pdf {
274private:
275        Array<shared_ptr<pdf> > pdfs;
276
277        //! Data link for each pdfs
278        Array<shared_ptr<datalink_m2m> > dls;
279
280public:
281        //! \brief Default constructor
282        mprod() { }
283
284        /*!\brief Constructor from list of mFacs
285        */
286        mprod ( const Array<shared_ptr<pdf> > &mFacs ) {
287                set_elements ( mFacs );
288        }
289        //! Set internal \c pdfs from given values
290        void set_elements ( const Array<shared_ptr<pdf> > &mFacs );
291
292        double evallogcond ( const vec &val, const vec &cond );
293
294        vec evallogcond_mat ( const mat &Dt, const vec &cond );
295
296        vec evallogcond_mat ( const Array<vec> &Dt, const vec &cond );
297
298        //TODO smarter...
299        vec samplecond ( const vec &cond ) {
300                //! Ugly hack to help to discover if mpfs are not in proper order. Correct solution = check that explicitely.
301                vec smp = std::numeric_limits<double>::infinity() * ones ( dimension() );
302                vec smpi;
303                // Hard assumption here!!! We are going backwards, to assure that samples that are needed from smp are already generated!
304                for ( int i = ( pdfs.length() - 1 ); i >= 0; i-- ) {
305                        // generate contribution of this pdf
306                        smpi = pdfs ( i )->samplecond ( dls ( i )->get_cond ( smp , cond ) );
307                        // copy contribution of this pdf into smp
308                        dls ( i )->pushup ( smp, smpi );
309                }
310                return smp;
311        }
312
313        //! Load from structure with elements:
314        //!  \code
315        //! { class='mprod';
316        //!   pdfs = (..., ...);     // list of pdfs in the order of chain rule
317        //! }
318        //! \endcode
319        //!@}
320        void from_setting ( const Setting &set ) {
321                Array<shared_ptr<pdf> > temp_array; 
322                UI::get ( temp_array, set, "pdfs", UI::compulsory );
323                set_elements ( temp_array );
324        }
325};
326UIREGISTER ( mprod );
327SHAREDPTR ( mprod );
328
329//! Product of independent epdfs. For dependent pdfs, use mprod.
330class eprod: public epdf {
331protected:
332        //! Components (epdfs)
333        Array<const epdf*> epdfs;
334        //! Array of indeces
335        Array<datalink*> dls;
336public:
337        //! Default constructor
338        eprod () : epdfs ( 0 ), dls ( 0 ) {};
339        //! Set internal
340        void set_parameters ( const Array<const epdf*> &epdfs0, bool named = true ) {
341                epdfs = epdfs0;//.set_length ( epdfs0.length() );
342                dls.set_length ( epdfs.length() );
343
344                bool independent = true;
345                if ( named ) {
346                        for ( int i = 0; i < epdfs.length(); i++ ) {
347                                independent = rv.add ( epdfs ( i )->_rv() );
348                                bdm_assert_debug ( independent, "eprod:: given components are not independent." );
349                        }
350                        dim = rv._dsize();
351                } else {
352                        dim = 0;
353                        for ( int i = 0; i < epdfs.length(); i++ ) {
354                                dim += epdfs ( i )->dimension();
355                        }
356                }
357                //
358                int cumdim = 0;
359                int dimi = 0;
360                int i;
361                for ( i = 0; i < epdfs.length(); i++ ) {
362                        dls ( i ) = new datalink;
363                        if ( named ) {
364                                dls ( i )->set_connection ( epdfs ( i )->_rv() , rv );
365                        } else {
366                                dimi = epdfs ( i )->dimension();
367                                dls ( i )->set_connection ( dimi, dim, linspace ( cumdim, cumdim + dimi - 1 ) );
368                                cumdim += dimi;
369                        }
370                }
371        }
372
373        vec mean() const;
374
375        vec variance() const;
376
377        vec sample() const;
378
379        double evallog ( const vec &val ) const;
380
381        //!access function
382        const epdf* operator () ( int i ) const {
383                bdm_assert_debug ( i < epdfs.length(), "wrong index" );
384                return epdfs ( i );
385        }
386
387        //!Destructor
388        ~eprod() {
389                for ( int i = 0; i < epdfs.length(); i++ ) {
390                        delete dls ( i );
391                }
392        }
393};
394
395
396/*! \brief Mixture of pdfs with constant weights, all pdfs are of equal RV and RVC
397
398*/
399class mmix : public pdf {
400protected:
401        //! Component (pdfs)
402        Array<shared_ptr<pdf> > Coms;
403        //!weights of the components
404        vec w;
405public:
406        //!Default constructor
407        mmix() : Coms ( 0 ) { }
408
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 );
413                }
414                return ll;
415        }
416
417        vec samplecond ( const vec &cond );
418
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        //!@}
427        void from_setting ( const Setting &set );
428
429        virtual void validate();
430};
431SHAREDPTR ( mmix );
432UIREGISTER ( mmix );
433
434}
435#endif //MX_H
Note: See TracBrowser for help on using the browser.