1 | |
---|
2 | #include "libKF.h" |
---|
3 | |
---|
4 | namespace bdm{ |
---|
5 | |
---|
6 | using std::endl; |
---|
7 | |
---|
8 | KalmanFull::KalmanFull ( mat A0, mat B0, mat C0, mat D0, mat Q0, mat R0, mat P0, vec mu0 ) { |
---|
9 | dimx = A0.rows(); |
---|
10 | dimu = B0.cols(); |
---|
11 | dimy = C0.rows(); |
---|
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 ( ( Q0.cols() ==dimx ) || ( Q0.rows() ==dimx ), "KalmanFull: Q is not compatible" ); |
---|
18 | it_assert_debug ( ( R0.cols() ==dimy ) || ( R0.rows() ==dimy ), "KalmanFull: R is not compatible" ); |
---|
19 | |
---|
20 | A = A0; |
---|
21 | B = B0; |
---|
22 | C = C0; |
---|
23 | D = D0; |
---|
24 | R = R0; |
---|
25 | Q = Q0; |
---|
26 | mu = mu0; |
---|
27 | P = P0; |
---|
28 | |
---|
29 | ll = 0.0; |
---|
30 | evalll=true; |
---|
31 | } |
---|
32 | |
---|
33 | void KalmanFull::bayes ( const vec &dt ) { |
---|
34 | it_assert_debug ( dt.length() == ( dimy+dimu ),"KalmanFull::bayes wrong size of dt" ); |
---|
35 | |
---|
36 | vec u = dt.get ( dimy,dimy+dimu-1 ); |
---|
37 | vec y = dt.get ( 0,dimy-1 ); |
---|
38 | //Time update |
---|
39 | mu = A*mu + B*u; |
---|
40 | P = A*P*A.transpose() + Q; |
---|
41 | |
---|
42 | //Data update |
---|
43 | _Ry = C*P*C.transpose() + R; |
---|
44 | _iRy = inv ( _Ry ); |
---|
45 | _K = P*C.transpose() *_iRy; |
---|
46 | P -= _K*C*P; // P = P -KCP; |
---|
47 | mu += _K* ( y-C*mu-D*u ); |
---|
48 | |
---|
49 | if ( evalll ) { |
---|
50 | //from enorm |
---|
51 | vec x=y-C*mu-D*u; |
---|
52 | ll = -0.5* ( R.cols() * 1.83787706640935 +log ( det ( _Ry ) ) +x* ( _iRy*x ) ); |
---|
53 | } |
---|
54 | }; |
---|
55 | |
---|
56 | std::ostream &operator<< ( std::ostream &os, const KalmanFull &kf ) { |
---|
57 | os << "mu:" << kf.mu << endl << "P:" << kf.P <<endl; |
---|
58 | return os; |
---|
59 | } |
---|
60 | |
---|
61 | |
---|
62 | |
---|
63 | /////////////////////////////// EKFS |
---|
64 | EKFfull::EKFfull ( ) : BM (),E() {}; |
---|
65 | |
---|
66 | void EKFfull::set_parameters ( diffbifn* pfxu0, diffbifn* phxu0,const mat Q0,const mat R0 ) { |
---|
67 | pfxu = pfxu0; |
---|
68 | phxu = phxu0; |
---|
69 | |
---|
70 | dimx = pfxu0->_dimx(); |
---|
71 | dimy = phxu0->dimension(); |
---|
72 | dimu = pfxu0->_dimu(); |
---|
73 | |
---|
74 | A.set_size(dimx,dimx); |
---|
75 | C.set_size(dimy,dimx); |
---|
76 | //initialize matrices A C, later, these will be only updated! |
---|
77 | pfxu->dfdx_cond ( mu,zeros ( dimu ),A,true ); |
---|
78 | B.clear(); |
---|
79 | phxu->dfdx_cond ( mu,zeros ( dimu ),C,true ); |
---|
80 | D.clear(); |
---|
81 | |
---|
82 | R = R0; |
---|
83 | Q = Q0; |
---|
84 | } |
---|
85 | |
---|
86 | void EKFfull::bayes ( const vec &dt ) { |
---|
87 | it_assert_debug ( dt.length() == ( dimy+dimu ),"KalmanFull::bayes wrong size of dt" ); |
---|
88 | |
---|
89 | vec u = dt.get ( dimy,dimy+dimu-1 ); |
---|
90 | vec y = dt.get ( 0,dimy-1 ); |
---|
91 | |
---|
92 | pfxu->dfdx_cond ( mu,zeros ( dimu ),A,true ); |
---|
93 | phxu->dfdx_cond ( mu,zeros ( dimu ),C,true ); |
---|
94 | |
---|
95 | //Time update |
---|
96 | mu = pfxu->eval(mu,u);// A*mu + B*u; |
---|
97 | P = A*P*A.transpose() + Q; |
---|
98 | |
---|
99 | //Data update |
---|
100 | _Ry = C*P*C.transpose() + R; |
---|
101 | _iRy = inv ( _Ry ); |
---|
102 | _K = P*C.transpose() *_iRy; |
---|
103 | P -= _K*C*P; // P = P -KCP; |
---|
104 | vec yp = phxu->eval(mu,u); |
---|
105 | mu += _K* ( y-yp ); |
---|
106 | |
---|
107 | E.set_mu(mu); |
---|
108 | |
---|
109 | if ( BM::evalll ) { |
---|
110 | //from enorm |
---|
111 | vec x=y-yp; |
---|
112 | BM::ll = -0.5* ( R.cols() * 1.83787706640935 +log ( det ( _Ry ) ) +x* ( _iRy*x ) ); |
---|
113 | } |
---|
114 | }; |
---|
115 | |
---|
116 | |
---|
117 | |
---|
118 | void KalmanCh::set_parameters ( const mat &A0,const mat &B0,const mat &C0,const mat &D0,const chmat &Q0,const chmat &R0 ) { |
---|
119 | |
---|
120 | ( ( Kalman<chmat>* ) this )->set_parameters ( A0,B0,C0,D0,Q0,R0 ); |
---|
121 | // Cholesky special! |
---|
122 | preA=zeros(dimy+dimx+dimx,dimy+dimx); |
---|
123 | // preA.clear(); |
---|
124 | preA.set_submatrix ( 0,0,R._Ch() ); |
---|
125 | preA.set_submatrix ( dimy+dimx,dimy,Q._Ch() ); |
---|
126 | } |
---|
127 | |
---|
128 | |
---|
129 | void KalmanCh::bayes ( const vec &dt ) { |
---|
130 | |
---|
131 | vec u = dt.get ( dimy,dimy+dimu-1 ); |
---|
132 | vec y = dt.get ( 0,dimy-1 ); |
---|
133 | vec pom(dimy); |
---|
134 | |
---|
135 | //TODO get rid of Q in qr()! |
---|
136 | // mat Q; |
---|
137 | |
---|
138 | //R and Q are already set in set_parameters() |
---|
139 | preA.set_submatrix ( dimy,0, ( _P._Ch() ) *C.T() ); |
---|
140 | //Fixme can be more efficient if .T() is not used |
---|
141 | preA.set_submatrix ( dimy,dimy, ( _P._Ch() ) *A.T() ); |
---|
142 | |
---|
143 | // if ( !qr ( preA,Q,postA ) ) it_warning ( "QR in kalman unstable!" ); |
---|
144 | if ( !qr ( preA,postA ) ) {it_warning ( "QR in kalman unstable!" );} |
---|
145 | |
---|
146 | ( _Ry._Ch() ) =postA ( 0,dimy-1, 0,dimy-1 ); |
---|
147 | _K = inv(A)*( postA ( 0,dimy-1 ,dimy,dimy+dimx-1 ) ).T(); |
---|
148 | ( _P._Ch() ) = postA ( dimy,dimy+dimx-1,dimy,dimy+dimx-1 ); |
---|
149 | |
---|
150 | _mu = A* ( _mu ) + B*u; |
---|
151 | _yp = C*_mu -D*u; |
---|
152 | |
---|
153 | backward_substitution(_Ry._Ch(),( y-_yp),pom); |
---|
154 | _mu += ( _K ) * pom; |
---|
155 | |
---|
156 | /* cout << "P:" <<_P.to_mat() <<endl; |
---|
157 | cout << "Ry:" <<_Ry.to_mat() <<endl; |
---|
158 | cout << "_K:" <<_K <<endl;*/ |
---|
159 | |
---|
160 | if ( evalll==true ) { //likelihood of observation y |
---|
161 | ll=fy.evallog ( y ); |
---|
162 | } |
---|
163 | } |
---|
164 | |
---|
165 | |
---|
166 | |
---|
167 | void EKFCh::set_parameters ( diffbifn* pfxu0, diffbifn* phxu0,const chmat Q0,const chmat R0 ) { |
---|
168 | pfxu = pfxu0; |
---|
169 | phxu = phxu0; |
---|
170 | |
---|
171 | dimx = pfxu0->dimension(); |
---|
172 | dimy = phxu0->dimension(); |
---|
173 | dimu = pfxu0->_dimu(); |
---|
174 | // set size of mu - just for constant terms of A and C |
---|
175 | _mu=zeros(dimx); |
---|
176 | A=zeros(dimx,dimx); |
---|
177 | C=zeros(dimy,dimx); |
---|
178 | preA=zeros(dimy+dimx+dimx, dimy+dimx); |
---|
179 | |
---|
180 | //initialize matrices A C, later, these will be only updated! |
---|
181 | pfxu->dfdx_cond ( _mu,zeros ( dimu ),A,true ); |
---|
182 | // pfxu->dfdu_cond ( *_mu,zeros ( dimu ),B,true ); |
---|
183 | B.clear(); |
---|
184 | phxu->dfdx_cond ( _mu,zeros ( dimu ),C,true ); |
---|
185 | // phxu->dfdu_cond ( *_mu,zeros ( dimu ),D,true ); |
---|
186 | D.clear(); |
---|
187 | |
---|
188 | R = R0; |
---|
189 | Q = Q0; |
---|
190 | |
---|
191 | // Cholesky special! |
---|
192 | preA.clear(); |
---|
193 | preA.set_submatrix ( 0,0,R._Ch() ); |
---|
194 | preA.set_submatrix ( dimy+dimx,dimy,Q._Ch() ); |
---|
195 | } |
---|
196 | |
---|
197 | |
---|
198 | void EKFCh::bayes ( const vec &dt ) { |
---|
199 | |
---|
200 | vec pom(dimy); |
---|
201 | vec u = dt.get ( dimy,dimy+dimu-1 ); |
---|
202 | vec y = dt.get ( 0,dimy-1 ); |
---|
203 | |
---|
204 | pfxu->dfdx_cond ( _mu,u,A,false ); //update A by a derivative of fx |
---|
205 | phxu->dfdx_cond ( _mu,u,C,false ); //update A by a derivative of fx |
---|
206 | |
---|
207 | //R and Q are already set in set_parameters() |
---|
208 | preA.set_submatrix ( dimy,0, ( _P._Ch() ) *C.T() ); |
---|
209 | //Fixme can be more efficient if .T() is not used |
---|
210 | preA.set_submatrix ( dimy,dimy, ( _P._Ch() ) *A.T() ); |
---|
211 | |
---|
212 | // mat Sttm = _P->to_mat(); |
---|
213 | // cout << preA <<endl; |
---|
214 | // cout << "_mu:" << _mu <<endl; |
---|
215 | |
---|
216 | // if ( !qr ( preA,Q,postA ) ) it_warning ( "QR in kalman unstable!" ); |
---|
217 | if ( !qr ( preA,postA ) ) {it_warning ( "QR in kalman unstable!" );} |
---|
218 | |
---|
219 | |
---|
220 | ( _Ry._Ch() ) =postA ( 0,dimy-1, 0,dimy-1 ); |
---|
221 | _K = inv(A)*( postA ( 0,dimy-1 ,dimy,dimy+dimx-1 ) ).T(); |
---|
222 | ( _P._Ch() ) = postA ( dimy,dimy+dimx-1,dimy,dimy+dimx-1 ); |
---|
223 | |
---|
224 | // mat iRY = inv(_Ry->to_mat()); |
---|
225 | // mat Stt = Sttm - Sttm * C.T() * iRY * C * Sttm; |
---|
226 | // mat _K2 = Stt*C.T()*inv(R.to_mat()); |
---|
227 | |
---|
228 | // prediction |
---|
229 | _mu = pfxu->eval ( _mu ,u ); |
---|
230 | _yp = phxu->eval ( _mu,u ); |
---|
231 | |
---|
232 | /* vec mu2 = *_mu + ( _K2 ) * ( y-*_yp );*/ |
---|
233 | |
---|
234 | //correction //= initial value is already prediction! |
---|
235 | backward_substitution(_Ry._Ch(),( y-_yp ),pom); |
---|
236 | _mu += ( _K ) *pom ; |
---|
237 | |
---|
238 | /* _K = (_P->to_mat())*C.transpose() * ( _iRy->to_mat() ); |
---|
239 | *_mu = pfxu->eval ( *_mu ,u ) + ( _K )* ( y-*_yp );*/ |
---|
240 | |
---|
241 | // cout << "P:" <<_P.to_mat() <<endl; |
---|
242 | // cout << "Ry:" <<_Ry.to_mat() <<endl; |
---|
243 | // cout << "_mu:" <<_mu <<endl; |
---|
244 | // cout << "dt:" <<dt <<endl; |
---|
245 | |
---|
246 | if ( evalll==true ) { //likelihood of observation y |
---|
247 | ll=fy.evallog ( y ); |
---|
248 | } |
---|
249 | } |
---|
250 | |
---|
251 | } |
---|