core/vnl/algo/vnl_powell.cxx

Go to the documentation of this file.
00001 // This is core/vnl/algo/vnl_powell.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 #include "vnl_powell.h"
00008 
00009 #include <vcl_cassert.h>
00010 #include <vnl/vnl_math.h>
00011 #include <vnl/algo/vnl_brent.h>
00012 #ifdef DEBUG
00013 #include <vnl/vnl_matlab_print.h>
00014 #include <vcl_iostream.h>
00015 #endif
00016 
00017 class vnl_powell_1dfun : public vnl_cost_function
00018 {
00019  public:
00020   vnl_powell* powell_;
00021   vnl_cost_function* f_;
00022   unsigned int n_;
00023   vnl_vector<double> x0_;
00024   vnl_vector<double> dx_;
00025   vnl_vector<double> tmpx_;
00026   vnl_powell_1dfun(int n, vnl_cost_function* f, vnl_powell* p)
00027    : vnl_cost_function(1), powell_(p), f_(f), n_(n), x0_(n), dx_(n), tmpx_(n) {}
00028 
00029   void init(vnl_vector<double> const& x0, vnl_vector<double> const& dx)
00030   {
00031     x0_ = x0;
00032     dx_ = dx;
00033     assert(x0.size() == n_);
00034     assert(dx.size() == n_);
00035   }
00036 
00037   double f(const vnl_vector<double>& x)
00038   {
00039     uninit(x[0], tmpx_);
00040     double e = f_->f(tmpx_);
00041     powell_->pub_report_eval(e);
00042     return e;
00043   }
00044 
00045   void uninit(double lambda, vnl_vector<double>& out)
00046   {
00047     for (unsigned int i = 0; i < n_; ++i)
00048       out[i] = x0_[i] + lambda * dx_[i];
00049   }
00050 };
00051 
00052 vnl_nonlinear_minimizer::ReturnCodes
00053 vnl_powell::minimize(vnl_vector<double>& p)
00054   //double p[], double **xi, int n
00055 {
00056  // verbose_ = true;
00057   int n = p.size();
00058   vnl_powell_1dfun f1d(n, functor_, this);
00059 
00060   vnl_matrix<double> xi(n,n, vnl_matrix_identity);
00061   vnl_vector<double> ptt(n);
00062   vnl_vector<double> xit(n);
00063   double fret = functor_->f(p);
00064   report_eval(fret);
00065   vnl_vector<double> pt = p;
00066   while (num_iterations_ < unsigned(maxfev))
00067   {
00068     double fp = fret;
00069     int ibig=0;
00070     double del=0.0;
00071 
00072     for (int i=0;i<n;i++)
00073     {
00074       // xit = ith column of xi
00075       for (int j = 0; j < n; ++j)
00076         xit[j] = xi[j][i];
00077       double fptt = fret;
00078 
00079       // 1D minimization along xi
00080       f1d.init(p, xit);
00081       vnl_brent brent(&f1d);
00082       double ax = 0.0;
00083       double xx = initial_step_;
00084       double bx;
00085       brent.bracket_minimum(&ax, &xx, &bx);
00086       fret = brent.minimize_given_bounds(bx, xx, ax, linmin_xtol_, &xx);
00087       f1d.uninit(xx, p);
00088       // Now p is minimizer along xi
00089 
00090       if (vcl_fabs(fptt-fret) > del) {
00091         del = vcl_fabs(fptt-fret);
00092         ibig = i;
00093       }
00094     }
00095 
00096     if (2.0*vcl_fabs(fp-fret) <= ftol*(vcl_fabs(fp)+vcl_fabs(fret)))
00097     {
00098 #ifdef DEBUG
00099       vnl_matlab_print(vcl_cerr, xi, "xi");
00100 #endif
00101       return CONVERGED_FTOL;
00102     }
00103 
00104     if (num_iterations_ == unsigned(maxfev))
00105       return TOO_MANY_ITERATIONS;
00106 
00107     for (int j=0;j<n;++j)
00108     {
00109       ptt[j]=2.0*p[j]-pt[j];
00110       xit[j]=p[j]-pt[j];
00111       pt[j]=p[j];
00112     }
00113 
00114     double fptt = functor_->f(ptt);
00115     report_eval(fret);
00116     if (fptt < fp)
00117     {
00118       double t=2.0*(fp-2.0*fret+fptt)*vnl_math_sqr(fp-fret-del)-del*vnl_math_sqr(fp-fptt);
00119       if (t < 0.0)
00120       {
00121         f1d.init(p, xit);
00122         vnl_brent brent(&f1d);
00123         double ax = 0.0;
00124         double xx = 1.0;
00125         double bx;
00126         brent.bracket_minimum(&ax, &xx, &bx);
00127         fret = brent.minimize_given_bounds(bx, xx, ax, linmin_xtol_, &xx);
00128         f1d.uninit(xx, p);
00129 
00130         for (int j=0;j<n;j++) {
00131           xi[j][ibig]=xi[j][n-1];
00132           xi[j][n-1]=xit[j];
00133         }
00134       }
00135     }
00136     if (this->report_iter())
00137       return FAILED_USER_REQUEST;
00138   }
00139   return TOO_MANY_ITERATIONS;
00140 }

Generated on Sat Nov 22 05:06:19 2008 for core/vnl by  doxygen 1.5.1