source: trunk/yat/utility/MultiMinimizer.h @ 4172

Last change on this file since 4172 was 4172, checked in by Peter, 11 months ago

refs #978. Wrapper classes around gsl_multimin_fminimizer.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 4.3 KB
Line 
1#ifndef theplu_yat_utility_multi_minimizer_
2#define theplu_yat_utility_multi_minimizer_
3
4// $Id: MultiMinimizer.h 4172 2022-05-12 02:15:31Z peter $
5
6/*
7  Copyright (C) 2022 Peter Johansson
8
9  This file is part of the yat library, https://dev.thep.lu.se/yat
10
11  The yat library is free software; you can redistribute it and/or
12  modify it under the terms of the GNU General Public License as
13  published by the Free Software Foundation; either version 3 of the
14  License, or (at your option) any later version.
15
16  The yat library is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  General Public License for more details.
20
21  You should have received a copy of the GNU General Public License
22  along with yat. If not, see <https://www.gnu.org/licenses/>.
23*/
24
25#include "multiminimizer/f.h"
26
27#include "Vector.h"
28#include "yat_assert.h"
29
30#include <gsl/gsl_multimin.h>
31
32#include <memory>
33
34namespace theplu {
35namespace yat {
36namespace utility {
37
38  /**
39     \brief Wrapper class around gsl_multimin_fminimizer in GSL.
40
41     Class is the abstract base class for several minimisation
42     algorithms not using the derivative.
43
44     \since New in yat 0.20
45   */
46  class MultiMinimizer
47  {
48  public:
49    /// \brief Copy is not allowed
50    MultiMinimizer(const MultiMinimizer&) = delete;
51
52    /// \brief Assignment is not allowed
53    MultiMinimizer& operator=(const MultiMinimizer&) = delete;
54
55    /**
56       \brief Number of epochs (iterations) used in last minimisation.
57     */
58    unsigned int epochs(void) const;
59
60    /**
61       \brief The size of the first step.
62
63       \see parameter \c step_size in gsl_multimin_fminimizer_set
64     */
65    const yat::utility::Vector& step(void) const;
66
67    /**
68       \brief Modify the initial step size.
69
70       The size of the vector cannot be modified but must equal the
71       size set in constructor.
72     */
73    yat::utility::Vector& step(void);
74
75    /**
76       Function finds an \c x that minimizes the function defined by
77       \c func. It calls gsl_multimin_fminimizer_iterate until either
78       \c GSL_ENOPROG is returned or the size is smaller than \c
79       epsabs, as tested by gsl_multimin_test_size.
80
81       Type Requirements:
82       - \c FUNC must have an operator
83       double operator()(const VectorBase& x)
84     */
85    template<class FUNC>
86    void operator()(yat::utility::VectorMutable& x, FUNC& func,
87                    double epsabs);
88
89    /**
90       Same as
91       operator()(yat::utility::VectorMutable&, FUNC& func, double epsabs);
92       but at maximum run \c max_epochs epochs (iterations).
93     */
94    template<class FUNC>
95    void operator()(yat::utility::VectorMutable&, FUNC& func,
96                    double epsabs, unsigned int max_epochs);
97  protected:
98    /**
99       \brief Constructor
100
101       \param t defines type of GSL minimizer
102       \param size Number of dimensions in the input space.
103     */
104    MultiMinimizer(const gsl_multimin_fminimizer_type* t, size_t size);
105  private:
106    const gsl_multimin_fminimizer_type* type_;
107    size_t size_;
108    struct GslFree
109    {
110      void operator()(gsl_multimin_fminimizer*) const;
111    };
112    std::unique_ptr<gsl_multimin_fminimizer, GslFree> solver_;
113    yat::utility::Vector step_size_;
114    unsigned int epochs_;
115  };
116
117
118  // template implementation
119
120  template<class FUNC>
121  void MultiMinimizer::operator()(yat::utility::VectorMutable& x,
122                                  FUNC& func, double epsabs)
123  {
124    unsigned int max_epochs = std::numeric_limits<unsigned int>::max();
125    (*this)(x, func, epsabs, max_epochs);
126  }
127
128
129  template<class FUNC>
130  void MultiMinimizer::operator()(yat::utility::VectorMutable& x,
131                                  FUNC& func, double epsabs,
132                                  unsigned int max_epochs)
133  {
134    YAT_ASSERT(size_ == x.size());
135    gsl_multimin_function gsl_func;
136    gsl_func.n = x.size();
137    gsl_func.f = multiminimizer::f<FUNC>;
138    gsl_func.params = &func;
139
140    gsl_multimin_fminimizer_set(solver_.get(), &gsl_func, x.gsl_vector_p(),
141                                step_size_.gsl_vector_p());
142
143    int status = 0;
144    for (epochs_=0; epochs_<max_epochs; ++epochs_) {
145      status = gsl_multimin_fminimizer_iterate(solver_.get());
146      if (status) {
147        if (status == GSL_ENOPROG)
148          break;
149        throw yat::utility::GSL_error("MultiMinimizer", status);
150      }
151      double size = gsl_multimin_fminimizer_size(solver_.get());
152      if (gsl_multimin_test_size(size, epsabs) != GSL_CONTINUE)
153        break;
154    }
155
156    // copy result to passed x
157    yat::utility::VectorConstView view(solver_->x);
158    x = view;
159  }
160
161}}}
162#endif
Note: See TracBrowser for help on using the repository browser.