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 {
00024 
00029         class KalmanFull
00030         {
00031                 protected:
00032                         int dimx, dimy, dimu;
00033                         mat A, B, C, D, R, Q;
00034 
00035                         
00036                         mat _Pp, _Ry, _iRy, _K;
00037                 public:
00038                         
00040                         vec mu;
00042                         mat P;
00043 
00044                         bool evalll;
00045                         double ll;
00046                 public:
00048                         KalmanFull ( mat A, mat B, mat C, mat D, mat R, mat Q, mat P0, vec mu0 );
00050                         void bayes ( const vec &dt );
00052                         friend std::ostream &operator<< ( std::ostream &os, const KalmanFull &kf );
00054                         KalmanFull() {};
00055         };
00056 
00057 
00065         template<class sq_T>
00066 
00067         class Kalman : public BM
00068         {
00069                 protected:
00071                         RV rvy;
00073                         RV rvu;
00075                         int dimx;
00077                         int dimy;
00079                         int dimu;
00081                         mat A;
00083                         mat B;
00085                         mat C;
00087                         mat D;
00089                         sq_T Q;
00091                         sq_T R;
00092 
00094                         enorm<sq_T> est;
00096                         enorm<sq_T> fy;
00097 
00099                         mat _K;
00101                         vec& _yp;
00103                         sq_T& _Ry;
00105                         vec& _mu;
00107                         sq_T& _P;
00108 
00109                 public:
00111                         Kalman ( );
00113                         Kalman ( const Kalman<sq_T> &K0 );
00115                         void set_parameters ( const mat &A0,const mat &B0,const mat &C0,const mat &D0,const sq_T &Q0,const sq_T &R0 );
00117                         void set_est ( const vec &mu0, const sq_T &P0 )
00118                         {
00119                                 sq_T pom ( dimy );
00120                                 est.set_parameters ( mu0,P0 );
00121                                 P0.mult_sym ( C,pom );
00122                                 fy.set_parameters ( C*mu0, pom );
00123                         };
00124 
00126                         void bayes ( const vec &dt );
00128                         const epdf& posterior() const {return est;}
00129                         const enorm<sq_T>* _e() const {return &est;}
00131                         mat& __K() {return _K;}
00133                         vec _dP() {return _P->getD();}
00134         };
00135 
00142         class KalmanCh : public Kalman<chmat>
00143         {
00144                 protected:
00146                         mat preA;
00148                         mat postA;
00149 
00150                 public:
00152                         BM* _copy_() const
00153                         {
00154                                 KalmanCh* K=new KalmanCh;
00155                                 K->set_parameters ( A,B,C,D,Q,R );
00156                                 K->set_statistics ( _mu,_P );
00157                                 return K;
00158                         }
00160                         void set_parameters ( const mat &A0,const mat &B0,const mat &C0,const mat &D0,const chmat &Q0,const chmat &R0 );
00161                         void set_statistics ( const vec &mu0, const chmat &P0 )
00162                         {
00163                                 est.set_parameters ( mu0,P0 );
00164                         };
00165 
00166 
00180                         void bayes ( const vec &dt );
00181         };
00182 
00188         class EKFfull : public KalmanFull, public BM
00189         {
00190                 protected:
00192                         diffbifn* pfxu;
00194                         diffbifn* phxu;
00195 
00196                         enorm<fsqmat> E;
00197                 public:
00199                         EKFfull ( );
00201                         void set_parameters ( diffbifn* pfxu, diffbifn* phxu, const mat Q0, const mat R0 );
00203                         void bayes ( const vec &dt );
00205                         void set_statistics ( vec mu0, mat P0 ) {mu=mu0;P=P0;};
00207                         const epdf& posterior() const{return E;};
00208                         const enorm<fsqmat>* _e() const{return &E;};
00209                         const mat _R() {return P;}
00210         };
00211 
00217         template<class sq_T>
00218         class EKF : public Kalman<fsqmat>
00219         {
00221                         diffbifn* pfxu;
00223                         diffbifn* phxu;
00224                 public:
00226                         EKF ( RV rvx, RV rvy, RV rvu );
00228                         EKF<sq_T>* _copy_() const { return new EKF<sq_T> ( this ); }
00230                         void set_parameters ( diffbifn* pfxu, diffbifn* phxu, const sq_T Q0, const sq_T R0 );
00232                         void bayes ( const vec &dt );
00233         };
00234 
00241         class EKFCh : public KalmanCh
00242         {
00243                 protected:
00245                         diffbifn* pfxu;
00247                         diffbifn* phxu;
00248                 public:
00250                         BM* _copy_() const
00251                         {
00252                                 EKFCh* E=new EKFCh;
00253                                 E->set_parameters ( pfxu,phxu,Q,R );
00254                                 E->set_statistics ( _mu,_P );
00255                                 return E;
00256                         }
00258                         void set_parameters ( diffbifn* pfxu, diffbifn* phxu, const chmat Q0, const chmat R0 );
00260                         void bayes ( const vec &dt );
00261 
00262                         void from_setting( const Setting &set );
00263 
00264                         
00265 
00266         };
00267 
00268         UIREGISTER(EKFCh);
00269 
00270 
00275         class KFcondQR : public Kalman<ldmat>
00276         {
00277 
00278                 public:
00279                         void condition ( const vec &QR )
00280                         {
00281                                 it_assert_debug ( QR.length() == ( dimx+dimy ),"KFcondRQ: conditioning by incompatible vector" );
00282 
00283                                 Q.setD ( QR ( 0, dimx-1 ) );
00284                                 R.setD ( QR ( dimx, -1 ) );
00285                         };
00286         };
00287 
00292         class KFcondR : public Kalman<ldmat>
00293         {
00294 
00295                 public:
00297                         KFcondR ( ) : Kalman<ldmat> ( ) {};
00298 
00299                         void condition ( const vec &R0 )
00300                         {
00301                                 it_assert_debug ( R0.length() == ( dimy ),"KFcondR: conditioning by incompatible vector" );
00302 
00303                                 R.setD ( R0 );
00304                         };
00305 
00306         };
00307 
00309 
00310         template<class sq_T>
00311         Kalman<sq_T>::Kalman ( const Kalman<sq_T> &K0 ) : BM ( ),rvy ( K0.rvy ),rvu ( K0.rvu ),
00312                         dimx ( K0.dimx ), dimy ( K0.dimy ),dimu ( K0.dimu ),
00313                         A ( K0.A ), B ( K0.B ), C ( K0.C ), D ( K0.D ),
00314                         Q ( K0.Q ), R ( K0.R ),
00315                         est ( K0.est ), fy ( K0.fy ), _yp ( fy._mu() ),_Ry ( fy._R() ), _mu ( est._mu() ), _P ( est._R() )
00316         {
00317 
00318 
00319 
00320 
00321 
00322 
00323 
00324         }
00325 
00326         template<class sq_T>
00327         Kalman<sq_T>::Kalman ( ) : BM (), est ( ), fy (),  _yp ( fy._mu() ), _Ry ( fy._R() ), _mu ( est._mu() ), _P ( est._R() )
00328         {
00329         };
00330 
00331         template<class sq_T>
00332         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 )
00333         {
00334                 dimx = A0.rows();
00335                 dimy = C0.rows();
00336                 dimu = B0.cols();
00337 
00338                 it_assert_debug ( A0.cols() ==dimx, "Kalman: A is not square" );
00339                 it_assert_debug ( B0.rows() ==dimx, "Kalman: B is not compatible" );
00340                 it_assert_debug ( C0.cols() ==dimx, "Kalman: C is not square" );
00341                 it_assert_debug ( ( D0.rows() ==dimy ) || ( D0.cols() ==dimu ), "Kalman: D is not compatible" );
00342                 it_assert_debug ( ( R0.cols() ==dimy ) || ( R0.rows() ==dimy ), "Kalman: R is not compatible" );
00343                 it_assert_debug ( ( Q0.cols() ==dimx ) || ( Q0.rows() ==dimx ), "Kalman: Q is not compatible" );
00344 
00345                 A = A0;
00346                 B = B0;
00347                 C = C0;
00348                 D = D0;
00349                 R = R0;
00350                 Q = Q0;
00351         }
00352 
00353         template<class sq_T>
00354         void Kalman<sq_T>::bayes ( const vec &dt )
00355         {
00356                 it_assert_debug ( dt.length() == ( dimy+dimu ),"KalmanFull::bayes wrong size of dt" );
00357 
00358                 sq_T iRy ( dimy );
00359                 vec u = dt.get ( dimy,dimy+dimu-1 );
00360                 vec y = dt.get ( 0,dimy-1 );
00361                 
00362                 _mu = A* _mu + B*u;
00363                 
00364                 _P.mult_sym ( A );
00365                 _P  +=Q;
00366 
00367                 
00368                 
00369                 _P.mult_sym ( C, _Ry );
00370                 _Ry  +=R;
00371 
00372                 mat Pfull = _P.to_mat();
00373 
00374                 _Ry.inv ( iRy ); 
00375                 _K = Pfull*C.transpose() * ( iRy.to_mat() );
00376 
00377                 sq_T pom ( ( int ) Pfull.rows() );
00378                 iRy.mult_sym_t ( C*Pfull,pom );
00379                 ( _P ) -= pom; 
00380                 ( _yp ) = C* _mu  +D*u; 
00381                 ( _mu ) += _K* ( y- _yp );
00382 
00383 
00384                 if ( evalll==true )   
00385                 {
00386                         ll=fy.evallog ( y );
00387                 }
00388 
00389 
00390 
00391         };
00392 
00400         class MultiModel: public BM
00401         {
00402                 protected:
00404                         Array<EKFCh*> Models;
00406                         vec w;
00408                         vec _lls;
00410                         int policy;
00412                         enorm<chmat> est;
00413                 public:
00414                         void set_parameters ( Array<EKFCh*> A, int pol0=1 )
00415                         {
00416                                 Models=A;
00417                                 w.set_length ( A.length() );
00418                                 _lls.set_length ( A.length() );
00419                                 policy=pol0;
00420                                 
00421                                 est.set_rv(RV("MM",A(0)->posterior().dimension(),0));
00422                                 est.set_parameters(A(0)->_e()->mean(), A(0)->_e()->_R());
00423                         }
00424                         void bayes ( const vec &dt )
00425                         {
00426                                 int n = Models.length();
00427                                 int i;
00428                                 for ( i=0;i<n;i++ )
00429                                 {
00430                                         Models ( i )->bayes ( dt );
00431                                         _lls ( i ) = Models ( i )->_ll();
00432                                 }
00433                                 double mlls=max ( _lls );
00434                                 w=exp ( _lls-mlls );
00435                                 w/=sum ( w ); 
00436                                 
00437                                 switch ( policy )
00438                                 {
00439                                         case 1:
00440                                         {
00441                                                 int mi=max_index ( w );
00442                                                 const enorm<chmat>* st=(Models(mi)->_e());
00443                                                 est.set_parameters(st->mean(), st->_R());
00444                                         }
00445                                         break;
00446                                         default: it_error ( "unknown policy" );
00447                                 }
00448                                 
00449                                 for ( i=0;i<n;i++ )
00450                                 {
00451                                                 Models ( i )->set_statistics ( est.mean(),est._R());
00452                                 }
00453                         }
00454                         
00455                         const enorm<chmat>* _e() const {return &est;}
00456                                 
00457                         const enorm<chmat>& posterior() const {return est;}
00458 
00459                         void from_setting( const Setting &set );
00460 
00461                         
00462 
00463         };
00464 
00465         UIREGISTER(MultiModel);
00466 
00467 
00468 
00469 
00470 
00471         template<class sq_T>
00472         EKF<sq_T>::EKF ( RV rvx0, RV rvy0, RV rvu0 ) : Kalman<sq_T> ( rvx0,rvy0,rvu0 ) {}
00473 
00474         template<class sq_T>
00475         void EKF<sq_T>::set_parameters ( diffbifn* pfxu0,  diffbifn* phxu0,const sq_T Q0,const sq_T R0 )
00476         {
00477                 pfxu = pfxu0;
00478                 phxu = phxu0;
00479 
00480                 
00481                 pfxu->dfdx_cond ( _mu,zeros ( dimu ),A,true );
00482 
00483                 B.clear();
00484                 phxu->dfdx_cond ( _mu,zeros ( dimu ),C,true );
00485 
00486                 D.clear();
00487 
00488                 R = R0;
00489                 Q = Q0;
00490         }
00491 
00492         template<class sq_T>
00493         void EKF<sq_T>::bayes ( const vec &dt )
00494         {
00495                 it_assert_debug ( dt.length() == ( dimy+dimu ),"KalmanFull::bayes wrong size of dt" );
00496 
00497                 sq_T iRy ( dimy,dimy );
00498                 vec u = dt.get ( dimy,dimy+dimu-1 );
00499                 vec y = dt.get ( 0,dimy-1 );
00500                 
00501                 _mu = pfxu->eval ( _mu, u );
00502                 pfxu->dfdx_cond ( _mu,u,A,false ); 
00503 
00504                 
00505                 _P.mult_sym ( A );
00506                 _P +=Q;
00507 
00508                 
00509                 phxu->dfdx_cond ( _mu,u,C,false ); 
00510                 
00511                 _P.mult_sym ( C, _Ry );
00512                 ( _Ry ) +=R;
00513 
00514                 mat Pfull = _P.to_mat();
00515 
00516                 _Ry.inv ( iRy ); 
00517                 _K = Pfull*C.transpose() * ( iRy.to_mat() );
00518 
00519                 sq_T pom ( ( int ) Pfull.rows() );
00520                 iRy.mult_sym_t ( C*Pfull,pom );
00521                 ( _P ) -= pom; 
00522                 _yp = phxu->eval ( _mu,u ); 
00523                 ( _mu ) += _K* ( y-_yp );
00524 
00525                 if ( evalll==true ) {ll+=fy.evallog ( y );}
00526         };
00527 
00528 
00529 }
00530 #endif // KF_H
00531 
00532