vnl_powell.cxx
Go to the documentation of this file.
1 // This is core/vnl/algo/vnl_powell.cxx
2 //:
3 // \file
4 #include <iostream>
5 #include <cassert>
6 #include "vnl_powell.h"
7 
8 #include <vnl/vnl_math.h>
9 #undef VNL_USE_OLD_BRENT_MINIMIZER // #define VNL_USE_OLD_BRENT_MINIMIZER
10 // This version was deprecated, and the refactoring to the new minimizer was not done correctly with respect to initialisation.
11 #ifdef VNL_USE_OLD_BRENT_MINIMIZER
12 #include <vnl/algo/vnl_brent.h>
13 #else
16 #endif
17 #ifdef DEBUG
18 #include <vnl/vnl_matlab_print.h>
19 #ifdef _MSC_VER
20 # include <vcl_msvc_warnings.h>
21 #endif
22 #endif
23 
25 {
26  public:
29  unsigned int n_;
34  : vnl_cost_function(1), powell_(p), f_(func), n_(n), x0_(n), dx_(n), tmpx_(n) {}
35 
36  void init(vnl_vector<double> const& x0, vnl_vector<double> const& dx)
37  {
38  x0_ = x0;
39  dx_ = dx;
40  assert(x0.size() == n_);
41  assert(dx.size() == n_);
42  }
43 
44  double f(const vnl_vector<double>& x) override
45  {
46  uninit(x[0], tmpx_);
47  double e = f_->f(tmpx_);
49  return e;
50  }
51 
52  void uninit(double lambda, vnl_vector<double>& out)
53  {
54  for (unsigned int i = 0; i < n_; ++i)
55  out[i] = x0_[i] + lambda * dx_[i];
56  }
57 };
58 
61 {
62  // verbose_ = true;
63  int n = p.size();
64  vnl_powell_1dfun f1d(n, functor_, this);
65 
66  vnl_matrix<double> xi(n,n, vnl_matrix_identity);
67  vnl_vector<double> ptt(n);
68  vnl_vector<double> xit(n);
69  double fret = functor_->f(p);
70  report_eval(fret);
71  vnl_vector<double> pt = p;
72  while (num_iterations_ < unsigned(maxfev))
73  {
74  double fp = fret;
75  int ibig=0;
76  double del=0.0;
77 
78  for (int i=0;i<n;i++)
79  {
80  // xit = ith column of xi
81  for (int j = 0; j < n; ++j)
82  xit[j] = xi[j][i];
83  double fptt = fret;
84 
85  // 1D minimization along xi
86  f1d.init(p, xit);
87 #ifdef VNL_USE_OLD_BRENT_MINIMIZER
88  vnl_brent brent(&f1d);
89  double ax;
90  double xx = initial_step_;
91  double bx = 0.0;
92  brent.bracket_minimum(&ax, &xx, &bx);
93  fret = brent.minimize_given_bounds(bx, xx, ax, linmin_xtol_, &xx);
94 #else
95  vnl_brent_minimizer brent(f1d);
96  double ax = 0.0;
97  double xx = initial_step_;
98  double bx;
99  {
100  double fa, fxx, fb;
101  vnl_bracket_minimum(f1d,ax,xx,bx,fa,fxx,fb);
102  }
104  xx=brent.minimize_given_bounds(ax,xx,bx);
105  fret=brent.f_at_last_minimum();
106 #endif
107 
108  f1d.uninit(xx, p);
109  // Now p is minimizer along xi
110 
111  if (std::fabs(fptt-fret) > del) {
112  del = std::fabs(fptt-fret);
113  ibig = i;
114  }
115  }
116 
117  if (2.0*std::fabs(fp-fret) <= ftol*(std::fabs(fp)+std::fabs(fret)))
118  {
119 #ifdef DEBUG
120  vnl_matlab_print(std::cerr, xi, "xi");
121 #endif
122  return CONVERGED_FTOL;
123  }
124 
125  if (num_iterations_ == unsigned(maxfev))
126  return TOO_MANY_ITERATIONS;
127 
128  for (int j=0;j<n;++j)
129  {
130  ptt[j]=2.0*p[j]-pt[j];
131  xit[j]=p[j]-pt[j];
132  pt[j]=p[j];
133  }
134 
135  double fptt = functor_->f(ptt);
136  report_eval(fret);
137  if (fptt < fp)
138  {
139  double t=2.0*(fp-2.0*fret+fptt)*vnl_math::sqr(fp-fret-del)-del*vnl_math::sqr(fp-fptt);
140  if (t < 0.0)
141  {
142  f1d.init(p, xit);
143 #ifdef VNL_USE_OLD_BRENT_MINIMIZER
144  vnl_brent brent(&f1d);
145  double ax;
146  double xx = 1.0;
147  double bx = 0.0;
148  brent.bracket_minimum(&ax, &xx, &bx);
149  fret = brent.minimize_given_bounds(bx, xx, ax, linmin_xtol_, &xx);
150 #else
151  vnl_brent_minimizer brent(f1d);
152  double ax = 0.0;
153  double xx = 1.0;
154  double bx;
155  {
156  double fa, fxx, fb;
157  vnl_bracket_minimum(f1d,ax,xx,bx,fa,fxx,fb);
158  }
160  xx=brent.minimize_given_bounds(ax,xx,bx);
161  fret=brent.f_at_last_minimum();
162 #endif
163  f1d.uninit(xx, p);
164 
165  for (int j=0;j<n;j++) {
166  xi[j][ibig]=xi[j][n-1];
167  xi[j][n-1]=xit[j];
168  }
169  }
170  }
171  if (report_iter())
172  return FAILED_USER_REQUEST;
173  }
174  return TOO_MANY_ITERATIONS;
175 }
double f(const vnl_vector< double > &x) override
Apply the function.
Definition: vnl_powell.cxx:44
An object that represents a function from R^n -> R.
Print matrices and vectors in nice MATLAB format.
double minimize_given_bounds(double ax, double bx, double cx, double tol, double *xmin)
Find the minimum value of f(x) within a<= x <= c.
Definition: vnl_brent.cxx:14
Brent 1D minimizer (deprecated).
Definition: vnl_brent.h:25
ReturnCodes minimize(vnl_vector< double > &x)
Run minimization, place result in x.
Definition: vnl_powell.cxx:60
unsigned int n_
Definition: vnl_powell.cxx:29
size_t size() const
Return the length, number of elements, dimension of this vector.
Definition: vnl_vector.h:126
double minimize_given_bounds(double ax, double bx, double cx)
Find the minimum value of f(x) within a<= x <= c.
vnl_vector< double > dx_
Definition: vnl_powell.cxx:31
Namespace with standard math functions.
double f(vnl_vector< double > const &x) override
The main function. Given the parameter vector x, compute the value of f(x).
vnl_cost_function * functor_
Definition: vnl_powell.h:44
void vnl_bracket_minimum(vnl_cost_function &fn, double &a, double &b, double &c, double &fa, double &fb, double &fc)
Given initial values a and b, find bracket a<b<c s.t. f(a)>f(b)<f(c).
vnl_powell * powell_
Definition: vnl_powell.cxx:27
Brent 1D minimizer.
double ftol
Termination tolerance on F (sum of squared residuals)
vnl_powell_1dfun(int n, vnl_cost_function *func, vnl_powell *p)
Definition: vnl_powell.cxx:33
void uninit(double lambda, vnl_vector< double > &out)
Definition: vnl_powell.cxx:52
The ever-popular Powell minimizer.
Definition: vnl_powell.h:24
void init(vnl_vector< double > const &x0, vnl_vector< double > const &dx)
Definition: vnl_powell.cxx:36
void report_eval(double f)
Called by derived classes after each function evaluation.
double linmin_xtol_
Tolerance on line search parameter step.
Definition: vnl_powell.h:50
virtual bool report_iter()
Called by derived classes after each iteration.
VNL_EXPORT std::ostream & vnl_matlab_print(std::ostream &, T const *array, unsigned length, vnl_matlab_print_format=vnl_matlab_print_format_default)
print a 1D array.
double initial_step_
Initial step when bracketing minima along a line.
Definition: vnl_powell.h:53
void pub_report_eval(double e)
Definition: vnl_powell.h:47
Powell minimizer.
Function to bracket a minimum.
void bracket_minimum(double *ax, double *bx, double *cx, double *fa, double *fb, double *fc)
Given distinct points ax, and bx, find a bracket for the minimum.
Definition: vnl_brent.cxx:41
ReturnCodes
Some generic return codes that apply to all minimizers.
long maxfev
Termination maximum number of iterations.
vnl_vector< double > tmpx_
Definition: vnl_powell.cxx:32
double f_at_last_minimum() const
Function evaluation at value returned by minimize(x).
vnl_cost_function * f_
Definition: vnl_powell.cxx:28
vnl_bignum sqr(vnl_bignum const &x)
Definition: vnl_bignum.h:434
vnl_vector< double > x0_
Definition: vnl_powell.cxx:30
void set_x_tolerance(double v)
Set the convergence tolerance on X.