core/vnl/algo/vnl_discrete_diff.cxx
Go to the documentation of this file.
00001 #include "vnl_discrete_diff.h"
00002 #include <vnl/vnl_least_squares_function.h>
00003 #include <vcl_cassert.h>
00004 /*
00005   fsm
00006 */
00007 
00008 bool vnl_discrete_diff_fwd(vnl_least_squares_function *lsf,
00009                            double h_,
00010                            vnl_vector<double> const &x,
00011                            vnl_matrix<double>       &J)
00012 {
00013   vnl_vector<double> y(lsf->get_number_of_residuals());
00014   lsf->f(x,y);
00015   if (lsf->failure)
00016     return false;
00017   vnl_vector<double> h(lsf->get_number_of_unknowns());
00018   h.fill(h_);
00019   return vnl_discrete_diff_fwd(lsf,h,x,y,J);
00020 }
00021 
00022 bool vnl_discrete_diff_fwd(vnl_least_squares_function *lsf,
00023                            vnl_vector<double> const &h,
00024                            vnl_vector<double> const &x,
00025                            vnl_matrix<double>       &J)
00026 {
00027   vnl_vector<double> y(lsf->get_number_of_residuals());
00028   lsf->f(x,y);
00029   if (lsf->failure)
00030     return false;
00031   return vnl_discrete_diff_fwd(lsf,h,x,y,J);
00032 }
00033 
00034 bool vnl_discrete_diff_fwd(vnl_least_squares_function *lsf,
00035                            vnl_vector<double> const &h,
00036                            vnl_vector<double> const &x,
00037                            vnl_vector<double> const &y,
00038                            vnl_matrix<double>       &J)
00039 {
00040   unsigned m=J.rows();
00041   unsigned n=J.columns();
00042   assert(m==lsf->get_number_of_residuals());
00043   assert(m==y.size());
00044   assert(n==lsf->get_number_of_unknowns());
00045   assert(n==h.size());
00046   assert(n==x.size());
00047 
00048   vnl_vector<double> tx(n);
00049   vnl_vector<double> ty(m);
00050 
00051   for (unsigned j=0;j<n;j++) {
00052     tx=x; tx(j) += h(j);
00053     lsf->f(tx,ty);
00054     if (lsf->failure)
00055       return false;
00056     for (unsigned i=0;i<m;i++)
00057       J(i,j) = (ty(i)-y(i))/h(j);
00058   }
00059   return true;
00060 }
00061 
00062 bool vnl_discrete_diff_sym(vnl_least_squares_function *lsf,
00063                            double h_,
00064                            vnl_vector<double> const &x,
00065                            vnl_matrix<double>       &J)
00066 {
00067   vnl_vector<double> h(lsf->get_number_of_unknowns());
00068   h.fill(h_);
00069   return vnl_discrete_diff_sym(lsf,h,x,J);
00070 }
00071 
00072 bool vnl_discrete_diff_sym(vnl_least_squares_function *lsf,
00073                            vnl_vector<double> const &h,
00074                            vnl_vector<double> const &x,
00075                            vnl_matrix<double>       &J)
00076 {
00077   unsigned m=J.rows();
00078   unsigned n=J.columns();
00079   assert(m==lsf->get_number_of_residuals());
00080   assert(n==lsf->get_number_of_unknowns());
00081   assert(n==h.size());
00082   assert(n==x.size());
00083 
00084   vnl_vector<double> xp(n),xm(n);
00085   vnl_vector<double> yp(m),ym(m);
00086 
00087   for (unsigned j=0;j<n;j++) {
00088     xp=x; xp(j) += h(j);
00089     lsf->f(xp,yp);
00090     if (lsf->failure)
00091       return false;
00092 
00093     xm=x; xm(j) -= h(j);
00094     lsf->f(xm,ym);
00095     if (lsf->failure)
00096       return false;
00097 
00098     for (unsigned i=0;i<m;i++)
00099       J(i,j) = (yp(i)-ym(i))/(2*h(j));
00100   }
00101   return true;
00102 }
00103 
00104 //----------------------------------------------------------------------
00105 
00106 #include <vcl_iostream.h>
00107 
00108 void vnl_discrete_diff_test_lsf(vnl_least_squares_function *lsf, vnl_vector<double> const &x)
00109 {
00110   unsigned int m = lsf->get_number_of_residuals();
00111   unsigned int n = lsf->get_number_of_unknowns ();
00112   assert(x.size() == n);
00113 
00114   vnl_matrix<double> J1(m, n);
00115   lsf->gradf(x, J1);
00116 
00117   vnl_matrix<double> J2(m, n);
00118   vnl_discrete_diff_sym(lsf, 0.0001, x, J2);
00119 
00120   double e = (J1 - J2).fro_norm();
00121   //assert(e <= 1e-3);
00122   double t = cos_angle(J1, J2);
00123   //assert(t >= 0.99);
00124 
00125   vcl_cerr << __FILE__ ": e = " << e << vcl_endl
00126            << __FILE__ ": t = " << t << vcl_endl;
00127 }