GCOP
1.0
|
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