root/bdm/estim/libPF.h @ 279

Revision 279, 5.3 kB (checked in by smidl, 15 years ago)

Transition of pmsm and libKF

  • 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; est.set_n(n);};
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                void set_elements ( int &i, double wi, const epdf* ep )
83                {_w ( i ) =wi; Coms ( i ) =ep;};
84
85                void set_n(int n){E.set_n(n); Coms.set_length(n);}
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                jest.set_n(n);
116                //
117                //TODO test if rv and BMcond.rv are compatible.
118//              rv.add ( rvlin );
119                //
120
121                if ( n>10000 ) {it_error ( "increase 10000 here!" );}
122
123                for ( int i=0;i<n;i++ ) {
124                        Bms[i] = new BM_T ( BMcond0 ); //copy constructor
125                        const epdf& pom=Bms[i]->posterior();
126                        jest.set_elements ( i,1.0/n,&pom );
127                }
128        };
129
130        ~MPF() {
131        }
132
133        void bayes ( const vec &dt );
134        const epdf& posterior() const {return jest;}
135        const epdf* _e() const {return &jest;} //Fixme: is it useful?
136        //! Set postrior of \c rvc to samples from epdf0. Statistics of Bms are not re-computed! Use only for initialization!
137        void set_est ( const epdf& epdf0 ) {
138                PF::set_est ( epdf0 );  // sample params in condition
139                // copy conditions to BMs
140
141                for ( int i=0;i<n;i++ ) {Bms[i]->condition ( _samples ( i ) );}
142        }
143
144        //!Access function
145        BM* _BM ( int i ) {return Bms[i];}
146};
147
148template<class BM_T>
149void MPF<BM_T>::bayes ( const vec &dt ) {
150        int i;
151        vec lls ( n );
152        vec llsP ( n );
153        ivec ind;
154        double mlls=-std::numeric_limits<double>::infinity();
155
156#pragma omp parallel for
157        for ( i=0;i<n;i++ ) {
158                //generate new samples from paramater evolution model;
159                _samples ( i ) = par->samplecond ( _samples ( i ) );
160                llsP ( i ) = par->_e()->evallog ( _samples ( i ) );
161                Bms[i]->condition ( _samples ( i ) );
162                Bms[i]->bayes ( dt );
163                lls ( i ) = Bms[i]->_ll(); // lls above is also in proposal her must be lls(i) =, not +=!!
164                if ( lls ( i ) >mlls ) mlls=lls ( i ); //find maximum likelihood (for numerical stability)
165        }
166
167        double sum_w=0.0;
168        // compute weights
169#pragma omp parallel for
170        for ( i=0;i<n;i++ ) {
171                _w ( i ) *= exp ( lls ( i ) - mlls ); // multiply w by likelihood
172                sum_w+=_w ( i );
173        }
174
175        if ( sum_w  >0.0 ) {
176                _w /=sum_w; //?
177        }
178        else {
179                cout<<"sum(w)==0"<<endl;
180        }
181
182
183        double eff = 1.0/ ( _w*_w );
184        if ( eff < ( 0.3*n ) ) {
185                ind = est.resample();
186                // Resample Bms!
187
188#pragma omp parallel for
189                for ( i=0;i<n;i++ ) {
190                        if ( ind ( i ) !=i ) {//replace the current Bm by a new one
191                                //fixme this would require new assignment operator
192                                // *Bms[i] = *Bms[ind ( i ) ];
193
194                                // poor-man's solution: replicate constructor here
195                                // copied from MPF::MPF
196                                delete Bms[i];
197                                Bms[i] = new BM_T ( *Bms[ind ( i ) ] ); //copy constructor
198                                const epdf& pom=Bms[i]->posterior();
199                                jest.set_elements ( i,1.0/n,&pom );
200                        }
201                };
202                cout << '.';
203        }
204}
205
206}
207#endif // KF_H
208
Note: See TracBrowser for help on using the browser.