core/vnl/vnl_least_squares_function.h
Go to the documentation of this file.
00001 // This is core/vnl/vnl_least_squares_function.h
00002 #ifndef vnl_least_squares_function_h_
00003 #define vnl_least_squares_function_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief Abstract base for minimising functions
00010 // \author Andrew W. Fitzgibbon, Oxford RRG
00011 // \date   31 Aug 96
00012 //
00013 // \verbatim
00014 //  Modifications
00015 //   280697 AWF Changed return type of f from double to void, as it wasn't used, and
00016 //              people were going to extra trouble to compute it.
00017 //   20 Apr 1999 FSM Added failure flag so that f() and grad() may signal failure to the caller.
00018 //   23/3/01 LSB (Manchester) Tidied documentation
00019 //   Feb.2002 - Peter Vanroose - brief doxygen comment placed on single line
00020 // \endverbatim
00021 //
00022 // not used? #include <vcl_string.h>
00023 #include <vnl/vnl_vector.h>
00024 #include <vnl/vnl_matrix.h>
00025 
00026 //:  Abstract base for minimising functions.
00027 //    vnl_least_squares_function is an abstract base for functions to be minimized
00028 //    by an optimizer.  To define your own function to be minimized, subclass
00029 //    from vnl_least_squares_function, and implement the pure virtual f (and
00030 //    optionally grad_f).
00031 //
00032 //    Whether or not f ought to be const is a problem.  Clients might well
00033 //    want to cache some information during the call, and if they're compute
00034 //    objects, will almost certainly be writing to members during the
00035 //    computation.  For the moment it's non-const, but we'll see...
00036 class vnl_least_squares_function
00037 {
00038  public:
00039   enum  UseGradient {
00040     no_gradient,
00041     use_gradient
00042   };
00043   bool failure;
00044 
00045   //: Construct vnl_least_squares_function.
00046   // Passing number of parameters (unknowns, domain dimension) and number of
00047   // residuals (range dimension).
00048   // The optional argument should be no_gradient if the gradf function has not
00049   // been implemented.  Default is use_gradient.
00050   vnl_least_squares_function(unsigned int number_of_unknowns,
00051                              unsigned int number_of_residuals,
00052                              UseGradient g = use_gradient)
00053   : failure(false), p_(number_of_unknowns), n_(number_of_residuals),
00054     use_gradient_(g == use_gradient)
00055   { dim_warning(p_,n_); }
00056 
00057   virtual ~vnl_least_squares_function() {}
00058 
00059   // the virtuals may call this to signal a failure.
00060   void throw_failure() { failure = true; }
00061   void clear_failure() { failure = false; }
00062 
00063   //: The main function.
00064   //  Given the parameter vector x, compute the vector of residuals fx.
00065   //  Fx has been sized appropriately before the call.
00066   virtual void f(vnl_vector<double> const& x, vnl_vector<double>& fx) = 0;
00067 
00068   //: Calculate the Jacobian, given the parameter vector x.
00069   virtual void gradf(vnl_vector<double> const& x, vnl_matrix<double>& jacobian);
00070 
00071   //: Use this to compute a finite-difference gradient other than lmdif
00072   void fdgradf(vnl_vector<double> const& x, vnl_matrix<double>& jacobian,
00073                double stepsize);
00074 
00075   //: Use this to compute a finite-forward-difference gradient other than lmdif
00076   // This takes about half as many estimates as fdgradf
00077   void ffdgradf(vnl_vector<double> const& x, vnl_matrix<double>& jacobian,
00078                 double stepsize);
00079 
00080   //: Called after each LM iteration to print debugging etc.
00081   virtual void trace(int iteration,
00082                      vnl_vector<double> const& x,
00083                      vnl_vector<double> const& fx);
00084 
00085   //: Compute the rms error at x by calling f and returning the norm of the residual vector.
00086   double rms(vnl_vector<double> const& x);
00087 
00088   //: Return the number of unknowns
00089   unsigned int get_number_of_unknowns() const { return p_; }
00090 
00091   //: Return the number of residuals.
00092   unsigned int get_number_of_residuals() const { return n_; }
00093 
00094   //: Return true if the derived class has indicated that gradf has been implemented
00095   bool has_gradient() const { return use_gradient_; }
00096 
00097  protected:
00098   unsigned int p_;
00099   unsigned int n_;
00100   bool use_gradient_;
00101 
00102   void init(unsigned int number_of_unknowns, unsigned int number_of_residuals)
00103   { p_ = number_of_unknowns; n_ = number_of_residuals; dim_warning(p_,n_); }
00104  private:
00105   void dim_warning(unsigned int n_unknowns, unsigned int n_residuals);
00106 };
00107 
00108 #endif // vnl_least_squares_function_h_