KJB
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsl_multimin.h
Go to the documentation of this file.
1 
9 /*
10  * $Id: gsl_multimin.h 17393 2014-08-23 20:19:14Z predoehl $
11  */
12 
13 #ifndef GSL_MULTIMIN_WRAP_H_KJBLIB_UARIZONAVISION
14 #define GSL_MULTIMIN_WRAP_H_KJBLIB_UARIZONAVISION
15 
16 #include <l_cpp/l_exception.h>
17 #include <gsl_cpp/gsl_util.h>
18 #include <gsl_cpp/gsl_vector.h>
19 
20 #include <boost/function/function1.hpp>
21 
22 #ifdef KJB_HAVE_GSL
23 #include "gsl/gsl_multimin.h" /* no need for extern "C" */
24 #else
25 #warning "Gnu Scientific Library is absent, yet essential to this program."
26 
27 /*
28  * Here is some fakery to make client programs compile even when GSL is absent.
29  */
32 #define gsl_multimin_fdfminimizer_conjugate_pr ((void*)0)
33 #define gsl_multimin_fdfminimizer_vector_bfgs2 ((void*)0)
34 #define gsl_multimin_fdfminimizer_alloc(x,z) 0
35 #define gsl_set_error_handler_off() (0)
37  int n; void *params;
38  double (*f)( const gsl_vector*, void* );
39  void (*df)( const gsl_vector*, void*, gsl_vector* );
40  void (*fdf)( const gsl_vector*, void*, double*, gsl_vector* );
41 };
42 
45 #define gsl_multimin_fminimizer_nmsimplex ((void*)0)
46 #define gsl_multimin_fminimizer_nmsimplex2 ((void*)0)
47 #define gsl_multimin_fminimizer_alloc(x,z) 0
49  size_t n; void *params;
50  double (*f)( const gsl_vector*, void* );
51 };
52 #define GSL_NAN (1.0/0.0)
53 
54 #endif
55 
56 
57 
58 namespace kjb {
59 
60 
61 
70 
71 #ifdef KJB_HAVE_GSL
72 
86  struct basic_Gsl_Multimin_fdf {
88 
89  basic_Gsl_Multimin_fdf(
91  size_t dim
92  )
93  : p( dim ? gsl_multimin_fdfminimizer_alloc( type, dim ) : 00 )
94  {
95  ETX_2( 0 == dim, "basic_Gsl_Multimin_fdf(): Zero dimensions" );
96  ETX_2( 00 == p, "basic_Gsl_Multimin_fdf(): Memory alloc failed" );
97  }
98 
99  ~basic_Gsl_Multimin_fdf()
100  {
101  gsl_multimin_fdfminimizer_free( p );
102  }
103 
104  void swap( basic_Gsl_Multimin_fdf& that )
105  {
106  using std::swap;
107  swap( p, that.p );
108  }
109 
110  private:
111  // this class is not copyable, nor assignable, nor has a default ctor.
112  basic_Gsl_Multimin_fdf( const basic_Gsl_Multimin_fdf& );
113  basic_Gsl_Multimin_fdf();
114  basic_Gsl_Multimin_fdf& operator=( const basic_Gsl_Multimin_fdf& );
115  };
116 
117  basic_Gsl_Multimin_fdf m_min;
118 #endif
119 
120  bool m_verbose;
121 
122 public:
123 
146  const gsl_multimin_fdfminimizer_type* type,
148  const gsl_vector* x0,
149  double step_size,
150  double tol,
151  bool verbosity = true
152  )
153 #ifdef KJB_HAVE_GSL
154  : m_min( type, x0 ? x0 -> size : 0 ),
155  m_verbose( verbosity )
156  {
157  GSL_ETX( gsl_multimin_fdfminimizer_set( m_min.p, fdf, x0, step_size,
158  tol ) );
159  }
160 #else
161  {
162  KJB_THROW_2( Missing_dependency, "GNU GSL" );
163  }
164 #endif
165 
174  int iterate()
175  {
176 #ifdef KJB_HAVE_GSL
177  int rc = gsl_multimin_fdfminimizer_iterate( m_min.p );
178  if (m_verbose) gsl_iterate_EPE(rc);
179  return rc;
180 #endif
181  }
182 
185  {
186 #ifdef KJB_HAVE_GSL
187  return gsl_multimin_fdfminimizer_x( m_min.p );
188 #endif
189  }
190 
192  double min() const
193  {
194 #ifdef KJB_HAVE_GSL
195  return gsl_multimin_fdfminimizer_minimum( m_min.p );
196 #endif
197  }
198 
201  {
202 #ifdef KJB_HAVE_GSL
203  return gsl_multimin_fdfminimizer_gradient( m_min.p );
204 #endif
205  }
206 
208  const char* name() const
209  {
210 #ifdef KJB_HAVE_GSL
211  return gsl_multimin_fdfminimizer_name( m_min.p );
212 #endif
213  }
214 
220  int test_gradient( double epsabs ) const
221  {
222 #ifdef KJB_HAVE_GSL
223  return gsl_multimin_test_gradient( m_min.p -> gradient, epsabs );
224 #endif
225  }
226 
240  void restart()
241  {
242 #ifdef KJB_HAVE_GSL
243  GSL_ETX( gsl_multimin_fdfminimizer_restart( m_min.p ) );
244 #endif
245  }
246 
254  void swap( Gsl_Multimin_fdf& that )
255  {
256 #ifdef KJB_HAVE_GSL
257  if ( this == &that )
258  {
259  return;
260  }
261  m_min.swap( that.m_min );
262  using std::swap;
263  swap( m_verbose, that.m_verbose );
264 #endif
265  }
266 
273  bool verbosity( bool v )
274  {
275  bool oldv = m_verbose;
276  m_verbose = v;
277  return oldv;
278  }
279 };
280 
281 
290 
291 #ifdef KJB_HAVE_GSL
292 
306  struct basic_Gsl_Multimin_f {
308  size_t dim;
309 
310  basic_Gsl_Multimin_f(
311  const gsl_multimin_fminimizer_type* type,
312  size_t dimension
313  )
314  : p( dimension ? gsl_multimin_fminimizer_alloc( type, dimension ) : 00 ),
315  dim( dimension )
316  {
317  ETX_2( 0 == dimension, "basic_Gsl_Multimin_f(): Zero dimensions" );
318  ETX_2( 00 == p, "basic_Gsl_Multimin_f(): Memory alloc failed" );
319  }
320 
321  ~basic_Gsl_Multimin_f()
322  {
323  gsl_multimin_fminimizer_free( p );
324  }
325 
326  void swap( basic_Gsl_Multimin_f& that )
327  {
328  using std::swap;
329  swap( p, that.p );
330  }
331 
332  private:
333  // this class is not copyable, nor assignable, nor has a default ctor.
334  basic_Gsl_Multimin_f( const basic_Gsl_Multimin_f& );
335  basic_Gsl_Multimin_f& operator=( const basic_Gsl_Multimin_f& );
336  };
337 
338  basic_Gsl_Multimin_f m_min;
339 #endif
340 
341  bool m_verbose;
342 
343  boost::function1<double, const gsl_vector*> boost_f_;
344  gsl_multimin_function gsl_f_;
345  bool m_initialized;
346 
347 public:
348 
371  const gsl_multimin_fminimizer_type* type,
373  const gsl_vector* x0,
374  const gsl_vector* step_size,
375  bool verbosity = true
376  )
377 #ifdef KJB_HAVE_GSL
378  : m_min( type, x0 ? x0 -> size : 0 ),
379  m_verbose( verbosity ),
380  m_initialized(false)
381  {
382  initialize(f, x0, step_size);
383  }
384 #else
385  {
386  KJB_THROW_2( Missing_dependency, "GNU GSL" );
387  }
388 #endif
389 
391  size_t size,
393 #ifdef KJB_HAVE_GSL
394  : m_min( type, size),
395  m_verbose( false ),
396  m_initialized(false)
397  {}
398 #else
399  {
400  KJB_THROW_2( Missing_dependency, "GNU GSL" );
401  }
402 #endif
403 
406  const gsl_vector* x0,
407  const gsl_vector* step_size)
408  {
409 #ifdef KJB_HAVE_GSL
410  if(x0->size != step_size->size)
412  GSL_ETX( gsl_multimin_fminimizer_set( m_min.p, f, x0, step_size ) );
413  m_initialized = true;
414 #endif
415  }
416 
417  size_t dim() const
418  {
419 #ifdef KJB_HAVE_GSL
420  return m_min.dim;
421 #endif
422  }
423 
432  int iterate()
433  {
434 #ifdef KJB_HAVE_GSL
435  if(!m_initialized)
436  {
437  KJB_THROW_2(Runtime_error, "Minimizer not initialized");
438  }
439 
440  int rc = gsl_multimin_fminimizer_iterate( m_min.p );
441  if (m_verbose) gsl_iterate_EPE(rc);
442  return rc;
443 #endif
444  }
445 
448  {
449 #ifdef KJB_HAVE_GSL
450  return gsl_multimin_fminimizer_x( m_min.p );
451 #endif
452  }
453 
455  virtual double min() const
456  {
457 #ifdef KJB_HAVE_GSL
458  return gsl_multimin_fminimizer_minimum( m_min.p );
459 #endif
460  }
461 
463  const char* name() const
464  {
465 #ifdef KJB_HAVE_GSL
466  return gsl_multimin_fminimizer_name( m_min.p );
467 #endif
468  }
469 
477  int test_size( double epsabs ) const
478  {
479 #ifdef KJB_HAVE_GSL
480 
481  double size = gsl_multimin_fminimizer_size(m_min.p);
482  return gsl_multimin_test_size( size, epsabs );
483 #endif
484  }
485 
486 
494  void swap( Gsl_Multimin_f& that )
495  {
496 #ifdef KJB_HAVE_GSL
497  if ( this == &that )
498  {
499  return;
500  }
501  m_min.swap( that.m_min );
502  using std::swap;
503  swap( m_verbose, that.m_verbose );
504 #endif
505  }
506 
513  bool verbosity( bool v )
514  {
515  bool oldv = m_verbose;
516  m_verbose = v;
517  return oldv;
518  }
519 };
520 
521 
522 
523 inline
524 double gsl_evaluate_Nd_boost_function(const gsl_vector* v, void* params)
525 {
526  typedef boost::function1<double, const gsl_vector*> Func_type;
527  Func_type* f = static_cast<Func_type*>(params);
528 
529  return (*f)(v);
530 }
531 
532 template<class T>
534 {
535 public:
536  typedef boost::function1<double, T> Evaluator;
537 
538  // @note this function can assume that T is initialized to the value from the previous optimization iteration
539  typedef boost::function2<void, const gsl_vector*, T&> From_gsl;
540 
541  // @note this function can assume gsl_vector* is initialized to correct dimension
542  typedef boost::function2<void, const T&, gsl_vector*> To_gsl;
543 
544 private:
545 
546  typedef Gsl_Multimin_f Base;
547 
557  template <class Eval_type>
558  struct gsl_adapter_func
559  {
560  gsl_adapter_func(
561  const Eval_type& e,
562  From_gsl& from_gsl,
563  bool negate = false) :
564  f_(),
565  from_gsl_(from_gsl),
566  workspace_(),
567  negate_(negate)
568  {
569  f_ = boost::ref(e);
570  }
571 
579  gsl_adapter_func(
580  const Eval_type& e,
581  From_gsl& from_gsl,
582  const T& initial,
583  bool negate = false) :
584  f_(),
585  from_gsl_(from_gsl),
586  workspace_(initial),
587  negate_(negate)
588  {
589  f_ = boost::ref(e);
590  }
591 
592  double operator()(const gsl_vector* x) const
593  {
594  from_gsl_(x, workspace_);
595  if(negate_)
596  return -f_(workspace_);
597  else
598  return f_(workspace_);
599  }
600 
601  Evaluator f_;
602  From_gsl& from_gsl_;
603  mutable T workspace_;
604  bool negate_;
605  };
606 public:
608  size_t size,
609  const To_gsl& to_gsl,
610  const From_gsl& from_gsl,
612  Base(size, type),
613  boost_f_(),
614  gsl_f_(),
615  to_gsl_(to_gsl),
616  from_gsl_(from_gsl),
617  negate_evaluator_(false)
618  {}
619 
620  template <class Eval_type, class VectorType>
622  const Eval_type& e,
623  const T& guess,
624  const VectorType& step_size,
625  bool negate_evaluator = false)
626  {
627  negate_evaluator_ = negate_evaluator;
628 #ifdef KJB_HAVE_GSL
629  size_t num_dimensions = dim();
630  // WARNING: possibly guess and/or step_size need to exist throughout the life of the minimizer. If this immediately segfaults, this is probably why.
631 
632  if(!reference_)
633  {
634  // save the initial guess in case immutable parameters
635  // need to be restored at the end
636  boost::shared_ptr<T> tmp(new T(guess));
637  reference_ = tmp;
638  }
639 
640  boost_f_ = gsl_adapter_func<Eval_type>(e, from_gsl_, *reference_, negate_evaluator);
642  gsl_f_.n = num_dimensions;
643  gsl_f_.params = static_cast<void*>(&boost_f_);
644 
645  // TODO: find a way to avoid an extra allocation here.
646  Gsl_Vector gsl_guess(num_dimensions);
647  to_gsl_(guess, gsl_guess);
648 
649  Gsl_Vector gsl_step_size(step_size.begin(), step_size.end());
650 
651  Base::initialize(&gsl_f_, gsl_guess, gsl_step_size);
652 #else
654 #endif
655  }
656 
657  const T& get() const
658  {
659  if(!reference_)
660  KJB_THROW_2(Runtime_error, "Not initialized");
661  from_gsl_(argmin(), *reference_);
662  return *reference_;
663  }
664 
666  double min() const
667  {
668 #ifdef KJB_HAVE_GSL
669 
670  double result = Base::min();
671  return (negate_evaluator_ ? -result : result);
672 
673 #endif
674  }
675 
676 
677 private:
678  boost::function1<double, const gsl_vector*> boost_f_;
679  gsl_multimin_function gsl_f_;
680  To_gsl to_gsl_;
681  From_gsl from_gsl_;
682  bool negate_evaluator_;
683  mutable boost::shared_ptr<T> reference_;
684 };
685 
686 
687 } // namespace kjb
688 
689 namespace std {
690 
692  template<>
694  {
695  m1.swap( m2 );
696  }
697 
699  template<>
701  {
702  m1.swap( m2 );
703  }
704 }
705 
706 
707 #endif /* GSL_MULTIMIN_WRAP_H_KJBLIB_UARIZONAVISION */
Definition: gsl_vector.h:35
size_t size
Definition: gsl_vector.h:36
boost::function1< double, T > Evaluator
Definition: gsl_multimin.h:536
const char * name() const
access a string describing the algorithm
Definition: gsl_multimin.h:463
double gsl_evaluate_Nd_boost_function(const gsl_vector *v, void *params)
Definition: gsl_multimin.h:524
void * params
Definition: gsl_multimin.h:49
Gsl_Multimin_fdf(const gsl_multimin_fdfminimizer_type *type, gsl_multimin_function_fdf *fdf, const gsl_vector *x0, double step_size, double tol, bool verbosity=true)
ctor builds the minimizer by allocating and setting up params
Definition: gsl_multimin.h:145
Object thrown when an argument is of the wrong size or dimensions.
Definition: l_exception.h:426
void(* fdf)(const gsl_vector *, void *, double *, gsl_vector *)
Definition: gsl_multimin.h:40
#define gsl_multimin_fminimizer_nmsimplex2
Definition: gsl_multimin.h:46
int n
Definition: gsl_multimin.h:37
int iterate()
Perform one iteration of the minimizer.
Definition: gsl_multimin.h:174
void swap(Gsl_Multimin_fdf &that)
Swap the contents of this minimizer and another (fast).
Definition: gsl_multimin.h:254
void gsl_multimin_fminimizer_type
Definition: gsl_multimin.h:43
#define KJB_THROW(ex)
Definition: l_exception.h:46
GSL utility stuff to help those using the C++ wrapper on GSL code.
#define gsl_multimin_fminimizer_alloc(x, z)
Definition: gsl_multimin.h:47
void(* df)(const gsl_vector *, void *, gsl_vector *)
Definition: gsl_multimin.h:39
size_t dim() const
Definition: gsl_multimin.h:417
int iterate()
Perform one iteration of the minimizer.
Definition: gsl_multimin.h:432
int test_size(double epsabs) const
check the magnitude the minimizer specific characteristic size against the tolerance epsabs...
Definition: gsl_multimin.h:477
Definition: gsl_multimin.h:48
Gsl_Multimin_f(size_t size, const gsl_multimin_fminimizer_type *type=gsl_multimin_fminimizer_nmsimplex2)
Definition: gsl_multimin.h:390
Wrapper for GSL's multidimensional minimizer, when you have gradient.
Definition: gsl_multimin.h:69
void gsl_iterate_EPE(int gsl_error_code)
On error, print a GSL iteration error message (like EPE)
Definition: gsl_util.cpp:40
size_t n
Definition: gsl_multimin.h:49
x
Definition: APPgetLargeConnectedEdges.m:100
int test_gradient(double epsabs) const
check the magnitude the gradient of the function now
Definition: gsl_multimin.h:220
#define GSL_ETX(gsl_expr)
Definition: gsl_util.h:37
double(* f)(const gsl_vector *, void *)
Definition: gsl_multimin.h:50
const char * name() const
access a string describing the algorithm
Definition: gsl_multimin.h:208
double min() const
query the current best min value of the function to be minimized
Definition: gsl_multimin.h:666
double min() const
query the current best min value of the function to be minimized
Definition: gsl_multimin.h:192
Wrapper for GSL's multidimensional minimizer, without using gradient.
Definition: gsl_multimin.h:289
void initialize(gsl_multimin_function *f, const gsl_vector *x0, const gsl_vector *step_size)
Definition: gsl_multimin.h:404
RAII wrapper for GSL vector objects.
Definition: gsl_vector.h:78
#define KJB_THROW_2(ex, msg)
Definition: l_exception.h:48
#define gsl_multimin_fdfminimizer_alloc(x, z)
Definition: gsl_multimin.h:34
bool verbosity(bool v)
Alter the verbosity attribute of the object.
Definition: gsl_multimin.h:513
void swap(kjb::Gsl_Multimin_fdf &m1, kjb::Gsl_Multimin_fdf &m2)
Swap two wrapped multimin objects.
Definition: gsl_multimin.h:693
void gsl_multimin_fdfminimizer_type
Definition: gsl_multimin.h:30
Gsl_Multimin_f(const gsl_multimin_fminimizer_type *type, gsl_multimin_function *f, const gsl_vector *x0, const gsl_vector *step_size, bool verbosity=true)
ctor builds the minimizer by allocating and setting up params
Definition: gsl_multimin.h:370
#define ETX_2(a, msg)
Definition: l_exception.h:78
void initialize(const Eval_type &e, const T &guess, const VectorType &step_size, bool negate_evaluator=false)
Definition: gsl_multimin.h:621
gsl_vector * argmin() const
query the current best argmin of the minimizer
Definition: gsl_multimin.h:447
Definition: gsl_multimin.h:36
virtual double min() const
query the current best min value of the function to be minimized
Definition: gsl_multimin.h:455
gsl_vector * argmin() const
query the current best argmin of the minimizer
Definition: gsl_multimin.h:184
boost::function2< void, const gsl_vector *, T & > From_gsl
Definition: gsl_multimin.h:539
bool verbosity(bool v)
Alter the verbosity attribute of the object.
Definition: gsl_multimin.h:273
C++ wrapper on GSL vector class to prevent resource leaks.
void restart()
Restart the minimizer at the current argmin value.
Definition: gsl_multimin.h:240
boost::function2< void, const T &, gsl_vector * > To_gsl
Definition: gsl_multimin.h:542
Definition: gsl_multimin.h:533
gsl_vector * gradient() const
query the gradient of the function at the current location
Definition: gsl_multimin.h:200
void gsl_multimin_fdfminimizer
Definition: gsl_multimin.h:31
void swap(Gsl_Multimin_f &that)
Swap the contents of this minimizer and another (fast).
Definition: gsl_multimin.h:494
void * params
Definition: gsl_multimin.h:37
Support for error handling exception classes in libKJB.
Object thrown when a program lacks required resources or libraries.
Definition: l_exception.h:539
Object thrown when computation fails somehow during execution.
Definition: l_exception.h:321
Generic_multimin(size_t size, const To_gsl &to_gsl, const From_gsl &from_gsl, const gsl_multimin_fminimizer_type *type=gsl_multimin_fminimizer_nmsimplex2)
Definition: gsl_multimin.h:607
void gsl_multimin_fminimizer
Definition: gsl_multimin.h:44
double(* f)(const gsl_vector *, void *)
Definition: gsl_multimin.h:38