Gaussian.cpp
Go to the documentation of this file.
1// *****************************************************************
2// Filename: Gaussian.h
3// Copyright: Kai Welke, Chair Prof. Dillmann (IAIM),
4// Institute for Computer Science and Engineering (CSE),
5// University of Karlsruhe. All rights reserved.
6// Author: Kai Welke
7// Date: 27.05.2012
8// *****************************************************************
9
10// *****************************************************************
11// includes
12// *****************************************************************
13#include "Gaussian.h"
14
15#include <cstdio>
16#include <iostream>
17
18// *****************************************************************
19// construction
20// *****************************************************************
22{
23 this->dimension = -1;
24}
25
26Gaussian::Gaussian(int dimension)
27{
28 this->dimension = dimension;
29
30 // initialize valid distribution
31 this->cov = covariance_type::Identity(dimension, dimension);
32 this->mean = value_type::Zero(dimension, 1);
33}
34
36{
37 *this = prototype;
38}
39
40Gaussian::Gaussian(const value_type& mean, const covariance_type& covariance)
41{
42 this->cov = covariance;
43 this->mean = mean;
44
45 dimension = cov.rows();
46
47 if (mean.rows() != dimension)
48 {
50 }
51}
52
53// *****************************************************************
54// readouts
55// *****************************************************************
56double
58{
59 if (dimension == -1)
60 {
62 }
63
64 if (point.rows() != dimension)
65 {
67 }
68
70 -0.5 * (point - mean).transpose() * cov.inverse() * (point - mean);
71 double e = exp(inner(0, 0));
72
73 covariance_type i = cov;
74 return pow(2 * M_PI, -getDimensions() / 2.0f) * pow(i.determinant(), -0.5) * e;
75}
76
77double
79{
80 if (dimension == -1)
81 {
83 }
84
85 if (point.rows() != dimension)
86 {
88 }
89
91 dist = (point - mean).transpose() * cov.inverse() * (point - mean);
92
93 return std::sqrt(dist(0, 0));
94}
95
96// generic draw sample for arbitrary covariance matrix
99{
100 if (dimension == -1)
101 {
103 }
104
105 // go through all dimensions and calculate independen random processes on unit
106 // gaussian using Box-Muller method
107
108 float fRand1, fRand2;
109 value_type gaussianSample(getDimensions());
110
111 // calculate gaussian distributed with Cov=I and mean = 0 (ndimension independant box muller gaussians)
112 for (int d = 0; d < getDimensions(); d++)
113 {
114 fRand1 = float(rand()) / RAND_MAX;
115 fRand2 = float(rand()) / RAND_MAX;
116
117 // calculate standard normal distribution sample (Box-Muller)
118 gaussianSample(d) = sqrt(-2 * log(fRand1)) * cos(2 * M_PI * fRand2);
119 }
120
121 // in order to retrieve samples distributed according to cov
122 // use cholesky decomposition:
123 // A * A^t = cov
124 // ==> random_vector=A * gaussianSample
125 // (can be proved by X=AY, D= cov(Y) (with D=I, produced by above code), C=cov(X) (which is desired cov), C= E(XX^T)=E(AY(AY)^t)=AE(YY^t)A^t=ADA^t)
126 // thus only matrx A has to be found
127 covariance_type A = cov.llt().matrixL();
128
129 value_type sample = A * gaussianSample + mean;
130
131 return sample;
132}
133
134// draw sample for cases where only elements in diagonal of cov (can be used with zero in diagonal)
137{
138 if (dimension == -1)
139 {
141 }
142
143 // go through all dimensions and calculate independen random processes on unit
144 // gaussian using Box-Muller method
145
146 float fRand1, fRand2;
147 value_type gaussianSample(getDimensions());
148
149 // calculate gaussian distributed with Cov=I and mean = 0 (ndimension independant box muller gaussians)
150 for (int d = 0; d < getDimensions(); d++)
151 {
152 fRand1 = float(rand()) / RAND_MAX;
153 fRand2 = float(rand()) / RAND_MAX;
154
155 // calculate standard normal distribution sample (Box-Muller)
156 gaussianSample(d) = sqrt(-2 * log(fRand1)) * cos(2 * M_PI * fRand2);
157 }
158
159 // generate matrix A
161
162 for (int i = 0; i < getDimensions(); i++)
163 for (int u = 0; u < getDimensions(); u++)
164 if (i == u)
165 {
166 A(i, u) = sqrt(cov(i, u));
167 }
168 else
169 {
170 A(i, u) = 0;
171 }
172
173 value_type sample = A * gaussianSample + mean;
174
175 return sample;
176}
177
178// *****************************************************************
179// content manipulation
180// *****************************************************************
181void
183{
184 if (dimension == -1)
185 {
187 }
188
189 if (samples.rows() != dimension)
190 {
192 }
193
194 int numberSamples = samples.cols();
195
196 // calculate mean
197 mean = value_type::Zero(dimension, 1);
198
199 for (int i = 0; i < numberSamples; i++)
200 {
201 mean += samples.block(0, i, mean.rows(), 1);
202 }
203
204 mean = mean / numberSamples;
205
206 samples_type meanadj = samples;
207
208 // mean adjust
209 for (int s = 0; s < numberSamples; s++)
210 {
211 meanadj.block(0, s, meanadj.rows(), 1) -= mean;
212 }
213
214 // calculate covariance
215 cov = meanadj * meanadj.transpose() / numberSamples;
216}
217
218void
219Gaussian::set(const Gaussian& prototype)
220{
221 if ((dimension != prototype.getDimensions()))
222 {
224 }
225
226 this->mean = prototype.getMean();
227 this->cov = prototype.getCovariance();
228}
229
230void
232{
233 // isSymmetric(cov);
234
235 if ((dimension != -1) && (mean.rows() != dimension))
236 {
238 }
239
240 if ((dimension != -1) && (cov.rows() != dimension))
241 {
243 }
244
245 if (dimension == -1)
246 {
247 dimension = cov.rows();
248 }
249
250 this->mean = mean;
251 this->cov = cov;
252}
253
254void
256{
257 if ((dimension != -1) && (mean.rows() != dimension))
258 {
260 }
261
262 if (dimension == -1)
263 {
264 dimension = mean.rows();
265 this->cov = Eigen::MatrixXd::Identity(dimension, dimension);
266 }
267
268 this->mean = mean;
269}
270
271void
273{
274 if ((dimension != -1) && (cov.rows() != dimension))
275 {
277 }
278
279 if ((dimension != -1) && (cov.cols() != dimension))
280 {
282 }
283
284 if ((dimension == -1) && (cov.rows() != cov.cols()))
285 {
287 }
288
289 if (dimension == -1)
290 {
291 dimension = cov.rows();
292 this->mean = Eigen::VectorXd::Zero(dimension);
293 }
294
295 this->cov = cov;
296}
297
298// *****************************************************************
299// content manipulation
300// *****************************************************************
301void
302Gaussian::isSymmetric(const covariance_type& matrix)
303{
304 if (matrix.rows() != matrix.cols())
305 {
307 }
308
309 for (int r = 0; r < matrix.rows(); r++)
310 {
311 for (int c = 0; c < matrix.cols(); c++)
312 {
313 if (matrix(r, c) != matrix(c, r))
314 {
315 throw CovarianceNotSymmetricException();
316 }
317 }
318 }
319}
#define float
Definition 16_Level.h:22
class A(deque< T, A >)) ARMARX_OVERLOAD_STD_HASH_FOR_ITERABLE((class T
Enables hashing of std::list.
#define M_PI
Definition MathTools.h:17
constexpr T c
const covariance_type & getCovariance() const
Definition Gaussian.h:82
Eigen::VectorXd value_type
Definition Gaussian.h:56
double evaluate(const value_type &point)
Definition Gaussian.cpp:57
value_type drawSample()
Definition Gaussian.cpp:98
int getDimensions() const
Definition Gaussian.h:94
Eigen::MatrixXd samples_type
Definition Gaussian.h:58
void set(const Gaussian &prototype)
Definition Gaussian.cpp:219
Eigen::MatrixXd covariance_type
Definition Gaussian.h:57
void setCovariance(const covariance_type &cov)
Definition Gaussian.cpp:272
void setMean(const value_type &mean)
Definition Gaussian.cpp:255
value_type drawSampleDiagonalCovariance()
Definition Gaussian.cpp:136
const value_type & getMean() const
Definition Gaussian.h:88
void generateFromSamples(const samples_type &samples)
Definition Gaussian.cpp:182
double mahalanobis(const value_type &point)
Definition Gaussian.cpp:78