contrib/rpl/rrel/rrel_lms_obj.cxx
Go to the documentation of this file.
00001 // This is rpl/rrel/rrel_lms_obj.cxx
00002 #include "rrel_lms_obj.h"
00003 #include "rrel_util.h"
00004 
00005 #include <vnl/vnl_math.h>
00006 
00007 #include <vcl_algorithm.h>
00008 #include <vcl_vector.h>
00009 
00010 #include <vcl_cassert.h>
00011 
00012 rrel_lms_obj::rrel_lms_obj( unsigned int num_sam_inst, double inlier_frac )
00013   : num_sam_inst_( num_sam_inst ),
00014     inlier_frac_( inlier_frac )
00015 {
00016 }
00017 
00018 rrel_lms_obj::~rrel_lms_obj()
00019 {
00020 }
00021 
00022 
00023 double
00024 rrel_lms_obj::fcn( vect_const_iter begin, vect_const_iter end,
00025                    vect_const_iter /*scale begin*/,
00026                    vnl_vector<double>* /*param_vector*/ ) const
00027 {
00028   return fcn( begin, end, 0.0, (vnl_vector<double>*)0 );
00029 }
00030 
00031 
00032 double
00033 rrel_lms_obj::fcn( vect_const_iter begin, vect_const_iter end,
00034                    double /*scale*/,
00035                    vnl_vector<double>* /*param_vector*/ ) const
00036 {
00037   // 1. We need to sort the squared residuals.
00038 
00039   // Since we know that vect_const_iter is vector::iterator, we can
00040   // use the size of the incoming vector to preallocate the sq_res
00041   // vector. If/when this becomes more general, the we can remove the
00042   // preallocation if necessary. The cost of a few reallocs as we
00043   // compute the squared residuals are unlikely to seriously affect
00044   // anything.
00045 
00046   vcl_vector<double> sq_res;
00047   sq_res.reserve( end - begin );
00048   for ( ; begin != end; ++begin ) {
00049     sq_res.push_back( (*begin) * (*begin) );
00050   }
00051 
00052   unsigned int num_residuals = sq_res.size();
00053   assert( num_residuals >= num_sam_inst_ );
00054 
00055   // 2. Find the index of the "median value" if the residuals are sorted.
00056 
00057   unsigned int index;
00058   if ( inlier_frac_ == 0.5 ) 
00059     index = (num_residuals-num_sam_inst_)/2 + num_sam_inst_;
00060   else
00061     index = vnl_math_rnd( (num_residuals-num_sam_inst_)*inlier_frac_ ) + num_sam_inst_;
00062   if ( index >= num_residuals ) index = num_residuals-1;
00063 
00064   // 3. Sort the squared residuals and extract the "median".
00065   vcl_vector<double>::iterator loc = sq_res.begin() + index;
00066   vcl_nth_element( sq_res.begin(), loc, sq_res.end() );
00067 
00068   return *loc;
00069 }
00070 
00071 double
00072 rrel_lms_obj::scale( vect_const_iter begin, vect_const_iter end ) const
00073 {
00074   // Work on a copy of the vector, since the MAD scale estimator
00075   // will change the content of the vector
00076   vcl_vector<double> vec_copy;
00077   vec_copy.reserve( end - begin );
00078   for ( ; begin != end; ++begin ) {
00079     vec_copy.push_back( *begin);
00080   }
00081 
00082   return rrel_util_median_abs_dev_scale( vec_copy.begin(), vec_copy.end(), num_sam_inst_);
00083 }