00001 // This is core/vpdl/vpdl_distribution.h 00002 #ifndef vpdl_distribution_h_ 00003 #define vpdl_distribution_h_ 00004 //: 00005 // \file 00006 // \author Matthew Leotta 00007 // \date February 5, 2009 00008 // \brief The templated base class for all distributions 00009 // 00010 // \verbatim 00011 // Modifications 00012 // None 00013 // \endverbatim 00014 00015 #include <vpdl/vpdt/vpdt_field_traits.h> 00016 #include <vpdl/vpdt/vpdt_field_default.h> 00017 #include <vcl_cmath.h> 00018 00019 //: The base class for all probability distributions. 00020 // There is a distinct polymorphic class hierarchy for each choice of 00021 // template parameters. The vector and matrix data types vary with both \c T and \c n. 00022 // \tparam T is the scalar type use for numerical calculations (generally double or float) 00023 // \tparam n is the fixed dimension of the space with special case 0 (the default) 00024 // indicating dynamic dimension set at run time. 00025 // - For n > 1 the data types are vnl_vector_fixed<T,n> and vnl_matrix_fixed<T,n,n> 00026 // - For n == 1 the data types are T and T 00027 // - For n == 0 the data types are vnl_vector<T> and vnl_matrix<T> 00028 // 00029 template<class T, unsigned int n=0> 00030 class vpdl_distribution 00031 { 00032 public: 00033 virtual ~vpdl_distribution() {} 00034 00035 //: the data type used for vectors 00036 typedef typename vpdt_field_default<T,n>::type field_type; 00037 00038 //: the data type used for vectors 00039 typedef typename vpdt_field_default<T,n>::type vector; 00040 //: the data type used for matrices 00041 typedef typename vpdt_field_traits<field_type>::matrix_type matrix; 00042 00043 //: Return the run time dimension, which does not equal \c n when \c n==0 00044 virtual unsigned int dimension() const = 0; 00045 00046 //: Create a copy on the heap and return base class pointer 00047 virtual vpdl_distribution<T,n>* clone() const = 0; 00048 00049 //: Evaluate the unnormalized density at a point 00050 // \note This is not a probability density. 00051 // To make this a probability multiply by norm_const() 00052 // \sa prob_density 00053 virtual T density(const vector& pt) const = 0; 00054 00055 //: Evaluate the probability density at a point 00056 virtual T prob_density(const vector& pt) const 00057 { 00058 return density(pt) * norm_const(); 00059 } 00060 00061 //: Evaluate the log probability density at a point 00062 virtual T log_prob_density(const vector& pt) const 00063 { 00064 return vcl_log(prob_density(pt)); 00065 }; 00066 00067 //: Compute the gradient of the unnormalized density at a point 00068 // \return the density at \a pt since it is usually needed as well, and 00069 // is often trivial to compute while computing gradient 00070 // \retval g the gradient vector 00071 virtual T gradient_density(const vector& pt, vector& g) const = 0; 00072 00073 //: The normalization constant for the density 00074 // When density() is multiplied by this value it becomes prob_density 00075 // norm_const() is reciprocal of the integral of density over the entire field 00076 virtual T norm_const() const = 0; 00077 00078 //: Evaluate the cumulative distribution function at a point 00079 // This is the integral of the density function from negative infinity 00080 // (in all dimensions) to the point in question 00081 // \note It is not possible to compute this value for all functions in 00082 // closed form. In some cases, numerical integration may be used. 00083 // If no good solutions exists the function should return a quiet NaN. 00084 virtual T cumulative_prob(const vector& pt) const = 0; 00085 00086 //: Compute the inverse of the cumulative_prob() function 00087 // The value of x: P(x'<x) = P for x' drawn from the distribution. 00088 // \note This is only valid for univariate distributions 00089 // multivariate distributions will return a quiet NaN 00090 virtual vector inverse_cdf(const T& p) const; 00091 00092 //: The probability of being in an axis-aligned box 00093 // The box is defined by two points, the minimum and maximum. 00094 // Implemented in terms of \c cumulative_prob() by default. 00095 virtual T box_prob(const vector& min_pt, const vector& max_pt) const; 00096 00097 //: Compute the mean of the distribution. 00098 // This may be trivial for distributions like Gaussians, 00099 // but actually involves computation for others. 00100 virtual void compute_mean(vector& mean) const = 0; 00101 00102 //: Compute the covariance of the distribution. 00103 // This may be trivial for distributions like Gaussians, 00104 // but actually involves computation for others. 00105 virtual void compute_covar(matrix& covar) const = 0; 00106 }; 00107 00108 00109 //: Default implementation of numerical CDF inverse computation. 00110 // This function is called by the virtual function inverse_cdf() by default 00111 // in the univariate case. 00112 template <class T> 00113 T vpdl_compute_inverse_cdf(const vpdl_distribution<T,1>& dist, double p); 00114 00115 00116 //============================================================================= 00117 // These global functions allow vpdl_distributions be used efficiently as 00118 // components in vpdt distributions like vpdt_mixture_of 00119 00120 //: probability density wrapper for vpdt 00121 template<class T, unsigned int n> 00122 inline T vpdt_prob_density(const vpdl_distribution<T,n>& d, 00123 const typename vpdt_field_default<T,n>::type& pt) 00124 { 00125 return d.prob_density(pt); 00126 } 00127 00128 //: The box probability wrapper for vpdt 00129 template<class T, unsigned int n> 00130 inline T vpdt_box_prob(const vpdl_distribution<T,n>& d, 00131 const typename vpdt_field_default<T,n>::type& min_pt, 00132 const typename vpdt_field_default<T,n>::type& max_pt) 00133 { 00134 return d.box_prob(min_pt,max_pt); 00135 } 00136 00137 //: The log density wrapper for vpdt 00138 template<class T, unsigned int n> 00139 inline T vpdt_log_density(const vpdl_distribution<T,n>& d, 00140 const typename vpdt_field_default<T,n>::type& pt) 00141 { 00142 return d.log_density(pt); 00143 } 00144 00145 //: The log probability density wrapper for vpdt 00146 template<class T, unsigned int n> 00147 inline T vpdt_log_prob_density(const vpdl_distribution<T,n>& d, 00148 const typename vpdt_field_default<T,n>::type& pt) 00149 { 00150 return d.log_prob_density(pt); 00151 } 00152 00153 00154 #endif // vpdl_distribution_h_