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

Revision 850, 11.7 kB (checked in by smidl, 14 years ago)

changes in Loggers!

  • 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 "../estim/arx_ext.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 {
28        //! Introduces two new options:
29        //! \li weights - meaning that all weightes will be logged
30        //! \li samples - all samples will be also logged
31        LOG_LEVEL(PF,weights,samples);
32
33protected:
34        //!number of particles;
35        int n;
36        //!posterior density
37        eEmp est;
38        //! pointer into \c eEmp
39        vec &_w;
40        //! pointer into \c eEmp
41        Array<vec> &_samples;
42        //! Parameter evolution model
43        shared_ptr<pdf> par;
44        //! Observation model
45        shared_ptr<pdf> obs;
46        //! internal structure storing loglikelihood of predictions
47        vec lls;
48
49        //! which resampling method will be used
50        RESAMPLING_METHOD resmethod;
51        //! resampling threshold; in this case its meaning is minimum ratio of active particles
52        //! For example, for 0.5 resampling is performed when the numebr of active aprticles drops belo 50%.
53        double res_threshold;
54
55        //! \name Options
56        //!@{
57        //!@}
58
59public:
60        //! \name Constructors
61        //!@{
62        PF ( ) : est(), _w ( est._w() ), _samples ( est._samples() ) {
63        };
64
65        void set_parameters ( int n0, double res_th0 = 0.5, RESAMPLING_METHOD rm = SYSTEMATIC ) {
66                n = n0;
67                res_threshold = res_th0;
68                resmethod = rm;
69        };
70        void set_model ( shared_ptr<pdf> par0, shared_ptr<pdf> obs0 ) {
71                par = par0;
72                obs = obs0;
73                // set values for posterior
74                est.set_rv ( par->_rv() );
75        };
76        void set_statistics ( const vec w0, const epdf &epdf0 ) {
77                est.set_statistics ( w0, epdf0 );
78        };
79        void set_statistics ( const eEmp &epdf0 ) {
80                bdm_assert_debug ( epdf0._rv().equal ( par->_rv() ), "Incompatible input" );
81                est = epdf0;
82        };
83        //!@}
84
85        //! Set posterior density by sampling from epdf0
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                lls=zeros(n);
186        }
187
188        void validate() {
189                BM::validate();
190                bdm_assert ( par, "PF::parameter_pdf not specified." );
191                n = _w.length();
192                lls = zeros ( n );
193
194                if ( par->_rv()._dsize() > 0 ) {
195                        bdm_assert ( par->_rv()._dsize() == est.dimension(), "Mismatch of RV and dimension of posterior" );
196                }
197        }
198        //! resample posterior density (from outside - see MPF)
199        void resample ( ivec &ind ) {
200                est.resample ( ind, resmethod );
201        }
202        //! access function
203        Array<vec>& __samples() {
204                return _samples;
205        }
206
207        virtual double logpred ( const vec &yt ) const NOT_IMPLEMENTED(0);
208
209        virtual epdf* epredictor() const NOT_IMPLEMENTED(NULL);
210       
211        virtual pdf* predictor() const NOT_IMPLEMENTED(NULL);
212};
213UIREGISTER ( PF );
214
215/*!
216\brief Marginalized Particle filter
217
218A composition of particle filter with exact (or almost exact) bayesian models (BMs).
219The Bayesian models provide marginalized predictive density. Internaly this is achieved by virtual class MPFpdf.
220*/
221
222class MPF : public BM  {
223        //! Introduces new option
224        //! \li means - meaning TODO
225        LOG_LEVEL(MPF,means);
226protected:
227        //! particle filter on non-linear variable
228        shared_ptr<PF> pf;
229        //! Array of Bayesian models
230        Array<BM*> BMs;
231
232        //! internal class for pdf providing composition of eEmp with external components
233
234        class mpfepdf : public epdf  {
235                //! pointer to particle filter
236                shared_ptr<PF> &pf;
237                //! pointer to Array of BMs
238                Array<BM*> &BMs;
239        public:
240                //! constructor
241                mpfepdf ( shared_ptr<PF> &pf0, Array<BM*> &BMs0 ) : epdf(), pf ( pf0 ), BMs ( BMs0 ) { };
242                //! a variant of set parameters - this time, parameters are read from BMs and pf
243                void read_parameters() {
244                        rv = concat ( pf->posterior()._rv(), BMs ( 0 )->posterior()._rv() );
245                        dim = pf->posterior().dimension() + BMs ( 0 )->posterior().dimension();
246                        bdm_assert_debug ( dim == rv._dsize(), "Wrong name " );
247                }
248                vec mean() const;
249
250                vec variance() const;
251
252                void qbounds ( vec &lb, vec &ub, double perc = 0.95 ) const;
253
254                vec sample() const NOT_IMPLEMENTED(0);
255
256                double evallog ( const vec &val ) const NOT_IMPLEMENTED(0);             
257        };
258
259        //! Density joining PF.est with conditional parts
260        mpfepdf jest;
261
262        //! datalink from global yt and cond (Up) to BMs yt and cond (Down)
263        datalink_m2m this2bm;
264        //! datalink from global yt and cond (Up) to PFs yt and cond (Down)
265        datalink_m2m this2pf;
266        //!datalink from PF part to BM
267        datalink_part pf2bm;
268
269public:
270        //! Default constructor.
271        MPF () :  jest ( pf, BMs ) {};
272        //! set all parameters at once
273        void set_pf ( shared_ptr<pdf> par0, int n0, RESAMPLING_METHOD rm = SYSTEMATIC ) {
274                if (!pf) pf=new PF;
275                pf->set_model ( par0, par0 ); // <=== nasty!!!
276                pf->set_parameters ( n0, rm );
277                pf->set_rv(par0->_rv());
278                BMs.set_length ( n0 );
279        }
280        //! set a prototype of BM, copy it to as many times as there is particles in pf
281        void set_BM ( const BM &BMcond0 ) {
282
283                int n = pf->__w().length();
284                BMs.set_length ( n );
285                // copy
286                //BMcond0 .condition ( pf->posterior()._sample ( 0 ) );
287                for ( int i = 0; i < n; i++ ) {
288                        BMs ( i ) = (BM*) BMcond0._copy();
289                }
290        };
291
292        void bayes ( const vec &yt, const vec &cond );
293
294        const epdf& posterior() const {
295                return jest;
296        }
297
298        //!Access function
299        const BM* _BM ( int i ) {
300                return BMs ( i );
301        }
302        PF& _pf() {return *pf;}
303
304
305        virtual double logpred ( const vec &yt ) const NOT_IMPLEMENTED(0); 
306               
307        virtual epdf* epredictor() const NOT_IMPLEMENTED(NULL); 
308       
309        virtual pdf* predictor() const NOT_IMPLEMENTED(NULL); 
310
311
312        /*! configuration structure for basic PF
313        \code
314        BM              = BM_class;           // Bayesian filtr for analytical part of the model
315        parameter_pdf   = pdf_class;         // transitional pdf for non-parametric part of the model
316        prior           = epdf_class;         // prior probability density
317        --- optional ---
318        n               = 10;                 // number of particles
319        resmethod       = 'systematic', or 'multinomial', or 'stratified'
320                                                                                  // resampling method
321        \endcode
322        */
323        void from_setting ( const Setting &set ) {
324                BM::from_setting( set );
325
326                shared_ptr<pdf> par = UI::build<pdf> ( set, "parameter_pdf", UI::compulsory );
327
328                pf = new PF;
329                // prior must be set before BM
330                pf->prior_from_set ( set );
331                pf->resmethod_from_set ( set );
332                pf->set_model ( par, par ); // too hackish!
333
334                shared_ptr<BM> BM0 = UI::build<BM> ( set, "BM", UI::compulsory );
335                set_BM ( *BM0 );
336
337                //set drv
338                //??set_yrv(concat(BM0->_yrv(),u) );
339                set_yrv ( BM0->_yrv() );
340                rvc = BM0->_rvc().subt ( par->_rv() );
341                //find potential input - what remains in rvc when we subtract rv
342                RV u = par->_rvc().subt ( par->_rv().copy_t ( -1 ) );
343                rvc.add ( u );
344                dimc = rvc._dsize();
345                validate();
346        }
347
348        void validate() {
349                BM::validate();
350                try {
351                        pf->validate();
352                } catch ( std::exception ) {
353                        throw UIException ( "Error in PF part of MPF:" );
354                }
355                jest.read_parameters();
356                this2bm.set_connection ( BMs ( 0 )->_yrv(), BMs ( 0 )->_rvc(), yrv, rvc );
357                this2pf.set_connection ( pf->_yrv(), pf->_rvc(), yrv, rvc );
358                pf2bm.set_connection ( BMs ( 0 )->_rvc(), pf->posterior()._rv() );
359        }
360};
361UIREGISTER ( MPF );
362
363/*! ARXg for estimation of state-space variances
364*/
365class MPF_ARXg :public BM{
366        protected:
367        shared_ptr<PF> pf;
368        //! pointer to Array of BMs
369        Array<ARX*> BMso;
370        //! pointer to Array of BMs
371        Array<ARX*> BMsp;
372        //!parameter evolution
373        shared_ptr<fnc> g;
374        //!observation function
375        shared_ptr<fnc> h;
376       
377        public:
378                void bayes(const vec &yt, const vec &cond );
379                void from_setting(const Setting &set) ;
380                void validate() {
381                        bdm_assert(g->dimensionc()==g->dimension(),"not supported yet");
382                        bdm_assert(h->dimensionc()==g->dimension(),"not supported yet");                       
383                }
384
385                double logpred(const vec &cond) const NOT_IMPLEMENTED(0.0);
386                epdf* epredictor() const NOT_IMPLEMENTED(NULL);
387                pdf* predictor() const NOT_IMPLEMENTED(NULL);
388                const epdf& posterior() const {return pf->posterior();};
389               
390                void log_register( logger &L, const string &prefix ){
391                        BM::log_register(L,prefix);
392                        logrec->ids.set_size ( 3 );
393                        logrec->ids(1)= L.add_vector(RV("Q",dimension()*dimension()), prefix+L.prefix_sep()+"Q");
394                        logrec->ids(2)= L.add_vector(RV("R",dimensiony()*dimensiony()), prefix+L.prefix_sep()+"R");
395                       
396                };
397                void log_write() const {
398                        BM::log_write();
399                        mat mQ=zeros(dimension(),dimension());
400                        mat pom=zeros(dimension(),dimension());
401                        mat mR=zeros(dimensiony(),dimensiony());
402                        mat pom2=zeros(dimensiony(),dimensiony());
403                        mat dum;
404                        const vec w=pf->posterior()._w();
405                        for (int i=0; i<w.length(); i++){
406                                BMsp(i)->posterior().mean_mat(dum,pom);
407                                mQ += w(i) * pom;
408                                BMso(i)->posterior().mean_mat(dum,pom2);
409                                mR += w(i) * pom2;
410                               
411                        }
412                        logrec->L.log_vector ( logrec->ids ( 1 ), cvectorize(mQ) );
413                        logrec->L.log_vector ( logrec->ids ( 2 ), cvectorize(mR) );
414                       
415                }
416};
417UIREGISTER(MPF_ARXg);
418
419
420}
421#endif // KF_H
422
Note: See TracBrowser for help on using the browser.