MLPACK
1.0.4
|
00001 00023 #ifndef __MLPACK_CORE_KERNELS_SPHERICAL_KERNEL_H 00024 #define __MLPACK_CORE_KERNELS_SPHERICAL_KERNEL_H 00025 00026 #include <boost/math/special_functions/gamma.hpp> 00027 #include <mlpack/core.hpp> 00028 00029 namespace mlpack { 00030 namespace kernel { 00031 00032 class SphericalKernel 00033 { 00034 public: 00035 SphericalKernel() : 00036 bandwidth(1.0), 00037 bandwidthSquared(1.0) {} 00038 SphericalKernel(double b) : 00039 bandwidth(b), 00040 bandwidthSquared(b*b) {} 00041 00042 template<typename VecType> 00043 double Evaluate(const VecType& a, const VecType& b) 00044 { 00045 return 00046 (metric::SquaredEuclideanDistance::Evaluate(a, b) <= bandwidthSquared) ? 00047 1.0 : 0.0; 00048 } 00061 template<typename VecType> 00062 double ConvolutionIntegral(const VecType& a, const VecType& b) 00063 { 00064 double distance = sqrt(metric::SquaredEuclideanDistance::Evaluate(a, b)); 00065 if (distance >= 2.0 * bandwidth) 00066 { 00067 return 0.0; 00068 } 00069 double volumeSquared = pow(Normalizer(a.n_rows), 2.0); 00070 00071 switch(a.n_rows) 00072 { 00073 case 1: 00074 return 1.0 / volumeSquared * (2.0 * bandwidth - distance); 00075 break; 00076 case 2: 00077 return 1.0 / volumeSquared * 00078 (2.0 * bandwidth * bandwidth * acos(distance/(2.0 * bandwidth)) - 00079 distance / 4.0 * sqrt(4.0*bandwidth*bandwidth-distance*distance)); 00080 break; 00081 default: 00082 Log::Fatal << "The spherical kernel does not support convolution\ 00083 integrals above dimension two, yet..." << std::endl; 00084 return -1.0; 00085 break; 00086 } 00087 } 00088 double Normalizer(size_t dimension) 00089 { 00090 return pow(bandwidth, (double) dimension) * pow(M_PI, dimension / 2.0) / 00091 boost::math::tgamma(dimension / 2.0 + 1.0); 00092 } 00093 double Evaluate(double t) 00094 { 00095 return (t <= bandwidth) ? 1.0 : 0.0; 00096 } 00097 private: 00098 double bandwidth; 00099 double bandwidthSquared; 00100 }; 00101 00102 }; // namespace kernel 00103 }; // namespace mlpack 00104 00105 #endif