vpdt_gaussian.h
Go to the documentation of this file.
1 // This is core/vpdl/vpdt/vpdt_gaussian.h
2 #ifndef vpdt_gaussian_h_
3 #define vpdt_gaussian_h_
4 //:
5 // \file
6 // \author Matthew Leotta
7 // \date March 5, 2009
8 // \brief A generic Gaussian distribution
9 //
10 // \verbatim
11 // Modifications
12 // <None yet>
13 // \endverbatim
14 
15 
16 #include <limits>
20 #include <vpdl/vpdt/vpdt_access.h>
23 #include <vnl/vnl_math.h> // for twopi
24 #ifdef _MSC_VER
25 # include <vcl_msvc_warnings.h>
26 #endif
27 #include <vnl/vnl_erf.h>
28 
29 
30 //: Forward declare integration helper struct
31 template <class F, class Covar, class Metric, class Disambiguate= void >
33 
34 
35 //: A Gaussian with variance independent in each dimension
36 template<class F,
37  class Covar = typename vpdt_eigen_sym_matrix_gen<F>::type,
38  class Metric = vpdt_norm_metric<F,Covar> >
40 {
41  public:
42  //: The field type
43  typedef F field_type;
44  //: The covariance type
45  typedef Covar covar_type;
46  //: The metric type
47  typedef Metric metric_type;
48 
49  //: the data type used for scalars
51  //: the data type used for vectors
53  //: the data type used for matrices
55 
56  //: Constructor
57  // Optionally initialize the dimension for when n==0.
58  // Otherwise var_dim is ignored
60  {
61  vpdt_set_size(mean,var_dim);
62  vpdt_set_size(covar,var_dim);
63  vpdt_fill(mean,T(0));
64  vpdt_fill(covar,T(0));
65  }
66 
67  //: Constructor - from mean and variance
68  vpdt_gaussian(const F& m, const covar_type& c)
69  : mean(m), covar(c) {}
70 
71  //: Return the dimension
72  unsigned int dimension() const { return vpdt_size(mean); }
73 
74  //: Evaluate the unnormalized density at a point \a pt
75  // This must be multiplied by norm_const() to integrate to 1
76  T density(const F& pt) const
77  {
78  return static_cast<T>(std::exp(-sqr_mahal_dist(pt)/2));
79  }
80 
81  //: Compute the gradient of the density function, returned in \a g
82  // The return value of the function is the density itself
83  T gradient_density(const F& pt, vector& g) const
84  {
85  T d = Metric::sqr_distance_deriv(pt,mean,covar,g);
86  d = std::exp(-d/2);
87  g *= -d/2;
88  return d;
89  }
90 
91  //: compute the normalization constant (independent of sample point).
92  // Can be precomputed when evaluating at multiple points
93  T norm_const() const
94  {
96  domain_integral(*this);
97  }
98 
99  //: The squared Mahalanobis distance to this point
100  // Non-virtual for efficiency
101  T sqr_mahal_dist(const F& pt) const
102  {
103  return Metric::sqr_distance(pt,mean,covar);
104  }
105 
106  //: Evaluate the cumulative distribution function at a point
107  // This is the integral of the density function from negative infinity
108  // (in all dimensions) to the point in question
109  T cumulative_prob(const F& pt) const
110  {
112  partial_integral(*this,pt);
113  }
114 
115  //: Compute the mean of the distribution.
116  void compute_mean(vector& m) const { m = mean; }
117 
118  //: Compute the covariance matrix of the distribution.
119  void compute_covar(matrix& c) const
120  {
121  // use the metric to compute the covariance at the mean
122  Metric::compute_covar(c, mean, covar);
123  }
124 
125  //=========================================
126  // member variables - public for efficiency
127 
128  //: the mean
129  F mean;
130  //: the matrix covariance
132 };
133 
134 
135 //: Compute the log of the unnormalized density
136 template<class F, class C, class M >
137 inline typename vpdt_dist_traits<vpdt_gaussian<F,C,M> >::scalar_type
139  const typename vpdt_dist_traits<vpdt_gaussian<F,C,M> >::field_type& pt)
140 {
141  typedef typename vpdt_dist_traits<vpdt_gaussian<F,C,M> >::scalar_type T;
142  return static_cast<T>(-d.sqr_mahal_dist(pt)/2);
143 }
144 
145 //: Compute the gradient of the log of the unnormalized density
146 template<class F, class C, class M >
147 inline typename vpdt_dist_traits<vpdt_gaussian<F,C,M> >::scalar_type
149  const typename vpdt_dist_traits<vpdt_gaussian<F,C,M> >::field_type& pt,
150  typename vpdt_dist_traits<vpdt_gaussian<F,C,M> >::field_type& g)
151 {
152  typedef typename vpdt_dist_traits<vpdt_gaussian<F,C,M> >::scalar_type T;
153  T logd = M::sqr_distance_deriv(pt,d.mean,d.covar,g);
154  g /= -2;
155  return static_cast<T>(-logd/2);
156 }
157 
158 
159 //=============================================================================
160 // Implementations of Gaussian integration structs
161 
162 //: integrate over a Gaussian distribution
163 // This is the variation for multivariate with general covariance
164 template <class F>
166  vpdt_norm_metric<F, typename vpdt_eigen_sym_matrix_gen<F>::type>,
167  typename vpdt_field_traits<F>::type_is_vector >
168 {
172 
173  //: integrate over the entire domain
174  static inline T domain_integral(const vpdt_gaussian<F,Covar>& g)
175  {
176  const unsigned int d = g.dimension();
177  const double two_pi = vnl_math::twopi;
178  double two_pi_n = two_pi;
179  for (unsigned int i=1; i<d; ++i)
180  two_pi_n *= two_pi;
181 
182  return static_cast<T>(std::sqrt(two_pi_n*Metric::covar_det(g.mean,g.covar)));
183  }
184 
185  //: integrate from -infinity to \c pt
186  static inline T partial_integral(const vpdt_gaussian<F,Covar>& /*g*/, const F& /*pt*/)
187  {
188  // FIXME: implement this
189  // probably requires numerical integration
190  return std::numeric_limits<T>::quiet_NaN();
191  }
192 };
193 
194 
195 //: integrate over a Gaussian distribution
196 // This is the variation for multivariate with independent covariance
197 template <class F>
199  typename vpdt_field_traits<F>::type_is_vector >
200 {
202 
203  //: integrate over the entire domain
204  static inline T domain_integral(const vpdt_gaussian<F,F>& g)
205  {
206  const unsigned int d = g.dimension();
207  const double two_pi = vnl_math::twopi;
208  double val = 1.0;
209  for (unsigned int i=0; i<d; ++i)
210  val *= two_pi*g.covar[i];
211 
212  return static_cast<T>(std::sqrt(val));
213  }
214 
215  //: integrate from -infinity to \c pt
216  static inline T partial_integral(const vpdt_gaussian<F,F>& g, const F& pt)
217  {
218  const unsigned int d = g.dimension();
219  double val = 1.0;
220  for (unsigned int i=0; i<d; ++i)
221  {
222  if (vpdt_index(g.covar,i) <= T(0))
223  {
224  if (vpdt_index(pt,i) < vpdt_index(g.mean,i))
225  return T(0);
226  }
227  else{
228  double s2 = std::sqrt(2.0*vpdt_index(g.covar,i));
229  val *= 0.5*vnl_erf((vpdt_index(pt,i)-vpdt_index(g.mean,i))/s2) + 0.5;
230  }
231  }
232  return static_cast<T>(val);
233  }
234 };
235 
236 
237 //: integrate over a Gaussian distribution
238 // This is the variation for multivariate with hyper-spherical covariance
239 template <class F>
240 struct vpdt_gaussian_integrator<F,typename vpdt_field_traits<F>::scalar_type,
241  vpdt_norm_metric<F,typename vpdt_field_traits<F>::scalar_type>,
242  typename vpdt_field_traits<F>::type_is_vector>
243 {
246 
247  //: integrate over the entire domain
248  static inline T domain_integral(const vpdt_gaussian<F,T>& g)
249  {
250  const unsigned int d = g.dimension();
251  const double two_pi = vnl_math::twopi;
252  double val = 1.0;
253  for (unsigned int i=0; i<d; ++i)
254  val *= two_pi*g.covar;
255 
256  return static_cast<T>(std::sqrt(val));
257  }
258 
259  //: integrate from -infinity to \c pt
260  static inline T partial_integral(const vpdt_gaussian<F,T>& g, const F& pt)
261  {
262  const unsigned int d = g.dimension();
263  if (g.covar<=T(0))
264  {
265  for (unsigned int i=0; i<d; ++i)
266  if (vpdt_index(pt,i) < vpdt_index(g.mean,i))
267  return T(0);
268  return T(1);
269  }
270  double s2 = 1/std::sqrt(2.0*g.covar);
271  double val = 1.0;
272  for (unsigned int i=0; i<d; ++i)
273  {
274  val *= 0.5*vnl_erf(s2*(vpdt_index(pt,i)-vpdt_index(g.mean,i))) + 0.5;
275  }
276  return static_cast<T>(val);
277  }
278 };
279 
280 
281 //: integrate over a Gaussian distribution
282 // This is the variation for univariate
283 template <class F>
285 typename vpdt_field_traits<F>::type_is_scalar>
286 {
288 
289  //: integrate over the entire domain
290  static inline T domain_integral(const vpdt_gaussian<F,F>& g)
291  {
292  return static_cast<T>(std::sqrt(vnl_math::twopi*g.covar));
293  }
294 
295  //: integrate from -infinity to \c pt
296  static inline T partial_integral(const vpdt_gaussian<F,F>& g, const F& pt)
297  {
298  if (g.covar<=T(0))
299  {
300  if (pt < g.mean)
301  return T(0);
302  return T(1);
303  }
304  double val = 0.5*vnl_erf((pt-g.mean)/std::sqrt(2.0*g.covar)) + 0.5;
305  return static_cast<T>(val);
306  }
307 };
308 
309 
310 #endif // vpdt_gaussian_h_
T norm_const() const
compute the normalization constant (independent of sample point).
Definition: vpdt_gaussian.h:93
The distribution traits class.
F field_type
The field type.
Definition: vpdt_gaussian.h:43
static T partial_integral(const vpdt_gaussian< F, F > &g, const F &pt)
integrate from -infinity to pt.
T sqr_mahal_dist(const F &pt) const
The squared Mahalanobis distance to this point.
covar_type covar
the matrix covariance.
void compute_covar(matrix &c) const
Compute the covariance matrix of the distribution.
Forward declare integration helper struct.
Definition: vpdt_gaussian.h:32
T cumulative_prob(const F &pt) const
Evaluate the cumulative distribution function at a point.
#define m
A type generator for the default types (those used in vpdl)
unsigned int dimension() const
Return the dimension.
Definition: vpdt_gaussian.h:72
Metrics derived from norms.
Covar covar_type
The covariance type.
Definition: vpdt_gaussian.h:45
T density(const F &pt) const
Evaluate the unnormalized density at a point pt.
Definition: vpdt_gaussian.h:76
Metric metric_type
The metric type.
Definition: vpdt_gaussian.h:47
T & vpdt_index(vnl_vector< T > &v, unsigned int i)
Index into a vnl_vector.
Definition: vpdt_access.h:101
vpdt_field_traits< F >::matrix_type matrix
the data type used for matrices.
Definition: vpdt_gaussian.h:54
A Gaussian with variance independent in each dimension.
Definition: vpdt_gaussian.h:39
double vnl_erf(double x)
vpdt_gaussian(unsigned int var_dim=vpdt_field_traits< F >::dimension)
Constructor.
Definition: vpdt_gaussian.h:59
static T domain_integral(const vpdt_gaussian< F, F > &g)
integrate over the entire domain.
static T domain_integral(const vpdt_gaussian< F, F > &g)
integrate over the entire domain.
specialized template trait classes for properties of a field type
vpdt_gaussian(const F &m, const covar_type &c)
Constructor - from mean and variance.
Definition: vpdt_gaussian.h:68
void vpdt_set_size(vnl_vector< T > &v, unsigned int s)
Set the size of a vnl_vector.
Definition: vpdt_access.h:63
The field traits class (scalar).
generate the vpdt_eigen_sys_matrix type from a field type.
void compute_mean(vector &m) const
Compute the mean of the distribution.
F mean
the mean.
vpdt_field_traits< F >::scalar_type T
the data type used for scalars.
Definition: vpdt_gaussian.h:50
Overloaded functions to allow uniform API access to various field types.
vpdt_field_traits< F >::vector_type vector
the data type used for vectors.
Definition: vpdt_gaussian.h:52
A metric in field F with metric tensor Tensor.
A symmetric matrix represented in eigenvalue decomposition.
specialized template trait classes for properties of a distribution type
T gradient_density(const F &pt, vector &g) const
Compute the gradient of the density function, returned in g.
Definition: vpdt_gaussian.h:83
vpdt_dist_traits< vpdt_gaussian< F, C, M > >::scalar_type vpdt_gradient_log_density(const vpdt_gaussian< F, C, M > &d, const typename vpdt_dist_traits< vpdt_gaussian< F, C, M > >::field_type &pt, typename vpdt_dist_traits< vpdt_gaussian< F, C, M > >::field_type &g)
Compute the gradient of the log of the unnormalized density.
unsigned int vpdt_size(const vnl_vector< T > &v)
Access the size of a vnl_vector.
Definition: vpdt_access.h:36
void vpdt_fill(vnl_vector< T > &v, const T &val)
Fill a vnl_vector.
Definition: vpdt_access.h:78
vpdt_dist_traits< vpdt_gaussian< F, C, M > >::scalar_type vpdt_log_density(const vpdt_gaussian< F, C, M > &d, const typename vpdt_dist_traits< vpdt_gaussian< F, C, M > >::field_type &pt)
Compute the log of the unnormalized density.
static T partial_integral(const vpdt_gaussian< F, F > &g, const F &pt)
integrate from -infinity to pt.