00001
00013 #ifndef KF_H
00014 #define KF_H
00015
00016
00017 #include "../math/functions.h"
00018 #include "../stat/exp_family.h"
00019 #include "../math/chmat.h"
00020 #include "../base/user_info.h"
00021
00022 namespace bdm {
00023
00028 class KalmanFull {
00029 protected:
00030 int dimx, dimy, dimu;
00031 mat A, B, C, D, R, Q;
00032
00033
00034 mat _Pp, _Ry, _iRy, _K;
00035 public:
00036
00038 vec mu;
00040 mat P;
00041
00042 bool evalll;
00043 double ll;
00044 public:
00046 KalmanFull ( mat A, mat B, mat C, mat D, mat R, mat Q, mat P0, vec mu0 );
00048 void bayes ( const vec &dt );
00050 friend std::ostream &operator<< ( std::ostream &os, const KalmanFull &kf );
00052 KalmanFull() {};
00053 };
00054
00055
00063 template<class sq_T>
00064
00065 class Kalman : public BM {
00066 protected:
00068 RV rvy;
00070 RV rvu;
00072 int dimx;
00074 int dimy;
00076 int dimu;
00078 mat A;
00080 mat B;
00082 mat C;
00084 mat D;
00086 sq_T Q;
00088 sq_T R;
00089
00091 enorm<sq_T> est;
00093 enorm<sq_T> fy;
00094
00096 mat _K;
00098 vec& _yp;
00100 sq_T& _Ry;
00102 vec& _mu;
00104 sq_T& _P;
00105
00106 public:
00108 Kalman ( );
00110 Kalman ( const Kalman<sq_T> &K0 );
00112 void set_parameters ( const mat &A0, const mat &B0, const mat &C0, const mat &D0, const sq_T &Q0, const sq_T &R0 );
00114 void set_est ( const vec &mu0, const sq_T &P0 ) {
00115 sq_T pom ( dimy );
00116 est.set_parameters ( mu0, P0 );
00117 P0.mult_sym ( C, pom );
00118 fy.set_parameters ( C*mu0, pom );
00119 };
00120
00122 void bayes ( const vec &dt );
00124 const epdf& posterior() const {
00125 return est;
00126 }
00128 mat& __K() {
00129 return _K;
00130 }
00132 vec _dP() {
00133 return _P->getD();
00134 }
00135 };
00136
00143 class KalmanCh : public Kalman<chmat> {
00144 protected:
00146 mat preA;
00148 mat postA;
00149
00150 public:
00152 BM* _copy_() const {
00153 KalmanCh* K = new KalmanCh;
00154 K->set_parameters ( A, B, C, D, Q, R );
00155 K->set_statistics ( _mu, _P );
00156 return K;
00157 }
00159 void set_parameters ( const mat &A0, const mat &B0, const mat &C0, const mat &D0, const chmat &Q0, const chmat &R0 );
00160 void set_statistics ( const vec &mu0, const chmat &P0 ) {
00161 est.set_parameters ( mu0, P0 );
00162 };
00163
00164
00178 void bayes ( const vec &dt );
00179 };
00180
00186 class EKFfull : public KalmanFull, public BM {
00187 protected:
00189 shared_ptr<diffbifn> pfxu;
00190
00192 shared_ptr<diffbifn> phxu;
00193
00194 enorm<fsqmat> E;
00195 public:
00197 EKFfull ( );
00198
00200 void set_parameters ( const shared_ptr<diffbifn> &pfxu, const shared_ptr<diffbifn> &phxu, const mat Q0, const mat R0 );
00201
00203 void bayes ( const vec &dt );
00205 void set_statistics ( vec mu0, mat P0 ) {
00206 mu = mu0;
00207 P = P0;
00208 };
00210 const epdf& posterior() const {
00211 return E;
00212 };
00213 const mat _R() {
00214 return P;
00215 }
00216 };
00217
00223 template<class sq_T>
00224 class EKF : public Kalman<fsqmat> {
00226 diffbifn* pfxu;
00228 diffbifn* phxu;
00229 public:
00231 EKF ( RV rvx, RV rvy, RV rvu );
00233 EKF<sq_T>* _copy_() const {
00234 return new EKF<sq_T> ( this );
00235 }
00237 void set_parameters ( diffbifn* pfxu, diffbifn* phxu, const sq_T Q0, const sq_T R0 );
00239 void bayes ( const vec &dt );
00240 };
00241
00248 class EKFCh : public KalmanCh {
00249 protected:
00251 shared_ptr<diffbifn> pfxu;
00252
00254 shared_ptr<diffbifn> phxu;
00255 public:
00257 BM* _copy_() const {
00258 EKFCh* E = new EKFCh;
00259 E->set_parameters ( pfxu, phxu, Q, R );
00260 E->set_statistics ( _mu, _P );
00261 return E;
00262 }
00264 void set_parameters ( const shared_ptr<diffbifn> &pfxu, const shared_ptr<diffbifn> &phxu, const chmat Q0, const chmat R0 );
00265
00267 void bayes ( const vec &dt );
00268
00269 void from_setting ( const Setting &set );
00270
00271
00272
00273 const enorm<chmat>& posterior() {return est;}
00274 };
00275
00276 UIREGISTER ( EKFCh );
00277 SHAREDPTR ( EKFCh );
00278
00279
00284 class KFcondQR : public Kalman<ldmat> {
00285
00286 public:
00287 void condition ( const vec &QR ) {
00288 it_assert_debug ( QR.length() == ( dimx + dimy ), "KFcondRQ: conditioning by incompatible vector" );
00289
00290 Q.setD ( QR ( 0, dimx - 1 ) );
00291 R.setD ( QR ( dimx, -1 ) );
00292 };
00293 };
00294
00299 class KFcondR : public Kalman<ldmat> {
00300
00301 public:
00303 KFcondR ( ) : Kalman<ldmat> ( ) {};
00304
00305 void condition ( const vec &R0 ) {
00306 it_assert_debug ( R0.length() == ( dimy ), "KFcondR: conditioning by incompatible vector" );
00307
00308 R.setD ( R0 );
00309 };
00310
00311 };
00312
00314
00315 template<class sq_T>
00316 Kalman<sq_T>::Kalman ( const Kalman<sq_T> &K0 ) : BM ( ), rvy ( K0.rvy ), rvu ( K0.rvu ),
00317 dimx ( K0.dimx ), dimy ( K0.dimy ), dimu ( K0.dimu ),
00318 A ( K0.A ), B ( K0.B ), C ( K0.C ), D ( K0.D ),
00319 Q ( K0.Q ), R ( K0.R ),
00320 est ( K0.est ), fy ( K0.fy ), _yp ( fy._mu() ), _Ry ( fy._R() ), _mu ( est._mu() ), _P ( est._R() ) {
00321
00322
00323
00324
00325
00326
00327
00328 }
00329
00330 template<class sq_T>
00331 Kalman<sq_T>::Kalman ( ) : BM (), est ( ), fy (), _yp ( fy._mu() ), _Ry ( fy._R() ), _mu ( est._mu() ), _P ( est._R() ) {
00332 };
00333
00334 template<class sq_T>
00335 void Kalman<sq_T>::set_parameters ( const mat &A0, const mat &B0, const mat &C0, const mat &D0, const sq_T &Q0, const sq_T &R0 ) {
00336 dimx = A0.rows();
00337 dimy = C0.rows();
00338 dimu = B0.cols();
00339
00340 it_assert_debug ( A0.cols() == dimx, "Kalman: A is not square" );
00341 it_assert_debug ( B0.rows() == dimx, "Kalman: B is not compatible" );
00342 it_assert_debug ( C0.cols() == dimx, "Kalman: C is not square" );
00343 it_assert_debug ( ( D0.rows() == dimy ) || ( D0.cols() == dimu ), "Kalman: D is not compatible" );
00344 it_assert_debug ( ( R0.cols() == dimy ) || ( R0.rows() == dimy ), "Kalman: R is not compatible" );
00345 it_assert_debug ( ( Q0.cols() == dimx ) || ( Q0.rows() == dimx ), "Kalman: Q is not compatible" );
00346
00347 A = A0;
00348 B = B0;
00349 C = C0;
00350 D = D0;
00351 R = R0;
00352 Q = Q0;
00353 }
00354
00355 template<class sq_T>
00356 void Kalman<sq_T>::bayes ( const vec &dt ) {
00357 it_assert_debug ( dt.length() == ( dimy + dimu ), "KalmanFull::bayes wrong size of dt" );
00358
00359 sq_T iRy ( dimy );
00360 vec u = dt.get ( dimy, dimy + dimu - 1 );
00361 vec y = dt.get ( 0, dimy - 1 );
00362
00363 _mu = A * _mu + B * u;
00364
00365 _P.mult_sym ( A );
00366 _P += Q;
00367
00368
00369
00370 _P.mult_sym ( C, _Ry );
00371 _Ry += R;
00372
00373 mat Pfull = _P.to_mat();
00374
00375 _Ry.inv ( iRy );
00376 _K = Pfull * C.transpose() * ( iRy.to_mat() );
00377
00378 sq_T pom ( ( int ) Pfull.rows() );
00379 iRy.mult_sym_t ( C*Pfull, pom );
00380 ( _P ) -= pom;
00381 ( _yp ) = C * _mu + D * u;
00382 ( _mu ) += _K * ( y - _yp );
00383
00384
00385 if ( evalll == true ) {
00386 ll = fy.evallog ( y );
00387 }
00388
00389
00390
00391 };
00392
00400 class MultiModel: public BM {
00401 protected:
00403 Array<EKFCh*> Models;
00405 vec w;
00407 vec _lls;
00409 int policy;
00411 enorm<chmat> est;
00412 public:
00413 void set_parameters ( Array<EKFCh*> A, int pol0 = 1 ) {
00414 Models = A;
00415 w.set_length ( A.length() );
00416 _lls.set_length ( A.length() );
00417 policy = pol0;
00418
00419 est.set_rv ( RV ( "MM", A ( 0 )->posterior().dimension(), 0 ) );
00420 est.set_parameters ( A ( 0 )->posterior().mean(), A ( 0 )->posterior()._R() );
00421 }
00422 void bayes ( const vec &dt ) {
00423 int n = Models.length();
00424 int i;
00425 for ( i = 0; i < n; i++ ) {
00426 Models ( i )->bayes ( dt );
00427 _lls ( i ) = Models ( i )->_ll();
00428 }
00429 double mlls = max ( _lls );
00430 w = exp ( _lls - mlls );
00431 w /= sum ( w );
00432
00433 switch ( policy ) {
00434 case 1: {
00435 int mi = max_index ( w );
00436 const enorm<chmat> &st = Models ( mi )->posterior() ;
00437 est.set_parameters ( st.mean(), st._R() );
00438 }
00439 break;
00440 default:
00441 it_error ( "unknown policy" );
00442 }
00443
00444 for ( i = 0; i < n; i++ ) {
00445 Models ( i )->set_statistics ( est.mean(), est._R() );
00446 }
00447 }
00449 const enorm<chmat>& posterior() const {
00450 return est;
00451 }
00452
00453 void from_setting ( const Setting &set );
00454
00455
00456
00457 };
00458
00459 UIREGISTER ( MultiModel );
00460 SHAREDPTR ( MultiModel );
00461
00462
00463
00464
00465
00466 template<class sq_T>
00467 EKF<sq_T>::EKF ( RV rvx0, RV rvy0, RV rvu0 ) : Kalman<sq_T> ( rvx0, rvy0, rvu0 ) {}
00468
00469 template<class sq_T>
00470 void EKF<sq_T>::set_parameters ( diffbifn* pfxu0, diffbifn* phxu0, const sq_T Q0, const sq_T R0 ) {
00471 pfxu = pfxu0;
00472 phxu = phxu0;
00473
00474
00475 pfxu->dfdx_cond ( _mu, zeros ( dimu ), A, true );
00476
00477 B.clear();
00478 phxu->dfdx_cond ( _mu, zeros ( dimu ), C, true );
00479
00480 D.clear();
00481
00482 R = R0;
00483 Q = Q0;
00484 }
00485
00486 template<class sq_T>
00487 void EKF<sq_T>::bayes ( const vec &dt ) {
00488 it_assert_debug ( dt.length() == ( dimy + dimu ), "KalmanFull::bayes wrong size of dt" );
00489
00490 sq_T iRy ( dimy, dimy );
00491 vec u = dt.get ( dimy, dimy + dimu - 1 );
00492 vec y = dt.get ( 0, dimy - 1 );
00493
00494 _mu = pfxu->eval ( _mu, u );
00495 pfxu->dfdx_cond ( _mu, u, A, false );
00496
00497
00498 _P.mult_sym ( A );
00499 _P += Q;
00500
00501
00502 phxu->dfdx_cond ( _mu, u, C, false );
00503
00504 _P.mult_sym ( C, _Ry );
00505 ( _Ry ) += R;
00506
00507 mat Pfull = _P.to_mat();
00508
00509 _Ry.inv ( iRy );
00510 _K = Pfull * C.transpose() * ( iRy.to_mat() );
00511
00512 sq_T pom ( ( int ) Pfull.rows() );
00513 iRy.mult_sym_t ( C*Pfull, pom );
00514 ( _P ) -= pom;
00515 _yp = phxu->eval ( _mu, u );
00516 ( _mu ) += _K * ( y - _yp );
00517
00518 if ( evalll == true ) {
00519 ll += fy.evallog ( y );
00520 }
00521 };
00522
00523
00524 }
00525 #endif // KF_H
00526
00527