root/library/bdm/estim/kalman.cpp @ 679

Revision 679, 7.6 kB (checked in by smidl, 15 years ago)

Major changes in BM -- OK is only test suite and tests/tutorial -- the rest is broken!!!

  • Property svn:eol-style set to native
Line 
1
2#include "kalman.h"
3
4namespace bdm {
5
6using std::endl;
7
8
9
10void KalmanFull::bayes ( const vec &yt, const vec &cond ) {
11        bdm_assert_debug ( yt.length() == ( dimy ), "KalmanFull::bayes wrong size of dt" );
12
13        const vec &u = cond; // in this case cond=ut
14        const vec &y = yt;
15       
16        vec& mu = est._mu();
17        mat &P = est._R();
18        mat& _Ry = fy._R();
19        vec& yp = fy._mu();
20        //Time update
21        mu = A * mu + B * u;
22        P  = A * P * A.transpose() + (mat)Q;
23
24        //Data update
25        _Ry = C * P * C.transpose() + (mat)R;
26        _K = P * C.transpose() * inv ( _Ry );
27        P -= _K * C * P; // P = P -KCP;
28        yp = C * mu + D * u;
29        mu += _K * ( y - yp );
30
31        if ( evalll ) {
32                ll=fy.evallog(y);
33        }
34};
35
36
37
38/////////////////////////////// EKFS
39EKFfull::EKFfull ( ) : KalmanFull () {};
40
41void EKFfull::set_parameters ( const shared_ptr<diffbifn> &pfxu0, const shared_ptr<diffbifn> &phxu0, const mat Q0, const mat R0 ) {
42        pfxu = pfxu0;
43        phxu = phxu0;
44
45        set_dim( pfxu0->_dimx());
46        dimy = phxu0->dimension();
47        dimc = pfxu0->_dimu();
48        est.set_parameters( zeros(dimension()), eye(dimension()) );
49
50        A.set_size ( dimension(), dimension() );
51        C.set_size ( dimy, dimension() );
52        //initialize matrices A C, later, these will be only updated!
53        pfxu->dfdx_cond ( est._mu(), zeros ( dimc ), A, true );
54        B.clear();
55        phxu->dfdx_cond ( est._mu(), zeros ( dimc ), C, true );
56        D.clear();
57
58        R = R0;
59        Q = Q0;
60}
61
62void EKFfull::bayes ( const vec &yt, const vec &cond) {
63        bdm_assert_debug ( yt.length() == ( dimy ), "EKFull::bayes wrong size of dt" );
64        bdm_assert_debug ( cond.length() == ( dimc ), "EKFull::bayes wrong size of dt" );
65       
66        const vec &u = cond;
67        const vec &y = yt; //lazy to change it
68        vec &mu = est._mu();
69        mat &P = est._R();
70        mat& _Ry = fy._R();
71        vec& yp = fy._mu();
72       
73        pfxu->dfdx_cond ( mu, zeros ( dimc ), A, true );
74        phxu->dfdx_cond ( mu, zeros ( dimc ), C, true );
75
76        //Time update
77        mu = pfxu->eval ( mu, u );// A*mu + B*u;
78        P  = A * P * A.transpose() + (mat)Q;
79
80        //Data update
81        _Ry = C * P * C.transpose() + (mat)R;
82        _K = P * C.transpose() * inv ( _Ry );
83        P -= _K * C * P; // P = P -KCP;
84        yp = phxu->eval ( mu, u );
85        mu += _K * ( y - yp );
86
87        if ( BM::evalll ) {
88                ll=fy.evallog(y);
89        }
90};
91
92
93
94void KalmanCh::set_parameters ( const mat &A0, const mat &B0, const mat &C0, const mat &D0, const chmat &Q0, const chmat &R0 ) {
95
96        ( ( StateSpace<chmat>* ) this )->set_parameters ( A0, B0, C0, D0, Q0, R0 );
97       
98        _K=zeros(dimension(),dimy);
99}
100
101void KalmanCh::initialize(){
102        preA = zeros ( dimy + dimension() + dimension(), dimy + dimension() );
103//      preA.clear();
104        preA.set_submatrix ( 0, 0, R._Ch() );
105        preA.set_submatrix ( dimy + dimension(), dimy, Q._Ch() );
106}
107
108void KalmanCh::bayes ( const vec &yt, const vec &cond ) {
109        bdm_assert_debug(yt.length()==dimy, "yt mismatch");
110        bdm_assert_debug(cond.length()==dimc, "yt mismatch");
111       
112        const vec &u = cond;
113        const vec &y = yt;
114        vec pom ( dimy );
115
116        chmat &_P=est._R();
117        vec &_mu = est._mu();
118        mat _K(dimension(),dimy);
119        chmat &_Ry=fy._R();
120        vec &_yp = fy._mu();
121        //TODO get rid of Q in qr()!
122//      mat Q;
123
124        //R and Q are already set in set_parameters()
125        preA.set_submatrix ( dimy, 0, ( _P._Ch() ) *C.T() );
126        //Fixme can be more efficient if .T() is not used
127        preA.set_submatrix ( dimy, dimy, ( _P._Ch() ) *A.T() );
128
129        if ( !qr ( preA, postA ) ) {
130                bdm_warning ( "QR in KalmanCh unstable!" );
131        }
132
133        ( _Ry._Ch() ) = postA ( 0, dimy - 1, 0, dimy - 1 );
134        _K = inv ( A ) * ( postA ( 0, dimy - 1 , dimy, dimy + dimension() - 1 ) ).T();
135        ( _P._Ch() ) = postA ( dimy, dimy + dimension() - 1, dimy, dimy + dimension() - 1 );
136
137        _mu = A * ( _mu ) + B * u;
138        _yp = C * _mu - D * u;
139
140        backward_substitution ( _Ry._Ch(), ( y - _yp ), pom );
141        _mu += ( _K ) * pom;
142
143        /*              cout << "P:" <<_P.to_mat() <<endl;
144                        cout << "Ry:" <<_Ry.to_mat() <<endl;
145                        cout << "_K:" <<_K <<endl;*/
146
147        if ( evalll == true ) { //likelihood of observation y
148                ll = fy.evallog ( y );
149        }
150}
151
152
153
154void EKFCh::set_parameters ( const shared_ptr<diffbifn> &pfxu0, const shared_ptr<diffbifn> &phxu0, const chmat Q0, const chmat R0 ) {
155        pfxu = pfxu0;
156        phxu = phxu0;
157
158        set_dim( pfxu0->_dimx());
159        dimy = phxu0->dimension();
160        dimc = pfxu0->_dimu();
161       
162        vec &_mu = est._mu();
163        // if mu is not set, set it to zeros, just for constant terms of A and C
164        if ( _mu.length() != dimension() ) _mu = zeros ( dimension() ); 
165        A = zeros ( dimension(), dimension() );
166        C = zeros ( dimy, dimension() );
167        preA = zeros ( dimy + dimension() + dimension(), dimy + dimension() );
168
169        //initialize matrices A C, later, these will be only updated!
170        pfxu->dfdx_cond ( _mu, zeros ( dimc ), A, true );
171//      pfxu->dfdu_cond ( *_mu,zeros ( dimu ),B,true );
172        B.clear();
173        phxu->dfdx_cond ( _mu, zeros ( dimc ), C, true );
174//      phxu->dfdu_cond ( *_mu,zeros ( dimu ),D,true );
175        D.clear();
176
177        R = R0;
178        Q = Q0;
179
180        // Cholesky special!
181        preA.clear();
182        preA.set_submatrix ( 0, 0, R._Ch() );
183        preA.set_submatrix ( dimy + dimension(), dimy, Q._Ch() );
184}
185
186
187void EKFCh::bayes ( const vec &yt, const vec &cond ) {
188
189        vec pom ( dimy );
190        const vec &u = cond;
191        const vec &y = yt;
192        vec &_mu = est._mu();
193        chmat &_P = est._R();
194        chmat &_Ry = fy._R();
195        vec &_yp = fy._mu();
196       
197        pfxu->dfdx_cond ( _mu, u, A, false ); //update A by a derivative of fx
198        phxu->dfdx_cond ( _mu, u, C, false ); //update A by a derivative of fx
199
200        //R and Q are already set in set_parameters()
201        preA.set_submatrix ( dimy, 0, ( _P._Ch() ) *C.T() );
202        //Fixme can be more efficient if .T() is not used
203        preA.set_submatrix ( dimy, dimy, ( _P._Ch() ) *A.T() );
204
205//      mat Sttm = _P->to_mat();
206//      cout << preA <<endl;
207//      cout << "_mu:" << _mu <<endl;
208
209        if ( !qr ( preA, postA ) ) {
210                bdm_warning ( "QR in EKFCh unstable!" );
211        }
212
213
214        ( _Ry._Ch() ) = postA ( 0, dimy - 1, 0, dimy - 1 );
215        _K = inv ( A ) * ( postA ( 0, dimy - 1 , dimy, dimy + dimension() - 1 ) ).T();
216        ( _P._Ch() ) = postA ( dimy, dimy + dimension() - 1, dimy, dimy + dimension() - 1 );
217
218//      mat iRY = inv(_Ry->to_mat());
219//      mat Stt = Sttm - Sttm * C.T() * iRY * C * Sttm;
220//      mat _K2 = Stt*C.T()*inv(R.to_mat());
221
222        // prediction
223        _mu = pfxu->eval ( _mu , u );
224        _yp = phxu->eval ( _mu, u );
225
226        /*      vec mu2 = *_mu + ( _K2 ) * ( y-*_yp );*/
227
228        //correction //= initial value is already prediction!
229        backward_substitution ( _Ry._Ch(), ( y - _yp ), pom );
230        _mu += ( _K ) * pom ;
231
232        /*      _K = (_P->to_mat())*C.transpose() * ( _iRy->to_mat() );
233                *_mu = pfxu->eval ( *_mu ,u ) + ( _K )* ( y-*_yp );*/
234
235//              cout << "P:" <<_P.to_mat() <<endl;
236//              cout << "Ry:" <<_Ry.to_mat() <<endl;
237//      cout << "_mu:" <<_mu <<endl;
238//      cout << "dt:" <<dt <<endl;
239
240        if ( evalll == true ) { //likelihood of observation y
241                ll = fy.evallog ( y );
242        }
243}
244
245void EKFCh::from_setting ( const Setting &set ) {
246        shared_ptr<diffbifn> IM = UI::build<diffbifn> ( set, "IM", UI::compulsory );
247        shared_ptr<diffbifn> OM = UI::build<diffbifn> ( set, "OM", UI::compulsory );
248
249        //statistics
250        int dim = IM->dimension();
251        vec mu0;
252        if ( !UI::get ( mu0, set, "mu0" ) )
253                mu0 = zeros ( dim );
254
255        mat P0;
256        vec dP0;
257        if ( UI::get ( dP0, set, "dP0" ) )
258                P0 = diag ( dP0 );
259        else if ( !UI::get ( P0, set, "P0" ) )
260                P0 = eye ( dim );
261
262        set_statistics ( mu0, P0 );
263
264        //parameters
265        vec dQ, dR;
266        UI::get ( dQ, set, "dQ", UI::compulsory );
267        UI::get ( dR, set, "dR", UI::compulsory );
268        set_parameters ( IM, OM, diag ( dQ ), diag ( dR ) );
269
270        //connect
271        shared_ptr<RV> drv = UI::build<RV> ( set, "drv", UI::compulsory );
272        set_yrv ( *drv );
273        shared_ptr<RV> rv = UI::build<RV> ( set, "rv", UI::compulsory );
274        set_rv ( *rv );
275
276        string options;
277        if ( UI::get ( options, set, "options" ) )
278                set_options ( options );
279}
280
281void MultiModel::from_setting ( const Setting &set ) {
282        Array<EKFCh*> A;
283        UI::get ( A, set, "models", UI::compulsory );
284
285        set_parameters ( A );
286        set_yrv ( A ( 0 )->_yrv() );
287        //set_rv(A(0)->_rv());
288
289        string options;
290        if ( set.lookupValue ( "options", options ) )
291                set_options ( options );
292}
293
294}
Note: See TracBrowser for help on using the browser.