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