00001
00002 #include "rrel_muset_obj.h"
00003
00004 #include <vcl_limits.h>
00005 #include <vcl_iostream.h>
00006 #include <vcl_vector.h>
00007 #include <vcl_algorithm.h>
00008 #include <vcl_cassert.h>
00009 #include <vnl/vnl_math.h>
00010 #include <rrel/rrel_muse_table.h>
00011
00012 rrel_muset_obj::rrel_muset_obj( int max_n,
00013 bool use_sk_refine )
00014 : use_sk_refine_( use_sk_refine ), muse_type_( RREL_MUSE_TRIMMED ),
00015 table_owned_(true)
00016 {
00017 table_ = new rrel_muse_table(max_n);
00018
00019
00020 set_min_inlier_fraction();
00021 set_max_inlier_fraction();
00022 set_inlier_fraction_increment();
00023 }
00024
00025
00026 rrel_muset_obj::rrel_muset_obj( rrel_muse_table* table,
00027 bool use_sk_refine )
00028 : use_sk_refine_(use_sk_refine), muse_type_( RREL_MUSE_TRIMMED ),
00029 table_owned_(false),
00030 table_(table)
00031 {
00032
00033 set_min_inlier_fraction();
00034 set_max_inlier_fraction();
00035 set_inlier_fraction_increment();
00036 }
00037
00038 rrel_muset_obj::~rrel_muset_obj()
00039 {
00040 if (table_owned_)
00041 delete table_;
00042 }
00043
00044 double
00045 rrel_muset_obj::fcn( vect_const_iter begin, vect_const_iter end,
00046 vect_const_iter ,
00047 vnl_vector<double>* ) const
00048 {
00049 double sigma;
00050 int best_k;
00051 internal_fcn( begin, end, sigma, best_k );
00052 return sigma;
00053 }
00054
00055
00056 double
00057 rrel_muset_obj::fcn( vect_const_iter begin, vect_const_iter end,
00058 double ,
00059 vnl_vector<double>* ) const
00060 {
00061 double sigma;
00062 int best_k;
00063 internal_fcn( begin, end, sigma, best_k );
00064 return sigma;
00065 }
00066
00067
00068 double
00069 rrel_muset_obj::scale( vect_const_iter begin, vect_const_iter end ) const
00070 {
00071 double sigma;
00072 int best_k;
00073 internal_fcn( begin, end, sigma, best_k );
00074 return sigma;
00075 }
00076
00077
00078 void
00079 rrel_muset_obj::internal_fcn( vect_const_iter begin, vect_const_iter end,
00080 double& sigma_est, int& best_k ) const
00081 {
00082
00083 vcl_vector<double> abs_residuals;
00084 abs_residuals.reserve( end - begin );
00085 for ( ; begin != end; ++begin ) {
00086 abs_residuals.push_back( vnl_math_abs( *begin ) );
00087 }
00088 vcl_sort( abs_residuals.begin(), abs_residuals.end() );
00089
00090 unsigned int num_residuals = abs_residuals.size();
00091 bool at_start=true;
00092 double best_sk = 0;
00093 double best_objective = 0;
00094
00095 best_k = 0;
00096 const double min_exp_kth_to_stddev_ratio = 3.0;
00097 static bool notwarned = true;
00098
00099 switch ( muse_type_ )
00100 {
00101 case RREL_MUSE_TRIMMED:
00102 {
00103 #ifdef DEBUG
00104 vcl_cout << "\nRREL_MUSE_TRIMMED\n";
00105 #endif
00106 double sum_residuals=0;
00107 double best_sum = 0;
00108 int prev_k = 0;
00109
00110
00111 for ( double frac=min_frac_; frac<=max_frac_+0.00001; frac+=frac_inc_ )
00112 {
00113 unsigned int k = vnl_math_rnd( frac*num_residuals );
00114 if ( k>num_residuals ) k=num_residuals;
00115 if ( k<=0 ) k=1;
00116 if ( table_->expected_kth(k, num_residuals) /
00117 table_->standard_dev_kth(k, num_residuals) < min_exp_kth_to_stddev_ratio )
00118 {
00119 if ( notwarned ) {
00120 vcl_cerr << "WARNING: rrel_muset_obj::internal_fcn "
00121 << "attempted evaluation at value of k that lead to unstable estimates\n";
00122 notwarned = false;
00123 }
00124 continue;
00125 }
00126
00127 for ( unsigned int i=prev_k; i<k; ++i ) {
00128 sum_residuals += abs_residuals[i];
00129 }
00130 double sk = sum_residuals / table_->muset_divisor(k, num_residuals);
00131 double objective = sk * table_->standard_dev_kth(k, num_residuals) /
00132 table_->expected_kth(k, num_residuals);
00133
00134 #ifdef DEBUG
00135 vcl_cout << "k = " << k << ", sk = " << sk
00136 << ", objective = " << objective << '\n';
00137 #endif
00138
00139 if ( at_start || objective < best_objective ) {
00140 at_start = false;
00141 best_k = k;
00142 best_sk = sk;
00143 best_sum = sum_residuals;
00144 best_objective = objective;
00145 }
00146 prev_k = k;
00147 }
00148
00149 if ( at_start ) {
00150 vcl_cerr << "WARNING: There were NO values of k with stable estimates.\n"
00151 << " Setting sigma = +Infinity\n";
00152 sigma_est = vcl_numeric_limits<double>::infinity();
00153 return;
00154 }
00155
00156
00157 if ( ! use_sk_refine_ ) {
00158 sigma_est = best_sk;
00159 #ifdef DEBUG
00160 vcl_cout << "No sk refinement\n";
00161 #endif
00162 }
00163 else {
00164 #ifdef DEBUG
00165 vcl_cout << "sk refinement\n";
00166 #endif
00167 unsigned int new_n = best_k;
00168 while ( new_n<num_residuals && abs_residuals[new_n] < 2.5*best_sk )
00169 ++new_n;
00170 #ifdef DEBUG
00171 vcl_cout << "New n = " << new_n << '\n';
00172 #endif
00173 sigma_est = best_sum / table_ -> muset_divisor(best_k, new_n);
00174 }
00175 break;
00176 }
00177
00178 case RREL_MUSE_TRIMMED_SQUARE:
00179 {
00180 #ifdef DEBUG
00181 vcl_cout << "\nRREL_MUSE_TRIMMED_SQUARE\n";
00182 #endif
00183 double sum_sq_residuals=0;
00184 double best_sum_sq = 0;
00185 int prev_k = 0;
00186
00187
00188 for ( double frac=min_frac_; frac<=max_frac_+0.00001; frac+=frac_inc_ ) {
00189 unsigned int k = vnl_math_rnd( frac*num_residuals );
00190 if ( k>num_residuals ) k=num_residuals;
00191 if ( k<=0 ) k=1;
00192 if ( table_->expected_kth(k, num_residuals) /
00193 table_->standard_dev_kth(k, num_residuals) < min_exp_kth_to_stddev_ratio )
00194 {
00195 if ( notwarned ) {
00196 vcl_cerr << "WARNING: rrel_muset_obj::internal_fcn attempted evaluation at "
00197 << "value of k that lead to unstable estimates\n";
00198 notwarned = false;
00199 }
00200 continue;
00201 }
00202
00203 for ( unsigned int i=prev_k; i<k; ++i ) {
00204 sum_sq_residuals += vnl_math_sqr( abs_residuals[i] );
00205 }
00206 double sk = vcl_sqrt( sum_sq_residuals
00207 / table_->muset_sq_divisor(k, num_residuals) );
00208 double objective = sk * table_->standard_dev_kth(k, num_residuals) /
00209 table_->expected_kth(k, num_residuals);
00210
00211 #ifdef DEBUG
00212 vcl_cout << "k = " << k << ", sk = " << sk
00213 << ", objective = " << objective << '\n';
00214 #endif
00215
00216 if ( at_start || objective < best_objective ) {
00217 at_start = false;
00218 best_k = k;
00219 best_sk = sk;
00220 best_sum_sq = sum_sq_residuals;
00221 best_objective = objective;
00222 }
00223 prev_k = k;
00224 }
00225
00226 if ( at_start ) {
00227 vcl_cerr << "WARNING: There were NO values of k with stable estimates.\n"
00228 << " Setting sigma = +Infinity\n";
00229 sigma_est = vcl_numeric_limits<double>::infinity();
00230 return;
00231 }
00232
00233
00234 if ( ! use_sk_refine_ ) {
00235 sigma_est = best_sk;
00236 #ifdef DEBUG
00237 vcl_cout << "No sk refinement\n";
00238 #endif
00239 }
00240 else {
00241 #ifdef DEBUG
00242 vcl_cout << "sk refinement\n";
00243 #endif
00244 unsigned int new_n = best_k;
00245 while ( new_n<num_residuals && abs_residuals[new_n] < 2.5*best_sk )
00246 ++new_n;
00247 #ifdef DEBUG
00248 vcl_cout << "New n = " << new_n << '\n';
00249 #endif
00250 sigma_est = vcl_sqrt( best_sum_sq
00251 / table_->muset_sq_divisor(best_k, new_n) );
00252 }
00253 break;
00254 }
00255
00256 case RREL_MUSE_QUANTILE:
00257 {
00258 #ifdef DEBUG
00259 vcl_cout << "\nRREL_MUSE_QUANTILE\n";
00260 #endif
00261 for ( double frac=min_frac_; frac<=max_frac_+0.00001; frac+=frac_inc_ ) {
00262 int kk = vnl_math_rnd( frac*num_residuals );
00263 unsigned int k = ( kk <= 0 ) ? 1 : kk;
00264 if ( k>num_residuals ) k=num_residuals;
00265 if ( table_->expected_kth(k, num_residuals) /
00266 table_->standard_dev_kth(k, num_residuals) < min_exp_kth_to_stddev_ratio )
00267 {
00268 if ( notwarned ) {
00269 vcl_cerr << "WARNING: rrel_muset_obj::internal_fcn attempted evaluation at "
00270 << "value of k that lead to unstable estimates\n";
00271 notwarned = false;
00272 }
00273 continue;
00274 }
00275
00276 double sk = abs_residuals[ k-1 ] / table_->expected_kth(k, num_residuals);
00277 double objective = sk * table_->standard_dev_kth(k, num_residuals) /
00278 table_->expected_kth(k, num_residuals);
00279
00280 #ifdef DEBUG
00281 vcl_cout << "k = " << k << ", sk = " << sk
00282 << ", objective = " << objective << '\n';
00283 #endif
00284
00285 if ( at_start || objective < best_objective ) {
00286 best_objective = objective;
00287 best_k = k;
00288 best_sk = sk;
00289 at_start = false;
00290 }
00291 }
00292
00293 if ( at_start ) {
00294 vcl_cerr << "WARNING: There were NO values of k with stable estimates.\n"
00295 << " Setting sigma = +Infinity\n";
00296 sigma_est = vcl_numeric_limits<double>::infinity();
00297 return;
00298 }
00299
00300
00301 if ( ! use_sk_refine_ ) {
00302 sigma_est = best_sk;
00303 #ifdef DEBUG
00304 vcl_cout << "No sk refinement\n";
00305 #endif
00306 }
00307 else {
00308 #ifdef DEBUG
00309 vcl_cout << "sk refinement\n";
00310 #endif
00311 unsigned int new_n = best_k;
00312 while ( new_n<num_residuals && abs_residuals[new_n] < 2.5*best_sk )
00313 ++new_n;
00314 #ifdef DEBUG
00315 vcl_cout << "New n = " << new_n << '\n';
00316 #endif
00317 sigma_est = abs_residuals[ best_k ] / table_->expected_kth(best_k, new_n);
00318 }
00319 break;
00320 }
00321 default:
00322 assert(!"invalid muse_type");
00323 }
00324 }