root/library/bdm/estim/particles.h @ 739

Revision 739, 9.9 kB (checked in by mido, 14 years ago)

the rest of h to cpp movements, with exception of from_setting and validate to avoid conflicts with Sarka

  • Property svn:eol-style set to native
Line 
1/*!
2  \file
3  \brief Bayesian Filtering using stochastic sampling (Particle Filters)
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 PARTICLES_H
14#define PARTICLES_H
15
16
17#include "../stat/exp_family.h"
18
19namespace bdm {
20
21/*!
22* \brief Trivial particle filter with proposal density equal to parameter evolution model.
23
24Posterior density is represented by a weighted empirical density (\c eEmp ).
25*/
26
27class PF : public BM {
28protected:
29        //!number of particles;
30        int n;
31        //!posterior density
32        eEmp est;
33        //! pointer into \c eEmp
34        vec &_w;
35        //! pointer into \c eEmp
36        Array<vec> &_samples;
37        //! Parameter evolution model
38        shared_ptr<pdf> par;
39        //! Observation model
40        shared_ptr<pdf> obs;
41        //! internal structure storing loglikelihood of predictions
42        vec lls;
43
44        //! which resampling method will be used
45        RESAMPLING_METHOD resmethod;
46        //! resampling threshold; in this case its meaning is minimum ratio of active particles
47        //! For example, for 0.5 resampling is performed when the numebr of active aprticles drops belo 50%.
48        double res_threshold;
49
50        //! \name Options
51        //!@{
52        //!@}
53
54public:
55        //! \name Constructors
56        //!@{
57        PF ( ) : est(), _w ( est._w() ), _samples ( est._samples() ) {
58        };
59
60        void set_parameters ( int n0, double res_th0 = 0.5, RESAMPLING_METHOD rm = SYSTEMATIC ) {
61                n = n0;
62                res_threshold = res_th0;
63                resmethod = rm;
64        };
65        void set_model ( shared_ptr<pdf> par0, shared_ptr<pdf> obs0 ) {
66                par = par0;
67                obs = obs0;
68                // set values for posterior
69                est.set_rv ( par->_rv() );
70        };
71        void set_statistics ( const vec w0, const epdf &epdf0 ) {
72                est.set_statistics ( w0, epdf0 );
73        };
74        void set_statistics ( const eEmp &epdf0 ) {
75                bdm_assert_debug ( epdf0._rv().equal ( par->_rv() ), "Incompatibel input" );
76                est = epdf0;
77        };
78        //!@}
79        //! Set posterior density by sampling from epdf0
80        //! Extends original BM::set_options by two more options:
81        //! \li logweights - meaning that all weightes will be logged
82        //! \li logsamples - all samples will be also logged
83        void set_options ( const string &opt ) {
84                BM::set_options ( opt );
85        }
86        //! bayes I - generate samples and add their weights to lls
87        virtual void bayes_gensmp ( const vec &ut );
88        //! bayes II - compute weights of the
89        virtual void bayes_weights();
90        //! important part of particle filtering - decide if it is time to perform resampling
91        virtual bool do_resampling() {
92                double eff = 1.0 / ( _w * _w );
93                return eff < ( res_threshold*n );
94        }
95        void bayes ( const vec &yt, const vec &cond );
96        //!access function
97        vec& __w() {
98                return _w;
99        }
100        //!access function
101        vec& _lls() {
102                return lls;
103        }
104        //!access function
105        RESAMPLING_METHOD _resmethod() const {
106                return resmethod;
107        }
108        //! return correctly typed posterior (covariant return)
109        const eEmp& posterior() const {
110                return est;
111        }
112
113        /*! configuration structure for basic PF
114        \code
115        parameter_pdf   = pdf_class;         // parameter evolution pdf
116        observation_pdf = pdf_class;         // observation pdf
117        prior           = epdf_class;         // prior probability density
118        --- optional ---
119        n               = 10;                 // number of particles
120        resmethod       = 'systematic', or 'multinomial', or 'stratified'
121                                                                                  // resampling method
122        res_threshold   = 0.5;                // resample when active particles drop below 50%
123        \endcode
124        */
125        void from_setting ( const Setting &set ) {
126                BM::from_setting ( set );
127                par = UI::build<pdf> ( set, "parameter_pdf", UI::compulsory );
128                obs = UI::build<pdf> ( set, "observation_pdf", UI::compulsory );
129
130                prior_from_set ( set );
131                resmethod_from_set ( set );
132                // set resampling method
133                //set drv
134                //find potential input - what remains in rvc when we subtract rv
135                RV u = par->_rvc().remove_time().subt ( par->_rv() );
136                //find potential input - what remains in rvc when we subtract x_t
137                RV obs_u = obs->_rvc().remove_time().subt ( par->_rv() );
138
139                u.add ( obs_u ); // join both u, and check if they do not overlap
140
141                set_yrv ( obs->_rv() );
142                rvc = u;
143        }
144        //! auxiliary function reading parameter 'resmethod' from configuration file
145        void resmethod_from_set ( const Setting &set ) {
146                string resmeth;
147                if ( UI::get ( resmeth, set, "resmethod", UI::optional ) ) {
148                        if ( resmeth == "systematic" ) {
149                                resmethod = SYSTEMATIC;
150                        } else  {
151                                if ( resmeth == "multinomial" ) {
152                                        resmethod = MULTINOMIAL;
153                                } else {
154                                        if ( resmeth == "stratified" ) {
155                                                resmethod = STRATIFIED;
156                                        } else {
157                                                bdm_error ( "Unknown resampling method" );
158                                        }
159                                }
160                        }
161                } else {
162                        resmethod = SYSTEMATIC;
163                };
164                if ( !UI::get ( res_threshold, set, "res_threshold", UI::optional ) ) {
165                        res_threshold = 0.5;
166                }
167                //validate();
168        }
169        //! load prior information from set and set internal structures accordingly
170        void prior_from_set ( const Setting & set ) {
171                shared_ptr<epdf> pri = UI::build<epdf> ( set, "prior", UI::compulsory );
172
173                eEmp *test_emp = dynamic_cast<eEmp*> ( & ( *pri ) );
174                if ( test_emp ) { // given pdf is sampled
175                        est = *test_emp;
176                } else {
177                        //int n;
178                        if ( !UI::get ( n, set, "n", UI::optional ) ) {
179                                n = 10;
180                        }
181                        // sample from prior
182                        set_statistics ( ones ( n ) / n, *pri );
183                }
184                n = est._w().length();
185                //validate();
186        }
187
188        void validate() {
189                bdm_assert ( par, "PF::parameter_pdf not specified." );
190                n = _w.length();
191                lls = zeros ( n );
192
193                if ( par->_rv()._dsize() > 0 ) {
194                        bdm_assert ( par->_rv()._dsize() == est.dimension(), "Mismatch of RV and dimension of posterior" );
195                }
196        }
197        //! resample posterior density (from outside - see MPF)
198        void resample ( ivec &ind ) {
199                est.resample ( ind, resmethod );
200        }
201        //! access function
202        Array<vec>& __samples() {
203                return _samples;
204        }
205};
206UIREGISTER ( PF );
207
208/*!
209\brief Marginalized Particle filter
210
211A composition of particle filter with exact (or almost exact) bayesian models (BMs).
212The Bayesian models provide marginalized predictive density. Internaly this is achieved by virtual class MPFpdf.
213*/
214
215class MPF : public BM  {
216protected:
217        //! particle filter on non-linear variable
218        shared_ptr<PF> pf;
219        //! Array of Bayesian models
220        Array<BM*> BMs;
221
222        //! internal class for pdf providing composition of eEmp with external components
223
224        class mpfepdf : public epdf  {
225                //! pointer to particle filter
226                shared_ptr<PF> &pf;
227                //! pointer to Array of BMs
228                Array<BM*> &BMs;
229        public:
230                //! constructor
231                mpfepdf ( shared_ptr<PF> &pf0, Array<BM*> &BMs0 ) : epdf(), pf ( pf0 ), BMs ( BMs0 ) { };
232                //! a variant of set parameters - this time, parameters are read from BMs and pf
233                void read_parameters() {
234                        rv = concat ( pf->posterior()._rv(), BMs ( 0 )->posterior()._rv() );
235                        dim = pf->posterior().dimension() + BMs ( 0 )->posterior().dimension();
236                        bdm_assert_debug ( dim == rv._dsize(), "Wrong name " );
237                }
238                vec mean() const;
239
240                vec variance() const;
241
242                void qbounds ( vec &lb, vec &ub, double perc = 0.95 ) const;
243
244                vec sample() const {
245                        bdm_error ( "Not implemented" );
246                        return vec();
247                }
248
249                double evallog ( const vec &val ) const {
250                        bdm_error ( "not implemented" );
251                        return 0.0;
252                }
253        };
254
255        //! Density joining PF.est with conditional parts
256        mpfepdf jest;
257
258        //! datalink from global yt and cond (Up) to BMs yt and cond (Down)
259        datalink_m2m this2bm;
260        //! datalink from global yt and cond (Up) to PFs yt and cond (Down)
261        datalink_m2m this2pf;
262        //!datalink from PF part to BM
263        datalink_part pf2bm;
264
265public:
266        //! Default constructor.
267        MPF () :  jest ( pf, BMs ) {};
268        //! set all parameters at once
269        void set_parameters ( shared_ptr<pdf> par0, shared_ptr<pdf> obs0, int n0, RESAMPLING_METHOD rm = SYSTEMATIC ) {
270                pf->set_model ( par0, obs0 );
271                pf->set_parameters ( n0, rm );
272                BMs.set_length ( n0 );
273        }
274        //! set a prototype of BM, copy it to as many times as there is particles in pf
275        void set_BM ( const BM &BMcond0 ) {
276
277                int n = pf->__w().length();
278                BMs.set_length ( n );
279                // copy
280                //BMcond0 .condition ( pf->posterior()._sample ( 0 ) );
281                for ( int i = 0; i < n; i++ ) {
282                        BMs ( i ) = BMcond0._copy_();
283                }
284        };
285
286        void bayes ( const vec &yt, const vec &cond );
287        const epdf& posterior() const {
288                return jest;
289        }
290        //! Extends options understood by BM::set_options by option
291        //! \li logmeans - meaning
292        void set_options ( const string &opt ) {
293                BM::set_options ( opt );
294        }
295
296        //!Access function
297        const BM* _BM ( int i ) {
298                return BMs ( i );
299        }
300
301        /*! configuration structure for basic PF
302        \code
303        BM              = BM_class;           // Bayesian filtr for analytical part of the model
304        parameter_pdf   = pdf_class;         // transitional pdf for non-parametric part of the model
305        prior           = epdf_class;         // prior probability density
306        --- optional ---
307        n               = 10;                 // number of particles
308        resmethod       = 'systematic', or 'multinomial', or 'stratified'
309                                                                                  // resampling method
310        \endcode
311        */
312        void from_setting ( const Setting &set ) {
313                shared_ptr<pdf> par = UI::build<pdf> ( set, "parameter_pdf", UI::compulsory );
314                shared_ptr<pdf> obs = new pdf(); // not used!!
315
316                pf = new PF;
317                // prior must be set before BM
318                pf->prior_from_set ( set );
319                pf->resmethod_from_set ( set );
320                pf->set_model ( par, obs );
321
322                shared_ptr<BM> BM0 = UI::build<BM> ( set, "BM", UI::compulsory );
323                set_BM ( *BM0 );
324
325                string opt;
326                if ( UI::get ( opt, set, "options", UI::optional ) ) {
327                        set_options ( opt );
328                }
329                //set drv
330                //??set_yrv(concat(BM0->_yrv(),u) );
331                set_yrv ( BM0->_yrv() );
332                rvc = BM0->_rvc().subt ( par->_rv() );
333                //find potential input - what remains in rvc when we subtract rv
334                RV u = par->_rvc().subt ( par->_rv().copy_t ( -1 ) );
335                rvc.add ( u );
336                dimc = rvc._dsize();
337                validate();
338        }
339        void validate() {
340                try {
341                        pf->validate();
342                } catch ( std::exception &e ) {
343                        throw UIException ( "Error in PF part of MPF:" );
344                }
345                jest.read_parameters();
346                this2bm.set_connection ( BMs ( 0 )->_yrv(), BMs ( 0 )->_rvc(), yrv, rvc );
347                this2pf.set_connection ( pf->_yrv(), pf->_rvc(), yrv, rvc );
348                pf2bm.set_connection ( BMs ( 0 )->_rvc(), pf->posterior()._rv() );
349        }
350
351};
352UIREGISTER ( MPF );
353
354}
355#endif // KF_H
356
Note: See TracBrowser for help on using the browser.