contrib/rpl/rrel/rrel_estimation_problem.h
Go to the documentation of this file.
00001 #ifndef rrel_estimation_problem_h_
00002 #define rrel_estimation_problem_h_
00003 //:
00004 // \file
00005 // \author Chuck Stewart
00006 // \date March 2001
00007 // \brief Base class for an estimation problem in the robust estimation library.
00008 
00009 #include <vcl_vector.h>
00010 #include <vnl/vnl_fwd.h>
00011 
00012 class rrel_wls_obj;
00013 
00014 //: Base class for (robust) estimation problems.
00015 // A fundamental design decision is that the objective function to be
00016 // minimized is not tied to the class.  This allows different robust
00017 // objective functions to be used with the same data and function
00018 // model.  A disadvantage is that computing the derivative of the
00019 // objective with respect to the data or the model parameters is not
00020 // straightforward.  So far this hasn't proven to be a problem.
00021 //
00022 // A second design decision is that functions are provided for
00023 // indirect access to the data for residual and weight calculation and
00024 // to support random sampling operations. Only a few key functions are
00025 // pure virtual; others will cause an abort (with an error message)
00026 // unless overridden. This allows errors to be detected (albeit at
00027 // run-time) if they are used improperly without requiring subclasses
00028 // to redefine unneeded functions.  For example, if a derived class
00029 // does not implement compute_weights(), then attempting to solve that
00030 // problem with IRLS will cause an abort at runtime.
00031 
00032 class rrel_estimation_problem
00033 {
00034  public:
00035   //: Type of scale information this problem provides.
00036   //  NONE: problem does not provide any scale information. SINGLE:
00037   //  problem provides a single prior scale (homoscedastic
00038   //  data). MULTIPLE: problem provides a scale for each residual
00039   //  (heteroscedastic data).
00040   enum scale_t { NONE = 0, SINGLE = 1, MULTIPLE = 2 };
00041 
00042  public:
00043   //: Constructor.
00044   // See the comments for param_dof() and num_samples_to_instantiate()
00045   // for the meaning of these two parameters.
00046   rrel_estimation_problem( unsigned int param_dof,
00047                            unsigned int num_samples_for_fit );
00048 
00049   //: Constructor.
00050   // Derived classes using this _must_ call set_dof() and set_num_samples_for_fit().
00051   rrel_estimation_problem( );
00052 
00053   //: Destructor.
00054   virtual ~rrel_estimation_problem();
00055 
00056   //: The degrees of freedom in the parameter set.
00057   unsigned int param_dof() const { return dof_; }
00058 
00059   //: Minimum number of samples required to uniquely instantiate a fit.
00060   //  dof()/num_samples_to_instantiate() gives the number of constraints per sample.
00061   unsigned int num_samples_to_instantiate( ) const { return num_samples_for_fit_; }
00062 
00063   //: The number of samples.
00064   virtual unsigned int num_samples( ) const = 0;
00065 
00066   //: The degrees of freedom in the residual.
00067   //  Most of the time, this would be 1 since the residual comes from
00068   //  a single random variable. In some problems, however, the error
00069   //  is the combination of more than one random variable. (For
00070   //  example, if the residual is a 2d Euclidean distance with
00071   //  possible error in both coordinates, the degrees of freedom in
00072   //  the error will be 2.)
00073   virtual unsigned int residual_dof() const { return 1; }
00074 
00075   //: The number of "unique" samples.
00076   // In most problems, this equals num_samples. With estimation
00077   // problems involving non-unique correspondences, however, the total
00078   // number of possible correspondences (= num_samples()) generally
00079   // much greater than the number of "unique samples" (which would be
00080   // the number of points from one image).
00081   //
00082   // This is used by random sampling techniques to determine the
00083   // number of samples required to get a given probability of success.
00084   virtual unsigned int num_unique_samples( ) const { return num_samples(); }
00085 
00086   //: Generate a parameter vector from a minimal sample set.
00087   // The \a point_indices vector are indices into the data set, and
00088   // must be filled in with num_samples_to_instantiate() indices.
00089   // Returns true if and only if the points resulted in a unique
00090   // parameter vector.
00091   virtual bool fit_from_minimal_set( const vcl_vector<int>& /* point_indices */,
00092                                      vnl_vector<double>& /* params */ ) const = 0;
00093 
00094   //: Compute the residuals relative to the given parameter vector.
00095   // The number of residuals must be equal to the value returned
00096   // by num_samples().
00097   //
00098   // This is a deterministic procedure, in that multiple calls with a
00099   // given parameter vector must return the same residuals (in the
00100   // same order).
00101   virtual void compute_residuals( const vnl_vector<double>& params,
00102                                   vcl_vector<double>& residuals ) const = 0;
00103 
00104   //: Compute the weights for the given residuals.
00105   // The residuals are essentially those returned by
00106   // compute_residuals(). The default behaviour is to apply obj->wgt()
00107   // to each residual. Some problems, however, many need to augment
00108   // the weights. Such problems should override this function (but
00109   // may want to call this to compute the "basic" weights).
00110   virtual void compute_weights( const vcl_vector<double>& residuals,
00111                                 const rrel_wls_obj* obj,
00112                                 double scale,
00113                                 vcl_vector<double>& weights ) const;
00114 
00115   //: Type of scale information the problem provides.
00116   virtual scale_t scale_type() const { return scale_type_; }
00117 
00118   //: The prior scale vector, if available.
00119   // The call is valid only if scale_type() == MULTIPLE.
00120   virtual const vcl_vector<double>& prior_multiple_scales() const;
00121 
00122   //: The prior scale, if available.
00123   // The call is valid only if scale_type() == SINGLE.
00124   virtual double prior_scale() const;
00125 
00126   //: Sets the scales for heteroscedastic data.
00127   //  Side effect: set scale_type() = MULTIPLE.
00128   virtual void set_prior_multiple_scales( const vcl_vector<double>& scales );
00129 
00130   //: Sets the scale for homoscedastic data.
00131   //  Side effect: set scale_type() = SINGLE.
00132   virtual void set_prior_scale( double scale );
00133 
00134   //: Removes the scale information for the problem.
00135   //  Side effect: set scale_type() = NONE.
00136   virtual void set_no_prior_scale( );
00137 
00138   //: Set similarity weights
00139   //  Currently it is only used in wgted random sampling search
00140   void set_similarity_weights( const vcl_vector<double>& wgts )
00141   { similarity_weights_ = wgts; }
00142   
00143   //: Get similarity weights
00144   const vcl_vector<double>& similarity_weights() const 
00145   { return similarity_weights_; }
00146 
00147   //: Compute the parameter vector and the normalised covariance matrix.
00148   //  (Multiplying this matrix by the variance in the measurements
00149   //  gives the covariance matrix.)
00150   //
00151   // If the weights are provided they are used in the process.  Note
00152   // that if the weights are in fact given, the number of weights
00153   // (num_wgts) MUST be equal to "num_residuals" returned by the
00154   // compute_residuals function.  If some of the residuals should be
00155   // ignored as outliers (e.g. as explicitly identified as such by
00156   // Least Median of Squares), then their weights should just be set
00157   // to 0.
00158   virtual bool weighted_least_squares_fit( vnl_vector<double>& params,
00159                                            vnl_matrix<double>& norm_covar,
00160                                            const vcl_vector<double>* weights=0 ) const = 0;
00161 
00162  protected:
00163   //: Set the degrees of freedom.
00164   void set_param_dof( unsigned int dof ) { dof_ = dof; }
00165 
00166   //: Set the number of samples needed for a unique fit.
00167   void set_num_samples_for_fit( unsigned int num_samp ) { num_samples_for_fit_ = num_samp; }
00168 
00169   //: Set the type of prior scale.
00170   void set_scale_type( scale_t t ) { scale_type_ = t; }
00171 
00172  private:
00173   unsigned int dof_;
00174   unsigned int num_samples_for_fit_;
00175   scale_t scale_type_;
00176   double single_scale_;
00177   vcl_vector<double>* multiple_scales_;
00178   vcl_vector<double>  similarity_weights_;
00179 };
00180 
00181 #endif