root/bdm/estim/libPF.h @ 281

Revision 281, 5.7 kB (checked in by smidl, 15 years ago)

new version of mpf_test for TR2245

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