contrib/rpl/rrel/rrel_muset_obj.cxx
Go to the documentation of this file.
00001 // This is rpl/rrel/rrel_muset_obj.cxx
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   // Set the parameters to their default values.
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   // Set the parameters to their default values.
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 /*scale begin*/,
00047                      vnl_vector<double>* /*param_vector*/ ) 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 /*scale*/,
00059                      vnl_vector<double>* /*param_vector*/ ) 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   // Calculate the absolute residuals and sort them.
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     //  Find the best k
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     //  Refine the scale estimate
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     //  Find the best k
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     //  Refine the scale estimate
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     //  Refine the scale estimate
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 }