core/vnl/vnl_least_squares_function.cxx
Go to the documentation of this file.
00001 // This is core/vnl/vnl_least_squares_function.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author Andrew W. Fitzgibbon, Oxford RRG
00008 // \date   31 Aug 96
00009 
00010 #include "vnl_least_squares_function.h"
00011 #include <vcl_iostream.h>
00012 #include <vcl_cassert.h>
00013 
00014 void vnl_least_squares_function::dim_warning(unsigned int number_of_unknowns,
00015                                              unsigned int number_of_residuals)
00016 {
00017   if (number_of_unknowns > number_of_residuals)
00018     vcl_cerr << "vnl_least_squares_function: WARNING: "
00019              << "unknowns(" << number_of_unknowns << ") > "
00020              << "residuals("<< number_of_residuals << ")\n";
00021 }
00022 
00023 void vnl_least_squares_function::gradf(vnl_vector<double> const& /*x*/,
00024                                        vnl_matrix<double>& /*jacobian*/)
00025 {
00026   vcl_cerr << "Warning: gradf() called but not implemented in derived class\n";
00027 }
00028 
00029 //: Compute finite differences gradient using central differences.
00030 void vnl_least_squares_function::fdgradf(vnl_vector<double> const& x,
00031                                          vnl_matrix<double>& jacobian,
00032                                          double stepsize)
00033 {
00034   unsigned int dim = x.size();
00035   unsigned int n = jacobian.rows();
00036   assert(dim == get_number_of_unknowns());
00037   assert(n == get_number_of_residuals());
00038   assert(dim == jacobian.columns());
00039 
00040   vnl_vector<double> tx = x;
00041   vnl_vector<double> fplus(n);
00042   vnl_vector<double> fminus(n);
00043   for (unsigned int i = 0; i < dim; ++i)
00044   {
00045     // calculate f just to the right of x[i]
00046     double tplus = tx[i] = x[i] + stepsize;
00047     this->f(tx, fplus);
00048 
00049     // calculate f just to the left of x[i]
00050     double tminus = tx[i] = x[i] - stepsize;
00051     this->f(tx, fminus);
00052 
00053     double h = 1.0 / (tplus - tminus);
00054     for (unsigned int j = 0; j < n; ++j)
00055       jacobian(j,i) = (fplus[j] - fminus[j]) * h;
00056 
00057     // restore tx
00058     tx[i] = x[i];
00059   }
00060 }
00061 
00062 
00063 //: Compute finite differences gradient using forward differences.
00064 void vnl_least_squares_function::ffdgradf(vnl_vector<double> const& x,
00065                                           vnl_matrix<double>& jacobian,
00066                                           double stepsize)
00067 {
00068   unsigned int dim = x.size();
00069   unsigned int n = jacobian.rows();
00070   assert(dim == get_number_of_unknowns());
00071   assert(n == get_number_of_residuals());
00072   assert(dim == jacobian.columns());
00073 
00074   vnl_vector<double> tx = x;
00075   vnl_vector<double> fplus(n);
00076   vnl_vector<double> fcentre(n);
00077   this->f(x, fcentre);
00078   for (unsigned int i = 0; i < dim; ++i)
00079   {
00080     // calculate f just to the right of x[i]
00081     double tplus = tx[i] = x[i] + stepsize;
00082     this->f(tx, fplus);
00083 
00084     double h = 1.0 / (tplus - x[i]);
00085     for (unsigned int j = 0; j < n; ++j)
00086       jacobian(j,i) = (fplus[j] - fcentre[j]) * h;
00087 
00088     // restore tx
00089     tx[i] = x[i];
00090   }
00091 }
00092 
00093 void vnl_least_squares_function::trace(int /* iteration */,
00094                                        vnl_vector<double> const& /*x*/,
00095                                        vnl_vector<double> const& /*fx*/)
00096 {
00097   // This default implementation is empty; overloaded in derived class.
00098 }
00099 
00100 double vnl_least_squares_function::rms(vnl_vector<double> const& x)
00101 {
00102   vnl_vector<double> fx(n_);
00103   f(x, fx);
00104   return fx.rms();
00105 }