root/bdm/estim/libPF.h @ 200

Revision 200, 5.0 kB (checked in by smidl, 16 years ago)

BM has now function _e() returning posterior of correct type

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