00001
00002 #include "rrel_kernel_density_obj.h"
00003 #include <rrel/rrel_muset_obj.h>
00004 #include <vnl/vnl_vector.h>
00005 #include <vnl/vnl_math.h>
00006 #include <vcl_algorithm.h>
00007 #include <vcl_cassert.h>
00008 #include <vcl_iostream.h>
00009
00010 namespace {
00011 inline void shft2(double &a, double &b, const double c)
00012 {
00013 a = b;
00014 b = c;
00015 }
00016
00017 inline void shft3(double &a, double &b, double &c, const double d)
00018 {
00019 a = b;
00020 b = c;
00021 c = d;
00022 }
00023 }
00024
00025 rrel_kernel_density_obj::rrel_kernel_density_obj(rrel_kernel_scale_type scale_type)
00026 : scale_type_(scale_type),
00027 fix_x_( false )
00028 {
00029 }
00030
00031 double
00032 rrel_kernel_density_obj::fcn(vect_const_iter , vect_const_iter ,
00033 vect_const_iter ,
00034 vnl_vector<double>* ) const
00035 {
00036 vcl_cerr << "rrel_kernel_density_obj::fcn() not implemented\n";
00037 return 0;
00038 }
00039
00040 double
00041 rrel_kernel_density_obj::fcn(vect_const_iter res_begin,
00042 vect_const_iter res_end,
00043 double prior_scale,
00044 vnl_vector<double>* ) const
00045 {
00046 double h = bandwidth ( res_begin, res_end, prior_scale );
00047 assert ( h != 0 );
00048 double x = best_x ( res_begin, res_end, prior_scale );
00049
00050 return -1 * kernel_density( res_begin, res_end, x, h );
00051 }
00052
00053 double
00054 rrel_kernel_density_obj::best_x(vect_const_iter res_begin,
00055 vect_const_iter res_end,
00056 double prior_scale) const
00057 {
00058 if (fix_x_)
00059 return 0;
00060
00061
00062
00063 const double R = 0.61803399, C = 1.0 - R;
00064 double f1, f2, x0, x1, x2, x3;
00065 double tol = 1.0e-9;
00066 double f0 = 0;
00067
00068 double h = bandwidth(res_begin, res_end, prior_scale);
00069 assert(h!=0);
00070
00071 vcl_vector<double> sort_res( res_begin, res_end );
00072 vcl_sort( sort_res.begin(), sort_res.end() );
00073
00074 unsigned int loc = 0;
00075 unsigned int i = 0;
00076 for ( ; i<sort_res.size(); ++i ) {
00077 double x = sort_res[i];
00078 double f = kernel_density( res_begin, res_end, x, h );
00079 if (f > f0) {
00080 f0 = f;
00081 loc = i;
00082 }
00083 }
00084
00085 x0 = sort_res[loc-1];
00086 x3 = sort_res[loc+1];
00087
00088 if ( vnl_math_abs( x3 - sort_res[loc] ) > vnl_math_abs( sort_res[loc] - x0 ) ) {
00089 x1 = sort_res[loc];
00090 x2 = sort_res[loc] + C * ( x3 - sort_res[loc] );
00091 }
00092 else {
00093 x2 = sort_res[loc];
00094 x1 = sort_res[loc] - C * ( sort_res[loc] - x0 );
00095 }
00096
00097 f1 = kernel_density( res_begin, res_end, x1, h );
00098 f2 = kernel_density( res_begin, res_end, x2, h );
00099 while ( vnl_math_abs( x3 - x0 ) >
00100 tol * vnl_math_abs( x1 ) + vnl_math_abs( x2 ) ) {
00101 if ( f2 > f1 ) {
00102 shft3( x0, x1, x2, R * x2 + C * x3 );
00103 shft2( f1, f2, kernel_density( res_begin, res_end, x2, h ) );
00104 }
00105 else {
00106 shft3( x3, x2, x1, R * x1 + C * x0 );
00107 shft2( f2, f1, kernel_density( res_begin, res_end, x1, h ) );
00108 }
00109 }
00110 if (f1 < f2)
00111 return x2;
00112 else
00113 return x1;
00114 }
00115
00116 double
00117 rrel_kernel_density_obj::bandwidth(vect_const_iter res_begin, vect_const_iter res_end,
00118 double prior_scale) const
00119 {
00120 vcl_vector<double>::difference_type n = res_end - res_begin;
00121 double scale = 1.0;
00122
00123 switch ( scale_type_ )
00124 {
00125 case RREL_KERNEL_MAD: {
00126
00127
00128
00129
00130
00131 vcl_vector<double> residuals(res_begin, res_end);
00132 vcl_vector<double>::iterator loc = residuals.begin() + n / 2;
00133 vcl_nth_element( residuals.begin(), loc, residuals.end() );
00134
00135 double res_median = *loc;
00136 vcl_vector<double> abs_res_median;
00137 abs_res_median.reserve( n );
00138 for (vcl_vector<double>::difference_type i=0; i<n; ++i ) {
00139 abs_res_median.push_back( vnl_math_abs( residuals[i] - res_median ) );
00140 }
00141 loc = abs_res_median.begin() + n / 2;
00142 vcl_nth_element( abs_res_median.begin(), loc, abs_res_median.end() );
00143
00144 scale = 0.5 * (*loc);
00145 break;
00146 }
00147
00148 case RREL_KERNEL_PRIOR:
00149 scale = prior_scale;
00150 break;
00151
00152 case RREL_KERNEL_MUSE: {
00153 rrel_muset_obj muse( (int)n );
00154 scale = muse.fcn( res_begin, res_end );
00155 break; }
00156
00157 default:
00158 assert(!"invalid scale_type");
00159 }
00160
00161
00162
00163
00164 const double c = 65610.0 / 143;
00165 return vcl_pow( c / n , 0.2 ) * scale;
00166 }
00167
00168 double
00169 rrel_kernel_density_obj::kernel_density(vect_const_iter res_begin,
00170 vect_const_iter res_end,
00171 double x,
00172 double h) const
00173 {
00174 double f=0;
00175 vcl_vector<double>::difference_type n = res_end - res_begin;
00176 for ( ; res_begin!= res_end; ++res_begin ) {
00177 f += kernel_function( ( *res_begin - x ) / h );
00178 }
00179 f /= n*h;
00180 return f;
00181 }
00182
00183 double
00184 rrel_kernel_density_obj::kernel_function(double u) const
00185 {
00186 if (vnl_math_abs(u) > 1)
00187 return 0;
00188
00189 double t = 1 - u * u;
00190 return 1.09375 * t * t * t;
00191 }
00192
00193