vnl_lbfgsb.cxx
Go to the documentation of this file.
1 // This is core/vnl/algo/vnl_lbfgsb.cxx
2 //:
3 // \file
4 //
5 // \author Brad King, Kitware Inc.
6 // \date 28 Aug 07
7 //
8 //-----------------------------------------------------------------------------
9 
10 #include <cstring>
11 #include <iostream>
12 #include "vnl_lbfgsb.h"
13 
14 #include <vnl/algo/vnl_netlib.h> // setulb_()
15 
16 //----------------------------------------------------------------------------
18 {
20 }
21 
22 //----------------------------------------------------------------------------
24 {
25  long n = this->f_->get_number_of_unknowns();
26  this->bound_selection_.set_size(n);
27  this->bound_selection_.fill(0);
28  this->max_corrections_ = 5;
29  this->convergence_factor_ = 1e+7;
30  this->projected_gradient_tolerance_ = 1e-5;
31 }
32 
33 //----------------------------------------------------------------------------
35 {
36  // Basic setup.
37  long n = this->f_->get_number_of_unknowns();
38  long m = this->max_corrections_;
39 
40  // Function and gradient.
41  double f = 0;
42  vnl_vector<double> gradient(n);
43 
44  // Working space.
45  // The total work space **wa** required by the new version is
46  //
47  // 2*m*n + 11*m*m + 5*n + 8*m
48  //
49  vnl_vector<double> wa(2*m*n + 11*m*m + 5*n + 8*m);
50  //
51  // the previous version required:
52  //
53  // 2*m*n + 12*m*m + 4*n + 12*m
54  //
55  //
56  vnl_vector<long> iwa(3*n);
57  char csave[60];
58  long lsave[4];
59  long isave[44];
60  double dsave[29];
61 
62  // Task communication.
63  char task[61]="START ";
64 
65  // Verbosity level inside lbfgs implementation.
66  // (-1 no o/p, 0 start and end, 1 every iter)
67  long const iprint = trace ? 1 : -1;
68 
69  // Initialize iteration.
70  this->num_evaluations_ = 0;
71  this->num_iterations_ = 0;
72 
73  // TODO: Deal with verbose_, check_derivatives_, trace, xtol,
74  // maxfev, ftol, gtol, epsfcn members of vnl_nonlinear_minimizer.
75 
76  // Track the best position found.
77  vnl_vector<double> x_best(x);
78 
79  bool ok = true;
80  for (;;)
81  {
82  // Call the L-BFGS-B code.
83  v3p_netlib_setulb_(
84  &n,
85  &m,
86  x.data_block(),
87  this->lower_bound_.data_block(),
88  this->upper_bound_.data_block(),
90  &f, gradient.data_block(),
91  &this->convergence_factor_,
93  wa.data_block(),
94  iwa.data_block(),
95  task,
96  &iprint,
97  csave, lsave, isave, dsave
98  );
99 
100  // Check the current task.
101  if (std::strncmp("FG", task, 2) == 0)
102  {
103  // Evaluate the function and gradient.
104  this->f_->compute(x, &f, &gradient);
105 
106  if (this->num_evaluations_ == 0)
107  {
108  x_best = x;
109  this->start_error_ = f;
110  this->end_error_ = f;
111  }
112  else if (f < this->end_error_)
113  {
114  x_best = x;
115  this->end_error_ = f;
116  }
117  this->report_eval(f);
118  }
119  else if (std::strncmp("NEW_X", task, 5) == 0)
120  {
121  // dsave[12] = the infinity norm of the projected gradient
122  this->inf_norm_projected_gradient_ = dsave[12];
123 
124  // Iteration.a
125  if (this->report_iter())
126  {
128  ok = false;
129  break;
130  }
131  }
132  else if (std::strncmp("ERROR", task, 5) == 0)
133  {
134  // some error
136  ok = false;
137  break;
138  }
139  else if (std::strncmp("CONVERGENCE", task, 11) == 0)
140  {
141  // convergence has been reached
142  if (f < this->end_error_)
143  {
144  x_best = x;
145  this->end_error_ = f;
146  }
147 
148  if (std::strncmp("CONVERGENCE: REL_REDUCTION_OF_F <= FACTR*EPSMCH",
149  task, 47) == 0)
150  {
151  // function tolerance reached
153  }
154  else if (std::strncmp("CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL",
155  task, 48) == 0)
156  {
157  // gradient tolerance reached
159  }
160  else
161  {
163  if (trace)
164  {
165  std::cerr << "Unknown convergence type: " << task << std::endl;
166  }
167  }
168  break;
169  }
170  else
171  {
172  // unknown task
174  if (trace)
175  {
176  std::cerr << "Unknown failure with task: " << task << std::endl;
177  }
178  ok = false;
179  break;
180  }
181 
182  if (this->num_evaluations_ > this->get_max_function_evals())
183  {
185  ok = false;
186  break;
187  }
188  }
189 
190  // Store the best known position no matter the outcome.
191  x = x_best;
192 
193  return ok;
194 }
void init_parameters()
Definition: vnl_lbfgsb.cxx:22
An object that represents a function from R^n -> R.
vnl_cost_function * f_
Definition: vnl_lbfgsb.h:120
int get_number_of_unknowns() const
Return the number of unknowns.
bool set_size(size_t n)
Resize to n elements.
Definition: vnl_vector.hxx:250
long max_corrections_
Definition: vnl_lbfgsb.h:112
vnl_lbfgsb()=delete
#define m
Definition: vnl_vector.h:43
T const * data_block() const
Access the contiguous block storing the elements in the vector. O(1).
Definition: vnl_vector.h:230
Limited memory Broyden Fletcher Goldfarb Shannon constrained opt.
void report_eval(double f)
Called by derived classes after each function evaluation.
virtual bool report_iter()
Called by derived classes after each iteration.
double projected_gradient_tolerance_
Definition: vnl_lbfgsb.h:114
vnl_vector< double > lower_bound_
Definition: vnl_lbfgsb.h:109
double inf_norm_projected_gradient_
Definition: vnl_lbfgsb.h:115
Declare in a central place the list of symbols from netlib.
vnl_vector & fill(T const &v)
Set all values to v.
Definition: vnl_vector.hxx:314
double convergence_factor_
Definition: vnl_lbfgsb.h:113
virtual void compute(vnl_vector< double > const &x, double *f, vnl_vector< double > *g)
Compute one or both of f and g.
vnl_vector< long > bound_selection_
Definition: vnl_lbfgsb.h:111
bool minimize(vnl_vector< double > &x)
Find a minimum in the feasible region given an initial guess.
Definition: vnl_lbfgsb.cxx:33
vnl_vector< double > upper_bound_
Definition: vnl_lbfgsb.h:110