| 34 | | class StateSpace |
| 35 | | { |
| 36 | | protected: |
| 37 | | //! Matrix A |
| 38 | | mat A; |
| 39 | | //! Matrix B |
| 40 | | mat B; |
| 41 | | //! Matrix C |
| 42 | | mat C; |
| 43 | | //! Matrix D |
| 44 | | mat D; |
| 45 | | //! Matrix Q in square-root form |
| 46 | | sq_T Q; |
| 47 | | //! Matrix R in square-root form |
| 48 | | sq_T R; |
| 49 | | public: |
| 50 | | StateSpace() : A(), B(), C(), D(), Q(), R() {} |
| 51 | | //!copy constructor |
| 52 | | StateSpace(const StateSpace<sq_T> &S0) : A(S0.A), B(S0.B), C(S0.C), D(S0.D), Q(S0.Q), R(S0.R) {} |
| 53 | | //! set all matrix parameters |
| 54 | | void set_parameters (const mat &A0, const mat &B0, const mat &C0, const mat &D0, const sq_T &Q0, const sq_T &R0); |
| 55 | | //! validation |
| 56 | | void validate(); |
| 57 | | //! not virtual in this case |
| 58 | | void from_setting (const Setting &set) { |
| 59 | | UI::get (A, set, "A", UI::compulsory); |
| 60 | | UI::get (B, set, "B", UI::compulsory); |
| 61 | | UI::get (C, set, "C", UI::compulsory); |
| 62 | | UI::get (D, set, "D", UI::compulsory); |
| 63 | | mat Qtm, Rtm; // full matrices |
| 64 | | if(!UI::get(Qtm, set, "Q", UI::optional)){ |
| 65 | | vec dq; |
| 66 | | UI::get(dq, set, "dQ", UI::compulsory); |
| 67 | | Qtm=diag(dq); |
| 68 | | } |
| 69 | | if(!UI::get(Rtm, set, "R", UI::optional)){ |
| 70 | | vec dr; |
| 71 | | UI::get(dr, set, "dQ", UI::compulsory); |
| 72 | | Rtm=diag(dr); |
| 73 | | } |
| 74 | | R=Rtm; // automatic conversion to square-root form |
| 75 | | Q=Qtm; |
| 76 | | |
| 77 | | validate(); |
| 78 | | } |
| 79 | | //! access function |
| 80 | | const mat& _A() const {return A;} |
| 81 | | //! access function |
| 82 | | const mat& _B()const {return B;} |
| 83 | | //! access function |
| 84 | | const mat& _C()const {return C;} |
| 85 | | //! access function |
| 86 | | const mat& _D()const {return D;} |
| 87 | | //! access function |
| 88 | | const sq_T& _Q()const {return Q;} |
| 89 | | //! access function |
| 90 | | const sq_T& _R()const {return R;} |
| 91 | | }; |
| 92 | | |
| 93 | | //! Common abstract base for Kalman filters |
| | 33 | class StateSpace { |
| | 34 | protected: |
| | 35 | //! Matrix A |
| | 36 | mat A; |
| | 37 | //! Matrix B |
| | 38 | mat B; |
| | 39 | //! Matrix C |
| | 40 | mat C; |
| | 41 | //! Matrix D |
| | 42 | mat D; |
| | 43 | //! Matrix Q in square-root form |
| | 44 | sq_T Q; |
| | 45 | //! Matrix R in square-root form |
| | 46 | sq_T R; |
| | 47 | public: |
| | 48 | StateSpace() : A(), B(), C(), D(), Q(), R() {} |
| | 49 | //!copy constructor |
| | 50 | StateSpace ( const StateSpace<sq_T> &S0 ) : A ( S0.A ), B ( S0.B ), C ( S0.C ), D ( S0.D ), Q ( S0.Q ), R ( S0.R ) {} |
| | 51 | //! set all matrix parameters |
| | 52 | void set_parameters ( const mat &A0, const mat &B0, const mat &C0, const mat &D0, const sq_T &Q0, const sq_T &R0 ); |
| | 53 | //! validation |
| | 54 | void validate(); |
| | 55 | //! not virtual in this case |
| | 56 | void from_setting ( const Setting &set ) { |
| | 57 | UI::get ( A, set, "A", UI::compulsory ); |
| | 58 | UI::get ( B, set, "B", UI::compulsory ); |
| | 59 | UI::get ( C, set, "C", UI::compulsory ); |
| | 60 | UI::get ( D, set, "D", UI::compulsory ); |
| | 61 | mat Qtm, Rtm; // full matrices |
| | 62 | if ( !UI::get ( Qtm, set, "Q", UI::optional ) ) { |
| | 63 | vec dq; |
| | 64 | UI::get ( dq, set, "dQ", UI::compulsory ); |
| | 65 | Qtm = diag ( dq ); |
| | 66 | } |
| | 67 | if ( !UI::get ( Rtm, set, "R", UI::optional ) ) { |
| | 68 | vec dr; |
| | 69 | UI::get ( dr, set, "dQ", UI::compulsory ); |
| | 70 | Rtm = diag ( dr ); |
| | 71 | } |
| | 72 | R = Rtm; // automatic conversion to square-root form |
| | 73 | Q = Qtm; |
| | 74 | |
| | 75 | validate(); |
| | 76 | } |
| | 77 | //! access function |
| | 78 | const mat& _A() const { |
| | 79 | return A; |
| | 80 | } |
| | 81 | //! access function |
| | 82 | const mat& _B() const { |
| | 83 | return B; |
| | 84 | } |
| | 85 | //! access function |
| | 86 | const mat& _C() const { |
| | 87 | return C; |
| | 88 | } |
| | 89 | //! access function |
| | 90 | const mat& _D() const { |
| | 91 | return D; |
| | 92 | } |
| | 93 | //! access function |
| | 94 | const sq_T& _Q() const { |
| | 95 | return Q; |
| | 96 | } |
| | 97 | //! access function |
| | 98 | const sq_T& _R() const { |
| | 99 | return R; |
| | 100 | } |
| | 101 | }; |
| | 102 | |
| | 103 | //! Common abstract base for Kalman filters |
| 95 | | class Kalman: public BM, public StateSpace<sq_T> |
| 96 | | { |
| 97 | | protected: |
| 98 | | //! id of output |
| 99 | | RV yrv; |
| 100 | | //! Kalman gain |
| 101 | | mat _K; |
| 102 | | //!posterior |
| 103 | | enorm<sq_T> est; |
| 104 | | //!marginal on data f(y|y) |
| 105 | | enorm<sq_T> fy; |
| 106 | | public: |
| 107 | | Kalman<sq_T>() : BM(), StateSpace<sq_T>(), yrv(), _K(), est(){} |
| 108 | | //! Copy constructor |
| 109 | | Kalman<sq_T>(const Kalman<sq_T> &K0) : BM(K0), StateSpace<sq_T>(K0), yrv(K0.yrv), _K(K0._K), est(K0.est), fy(K0.fy){} |
| 110 | | //!set statistics of the posterior |
| 111 | | void set_statistics (const vec &mu0, const mat &P0) {est.set_parameters (mu0, P0); }; |
| 112 | | //!set statistics of the posterior |
| 113 | | void set_statistics (const vec &mu0, const sq_T &P0) {est.set_parameters (mu0, P0); }; |
| 114 | | //! return correctly typed posterior (covariant return) |
| 115 | | const enorm<sq_T>& posterior() const {return est;} |
| 116 | | //! load basic elements of Kalman from structure |
| 117 | | void from_setting (const Setting &set) { |
| 118 | | StateSpace<sq_T>::from_setting(set); |
| 119 | | |
| 120 | | mat P0; vec mu0; |
| 121 | | UI::get(mu0, set, "mu0", UI::optional); |
| 122 | | UI::get(P0, set, "P0", UI::optional); |
| 123 | | set_statistics(mu0,P0); |
| 124 | | // Initial values |
| 125 | | UI::get (yrv, set, "yrv", UI::optional); |
| 126 | | UI::get (rvc, set, "urv", UI::optional); |
| 127 | | set_yrv(concat(yrv,rvc)); |
| 128 | | |
| 129 | | validate(); |
| 130 | | } |
| 131 | | //! validate object |
| 132 | | void validate() { |
| 133 | | StateSpace<sq_T>::validate(); |
| 134 | | dimy = this->C.rows(); |
| 135 | | dimc = this->B.cols(); |
| 136 | | set_dim(this->A.rows()); |
| 137 | | |
| 138 | | bdm_assert(est.dimension(), "Statistics and model parameters mismatch"); |
| 139 | | } |
| | 105 | class Kalman: public BM, public StateSpace<sq_T> { |
| | 106 | protected: |
| | 107 | //! id of output |
| | 108 | RV yrv; |
| | 109 | //! Kalman gain |
| | 110 | mat _K; |
| | 111 | //!posterior |
| | 112 | enorm<sq_T> est; |
| | 113 | //!marginal on data f(y|y) |
| | 114 | enorm<sq_T> fy; |
| | 115 | public: |
| | 116 | Kalman<sq_T>() : BM(), StateSpace<sq_T>(), yrv(), _K(), est() {} |
| | 117 | //! Copy constructor |
| | 118 | Kalman<sq_T> ( const Kalman<sq_T> &K0 ) : BM ( K0 ), StateSpace<sq_T> ( K0 ), yrv ( K0.yrv ), _K ( K0._K ), est ( K0.est ), fy ( K0.fy ) {} |
| | 119 | //!set statistics of the posterior |
| | 120 | void set_statistics ( const vec &mu0, const mat &P0 ) { |
| | 121 | est.set_parameters ( mu0, P0 ); |
| | 122 | }; |
| | 123 | //!set statistics of the posterior |
| | 124 | void set_statistics ( const vec &mu0, const sq_T &P0 ) { |
| | 125 | est.set_parameters ( mu0, P0 ); |
| | 126 | }; |
| | 127 | //! return correctly typed posterior (covariant return) |
| | 128 | const enorm<sq_T>& posterior() const { |
| | 129 | return est; |
| | 130 | } |
| | 131 | //! load basic elements of Kalman from structure |
| | 132 | void from_setting ( const Setting &set ) { |
| | 133 | StateSpace<sq_T>::from_setting ( set ); |
| | 134 | |
| | 135 | mat P0; |
| | 136 | vec mu0; |
| | 137 | UI::get ( mu0, set, "mu0", UI::optional ); |
| | 138 | UI::get ( P0, set, "P0", UI::optional ); |
| | 139 | set_statistics ( mu0, P0 ); |
| | 140 | // Initial values |
| | 141 | UI::get ( yrv, set, "yrv", UI::optional ); |
| | 142 | UI::get ( rvc, set, "urv", UI::optional ); |
| | 143 | set_yrv ( concat ( yrv, rvc ) ); |
| | 144 | |
| | 145 | validate(); |
| | 146 | } |
| | 147 | //! validate object |
| | 148 | void validate() { |
| | 149 | StateSpace<sq_T>::validate(); |
| | 150 | dimy = this->C.rows(); |
| | 151 | dimc = this->B.cols(); |
| | 152 | set_dim ( this->A.rows() ); |
| | 153 | |
| | 154 | bdm_assert ( est.dimension(), "Statistics and model parameters mismatch" ); |
| | 155 | } |
| 145 | | class KalmanFull : public Kalman<fsqmat> |
| 146 | | { |
| 147 | | public: |
| 148 | | //! For EKFfull; |
| 149 | | KalmanFull() :Kalman<fsqmat>(){}; |
| 150 | | //! Here dt = [yt;ut] of appropriate dimensions |
| 151 | | void bayes (const vec &yt, const vec &cond=empty_vec); |
| 152 | | BM* _copy_() const { |
| 153 | | KalmanFull* K = new KalmanFull; |
| 154 | | K->set_parameters (A, B, C, D, Q, R); |
| 155 | | K->set_statistics (est._mu(), est._R()); |
| 156 | | return K; |
| 157 | | } |
| 158 | | }; |
| 159 | | UIREGISTER(KalmanFull); |
| | 161 | class KalmanFull : public Kalman<fsqmat> { |
| | 162 | public: |
| | 163 | //! For EKFfull; |
| | 164 | KalmanFull() : Kalman<fsqmat>() {}; |
| | 165 | //! Here dt = [yt;ut] of appropriate dimensions |
| | 166 | void bayes ( const vec &yt, const vec &cond = empty_vec ); |
| | 167 | BM* _copy_() const { |
| | 168 | KalmanFull* K = new KalmanFull; |
| | 169 | K->set_parameters ( A, B, C, D, Q, R ); |
| | 170 | K->set_statistics ( est._mu(), est._R() ); |
| | 171 | return K; |
| | 172 | } |
| | 173 | }; |
| | 174 | UIREGISTER ( KalmanFull ); |
| 169 | | class KalmanCh : public Kalman<chmat> |
| 170 | | { |
| 171 | | protected: |
| 172 | | //! @{ \name Internal storage - needs initialize() |
| 173 | | //! pre array (triangular matrix) |
| 174 | | mat preA; |
| 175 | | //! post array (triangular matrix) |
| 176 | | mat postA; |
| 177 | | //!@} |
| 178 | | public: |
| 179 | | //! copy constructor |
| 180 | | BM* _copy_() const { |
| 181 | | KalmanCh* K = new KalmanCh; |
| 182 | | K->set_parameters (A, B, C, D, Q, R); |
| 183 | | K->set_statistics (est._mu(), est._R()); |
| 184 | | K->validate(); |
| 185 | | return K; |
| 186 | | } |
| 187 | | //! set parameters for adapt from Kalman |
| 188 | | void set_parameters (const mat &A0, const mat &B0, const mat &C0, const mat &D0, const chmat &Q0, const chmat &R0); |
| 189 | | //! initialize internal parametetrs |
| 190 | | void initialize(); |
| 191 | | |
| 192 | | /*!\brief Here dt = [yt;ut] of appropriate dimensions |
| 193 | | |
| 194 | | The following equality hold::\f[ |
| 195 | | \left[\begin{array}{cc} |
| 196 | | R^{0.5}\\ |
| 197 | | P_{t|t-1}^{0.5}C' & P_{t|t-1}^{0.5}CA'\\ |
| 198 | | & Q^{0.5}\end{array}\right]<\mathrm{orth.oper.}>=\left[\begin{array}{cc} |
| 199 | | R_{y}^{0.5} & KA'\\ |
| 200 | | & P_{t+1|t}^{0.5}\\ |
| 201 | | \\\end{array}\right]\f] |
| 202 | | |
| 203 | | Thus this object evaluates only predictors! Not filtering densities. |
| 204 | | */ |
| 205 | | void bayes (const vec &yt, const vec &cond=empty_vec); |
| 206 | | |
| 207 | | void from_setting(const Setting &set){ |
| 208 | | Kalman<chmat>::from_setting(set); |
| 209 | | validate(); |
| 210 | | } |
| 211 | | void validate() { |
| 212 | | Kalman<chmat>::validate(); |
| 213 | | initialize(); |
| 214 | | } |
| 215 | | }; |
| 216 | | UIREGISTER(KalmanCh); |
| | 184 | class KalmanCh : public Kalman<chmat> { |
| | 185 | protected: |
| | 186 | //! @{ \name Internal storage - needs initialize() |
| | 187 | //! pre array (triangular matrix) |
| | 188 | mat preA; |
| | 189 | //! post array (triangular matrix) |
| | 190 | mat postA; |
| | 191 | //!@} |
| | 192 | public: |
| | 193 | //! copy constructor |
| | 194 | BM* _copy_() const { |
| | 195 | KalmanCh* K = new KalmanCh; |
| | 196 | K->set_parameters ( A, B, C, D, Q, R ); |
| | 197 | K->set_statistics ( est._mu(), est._R() ); |
| | 198 | K->validate(); |
| | 199 | return K; |
| | 200 | } |
| | 201 | //! set parameters for adapt from Kalman |
| | 202 | void set_parameters ( const mat &A0, const mat &B0, const mat &C0, const mat &D0, const chmat &Q0, const chmat &R0 ); |
| | 203 | //! initialize internal parametetrs |
| | 204 | void initialize(); |
| | 205 | |
| | 206 | /*!\brief Here dt = [yt;ut] of appropriate dimensions |
| | 207 | |
| | 208 | The following equality hold::\f[ |
| | 209 | \left[\begin{array}{cc} |
| | 210 | R^{0.5}\\ |
| | 211 | P_{t|t-1}^{0.5}C' & P_{t|t-1}^{0.5}CA'\\ |
| | 212 | & Q^{0.5}\end{array}\right]<\mathrm{orth.oper.}>=\left[\begin{array}{cc} |
| | 213 | R_{y}^{0.5} & KA'\\ |
| | 214 | & P_{t+1|t}^{0.5}\\ |
| | 215 | \\\end{array}\right]\f] |
| | 216 | |
| | 217 | Thus this object evaluates only predictors! Not filtering densities. |
| | 218 | */ |
| | 219 | void bayes ( const vec &yt, const vec &cond = empty_vec ); |
| | 220 | |
| | 221 | void from_setting ( const Setting &set ) { |
| | 222 | Kalman<chmat>::from_setting ( set ); |
| | 223 | validate(); |
| | 224 | } |
| | 225 | void validate() { |
| | 226 | Kalman<chmat>::validate(); |
| | 227 | initialize(); |
| | 228 | } |
| | 229 | }; |
| | 230 | UIREGISTER ( KalmanCh ); |
| 223 | | class EKFfull : public KalmanFull |
| 224 | | { |
| 225 | | protected: |
| 226 | | //! Internal Model f(x,u) |
| 227 | | shared_ptr<diffbifn> pfxu; |
| 228 | | |
| 229 | | //! Observation Model h(x,u) |
| 230 | | shared_ptr<diffbifn> phxu; |
| 231 | | |
| 232 | | public: |
| 233 | | //! Default constructor |
| 234 | | EKFfull (); |
| 235 | | |
| 236 | | //! Set nonlinear functions for mean values and covariance matrices. |
| 237 | | void set_parameters (const shared_ptr<diffbifn> &pfxu, const shared_ptr<diffbifn> &phxu, const mat Q0, const mat R0); |
| 238 | | |
| 239 | | //! Here dt = [yt;ut] of appropriate dimensions |
| 240 | | void bayes (const vec &yt, const vec &cond=empty_vec); |
| 241 | | //! set estimates |
| 242 | | void set_statistics (const vec &mu0, const mat &P0) { |
| 243 | | est.set_parameters (mu0, P0); |
| 244 | | }; |
| 245 | | //! access function |
| 246 | | const mat _R() { |
| 247 | | return est._R().to_mat(); |
| 248 | | } |
| 249 | | void from_setting (const Setting &set) { |
| 250 | | BM::from_setting(set); |
| 251 | | shared_ptr<diffbifn> IM = UI::build<diffbifn> ( set, "IM", UI::compulsory ); |
| 252 | | shared_ptr<diffbifn> OM = UI::build<diffbifn> ( set, "OM", UI::compulsory ); |
| 253 | | |
| 254 | | //statistics |
| 255 | | int dim = IM->dimension(); |
| 256 | | vec mu0; |
| 257 | | if ( !UI::get ( mu0, set, "mu0" ) ) |
| 258 | | mu0 = zeros ( dim ); |
| 259 | | |
| 260 | | mat P0; |
| 261 | | vec dP0; |
| 262 | | if ( UI::get ( dP0, set, "dP0" ) ) |
| 263 | | P0 = diag ( dP0 ); |
| 264 | | else if ( !UI::get ( P0, set, "P0" ) ) |
| 265 | | P0 = eye ( dim ); |
| 266 | | |
| 267 | | set_statistics ( mu0, P0 ); |
| 268 | | |
| 269 | | //parameters |
| 270 | | vec dQ, dR; |
| 271 | | UI::get ( dQ, set, "dQ", UI::compulsory ); |
| 272 | | UI::get ( dR, set, "dR", UI::compulsory ); |
| 273 | | set_parameters ( IM, OM, diag ( dQ ), diag ( dR ) ); |
| 274 | | |
| 275 | | string options; |
| 276 | | if ( UI::get ( options, set, "options" ) ) |
| 277 | | set_options ( options ); |
| | 237 | class EKFfull : public KalmanFull { |
| | 238 | protected: |
| | 239 | //! Internal Model f(x,u) |
| | 240 | shared_ptr<diffbifn> pfxu; |
| | 241 | |
| | 242 | //! Observation Model h(x,u) |
| | 243 | shared_ptr<diffbifn> phxu; |
| | 244 | |
| | 245 | public: |
| | 246 | //! Default constructor |
| | 247 | EKFfull (); |
| | 248 | |
| | 249 | //! Set nonlinear functions for mean values and covariance matrices. |
| | 250 | void set_parameters ( const shared_ptr<diffbifn> &pfxu, const shared_ptr<diffbifn> &phxu, const mat Q0, const mat R0 ); |
| | 251 | |
| | 252 | //! Here dt = [yt;ut] of appropriate dimensions |
| | 253 | void bayes ( const vec &yt, const vec &cond = empty_vec ); |
| | 254 | //! set estimates |
| | 255 | void set_statistics ( const vec &mu0, const mat &P0 ) { |
| | 256 | est.set_parameters ( mu0, P0 ); |
| | 257 | }; |
| | 258 | //! access function |
| | 259 | const mat _R() { |
| | 260 | return est._R().to_mat(); |
| | 261 | } |
| | 262 | void from_setting ( const Setting &set ) { |
| | 263 | BM::from_setting ( set ); |
| | 264 | shared_ptr<diffbifn> IM = UI::build<diffbifn> ( set, "IM", UI::compulsory ); |
| | 265 | shared_ptr<diffbifn> OM = UI::build<diffbifn> ( set, "OM", UI::compulsory ); |
| | 266 | |
| | 267 | //statistics |
| | 268 | int dim = IM->dimension(); |
| | 269 | vec mu0; |
| | 270 | if ( !UI::get ( mu0, set, "mu0" ) ) |
| | 271 | mu0 = zeros ( dim ); |
| | 272 | |
| | 273 | mat P0; |
| | 274 | vec dP0; |
| | 275 | if ( UI::get ( dP0, set, "dP0" ) ) |
| | 276 | P0 = diag ( dP0 ); |
| | 277 | else if ( !UI::get ( P0, set, "P0" ) ) |
| | 278 | P0 = eye ( dim ); |
| | 279 | |
| | 280 | set_statistics ( mu0, P0 ); |
| | 281 | |
| | 282 | //parameters |
| | 283 | vec dQ, dR; |
| | 284 | UI::get ( dQ, set, "dQ", UI::compulsory ); |
| | 285 | UI::get ( dR, set, "dR", UI::compulsory ); |
| | 286 | set_parameters ( IM, OM, diag ( dQ ), diag ( dR ) ); |
| | 287 | |
| | 288 | string options; |
| | 289 | if ( UI::get ( options, set, "options" ) ) |
| | 290 | set_options ( options ); |
| 315 | | class EKFCh : public KalmanCh |
| 316 | | { |
| 317 | | protected: |
| 318 | | //! Internal Model f(x,u) |
| 319 | | shared_ptr<diffbifn> pfxu; |
| 320 | | |
| 321 | | //! Observation Model h(x,u) |
| 322 | | shared_ptr<diffbifn> phxu; |
| 323 | | public: |
| 324 | | //! copy constructor duplicated - calls different set_parameters |
| 325 | | BM* _copy_() const { |
| 326 | | EKFCh* E = new EKFCh; |
| 327 | | E->set_parameters (pfxu, phxu, Q, R); |
| 328 | | E->set_statistics (est._mu(), est._R()); |
| 329 | | return E; |
| 330 | | } |
| 331 | | //! Set nonlinear functions for mean values and covariance matrices. |
| 332 | | void set_parameters (const shared_ptr<diffbifn> &pfxu, const shared_ptr<diffbifn> &phxu, const chmat Q0, const chmat R0); |
| 333 | | |
| 334 | | //! Here dt = [yt;ut] of appropriate dimensions |
| 335 | | void bayes (const vec &yt, const vec &cond=empty_vec); |
| 336 | | |
| 337 | | void from_setting (const Setting &set); |
| 338 | | |
| 339 | | void validate(){}; |
| 340 | | // TODO dodelat void to_setting( Setting &set ) const; |
| 341 | | |
| 342 | | }; |
| 343 | | |
| 344 | | UIREGISTER (EKFCh); |
| 345 | | SHAREDPTR (EKFCh); |
| | 328 | class EKFCh : public KalmanCh { |
| | 329 | protected: |
| | 330 | //! Internal Model f(x,u) |
| | 331 | shared_ptr<diffbifn> pfxu; |
| | 332 | |
| | 333 | //! Observation Model h(x,u) |
| | 334 | shared_ptr<diffbifn> phxu; |
| | 335 | public: |
| | 336 | //! copy constructor duplicated - calls different set_parameters |
| | 337 | BM* _copy_() const { |
| | 338 | EKFCh* E = new EKFCh; |
| | 339 | E->set_parameters ( pfxu, phxu, Q, R ); |
| | 340 | E->set_statistics ( est._mu(), est._R() ); |
| | 341 | return E; |
| | 342 | } |
| | 343 | //! Set nonlinear functions for mean values and covariance matrices. |
| | 344 | void set_parameters ( const shared_ptr<diffbifn> &pfxu, const shared_ptr<diffbifn> &phxu, const chmat Q0, const chmat R0 ); |
| | 345 | |
| | 346 | //! Here dt = [yt;ut] of appropriate dimensions |
| | 347 | void bayes ( const vec &yt, const vec &cond = empty_vec ); |
| | 348 | |
| | 349 | void from_setting ( const Setting &set ); |
| | 350 | |
| | 351 | void validate() {}; |
| | 352 | // TODO dodelat void to_setting( Setting &set ) const; |
| | 353 | |
| | 354 | }; |
| | 355 | |
| | 356 | UIREGISTER ( EKFCh ); |
| | 357 | SHAREDPTR ( EKFCh ); |
| 357 | | class MultiModel: public BM |
| 358 | | { |
| 359 | | protected: |
| 360 | | //! List of models between which we switch |
| 361 | | Array<EKFCh*> Models; |
| 362 | | //! vector of model weights |
| 363 | | vec w; |
| 364 | | //! cache of model lls |
| 365 | | vec _lls; |
| 366 | | //! type of switching policy [1=maximum,2=...] |
| 367 | | int policy; |
| 368 | | //! internal statistics |
| 369 | | enorm<chmat> est; |
| 370 | | public: |
| 371 | | //! set internal parameters |
| 372 | | void set_parameters (Array<EKFCh*> A, int pol0 = 1) { |
| 373 | | Models = A;//TODO: test if evalll is set |
| 374 | | w.set_length (A.length()); |
| 375 | | _lls.set_length (A.length()); |
| 376 | | policy = pol0; |
| 377 | | |
| 378 | | est.set_rv (RV ("MM", A (0)->posterior().dimension(), 0)); |
| 379 | | est.set_parameters (A (0)->posterior().mean(), A (0)->posterior()._R()); |
| 380 | | } |
| 381 | | void bayes (const vec &yt, const vec &cond=empty_vec) { |
| 382 | | int n = Models.length(); |
| 383 | | int i; |
| 384 | | for (i = 0; i < n; i++) { |
| 385 | | Models (i)->bayes (yt); |
| 386 | | _lls (i) = Models (i)->_ll(); |
| 387 | | } |
| 388 | | double mlls = max (_lls); |
| 389 | | w = exp (_lls - mlls); |
| 390 | | w /= sum (w); //normalization |
| 391 | | //set statistics |
| 392 | | switch (policy) { |
| 393 | | case 1: { |
| 394 | | int mi = max_index (w); |
| 395 | | const enorm<chmat> &st = Models (mi)->posterior() ; |
| 396 | | est.set_parameters (st.mean(), st._R()); |
| 397 | | } |
| 398 | | break; |
| 399 | | default: |
| 400 | | bdm_error ("unknown policy"); |
| 401 | | } |
| 402 | | // copy result to all models |
| 403 | | for (i = 0; i < n; i++) { |
| 404 | | Models (i)->set_statistics (est.mean(), est._R()); |
| 405 | | } |
| 406 | | } |
| 407 | | //! return correctly typed posterior (covariant return) |
| 408 | | const enorm<chmat>& posterior() const { |
| 409 | | return est; |
| 410 | | } |
| 411 | | |
| 412 | | void from_setting (const Setting &set); |
| 413 | | |
| 414 | | // TODO dodelat void to_setting( Setting &set ) const; |
| 415 | | |
| 416 | | }; |
| 417 | | |
| 418 | | UIREGISTER (MultiModel); |
| 419 | | SHAREDPTR (MultiModel); |
| 420 | | |
| 421 | | //! conversion of outer ARX model (mlnorm) to state space model |
| | 369 | class MultiModel: public BM { |
| | 370 | protected: |
| | 371 | //! List of models between which we switch |
| | 372 | Array<EKFCh*> Models; |
| | 373 | //! vector of model weights |
| | 374 | vec w; |
| | 375 | //! cache of model lls |
| | 376 | vec _lls; |
| | 377 | //! type of switching policy [1=maximum,2=...] |
| | 378 | int policy; |
| | 379 | //! internal statistics |
| | 380 | enorm<chmat> est; |
| | 381 | public: |
| | 382 | //! set internal parameters |
| | 383 | void set_parameters ( Array<EKFCh*> A, int pol0 = 1 ) { |
| | 384 | Models = A;//TODO: test if evalll is set |
| | 385 | w.set_length ( A.length() ); |
| | 386 | _lls.set_length ( A.length() ); |
| | 387 | policy = pol0; |
| | 388 | |
| | 389 | est.set_rv ( RV ( "MM", A ( 0 )->posterior().dimension(), 0 ) ); |
| | 390 | est.set_parameters ( A ( 0 )->posterior().mean(), A ( 0 )->posterior()._R() ); |
| | 391 | } |
| | 392 | void bayes ( const vec &yt, const vec &cond = empty_vec ) { |
| | 393 | int n = Models.length(); |
| | 394 | int i; |
| | 395 | for ( i = 0; i < n; i++ ) { |
| | 396 | Models ( i )->bayes ( yt ); |
| | 397 | _lls ( i ) = Models ( i )->_ll(); |
| | 398 | } |
| | 399 | double mlls = max ( _lls ); |
| | 400 | w = exp ( _lls - mlls ); |
| | 401 | w /= sum ( w ); //normalization |
| | 402 | //set statistics |
| | 403 | switch ( policy ) { |
| | 404 | case 1: { |
| | 405 | int mi = max_index ( w ); |
| | 406 | const enorm<chmat> &st = Models ( mi )->posterior() ; |
| | 407 | est.set_parameters ( st.mean(), st._R() ); |
| | 408 | } |
| | 409 | break; |
| | 410 | default: |
| | 411 | bdm_error ( "unknown policy" ); |
| | 412 | } |
| | 413 | // copy result to all models |
| | 414 | for ( i = 0; i < n; i++ ) { |
| | 415 | Models ( i )->set_statistics ( est.mean(), est._R() ); |
| | 416 | } |
| | 417 | } |
| | 418 | //! return correctly typed posterior (covariant return) |
| | 419 | const enorm<chmat>& posterior() const { |
| | 420 | return est; |
| | 421 | } |
| | 422 | |
| | 423 | void from_setting ( const Setting &set ); |
| | 424 | |
| | 425 | // TODO dodelat void to_setting( Setting &set ) const; |
| | 426 | |
| | 427 | }; |
| | 428 | |
| | 429 | UIREGISTER ( MultiModel ); |
| | 430 | SHAREDPTR ( MultiModel ); |
| | 431 | |
| | 432 | //! conversion of outer ARX model (mlnorm) to state space model |
| 431 | | class StateCanonical: public StateSpace<fsqmat>{ |
| 432 | | protected: |
| 433 | | //! remember connection from theta ->A |
| 434 | | datalink_part th2A; |
| 435 | | //! remember connection from theta ->C |
| 436 | | datalink_part th2C; |
| 437 | | //! remember connection from theta ->D |
| 438 | | datalink_part th2D; |
| 439 | | //!cached first row of A |
| 440 | | vec A1row; |
| 441 | | //!cached first row of C |
| 442 | | vec C1row; |
| 443 | | //!cached first row of D |
| 444 | | vec D1row; |
| 445 | | |
| 446 | | public: |
| 447 | | //! set up this object to match given mlnorm |
| 448 | | void connect_mlnorm(const mlnorm<fsqmat> &ml){ |
| 449 | | //get ids of yrv |
| 450 | | const RV &yrv = ml._rv(); |
| 451 | | //need to determine u_t - it is all in _rvc that is not in ml._rv() |
| 452 | | RV rgr0 = ml._rvc().remove_time(); |
| 453 | | RV urv = rgr0.subt(yrv); |
| 454 | | |
| 455 | | //We can do only 1d now... :( |
| 456 | | bdm_assert(yrv._dsize()==1, "Only for SISO so far..." ); |
| 457 | | |
| 458 | | // create names for |
| 459 | | RV xrv; //empty |
| 460 | | RV Crv; //empty |
| 461 | | int td=ml._rvc().mint(); |
| 462 | | // assuming strictly proper function!!! |
| 463 | | for (int t=-1;t>=td;t--){ |
| 464 | | xrv.add(yrv.copy_t(t)); |
| 465 | | Crv.add(urv.copy_t(t)); |
| 466 | | } |
| 467 | | |
| 468 | | // get mapp |
| 469 | | th2A.set_connection(xrv, ml._rvc()); |
| 470 | | th2C.set_connection(Crv, ml._rvc()); |
| 471 | | th2D.set_connection(urv, ml._rvc()); |
| 472 | | |
| 473 | | //set matrix sizes |
| 474 | | this->A=zeros(xrv._dsize(),xrv._dsize()); |
| 475 | | for (int j=1; j<xrv._dsize(); j++){A(j,j-1)=1.0;} // off diagonal |
| 476 | | this->B=zeros(xrv._dsize(),1); |
| 477 | | this->B(0) = 1.0; |
| 478 | | this->C=zeros(1,xrv._dsize()); |
| 479 | | this->D=zeros(1,urv._dsize()); |
| 480 | | this->Q = zeros(xrv._dsize(),xrv._dsize()); |
| 481 | | // R is set by update |
| 482 | | |
| 483 | | //set cache |
| 484 | | this->A1row = zeros(xrv._dsize()); |
| 485 | | this->C1row = zeros(xrv._dsize()); |
| 486 | | this->D1row = zeros(urv._dsize()); |
| 487 | | |
| 488 | | update_from(ml); |
| 489 | | validate(); |
| 490 | | }; |
| 491 | | //! fast function to update parameters from ml - not checked for compatibility!! |
| 492 | | void update_from(const mlnorm<fsqmat> &ml){ |
| 493 | | |
| 494 | | vec theta = ml._A().get_row(0); // this |
| 495 | | |
| 496 | | th2A.filldown(theta,A1row); |
| 497 | | th2C.filldown(theta,C1row); |
| 498 | | th2D.filldown(theta,D1row); |
| 499 | | |
| 500 | | R = ml._R(); |
| 501 | | |
| 502 | | A.set_row(0,A1row); |
| 503 | | C.set_row(0,C1row+D1row(0)*A1row); |
| 504 | | D.set_row(0,D1row); |
| 505 | | |
| 506 | | } |
| | 442 | class StateCanonical: public StateSpace<fsqmat> { |
| | 443 | protected: |
| | 444 | //! remember connection from theta ->A |
| | 445 | datalink_part th2A; |
| | 446 | //! remember connection from theta ->C |
| | 447 | datalink_part th2C; |
| | 448 | //! remember connection from theta ->D |
| | 449 | datalink_part th2D; |
| | 450 | //!cached first row of A |
| | 451 | vec A1row; |
| | 452 | //!cached first row of C |
| | 453 | vec C1row; |
| | 454 | //!cached first row of D |
| | 455 | vec D1row; |
| | 456 | |
| | 457 | public: |
| | 458 | //! set up this object to match given mlnorm |
| | 459 | void connect_mlnorm ( const mlnorm<fsqmat> &ml ) { |
| | 460 | //get ids of yrv |
| | 461 | const RV &yrv = ml._rv(); |
| | 462 | //need to determine u_t - it is all in _rvc that is not in ml._rv() |
| | 463 | RV rgr0 = ml._rvc().remove_time(); |
| | 464 | RV urv = rgr0.subt ( yrv ); |
| | 465 | |
| | 466 | //We can do only 1d now... :( |
| | 467 | bdm_assert ( yrv._dsize() == 1, "Only for SISO so far..." ); |
| | 468 | |
| | 469 | // create names for |
| | 470 | RV xrv; //empty |
| | 471 | RV Crv; //empty |
| | 472 | int td = ml._rvc().mint(); |
| | 473 | // assuming strictly proper function!!! |
| | 474 | for ( int t = -1; t >= td; t-- ) { |
| | 475 | xrv.add ( yrv.copy_t ( t ) ); |
| | 476 | Crv.add ( urv.copy_t ( t ) ); |
| | 477 | } |
| | 478 | |
| | 479 | // get mapp |
| | 480 | th2A.set_connection ( xrv, ml._rvc() ); |
| | 481 | th2C.set_connection ( Crv, ml._rvc() ); |
| | 482 | th2D.set_connection ( urv, ml._rvc() ); |
| | 483 | |
| | 484 | //set matrix sizes |
| | 485 | this->A = zeros ( xrv._dsize(), xrv._dsize() ); |
| | 486 | for ( int j = 1; j < xrv._dsize(); j++ ) { |
| | 487 | A ( j, j - 1 ) = 1.0; // off diagonal |
| | 488 | } |
| | 489 | this->B = zeros ( xrv._dsize(), 1 ); |
| | 490 | this->B ( 0 ) = 1.0; |
| | 491 | this->C = zeros ( 1, xrv._dsize() ); |
| | 492 | this->D = zeros ( 1, urv._dsize() ); |
| | 493 | this->Q = zeros ( xrv._dsize(), xrv._dsize() ); |
| | 494 | // R is set by update |
| | 495 | |
| | 496 | //set cache |
| | 497 | this->A1row = zeros ( xrv._dsize() ); |
| | 498 | this->C1row = zeros ( xrv._dsize() ); |
| | 499 | this->D1row = zeros ( urv._dsize() ); |
| | 500 | |
| | 501 | update_from ( ml ); |
| | 502 | validate(); |
| | 503 | }; |
| | 504 | //! fast function to update parameters from ml - not checked for compatibility!! |
| | 505 | void update_from ( const mlnorm<fsqmat> &ml ) { |
| | 506 | |
| | 507 | vec theta = ml._A().get_row ( 0 ); // this |
| | 508 | |
| | 509 | th2A.filldown ( theta, A1row ); |
| | 510 | th2C.filldown ( theta, C1row ); |
| | 511 | th2D.filldown ( theta, D1row ); |
| | 512 | |
| | 513 | R = ml._R(); |
| | 514 | |
| | 515 | A.set_row ( 0, A1row ); |
| | 516 | C.set_row ( 0, C1row + D1row ( 0 ) *A1row ); |
| | 517 | D.set_row ( 0, D1row ); |
| | 518 | |
| | 519 | } |
| 521 | | class StateFromARX: public StateSpace<chmat>{ |
| 522 | | protected: |
| 523 | | //! remember connection from theta ->A |
| 524 | | datalink_part th2A; |
| 525 | | //! remember connection from theta ->B |
| 526 | | datalink_part th2B; |
| 527 | | //!function adds n diagonal elements from given starting point r,c |
| 528 | | void diagonal_part(mat &A, int r, int c, int n){ |
| 529 | | for(int i=0; i<n; i++){A(r,c)=1.0; r++;c++;} |
| 530 | | }; |
| 531 | | //! similar to ARX.have_constant |
| 532 | | bool have_constant; |
| 533 | | public: |
| 534 | | //! set up this object to match given mlnorm |
| 535 | | //! Note that state-space and common mpdf use different meaning of \f$ _t \f$ in \f$ u_t \f$. |
| 536 | | //!While mlnorm typically assumes that \f$ u_t \rightarrow y_t \f$ in state space it is \f$ u_{t-1} \rightarrow y_t \f$ |
| 537 | | //! For consequences in notation of internal variable xt see arx2statespace_notes.lyx. |
| 538 | | void connect_mlnorm(const mlnorm<chmat> &ml, RV &xrv, RV &urv){ |
| 539 | | |
| 540 | | //get ids of yrv |
| 541 | | const RV &yrv = ml._rv(); |
| 542 | | //need to determine u_t - it is all in _rvc that is not in ml._rv() |
| 543 | | const RV &rgr = ml._rvc(); |
| 544 | | RV rgr0 = rgr.remove_time(); |
| 545 | | urv = rgr0.subt(yrv); |
| 546 | | |
| 547 | | // create names for state variables |
| 548 | | xrv=yrv; |
| 549 | | |
| 550 | | int y_multiplicity = -rgr.mint(yrv); |
| 551 | | int y_block_size = yrv.length()*(y_multiplicity); // current yt + all delayed yts |
| 552 | | for (int m=0;m<y_multiplicity - 1;m++){ // ========= -1 is important see arx2statespace_notes |
| 553 | | xrv.add(yrv.copy_t(-m-1)); //add delayed yt |
| | 534 | class StateFromARX: public StateSpace<chmat> { |
| | 535 | protected: |
| | 536 | //! remember connection from theta ->A |
| | 537 | datalink_part th2A; |
| | 538 | //! remember connection from theta ->B |
| | 539 | datalink_part th2B; |
| | 540 | //!function adds n diagonal elements from given starting point r,c |
| | 541 | void diagonal_part ( mat &A, int r, int c, int n ) { |
| | 542 | for ( int i = 0; i < n; i++ ) { |
| | 543 | A ( r, c ) = 1.0; |
| | 544 | r++; |
| | 545 | c++; |
| | 546 | } |
| | 547 | }; |
| | 548 | //! similar to ARX.have_constant |
| | 549 | bool have_constant; |
| | 550 | public: |
| | 551 | //! set up this object to match given mlnorm |
| | 552 | //! Note that state-space and common mpdf use different meaning of \f$ _t \f$ in \f$ u_t \f$. |
| | 553 | //!While mlnorm typically assumes that \f$ u_t \rightarrow y_t \f$ in state space it is \f$ u_{t-1} \rightarrow y_t \f$ |
| | 554 | //! For consequences in notation of internal variable xt see arx2statespace_notes.lyx. |
| | 555 | void connect_mlnorm ( const mlnorm<chmat> &ml, RV &xrv, RV &urv ) { |
| | 556 | |
| | 557 | //get ids of yrv |
| | 558 | const RV &yrv = ml._rv(); |
| | 559 | //need to determine u_t - it is all in _rvc that is not in ml._rv() |
| | 560 | const RV &rgr = ml._rvc(); |
| | 561 | RV rgr0 = rgr.remove_time(); |
| | 562 | urv = rgr0.subt ( yrv ); |
| | 563 | |
| | 564 | // create names for state variables |
| | 565 | xrv = yrv; |
| | 566 | |
| | 567 | int y_multiplicity = -rgr.mint ( yrv ); |
| | 568 | int y_block_size = yrv.length() * ( y_multiplicity ); // current yt + all delayed yts |
| | 569 | for ( int m = 0; m < y_multiplicity - 1; m++ ) { // ========= -1 is important see arx2statespace_notes |
| | 570 | xrv.add ( yrv.copy_t ( -m - 1 ) ); //add delayed yt |
| | 571 | } |
| | 572 | //! temporary RV for connection to ml.rvc, since notation of xrv and ml.rvc does not match |
| | 573 | RV xrv_ml = xrv.copy_t ( -1 ); |
| | 574 | |
| | 575 | // add regressors |
| | 576 | ivec u_block_sizes ( urv.length() ); // no_blocks = yt + unique rgr |
| | 577 | for ( int r = 0; r < urv.length(); r++ ) { |
| | 578 | RV R = urv.subselect ( vec_1 ( r ) ); //non-delayed element of rgr |
| | 579 | int r_size = urv.size ( r ); |
| | 580 | int r_multiplicity = -rgr.mint ( R ); |
| | 581 | u_block_sizes ( r ) = r_size * r_multiplicity ; |
| | 582 | for ( int m = 0; m < r_multiplicity; m++ ) { |
| | 583 | xrv.add ( R.copy_t ( -m - 1 ) ); //add delayed yt |
| | 584 | xrv_ml.add ( R.copy_t ( -m - 1 ) ); //add delayed yt |
| 555 | | //! temporary RV for connection to ml.rvc, since notation of xrv and ml.rvc does not match |
| 556 | | RV xrv_ml = xrv.copy_t(-1); |
| 557 | | |
| 558 | | // add regressors |
| 559 | | ivec u_block_sizes(urv.length()); // no_blocks = yt + unique rgr |
| 560 | | for (int r=0;r<urv.length();r++){ |
| 561 | | RV R=urv.subselect(vec_1(r)); //non-delayed element of rgr |
| 562 | | int r_size=urv.size(r); |
| 563 | | int r_multiplicity=-rgr.mint(R); |
| 564 | | u_block_sizes(r)= r_size*r_multiplicity ; |
| 565 | | for(int m=0;m<r_multiplicity;m++){ |
| 566 | | xrv.add(R.copy_t(-m-1)); //add delayed yt |
| 567 | | xrv_ml.add(R.copy_t(-m-1)); //add delayed yt |
| 568 | | } |
| | 586 | } |
| | 587 | // add constant |
| | 588 | if ( any ( ml._mu_const() != 0.0 ) ) { |
| | 589 | have_constant = true; |
| | 590 | xrv.add ( RV ( "bdm_reserved_constant_one", 1 ) ); |
| | 591 | } else { |
| | 592 | have_constant = false; |
| | 593 | } |
| | 594 | |
| | 595 | |
| | 596 | // get mapp |
| | 597 | th2A.set_connection ( xrv_ml, ml._rvc() ); |
| | 598 | th2B.set_connection ( urv, ml._rvc() ); |
| | 599 | |
| | 600 | //set matrix sizes |
| | 601 | this->A = zeros ( xrv._dsize(), xrv._dsize() ); |
| | 602 | //create y block |
| | 603 | diagonal_part ( this->A, yrv._dsize(), 0, y_block_size - yrv._dsize() ); |
| | 604 | |
| | 605 | this->B = zeros ( xrv._dsize(), urv._dsize() ); |
| | 606 | //add diagonals for rgr |
| | 607 | int active_x = y_block_size; |
| | 608 | for ( int r = 0; r < urv.length(); r++ ) { |
| | 609 | diagonal_part ( this->A, active_x + urv.size ( r ), active_x, u_block_sizes ( r ) - urv.size ( r ) ); |
| | 610 | this->B.set_submatrix ( active_x, 0, eye ( urv.size ( r ) ) ); |
| | 611 | active_x += u_block_sizes ( r ); |
| | 612 | } |
| | 613 | this->C = zeros ( yrv._dsize(), xrv._dsize() ); |
| | 614 | this->C.set_submatrix ( 0, 0, eye ( yrv._dsize() ) ); |
| | 615 | this->D = zeros ( yrv._dsize(), urv._dsize() ); |
| | 616 | this->R.setCh ( zeros ( yrv._dsize(), yrv._dsize() ) ); |
| | 617 | this->Q.setCh ( zeros ( xrv._dsize(), xrv._dsize() ) ); |
| | 618 | // Q is set by update |
| | 619 | |
| | 620 | update_from ( ml ); |
| | 621 | validate(); |
| | 622 | }; |
| | 623 | //! fast function to update parameters from ml - not checked for compatibility!! |
| | 624 | void update_from ( const mlnorm<chmat> &ml ) { |
| | 625 | |
| | 626 | vec Arow = zeros ( A.cols() ); |
| | 627 | vec Brow = zeros ( B.cols() ); |
| | 628 | // ROW- WISE EVALUATION ===== |
| | 629 | for ( int i = 0; i < ml._rv()._dsize(); i++ ) { |
| | 630 | |
| | 631 | vec theta = ml._A().get_row ( i ); |
| | 632 | |
| | 633 | th2A.filldown ( theta, Arow ); |
| | 634 | if ( have_constant ) { |
| | 635 | // constant is always at the end no need for datalink |
| | 636 | Arow ( A.cols() - 1 ) = ml._mu_const() ( i ); |
| 570 | | // add constant |
| 571 | | if (any(ml._mu_const()!=0.0)){ |
| 572 | | have_constant=true; |
| 573 | | xrv.add(RV("bdm_reserved_constant_one",1)); |
| 574 | | } else {have_constant=false;} |
| 575 | | |
| 576 | | |
| 577 | | // get mapp |
| 578 | | th2A.set_connection(xrv_ml, ml._rvc()); |
| 579 | | th2B.set_connection(urv, ml._rvc()); |
| 580 | | |
| 581 | | //set matrix sizes |
| 582 | | this->A=zeros(xrv._dsize(),xrv._dsize()); |
| 583 | | //create y block |
| 584 | | diagonal_part(this->A, yrv._dsize(), 0, y_block_size-yrv._dsize() ); |
| 585 | | |
| 586 | | this->B=zeros(xrv._dsize(), urv._dsize()); |
| 587 | | //add diagonals for rgr |
| 588 | | int active_x=y_block_size; |
| 589 | | for (int r=0; r<urv.length(); r++){ |
| 590 | | diagonal_part( this->A, active_x+urv.size(r),active_x, u_block_sizes(r)-urv.size(r)); |
| 591 | | this->B.set_submatrix(active_x, 0, eye(urv.size(r))); |
| 592 | | active_x+=u_block_sizes(r); |
| 593 | | } |
| 594 | | this->C=zeros(yrv._dsize(), xrv._dsize()); |
| 595 | | this->C.set_submatrix(0,0,eye(yrv._dsize())); |
| 596 | | this->D=zeros(yrv._dsize(),urv._dsize()); |
| 597 | | this->R.setCh(zeros(yrv._dsize(),yrv._dsize())); |
| 598 | | this->Q.setCh(zeros(xrv._dsize(),xrv._dsize())); |
| 599 | | // Q is set by update |
| 600 | | |
| 601 | | update_from(ml); |
| 602 | | validate(); |
| 603 | | }; |
| 604 | | //! fast function to update parameters from ml - not checked for compatibility!! |
| 605 | | void update_from(const mlnorm<chmat> &ml){ |
| 606 | | |
| 607 | | vec Arow=zeros(A.cols()); |
| 608 | | vec Brow=zeros(B.cols()); |
| 609 | | // ROW- WISE EVALUATION ===== |
| 610 | | for(int i=0;i<ml._rv()._dsize(); i++){ |
| 611 | | |
| 612 | | vec theta = ml._A().get_row(i); |
| 613 | | |
| 614 | | th2A.filldown(theta,Arow); |
| 615 | | if (have_constant){ |
| 616 | | // constant is always at the end no need for datalink |
| 617 | | Arow(A.cols()-1) = ml._mu_const()(i); |
| 618 | | } |
| 619 | | this->A.set_row(i,Arow); |
| 620 | | |
| 621 | | th2B.filldown(theta,Brow); |
| 622 | | this->B.set_row(i,Brow); |
| 623 | | } |
| 624 | | this->Q._Ch().set_submatrix(0,0,ml.__R()._Ch()); |
| 625 | | |
| 626 | | }; |
| 627 | | //! access function |
| 628 | | bool _have_constant() const {return have_constant;} |
| | 638 | this->A.set_row ( i, Arow ); |
| | 639 | |
| | 640 | th2B.filldown ( theta, Brow ); |
| | 641 | this->B.set_row ( i, Brow ); |
| | 642 | } |
| | 643 | this->Q._Ch().set_submatrix ( 0, 0, ml.__R()._Ch() ); |
| | 644 | |
| | 645 | }; |
| | 646 | //! access function |
| | 647 | bool _have_constant() const { |
| | 648 | return have_constant; |
| | 649 | } |
| 647 | | void StateSpace<sq_T>::validate(){ |
| 648 | | bdm_assert (A.cols() == A.rows(), "KalmanFull: A is not square"); |
| 649 | | bdm_assert (B.rows() == A.rows(), "KalmanFull: B is not compatible"); |
| 650 | | bdm_assert (C.cols() == A.rows(), "KalmanFull: C is not compatible"); |
| 651 | | bdm_assert ( (D.rows() == C.rows()) && (D.cols() == B.cols()), "KalmanFull: D is not compatible"); |
| 652 | | bdm_assert ( (Q.cols() == A.rows()) && (Q.rows() == A.rows()), "KalmanFull: Q is not compatible"); |
| 653 | | bdm_assert ( (R.cols() == C.rows()) && (R.rows() == C.rows()), "KalmanFull: R is not compatible"); |
| | 667 | void StateSpace<sq_T>::validate() { |
| | 668 | bdm_assert ( A.cols() == A.rows(), "KalmanFull: A is not square" ); |
| | 669 | bdm_assert ( B.rows() == A.rows(), "KalmanFull: B is not compatible" ); |
| | 670 | bdm_assert ( C.cols() == A.rows(), "KalmanFull: C is not compatible" ); |
| | 671 | bdm_assert ( ( D.rows() == C.rows() ) && ( D.cols() == B.cols() ), "KalmanFull: D is not compatible" ); |
| | 672 | bdm_assert ( ( Q.cols() == A.rows() ) && ( Q.rows() == A.rows() ), "KalmanFull: Q is not compatible" ); |
| | 673 | bdm_assert ( ( R.cols() == C.rows() ) && ( R.rows() == C.rows() ), "KalmanFull: R is not compatible" ); |