root/bdm/estim/libPF.h @ 271

Revision 271, 5.2 kB (checked in by smidl, 15 years ago)

Next major revision

  • 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 PF_H
14#define PF_H
15
16
17#include "../stat/libEF.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        mpdf *par;
39        //! Observation model
40        mpdf *obs;
41public:
42        //! \name Constructors
43        //!@{
44        PF ( ) :est(), _w ( est._w() ),_samples ( est._samples() ) {};
45        PF( mpdf *par0, mpdf *obs0, epdf *epdf0, int n0 ) :
46                        est ( ),_w ( est._w() ),_samples ( est._samples() ) 
47                        { par = par0; obs=obs0; est.set_parameters ( ones(n0),epdf0 ); };
48        void set_parameters ( mpdf *par0, mpdf *obs0, int n0 ) 
49                        { par = par0; obs=obs0; n=n0; };
50        void set_statistics (const vec w0, epdf *epdf0){est.set_parameters ( w0,epdf0 );};
51        //!@}
52        //! Set posterior density by sampling from epdf0
53        void set_est ( const epdf &epdf0 );
54        void bayes ( const vec &dt );
55        //!access function
56        vec* __w() {return &_w;}
57};
58
59/*!
60\brief Marginalized Particle filter
61
62Trivial version: proposal = parameter evolution, observation model is not used. (it is assumed to be part of BM).
63*/
64
65template<class BM_T>
66
67class MPF : public PF {
68        BM_T* Bms[10000];
69
70        //! internal class for MPDF providing composition of eEmp with external components
71
72class mpfepdf : public epdf  {
73        protected:
74                eEmp &E;
75                vec &_w;
76                Array<const epdf*> Coms;
77        public:
78                mpfepdf ( eEmp &E0) :
79                                epdf ( ), E ( E0 ),  _w ( E._w() ),
80                                Coms ( _w.length() ) {
81                };
82
83                void set_elements ( int &i, double wi, const epdf* ep )
84                {_w ( i ) =wi; Coms ( i ) =ep;};
85
86                vec mean() const {
87                        // ugly
88                        vec pom=zeros ( Coms(0)->dimension() );
89                        for ( int i=0; i<_w.length(); i++ ) {pom += Coms ( i )->mean() * _w ( i );}
90                        return concat ( E.mean(),pom );
91                }
92                vec variance() const {
93                        // ugly
94                        vec pom=zeros ( Coms ( 0 )->dimension() );
95                        vec pom2=zeros (  Coms ( 0 )->dimension() );
96                        for ( int i=0; i<_w.length(); i++ ) {
97                                pom += Coms ( i )->mean() * _w ( i );
98                                pom2 += ( Coms ( i )->variance() + pow ( Coms ( i )->mean(),2 ) ) * _w ( i );
99                        }
100                        return concat ( E.variance(),pom2-pow ( pom,2 ) );
101                }
102
103                vec sample() const {it_error ( "Not implemented" );return 0;}
104
105                double evallog ( const vec &val ) const {it_error ( "not implemented" ); return 0.0;}
106        };
107
108        //! estimate joining PF.est with conditional
109        mpfepdf jest;
110
111public:
112        //! Default constructor.
113        MPF ( mpdf *par0, mpdf *obs0, int n, const BM_T &BMcond0 ) : PF (), jest ( est ) {
114                PF::set_parameters(par0,obs0,n);
115                //
116                //TODO test if rv and BMcond.rv are compatible.
117//              rv.add ( rvlin );
118                //
119
120                if ( n>10000 ) {it_error ( "increase 10000 here!" );}
121
122                for ( int i=0;i<n;i++ ) {
123                        Bms[i] = new BM_T ( BMcond0 ); //copy constructor
124                        const epdf& pom=Bms[i]->posterior();
125                        jest.set_elements ( i,1.0/n,&pom );
126                }
127        };
128
129        ~MPF() {
130        }
131
132        void bayes ( const vec &dt );
133        const epdf& posterior() const {return jest;}
134        const epdf* _e() const {return &jest;} //Fixme: is it useful?
135        //! Set postrior of \c rvc to samples from epdf0. Statistics of Bms are not re-computed! Use only for initialization!
136        void set_est ( const epdf& epdf0 ) {
137                PF::set_est ( epdf0 );  // sample params in condition
138                // copy conditions to BMs
139
140                for ( int i=0;i<n;i++ ) {Bms[i]->condition ( _samples ( i ) );}
141        }
142
143        //!Access function
144        BM* _BM ( int i ) {return Bms[i];}
145};
146
147template<class BM_T>
148void MPF<BM_T>::bayes ( const vec &dt ) {
149        int i;
150        vec lls ( n );
151        vec llsP ( n );
152        ivec ind;
153        double mlls=-std::numeric_limits<double>::infinity();
154
155#pragma omp parallel for
156        for ( i=0;i<n;i++ ) {
157                //generate new samples from paramater evolution model;
158                _samples ( i ) = par->samplecond ( _samples ( i ) );
159                llsP ( i ) = par->_e()->evallog ( _samples ( i ) );
160                Bms[i]->condition ( _samples ( i ) );
161                Bms[i]->bayes ( dt );
162                lls ( i ) = Bms[i]->_ll(); // lls above is also in proposal her must be lls(i) =, not +=!!
163                if ( lls ( i ) >mlls ) mlls=lls ( i ); //find maximum likelihood (for numerical stability)
164        }
165
166        double sum_w=0.0;
167        // compute weights
168#pragma omp parallel for
169        for ( i=0;i<n;i++ ) {
170                _w ( i ) *= exp ( lls ( i ) - mlls ); // multiply w by likelihood
171                sum_w+=_w ( i );
172        }
173
174        if ( sum_w  >0.0 ) {
175                _w /=sum_w; //?
176        }
177        else {
178                cout<<"sum(w)==0"<<endl;
179        }
180
181
182        double eff = 1.0/ ( _w*_w );
183        if ( eff < ( 0.3*n ) ) {
184                ind = est.resample();
185                // Resample Bms!
186
187#pragma omp parallel for
188                for ( i=0;i<n;i++ ) {
189                        if ( ind ( i ) !=i ) {//replace the current Bm by a new one
190                                //fixme this would require new assignment operator
191                                // *Bms[i] = *Bms[ind ( i ) ];
192
193                                // poor-man's solution: replicate constructor here
194                                // copied from MPF::MPF
195                                delete Bms[i];
196                                Bms[i] = new BM_T ( *Bms[ind ( i ) ] ); //copy constructor
197                                const epdf& pom=Bms[i]->posterior();
198                                jest.set_elements ( i,1.0/n,&pom );
199                        }
200                };
201                cout << '.';
202        }
203}
204
205}
206#endif // KF_H
207
Note: See TracBrowser for help on using the browser.