indii/ml/filter/LinearModel.cpp

00001 //#if defined(__GNUC__) && defined(GCC_PCH)
00002 //  #include "../aux/aux.hpp"
00003 //#endif
00004 
00005 #include "LinearModel.hpp"
00006 
00007 using namespace indii::ml::filter;
00008 
00009 namespace aux = indii::ml::aux;
00010 
00011 /**
00012  * @todo System noise needn't have the same number of dimensions at the state,
00013  * and likewise G may be N*P, not N*N, where P is the number of dimensions of
00014  * the noise.
00015  */
00016 LinearModel::LinearModel(aux::matrix& A, aux::matrix& G,
00017     aux::symmetric_matrix& Q, aux::matrix& C, aux::symmetric_matrix& R) :
00018     N(A.size1()), M(C.size1()), A(A), AT(trans(A)), G(G), GT(trans(G)), Q(Q),
00019     C(C), CT(trans(C)), R(R), AI(N,N) {
00020   /* pre-condition */
00021   #ifndef NDEBUG
00022   assert(A.size1() == N);
00023   assert(A.size2() == N);
00024   assert(G.size1() == N);
00025   assert(G.size2() == N);
00026   assert(Q.size1() == N);
00027   assert(Q.size2() == N);
00028   assert(C.size1() == M);
00029   assert(C.size2() == N);
00030   assert(R.size1() == M);
00031   assert(R.size2() == M);
00032   #endif
00033 
00034   /* for backwards pass */
00035   aux::matrix tmp(A);
00036   aux::inv(tmp,AI);
00037 }
00038 
00039 LinearModel::~LinearModel() {
00040   //
00041 }
00042 
00043 aux::GaussianPdf LinearModel::p_xtnp1_ytn(const aux::GaussianPdf& p_xtn_ytn,
00044       const unsigned int delta) {
00045   const aux::vector& x_xtn_ytn = p_xtn_ytn.getExpectation();
00046   const aux::symmetric_matrix& P_xtn_ytn = p_xtn_ytn.getCovariance();
00047   aux::vector x_xtnp1_ytn(N);
00048   aux::symmetric_matrix P_xtnp1_ytn(N,N);
00049 
00050   noalias(x_xtnp1_ytn) = prod(A,x_xtn_ytn);
00051   aux::matrix X(N,N);
00052   noalias(X) = prod(P_xtn_ytn,AT);
00053   noalias(P_xtnp1_ytn) = prod(A,X);
00054   noalias(X) = prod(Q,GT);
00055   noalias(P_xtnp1_ytn) += prod(G,X);
00056 
00057   return aux::GaussianPdf(x_xtnp1_ytn, P_xtnp1_ytn);
00058 }
00059 
00060 /**
00061  * @todo Doesn't consider delta currently. Should iterate as many
00062  * times as specified by delta, for example, in the case that there is
00063  * a missing observation. Just do this using recursion.
00064  */
00065 aux::GaussianPdf LinearModel::p_xtnp1_ytnp1(
00066     const aux::GaussianPdf& p_xtnp1_ytn, const aux::vector& ytnp1,
00067     const unsigned int delta) {
00068   const aux::vector& x_xtnp1_ytn = p_xtnp1_ytn.getExpectation();
00069   const aux::symmetric_matrix& P_xtnp1_ytn = p_xtnp1_ytn.getCovariance();
00070   aux::vector x_xtnp1_ytnp1(N);
00071   aux::symmetric_matrix P_xtnp1_ytnp1(N);
00072   aux::matrix X(M,M), Y(M,M), Z(N,M), K_tnp1(N,M);
00073 
00074   noalias(Z) = prod(P_xtnp1_ytn, CT);
00075   noalias(X) = prod(C, Z) + R;
00076   aux::inv(X, Y);
00077 
00078   noalias(Z) = prod(P_xtnp1_ytn, CT);
00079   noalias(K_tnp1) = prod(Z, Y); // kalman gain
00080 
00081   noalias(x_xtnp1_ytnp1) = x_xtnp1_ytn
00082       + prod(K_tnp1,aux::vector(ytnp1 - prod(C,x_xtnp1_ytn)));
00083   noalias(P_xtnp1_ytnp1) = P_xtnp1_ytn
00084       - prod(K_tnp1,aux::matrix(prod(C,P_xtnp1_ytn)));
00085 
00086   return aux::GaussianPdf(x_xtnp1_ytnp1, P_xtnp1_ytnp1);
00087 }
00088 
00089 aux::GaussianPdf LinearModel::p_y_x(const aux::GaussianPdf& p_x) {
00090   const aux::vector& x = p_x.getExpectation();
00091   const aux::symmetric_matrix& P_x = p_x.getCovariance();
00092   aux::vector y(M);
00093   aux::symmetric_matrix P_y(M,M);
00094   aux::matrix X(M,M);
00095 
00096   noalias(y) = prod(C,x);
00097 
00098   noalias(X) = prod(P_x, CT);
00099   noalias(P_y) = prod(C, X) + R;
00100 
00101   return aux::GaussianPdf(y, P_y);
00102 }
00103 
00104 aux::GaussianPdf LinearModel::p_xtn_ytT(const aux::GaussianPdf& p_xtnp1_ytT,
00105     const aux::GaussianPdf& p_xtnp1_ytn, const aux::GaussianPdf& p_xtn_ytn,
00106     const unsigned int delta) {
00107   const aux::vector& x_xtnp1_ytT = p_xtnp1_ytT.getExpectation();
00108   const aux::symmetric_matrix& P_xtnp1_ytT = p_xtnp1_ytT.getCovariance();
00109   const aux::vector& x_xtnp1_ytn = p_xtnp1_ytn.getExpectation();
00110   const aux::symmetric_matrix& P_xtnp1_ytn = p_xtnp1_ytn.getCovariance();
00111   const aux::vector& x_xtn_ytn = p_xtn_ytn.getExpectation();
00112   const aux::symmetric_matrix& P_xtn_ytn = p_xtn_ytn.getCovariance();
00113   aux::vector x_xtn_ytT(N);
00114   aux::symmetric_matrix P_xtn_ytT(N);
00115 
00116   aux::matrix L_tn(N,N), LT_tn(N,N), PI_xtnp1_ytn(N,N), X(N,N);
00117   noalias(X) = P_xtnp1_ytn;
00118   aux::inv(X, PI_xtnp1_ytn);
00119 
00120   noalias(X) = prod(AT, PI_xtnp1_ytn);
00121   noalias(L_tn) = prod(P_xtn_ytn, X);
00122   noalias(LT_tn) = trans(L_tn);
00123 
00124   noalias(x_xtn_ytT) = x_xtn_ytn + prod(L_tn, x_xtnp1_ytT - x_xtnp1_ytn);
00125   noalias(X) = prod(P_xtnp1_ytT - P_xtnp1_ytn, LT_tn);
00126   noalias(P_xtn_ytT) = P_xtn_ytn + prod(L_tn, X);
00127 
00128   return aux::GaussianPdf(x_xtn_ytT, P_xtn_ytT);
00129 }
00130 
00131 aux::GaussianPdf LinearModel::p_xtnm1_ytn(const aux::GaussianPdf& p_xtn_ytn,
00132     const unsigned int delta) {
00133   /* calculate inverse dynamics */
00134   const aux::vector x_xtn_ytn = p_xtn_ytn.getExpectation();
00135   const aux::matrix P_xtn_ytn = p_xtn_ytn.getCovariance();
00136 
00137   aux::matrix A_b(N,N);
00138   aux::matrix G_b(N,N);
00139   aux::matrix Q_b(N,N);
00140   aux::vector w_b(N);
00141 
00142   aux::matrix PI_xtn_ytn(N,N);
00143   aux::identity_matrix I(N);
00144   aux::matrix X(N,N);
00145 
00146   noalias(X) = P_xtn_ytn;
00147   aux::inv(X, PI_xtn_ytn);
00148 
00149   noalias(A_b) = prod(AI,G);
00150   A_b = prod(A_b,Q);
00151   A_b = prod(A_b,GT);
00152   A_b = prod(A_b,PI_xtn_ytn);
00153   A_b = I - A_b;
00154   A_b = prod(AI, A_b);
00155 
00156   noalias(G_b) = -1.0 * prod(AI,G);
00157 
00158   noalias(Q_b) = prod(Q,GT);
00159   Q_b = prod(Q_b,PI_xtn_ytn);
00160   Q_b = prod(Q_b,G);
00161   Q_b = prod(Q_b,Q);
00162   Q_b = Q - Q_b;
00163 
00164   noalias(w_b) = prod(PI_xtn_ytn,x_xtn_ytn);
00165   w_b = prod(GT,w_b);
00166   w_b = prod(Q,w_b);
00167   w_b *= -1.0;
00168 
00169   /* filter backwards */
00170   aux::vector x_xtnm1_ytn(N);
00171   aux::symmetric_matrix P_xtnm1_ytn(N,N);
00172 
00173   noalias(x_xtnm1_ytn) = prod(A_b,x_xtn_ytn) + prod(G_b,w_b);
00174   noalias(X) = prod(A_b,P_xtn_ytn);
00175   noalias(P_xtnm1_ytn) = prod(X,trans(A_b));
00176   noalias(X) = prod(G_b,Q_b);
00177   noalias(P_xtnm1_ytn) += prod(X,trans(G_b));
00178 
00179   return aux::GaussianPdf(x_xtnm1_ytn, P_xtnm1_ytn);
00180 }
00181 
00182 aux::GaussianPdf LinearModel::p_xtnm1_ytnm1(
00183     const aux::GaussianPdf& p_xtnm1_ytn, const aux::vector& ytnm1,
00184     const unsigned int delta) {
00185   return p_xtnp1_ytnp1(p_xtnm1_ytn, ytnm1, delta);
00186 }

Generated on Wed Dec 17 15:11:57 2008 for dysii Dynamical Systems Library by  doxygen 1.5.3