GCOP  1.0
normal.h
Go to the documentation of this file.
00001 #ifndef GCOP_NORMAL_H
00002 #define GCOP_NORMAL_H
00003 
00004 #include <Eigen/Dense>
00005 #include <vector>
00006 #include "utils.h"
00007 
00008 namespace gcop {
00009   
00010   using namespace Eigen;
00011   using namespace std;
00012 
00013   template <int _n = Dynamic>
00014   class Normal {
00015   public:
00016   typedef Matrix<double, _n, 1> Vectornd;
00017   typedef Matrix<double, _n, _n> Matrixnd;
00018 
00023   Normal(int n = 1);
00024   
00030   Normal(const Vectornd &mu, const Matrixnd &P);
00031   
00032   virtual ~Normal();
00033   
00039   double L(const Vectornd &x) const;
00040   
00041   
00047   double Sample(Vectornd &x);    
00048   
00053   bool Update();
00054   
00060   void Fit(const vector<pair<Vectornd, double> > xps, double a = 1);
00061   
00062   Vectornd mu;     
00063   Matrixnd P;      
00064   
00065   double det;      
00066   Matrixnd Pinv;   
00067   bool pd;         
00068   
00069   Matrixnd A;      
00070   Vectornd rn;     
00071   
00072   double norm;     
00073   
00074   int bd;          
00075   
00076   bool bounded;    
00077   Vectornd lb;     
00078   Vectornd ub;     
00079   
00080   LLT<Matrixnd> llt; 
00081   };
00082   
00083 
00084 
00085   template<int _n>
00086     Normal<_n>::Normal(int n):
00087     det(0),
00088     pd(false),
00089     norm(0),
00090     bd(0), 
00091     bounded(false) {
00092     
00093     if (_n == Dynamic) {
00094       mu.resize(n);
00095       P.resize(n,n);
00096       Pinv.resize(n,n);
00097       A.resize(n,n);
00098       rn.resize(n);
00099       lb.resize(n);
00100       ub.resize(n);
00101     }
00102     mu.setZero();
00103     P.setZero();
00104     Pinv.setZero();
00105     A.setZero();
00106     rn.setZero();
00107   }
00108   
00109   template<int _n>
00110     Normal<_n>::Normal(const Vectornd &mu, const Matrixnd &P):
00111     mu(mu),
00112     P(P),
00113     det(0),
00114     pd(false),
00115     norm(0),
00116     bd(0),
00117     bounded(false) {
00118     
00119     int n = mu.size();
00120 
00121     if (_n == Dynamic) {
00122       Pinv.resize(n,n);
00123       A.resize(n,n);
00124       rn.resize(n);
00125       lb.resize(n);
00126       ub.resize(n);
00127     }
00128     Pinv.setZero();
00129     A.setZero();
00130     rn.setZero();
00131     
00132     
00133     Update();
00134   }
00135   
00136 
00137   template<int _n>
00138     Normal<_n>::~Normal()
00139     {
00140     }
00141 
00142 
00143   template<int _n>
00144     double Normal<_n>::L(const Vectornd &x) const
00145     {
00146       if (!pd) {
00147         cout << "[W] Normal::L: not positive definite!" << endl;
00148       }
00149       
00150       Vectornd d = x - mu;
00151       return exp(-d.dot(Pinv*d))/2/norm;
00152     }
00153   
00154   template<int _n>
00155     bool Normal<_n>::Update()
00156     {
00157       llt.compute(P);
00158       
00159       if (llt.info() == Eigen::Success) {
00160         A = llt.matrixL();
00161         Pinv = P.inverse();
00162         det = P.determinant();
00163         norm = sqrt(pow(2*M_PI, mu.size())*det);    
00164         pd = true;
00165       } else {
00166         cout << "[W] Normal::Update: cholesky failed: P=" << P << endl;
00167         pd = false;    
00168       }
00169       
00170       return pd;
00171     }
00172 
00173   template<int _n>
00174     double Normal<_n>::Sample(Vectornd &x)
00175     {
00176       double p = 1;
00177       for (int i = 0; i < rn.size(); ++i) {
00178         rn(i) = random_normal();
00179         p *= rn(i);
00180       }
00181       
00182       x = mu + A*rn;
00183       
00184       if (bounded) {
00185         x = x.cwiseMax(lb);
00186         x = x.cwiseMin(ub);
00187       }
00188 
00189       return p;
00190     }
00191   
00192   template<int _n>
00193     void Normal<_n>::Fit(const vector<pair<Vectornd, double> > xws, double a)
00194     {
00195       int N = xws.size();
00196       
00197       Vectornd mu;
00198       if (_n == Dynamic)
00199         mu.resize(this->mu.size());
00200 
00201       mu.setZero();
00202       for (int j = 0; j < N; ++j) {
00203         const pair<Vectornd, double> &xw = xws[j];
00204         mu += xw.first*xw.second;
00205       }
00206       
00207       Matrixnd P;
00208       if (_n == Dynamic)
00209         P.resize(this->mu.size(), this->mu.size());
00210       P.setZero();
00211 
00212       for (int j = 0; j < N; ++j) {
00213         const pair<Vectornd, double> &xw = xws[j];
00214         Vectornd dx = xw.first - mu;
00215         if (!bd) {
00216           P += (xw.second*dx)*dx.transpose();
00217         } else {
00218           int b = dx.size()/bd;
00219           for (int i = 0; i < b; ++i) {
00220             int bi = i*bd;
00221             Vectornd bdx = dx.segment(bi, bd);        
00222             P.block(bi, bi, bd, bd) += (xw.second*bdx)*bdx.transpose();       
00223           }
00224         }
00225       }
00226       
00227       if (fabs(a-1) < 1e-16) {
00228         this->mu = mu;
00229         this->P = P;
00230       } else {
00231         this->mu = a*mu + (1-a)*this->mu;
00232         this->P = a*P + (1-a)*this->P;
00233       }
00234     }  
00235 }
00236 
00237 
00238 #endif