Legend:
- Unmodified
- Added
- Removed
-
bdm/estim/libKF.cpp
r28 r32 6 6 using std::endl; 7 7 8 KalmanFull::KalmanFull ( mat A0, mat B0, mat C0, mat D0, mat R0, mat Q0, mat P0, vec mu0 ) {8 KalmanFull::KalmanFull ( mat A0, mat B0, mat C0, mat D0, mat R0, mat Q0, mat P0, vec mu0 ) { 9 9 dimx = A0.rows(); 10 10 dimu = B0.cols(); 11 11 dimy = C0.rows(); 12 12 13 it_assert_debug ( A0.cols()==dimx, "KalmanFull: A is not square" );14 it_assert_debug ( B0.rows()==dimx, "KalmanFull: B is not compatible" );15 it_assert_debug ( C0.cols()==dimx, "KalmanFull: C is not square" );16 it_assert_debug (( D0.rows()==dimy ) || ( D0.cols()==dimu ), "KalmanFull: D is not compatible" );17 it_assert_debug (( R0.cols()==dimy ) || ( R0.rows()==dimy ), "KalmanFull: R is not compatible" );18 it_assert_debug (( Q0.cols()==dimx ) || ( Q0.rows()==dimx ), "KalmanFull: Q is not compatible" );13 it_assert_debug ( A0.cols() ==dimx, "KalmanFull: A is not square" ); 14 it_assert_debug ( B0.rows() ==dimx, "KalmanFull: B is not compatible" ); 15 it_assert_debug ( C0.cols() ==dimx, "KalmanFull: C is not square" ); 16 it_assert_debug ( ( D0.rows() ==dimy ) || ( D0.cols() ==dimu ), "KalmanFull: D is not compatible" ); 17 it_assert_debug ( ( R0.cols() ==dimy ) || ( R0.rows() ==dimy ), "KalmanFull: R is not compatible" ); 18 it_assert_debug ( ( Q0.cols() ==dimx ) || ( Q0.rows() ==dimx ), "KalmanFull: Q is not compatible" ); 19 19 20 20 A = A0; … … 28 28 } 29 29 30 void KalmanFull::bayes ( const vec &dt) {31 it_assert_debug ( dt.length()==( dimy+dimu ),"KalmanFull::bayes wrong size of dt" );30 void KalmanFull::bayes ( const vec &dt ) { 31 it_assert_debug ( dt.length() == ( dimy+dimu ),"KalmanFull::bayes wrong size of dt" ); 32 32 33 vec u = dt.get ( dimy,dimy+dimu-1 );34 vec y = dt.get ( 0,dimy-1 );33 vec u = dt.get ( dimy,dimy+dimu-1 ); 34 vec y = dt.get ( 0,dimy-1 ); 35 35 //Time update 36 36 mu = A*mu + B*u; … … 39 39 //Data update 40 40 _Ry = C*P*C.transpose() + R; 41 _iRy = inv ( _Ry );42 _K = P*C.transpose() *_iRy;41 _iRy = inv ( _Ry ); 42 _K = P*C.transpose() *_iRy; 43 43 P -= _K*C*P; // P = P -KCP; 44 mu += _K* ( y-C*mu-D*u );44 mu += _K* ( y-C*mu-D*u ); 45 45 }; 46 46 … … 50 50 } 51 51 52 void KFcondQR::condition ( const vec &QR ) { 53 it_assert_debug ( QR.length() == ( rvc.count() ),"KFcondRQ: conditioning by incompatible vector" ); 54 55 Q.setD ( QR ( 0, dimx-1 )); 56 R.setD ( QR ( dimx, -1 )); 57 }; 58 59 void KFcondR::condition ( const vec &R0 ) { 60 it_assert_debug ( R0.length() == ( rvc.count() ),"KFcondR: conditioning by incompatible vector" ); 61 62 R.setD ( R0 ); 63 }; -
bdm/estim/libKF.h
r28 r32 24 24 * \brief Basic Kalman filter with full matrices (education purpose only)! Will be deleted soon! 25 25 */ 26 class KalmanFull : public BM { 26 27 class KalmanFull { 27 28 int dimx, dimy, dimu; 28 29 mat A, B, C, D, R, Q; 29 30 //cache 30 31 //cache 31 32 mat _Pp, _Ry, _iRy, _K; 32 33 public: 33 //posterior 34 //posterior 34 35 //! Mean value of the posterior density 35 36 vec mu; … … 38 39 39 40 public: 40 //! Full constructor 41 KalmanFull ( mat A, mat B, mat C, mat D, mat R, mat Q, mat P0, vec mu0 );41 //! Full constructor 42 KalmanFull ( mat A, mat B, mat C, mat D, mat R, mat Q, mat P0, vec mu0 ); 42 43 //! Here dt = [yt;ut] of appropriate dimensions 43 void bayes(const vec &dt); 44 epdf* _epdf(){return NULL;}; 44 void bayes ( const vec &dt ); 45 45 46 46 friend std::ostream &operator<< ( std::ostream &os, const KalmanFull &kf ); … … 53 53 */ 54 54 template<class sq_T> 55 class Kalman : public BM { 55 56 class Kalman : public BM { 56 57 protected: 58 RV rvy; 59 RV rvu; 57 60 int dimx, dimy, dimu; 58 61 mat A, B, C, D; 59 sq_T R, Q;60 61 //!posterior on $x_t$62 sq_T Q,R; 63 64 //!posterior density on $x_t$ 62 65 enorm<sq_T> est; 63 66 //!preditive density on $y_t$ 64 67 enorm<sq_T> fy; 65 68 66 69 mat _K; 67 70 //cache of fy 68 vec* _yp; 71 vec* _yp; 69 72 sq_T* _Ry,*_iRy; 70 73 //cache of est 71 74 vec* _mu; 72 75 sq_T* _P, *_iP; 73 76 74 77 public: 75 78 //! Default constructor 76 Kalman (RV rvx0, RV rvy0, RV rvu0); 77 //! Set parameters with check of relevance 78 void set_parameters (const mat &A0,const mat &B0,const mat &C0,const mat &D0,const sq_T &R0,const sq_T &Q0); 79 Kalman ( RV rvx0, RV rvy0, RV rvu0 ); 80 //! Copy constructor 81 Kalman ( const Kalman<sq_T> &K0 ); 82 //! Set parameters with check of relevance 83 void set_parameters ( const mat &A0,const mat &B0,const mat &C0,const mat &D0,const sq_T &R0,const sq_T &Q0 ); 79 84 //! Set estimate values, used e.g. in initialization. 80 void set_est(const vec &mu0, const sq_T &P0 ){est.set_parameters(mu0,P0);}; 85 86 void set_est ( const vec &mu0, const sq_T &P0 ) { 87 sq_T pom(dimy); 88 est.set_parameters ( mu0,P0 ); 89 P0.mult_sym(C,pom); 90 fy.set_parameters ( C*mu0, pom ); 91 }; 92 81 93 //! Here dt = [yt;ut] of appropriate dimensions 82 void bayes(const vec &dt); 94 void bayes ( const vec &dt ); 95 epdf& _epdf() {return est;} 83 96 84 97 // friend std::ostream &operator<< ( std::ostream &os, const Kalman<sq_T> &kf ); 85 98 86 99 //!access functions 87 enorm<sq_T>* _epdf(){return &est;} 88 }; 89 90 /*! 91 \brief Extended Kalman Filter 100 }; 101 102 /*! 103 \brief Extended Kalman Filter 92 104 93 105 An approximation of the exact Bayesian filter with Gaussian noices and non-linear evolutions of their mean. 94 106 */ 95 107 template<class sq_T> 108 96 109 class EKF : public Kalman<ldmat> { 97 110 //! Internal Model f(x,u) … … 99 112 //! Observation Model h(x,u) 100 113 diffbifn* phxu; 101 public: 114 public: 102 115 //! Default constructor 103 EKF ( RV rvx, RV rvy, RV rvu);104 void set_parameters (diffbifn* pfxu, diffbifn* phxu, const sq_T Q0, const sq_T R0);116 EKF ( RV rvx, RV rvy, RV rvu ); 117 void set_parameters ( diffbifn* pfxu, diffbifn* phxu, const sq_T Q0, const sq_T R0 ); 105 118 //! Here dt = [yt;ut] of appropriate dimensions 106 void bayes(const vec &dt); 119 void bayes ( const vec &dt ); 120 }; 121 122 /*! 123 \brief Kalman Filter with conditional diagonal matrices R and Q. 124 */ 125 126 class KFcondQR : public Kalman<ldmat>, public BMcond { 127 //protected: 128 public: 129 KFcondQR ( RV rvx, RV rvy, RV rvu, RV rvRQ ) : Kalman<ldmat> ( rvx, rvy,rvu ),BMcond ( rvRQ ) {}; 130 131 void condition ( const vec &RQ ); 132 }; 133 134 /*! 135 \brief Kalman Filter with conditional diagonal matrices R and Q. 136 */ 137 138 class KFcondR : public Kalman<ldmat>, public BMcond { 139 //protected: 140 public: 141 KFcondR ( RV rvx, RV rvy, RV rvu, RV rvR ) : Kalman<ldmat> ( rvx, rvy,rvu ),BMcond ( rvR ) {}; 142 143 void condition ( const vec &R ); 107 144 }; 108 145 … … 110 147 111 148 template<class sq_T> 112 Kalman<sq_T>::Kalman(RV rvx, RV rvy, RV rvu): BM(), 113 dimx(rvx.count()), dimy(rvy.count()),dimu(rvu.count()), 114 A(dimx,dimx), B(dimx,dimu), C(dimy,dimx), D(dimy,dimu), est(rvx), fy(rvy){ 149 Kalman<sq_T>::Kalman ( const Kalman<sq_T> &K0 ) : BM ( K0.rv ),rvy ( K0.rvy ),rvu ( K0.rvu ), 150 dimx ( rv.count() ), dimy ( rvy.count() ),dimu ( rvu.count() ), 151 A ( dimx,dimx ), B ( dimx,dimu ), C ( dimy,dimx ), D ( dimy,dimu ),est ( rv ), fy ( rvy ) { 152 153 this->set_parameters ( K0.A, K0.B, K0.C, K0.D, K0.R, K0.Q ); 154 155 //establish pointers 156 _mu = est._mu(); 157 est._R ( _P,_iP ); 158 159 //fy 160 _yp = fy._mu(); 161 fy._R ( _Ry,_iRy ); 162 163 //reset copy values in pointers 164 *_mu = *K0._mu; 165 *_P = *K0._P; 166 *_iP = *K0._iP; 167 *_yp = *K0._yp; 168 *_iRy = *K0._iRy; 169 *_Ry = *K0._Ry; 170 171 } 172 173 template<class sq_T> 174 Kalman<sq_T>::Kalman ( RV rvx, RV rvy0, RV rvu0 ) : BM ( rvx ),rvy ( rvy0 ),rvu ( rvu0 ), 175 dimx ( rvx.count() ), dimy ( rvy.count() ),dimu ( rvu.count() ), 176 A ( dimx,dimx ), B ( dimx,dimu ), C ( dimy,dimx ), D ( dimy,dimu ), 177 Q(dimx), R (dimy), 178 est ( rvx ), fy ( rvy ) { 115 179 //assign cache 116 180 //est 117 _mu = est._mu();118 est._R(_P,_iP);181 _mu = est._mu(); 182 est._R ( _P,_iP ); 119 183 120 184 //fy 121 _yp = fy._mu();122 fy._R(_Ry,_iRy);123 }; 124 125 template<class sq_T> 126 void Kalman<sq_T>::set_parameters (const mat &A0,const mat &B0, const mat &C0, const mat &D0, const sq_T &R0, const sq_T &Q0) {127 it_assert_debug ( A0.cols()==dimx, "Kalman: A is not square" );128 it_assert_debug ( B0.rows()==dimx, "Kalman: B is not compatible" );129 it_assert_debug ( C0.cols()==dimx, "Kalman: C is not square" );130 it_assert_debug (( D0.rows()==dimy ) || ( D0.cols()==dimu ), "Kalman: D is not compatible" );131 it_assert_debug (( R0.cols()==dimy ) || ( R0.rows()==dimy ), "Kalman: R is not compatible" );132 it_assert_debug (( Q0.cols()==dimx ) || ( Q0.rows()==dimx ), "Kalman: Q is not compatible" );185 _yp = fy._mu(); 186 fy._R ( _Ry,_iRy ); 187 }; 188 189 template<class sq_T> 190 void Kalman<sq_T>::set_parameters ( const mat &A0,const mat &B0, const mat &C0, const mat &D0, const sq_T &R0, const sq_T &Q0 ) { 191 it_assert_debug ( A0.cols() ==dimx, "Kalman: A is not square" ); 192 it_assert_debug ( B0.rows() ==dimx, "Kalman: B is not compatible" ); 193 it_assert_debug ( C0.cols() ==dimx, "Kalman: C is not square" ); 194 it_assert_debug ( ( D0.rows() ==dimy ) || ( D0.cols() ==dimu ), "Kalman: D is not compatible" ); 195 it_assert_debug ( ( R0.cols() ==dimy ) || ( R0.rows() ==dimy ), "Kalman: R is not compatible" ); 196 it_assert_debug ( ( Q0.cols() ==dimx ) || ( Q0.rows() ==dimx ), "Kalman: Q is not compatible" ); 133 197 134 198 A = A0; … … 137 201 D = D0; 138 202 R = R0; 139 Q = Q0; 203 Q = Q0; 140 204 } 141 205 142 206 template<class sq_T> 143 void Kalman<sq_T>::bayes ( const vec &dt) {144 it_assert_debug ( dt.length()==( dimy+dimu ),"KalmanFull::bayes wrong size of dt" );145 146 vec u = dt.get ( dimy,dimy+dimu-1 );147 vec y = dt.get ( 0,dimy-1 );207 void Kalman<sq_T>::bayes ( const vec &dt ) { 208 it_assert_debug ( dt.length() == ( dimy+dimu ),"KalmanFull::bayes wrong size of dt" ); 209 210 vec u = dt.get ( dimy,dimy+dimu-1 ); 211 vec y = dt.get ( 0,dimy-1 ); 148 212 //Time update 149 *_mu = A* (*_mu) + B*u;213 *_mu = A* ( *_mu ) + B*u; 150 214 //P = A*P*A.transpose() + Q; in sq_T 151 _P->mult_sym ( A );152 ( *_P)+=Q;215 _P->mult_sym ( A ); 216 ( *_P ) +=Q; 153 217 154 218 //Data update 155 219 //_Ry = C*P*C.transpose() + R; in sq_T 156 _P->mult_sym ( C, *_Ry);157 ( *_Ry)+=R;220 _P->mult_sym ( C, *_Ry ); 221 ( *_Ry ) +=R; 158 222 159 223 mat Pfull = _P->to_mat(); 160 161 _Ry->inv( *_iRy ); // result is in _iRy; 162 _K = Pfull*C.transpose()*(_iRy->to_mat()); 163 164 sq_T pom((int)Pfull.rows()); 165 _iRy->mult_sym_t(C*Pfull,pom); 166 (*_P) -= pom; // P = P -PC'iRy*CP; 167 (*_yp) = C*(*_mu)+D*u; //y prediction 168 (*_mu) += _K*( y-(*_yp) ); 169 170 if (evalll==true) { 171 ll+=fy.evalpdflog(*_yp); 224 225 _Ry->inv ( *_iRy ); // result is in _iRy; 226 fy._cached ( true ); 227 _K = Pfull*C.transpose() * ( _iRy->to_mat() ); 228 229 sq_T pom ( ( int ) Pfull.rows() ); 230 _iRy->mult_sym_t ( C*Pfull,pom ); 231 ( *_P ) -= pom; // P = P -PC'iRy*CP; 232 ( *_yp ) = C* ( *_mu ) +D*u; //y prediction 233 ( *_mu ) += _K* ( y- ( *_yp ) ); 234 235 236 if ( evalll==true ) { //likelihood of observation y 237 ll=fy.evalpdflog ( y ); 172 238 } 239 240 //cout << "y: " << y-(*_yp) <<" R: " << _Ry->to_mat() << " iR: " << _iRy->to_mat() << " ll: " << ll <<endl; 241 173 242 }; 174 243 … … 176 245 177 246 template<class sq_T> 178 EKF<sq_T>::EKF (RV rvx0, RV rvy0, RV rvu0): Kalman<ldmat>(rvx0,rvy0,rvu0){}179 180 template<class sq_T> 181 void EKF<sq_T>::set_parameters (diffbifn* pfxu0, diffbifn* phxu0,const sq_T Q0,const sq_T R0) {182 183 184 185 186 pfxu->dfdx_cond(*_mu,zeros(dimu),A,true);187 pfxu->dfdu_cond(*_mu,zeros(dimu),B,true);188 phxu->dfdx_cond(*_mu,zeros(dimu),C,true);189 phxu->dfdu_cond(*_mu,zeros(dimu),D,true);190 191 192 247 EKF<sq_T>::EKF ( RV rvx0, RV rvy0, RV rvu0 ) : Kalman<ldmat> ( rvx0,rvy0,rvu0 ) {} 248 249 template<class sq_T> 250 void EKF<sq_T>::set_parameters ( diffbifn* pfxu0, diffbifn* phxu0,const sq_T Q0,const sq_T R0 ) { 251 pfxu = pfxu0; 252 phxu = phxu0; 253 254 //initialize matrices A C, later, these will be only updated! 255 pfxu->dfdx_cond ( *_mu,zeros ( dimu ),A,true ); 256 pfxu->dfdu_cond ( *_mu,zeros ( dimu ),B,true ); 257 phxu->dfdx_cond ( *_mu,zeros ( dimu ),C,true ); 258 phxu->dfdu_cond ( *_mu,zeros ( dimu ),D,true ); 259 260 R = R0; 261 Q = Q0; 193 262 194 263 using std::cout; … … 201 270 202 271 template<class sq_T> 203 void EKF<sq_T>::bayes ( const vec &dt) {204 it_assert_debug ( dt.length()==( dimy+dimu ),"KalmanFull::bayes wrong size of dt" );205 206 vec u = dt.get ( dimy,dimy+dimu-1 );207 vec y = dt.get ( 0,dimy-1 );272 void EKF<sq_T>::bayes ( const vec &dt ) { 273 it_assert_debug ( dt.length() == ( dimy+dimu ),"KalmanFull::bayes wrong size of dt" ); 274 275 vec u = dt.get ( dimy,dimy+dimu-1 ); 276 vec y = dt.get ( 0,dimy-1 ); 208 277 //Time update 209 *_mu = pfxu->eval (*_mu, u);210 pfxu->dfdx_cond (*_mu,u,A,false); //update A by a derivative of fx211 278 *_mu = pfxu->eval ( *_mu, u ); 279 pfxu->dfdx_cond ( *_mu,u,A,false ); //update A by a derivative of fx 280 212 281 //P = A*P*A.transpose() + Q; in sq_T 213 _P->mult_sym ( A );214 ( *_P)+=Q;282 _P->mult_sym ( A ); 283 ( *_P ) +=Q; 215 284 216 285 //Data update 217 phxu->dfdx_cond (*_mu,u,C,false); //update C by a derivative hx286 phxu->dfdx_cond ( *_mu,u,C,false ); //update C by a derivative hx 218 287 //_Ry = C*P*C.transpose() + R; in sq_T 219 _P->mult_sym ( C, *_Ry);220 ( *_Ry)+=R;288 _P->mult_sym ( C, *_Ry ); 289 ( *_Ry ) +=R; 221 290 222 291 mat Pfull = _P->to_mat(); 223 224 _Ry->inv( *_iRy ); // result is in _iRy; 225 _K = Pfull*C.transpose()*(_iRy->to_mat()); 226 (*_P) -= _K*C*Pfull; // P = P -KCP; 227 *_yp = phxu->eval(*_mu,u); //y prediction 228 (*_mu) += _K*( y-*_yp ); 229 230 if (evalll==true) {ll+=est.evalpdflog(y);} 292 293 _Ry->inv ( *_iRy ); // result is in _iRy; 294 _K = Pfull*C.transpose() * ( _iRy->to_mat() ); 295 296 sq_T pom ( ( int ) Pfull.rows() ); 297 _iRy->mult_sym_t ( C*Pfull,pom ); 298 ( *_P ) -= pom; // P = P -PC'iRy*CP; 299 *_yp = phxu->eval ( *_mu,u ); //y prediction 300 ( *_mu ) += _K* ( y-*_yp ); 301 302 if ( evalll==true ) {ll+=fy.evalpdflog ( y );} 231 303 }; 232 304 -
bdm/estim/libPF.cpp
r28 r32 5 5 using std::endl; 6 6 7 PF::PF(vec w0){w=w0/sum(w0); n=w.length();}8 7 9 ivec PF::resample( RESAMPLING_METHOD method ) { 10 ivec ind=zeros_i( n ); 11 ivec N_babies = zeros_i( n ); 12 vec cumDist = cumsum( w ); 13 vec u( n ); 14 int i,j,parent; 15 double u0; 8 void PF::bayes ( const vec &dt ) { 9 int i; 10 vec lls ( n ); 11 ivec ind; 12 double mlls=-std::numeric_limits<double>::infinity(), sum=0.0; 16 13 17 switch ( method ) { 18 case MULTINOMIAL: 19 u( n - 1 ) = pow( URNG.sample(), 1.0 / n ); 20 for ( i = n - 2;i >= 0;i-- ) { 21 u( i ) = u( i + 1 ) * pow( URNG.sample(), 1.0 / ( i + 1 ) ); 22 } 23 break; 24 case STRATIFIED: 25 for ( i = 0;i < n;i++ ) { 26 u( i ) = ( i + URNG.sample() ) / n; 27 } 28 break; 29 case SYSTEMATIC: 30 u0 = URNG.sample(); 31 for ( i = 0;i < n;i++ ) { 32 u( i ) = ( i + u0 ) / n; 33 } 34 break; 35 default: 36 it_error( "PF::resample(): Unknown resampling method" ); 37 } 38 39 // // <<<<<<<<<<< 40 // using std::cout; 41 // cout << "resampling:" << endl; 42 // cout << w <<endl; 43 // cout << cumDist <<endl; 44 // cout << u <<endl; 14 for ( i=0;i<n;i++ ) { 15 //generate new samples from paramater evolution model; 16 _samples ( i ) = par.samplecond ( _samples ( i ), lls ( i ) ); 17 lls ( i ) *= obs.evalcond ( dt,_samples ( i ) ); 45 18 46 // U is now full 47 j = 0; 48 for ( i = 0;i < n;i++ ) { 49 while ( u( i ) > cumDist( j ) ) j++; 50 N_babies( j )++; 19 if ( lls ( i ) >mlls ) mlls=lls ( i ); //find maximum 51 20 } 52 21 53 // // <<<<<<<<<<< 54 // cout << N_babies <<endl; 22 // compute weights 23 for ( i=0;i<n;i++ ) { 24 _w ( i ) *= exp ( lls ( i ) - mlls ); // multiply w by likelihood 25 } 55 26 56 // We have assigned new babies for each Particle 57 // Now, we fill the resulting index such that: 58 // * particles with at least one baby should not move * 59 // This assures that reassignment can be done inplace; 27 //renormalize 28 for ( i=0;i<n;i++ ) {sum+=_w ( i );}; 60 29 61 // find the first parent; 62 parent=0; while(N_babies(parent)==0) parent++; 63 // Build index 64 for ( i = 0;i < n;i++ ) { 65 if ( N_babies( i ) > 0 ){ 66 ind( i ) = i; 67 N_babies( i ) --; //this index was now replicated; 68 } 69 else { 70 // test if the parent has been fully replicated 71 // if yes, find the next one 72 while((N_babies(parent)==0) || (N_babies(parent)==1 && parent>i) ) parent++; 73 // Replicate parent 74 ind (i) = parent; 75 N_babies( parent ) --; //this index was now replicated; 76 } 77 /* // <<<<<<<<<<< 78 cout <<ind << endl;*/ 79 } 80 return ind; 30 _w ( i ) /=sum; //? 31 32 ind = est.resample(); 33 81 34 } 82 35 83 TrivialPF::TrivialPF( mpdf &par0, mpdf &obs0, BM &prop0, int n0 ) : PF(1/n*ones(n)) { 84 is_proposal = true; 85 prop = &prop0; 86 par = &par0; 87 obs = &obs0; 88 } 89 TrivialPF::TrivialPF( mpdf &par0, mpdf &obs0, int n0 ) : PF(1/n*ones(n)) { 90 is_proposal = false; 91 par = &par0; 92 obs = &obs0; 36 void PF::set_est ( const epdf &epdf0 ) { 37 int i; 38 39 for ( i=0;i<n;i++ ) { 40 _samples ( i ) = epdf0.sample(); 41 } 93 42 } 94 43 95 void TrivialPF::bayes( const vec &dt , bool evalll ) { 96 int i; 97 vec oldp; 98 double ll, gl, sum = 0.0; 99 Sort<double> S; 100 ivec ind, iw; 101 102 //generate new samples 103 for ( i=0;i<n;i++ ) { 104 if(is_proposal) { 105 epdf* prop_epdf; 106 // prop_epdf = prop._epdf(); 107 prop->bayes(dt); 108 ptcls( i ) = prop_epdf->sample(); 109 } 110 // gl = prop_cond.eval( ptcls( i ) ); 111 112 // obs.evalcond( ptcls( i ), &obs_cond ); 113 // ll = obs_cond.eval( dt ); 114 w( i ) *= ll/gl; 115 } 116 //renormalize 117 for ( i=0;i<n;i++ ){sum+=w( i );}; 118 w( i ) /=sum; //? 119 120 ind = resample(); 121 iw = S.sort_index( 0,n-1,w ); // the first one in iw is the strongest 122 123 for ( i=0;i<n;i++ ) { 124 ptcls( i ) = ptcls( i ); //potentionally dangerous! 125 } 126 127 } 44 //MPF::MPF:{} -
bdm/estim/libPF.h
r28 r32 15 15 16 16 #include <itpp/itbase.h> 17 #include "../stat/lib BM.h"17 #include "../stat/libEF.h" 18 18 #include "../math/libDC.h" 19 19 20 20 using namespace itpp; 21 21 22 enum RESAMPLING_METHOD { MULTINOMIAL = 0, STRATIFIED = 1, SYSTEMATIC = 3 }; 22 /*! 23 * \brief Trivial particle filter with proposal density equal to parameter evolution model. 23 24 24 /*! 25 * \brief A Particle Filter prototype25 Posterior density is represented by a weighted empirical density (\c eEmp ). 26 */ 26 27 27 Bayesian Filtering equations hold. 28 */ 29 class PF : public BM { 28 class PF : public BM { 30 29 protected: 31 int n; //number of particles 32 vec w; //particle weights 33 Uniform_RNG URNG; //used for resampling 34 30 //!number of particles; 31 int n; 32 //!posterior density 33 eEmp est; 34 //! pointer into \c eEmp 35 vec &_w; 36 //! pointer into \c eEmp 37 Array<vec> &_samples; 38 //! Parameter evolution model 39 mpdf ∥ 40 //! Observation model 41 mpdf &obs; 35 42 public: 36 //! Returns indexes of particles that should be resampled. The ordering MUST guarantee inplace replacement. (Important for MPF.) 37 ivec resample(RESAMPLING_METHOD method = SYSTEMATIC); 38 PF (vec w); 43 PF ( const RV &rv0, mpdf &par0, mpdf &obs0, int n0 ) :BM ( rv0 ), 44 n ( n0 ),est ( rv0,n ),_w ( est._w() ),_samples ( est._samples() ), 45 par ( par0 ), obs ( obs0 ) {}; 46 47 // void set_parametres(mpdf &par0, mpdf &obs0) {par=&par0;obs=&obs0;}; 48 void set_est ( const epdf &epdf0 ); 39 49 //TODO remove or implement bayes()! 40 void bayes(const vec &dt){}; 41 epdf* _epdf(){return NULL;} 50 void bayes ( const vec &dt ); 42 51 }; 43 52 44 53 /*! 45 * \brief Trivial particle filter with proposal density that is not conditioned on the data. 54 \brief Marginalized Particle filter 46 55 47 56 Trivial version: proposal $=$ parameter evolution, observation model is not used. (it is assumed to be part of BM). 48 57 */ 49 58 50 class TrivialPF : public PF { 51 Array<vec> ptcls; 52 53 bool is_proposal; 54 BM *prop; 55 mpdf *par; 56 mpdf *obs; 57 59 template<class BM_T> 60 61 class MPF : public PF { 62 BM_T* Bms[1000]; 63 64 //! internal class for MPDF providing composition of eEmp with external components 65 66 class mpfepdf : public epdf { 67 protected: 68 eEmp &E; 69 vec &_w; 70 Array<epdf*> Coms; 58 71 public: 59 TrivialPF(mpdf &par, mpdf &obs, BM &prop, int n0); 60 TrivialPF(mpdf &par, mpdf &obs, int n0); 61 void bayes(const vec &dt, bool evalll); 72 mpfepdf ( eEmp &E0, const RV &rvc ) : 73 epdf ( RV( ) ), E ( E0 ), _w ( E._w() ), 74 Coms ( _w.length() ) { 75 rv.add ( E._rv() ); 76 rv.add ( rvc ); 77 }; 78 79 void set_elements ( int &i, double wi, epdf* ep ) 80 {_w ( i ) =wi; Coms ( i ) =ep;}; 81 82 vec mean() const { 83 // ugly 84 vec pom=zeros ( ( Coms ( 0 )->_rv() ).count() ); 85 86 for ( int i=0; i<_w.length(); i++ ) {pom += Coms ( i )->mean() * _w ( i );} 87 88 return concat ( E.mean(),pom ); 89 } 90 91 vec sample() const {it_error ( "Not implemented" );return 0;} 92 93 double evalpdflog ( const vec &val ) const {it_error ( "not implemented" ); return 0.0;} 94 }; 95 96 //! estimate joining PF.est with conditional 97 mpfepdf jest; 98 99 public: 100 //! Default constructor. 101 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 ) { 102 // 103 //TODO test if rv and BMcond.rv are compatible. 104 rv.add ( rvlin ); 105 // 106 107 if ( n>1000 ) it_error ( "increase 1000 here!" ); 108 109 for ( int i=0;i<n;i++ ) { 110 Bms[i] = new BM_T ( BMcond0 ); //copy constructor 111 epdf& pom=Bms[i]->_epdf(); 112 jest.set_elements ( i,1.0/n,&pom ); 113 } 114 }; 115 116 ~MPF() { 117 } 118 119 void bayes ( const vec &dt ); 120 epdf& _epdf() {return jest;} 121 122 void set_est ( const epdf& epdf0 ) { 123 PF::set_est ( epdf0 ); // sample params in condition 124 // copy conditions to BMs 125 126 for ( int i=0;i<n;i++ ) {Bms[i]->condition ( _samples ( i ) );} 127 } 62 128 }; 63 129 64 class MPF : public TrivialPF { 65 Array<BM> Bms; 66 public: 67 MPF(BM &B, BM &prop, mpdf &obs, mpdf &par); 68 void bayes(vec &dt); 69 }; 130 template<class BM_T> 131 void MPF<BM_T>::bayes ( const vec &dt ) { 132 int i; 133 vec lls ( n ); 134 ivec ind; 135 double mlls=-std::numeric_limits<double>::infinity(); 136 double sum=0.0; 137 138 for ( i=0;i<n;i++ ) { 139 //generate new samples from paramater evolution model; 140 _samples ( i ) = par.samplecond ( _samples ( i ), lls ( i ) ); 141 Bms[i]->condition ( _samples ( i ) ); 142 Bms[i]->bayes ( dt ); 143 lls ( i ) += Bms[i]->_ll(); 144 145 if ( lls ( i ) >mlls ) mlls=lls ( i ); //find maximum likelihood (for numerical stability) 146 } 147 148 // compute weights 149 for ( i=0;i<n;i++ ) { 150 _w ( i ) *= exp ( lls ( i ) - mlls ); // multiply w by likelihood 151 } 152 153 //renormalize 154 for ( i=0;i<n;i++ ) {sum+=_w ( i );}; 155 156 _w /=sum; //? 157 158 if ( ( _w*_w ) < ( 0.5*n ) ) { 159 ind = est.resample(); 160 // Resample Bms! 161 162 for ( i=0;i<n;i++ ) { 163 if ( ind ( i ) !=i ) {//replace the current Bm by a new one 164 //fixme this would require new assignment operator 165 // *Bms[i] = *Bms[ind ( i ) ]; 166 167 // poor-man's solution: replicate constructor here 168 // copied from MPF::MPF 169 delete Bms[i]; 170 Bms[i] = new BM_T ( *Bms[ind ( i ) ] ); //copy constructor 171 epdf& pom=Bms[i]->_epdf(); 172 jest.set_elements ( i,1.0/n,&pom ); 173 } 174 }; 175 } 176 } 70 177 71 178 #endif // KF_H