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

Last change on this file since 4252 was 4252, checked in by Peter, 4 months ago

merge 0.20 release into trunk

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 5.3 KB
Line 
1#ifndef theplu_yat_utility_multi_minimizer_
2#define theplu_yat_utility_multi_minimizer_
3
4// $Id: MultiMinimizer.h 4252 2022-11-18 02:54:04Z 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 "Exception.h"
26#include "multivariable/f.h"
27
28#include "Vector.h"
29#include "yat_assert.h"
30
31#include <gsl/gsl_multimin.h>
32
33#include <memory>
34
35namespace theplu {
36namespace yat {
37namespace utility {
38
39  /**
40     \brief Wrapper class around gsl_multimin_fminimizer in GSL.
41
42     Class is the abstract base class for several minimisation
43     algorithms not using the derivative.
44
45     \since New in yat 0.20
46   */
47  class MultiMinimizer
48  {
49  public:
50    /// \brief Copy is not allowed
51    MultiMinimizer(const MultiMinimizer&) = delete;
52
53    /// \brief Assignment is not allowed
54    MultiMinimizer& operator=(const MultiMinimizer&) = delete;
55
56    /**
57       \brief Number of epochs (iterations) used in last minimisation.
58     */
59    unsigned int epochs(void) const;
60
61    /**
62       \brief The size of the first step.
63
64       \see parameter \c step_size in gsl_multimin_fminimizer_set
65     */
66    const yat::utility::Vector& step(void) const;
67
68    /**
69       \brief Modify the initial step size.
70
71       The size of the vector cannot be modified but must equal the
72       size set in constructor.
73     */
74    yat::utility::Vector& step(void);
75
76    /// Abstract class defining the interface for functions
77    /// determining when the minimisation stops.
78    class Stopper
79    {
80    public:
81      /// return true when search should stop
82      virtual bool operator()(const gsl_multimin_fminimizer*)=0;
83    };
84
85
86    /**
87       wrapper around
88       <a href="https://www.gnu.org/software/gsl/doc/html/multimin.html#stopping-criteria">gsl_multimin_test_size</a>
89    */
90    class Size : public Stopper
91    {
92    public:
93      /// \param epsabs tolerance
94      explicit Size(double epsabs);
95
96      /**
97         \return \c true if <a
98         href="https://www.gnu.org/software/gsl/doc/html/multimin.html#stopping-criteria">gsl_multimin_test_size</a>(size,
99         epsabs) does not return \c GSL_CONTINUE, where \c size is
100         defined by \c gsl_multimin_fminimizer_size and \c epsabs is
101         defined in constructor.
102       */
103      bool operator()(const gsl_multimin_fminimizer*);
104    private:
105      double epsabs_;
106    };
107
108    /**
109       Function finds an \c x that minimizes the function defined by
110       \c func. It calls gsl_multimin_fminimizer_iterate until either
111       \c GSL_ENOPROG is returned or the \c stopper returns true.
112
113       Type Requirements:
114       - \c FUNC must have an operator
115       double operator()(const VectorBase& x)
116     */
117    template<class FUNC>
118    void operator()(yat::utility::VectorMutable& x, FUNC& func,
119                    Stopper&& stopper);
120
121    /**
122       Same as
123       operator()(yat::utility::VectorMutable&, FUNC& func, Stopper&&);
124       but at maximum run \c max_epochs epochs (iterations).
125     */
126    template<class FUNC>
127    void operator()(yat::utility::VectorMutable&, FUNC& func,
128                    Stopper&& stopper, unsigned int max_epochs);
129  protected:
130    /**
131       \brief Constructor
132
133       \param t defines type of GSL minimizer
134       \param size Number of dimensions in the input space.
135     */
136    MultiMinimizer(const gsl_multimin_fminimizer_type* t, size_t size);
137  private:
138    const gsl_multimin_fminimizer_type* type_;
139    size_t size_;
140    struct GslFree
141    {
142      void operator()(gsl_multimin_fminimizer*) const;
143    };
144    std::unique_ptr<gsl_multimin_fminimizer, GslFree> solver_;
145    yat::utility::Vector step_size_;
146    unsigned int epochs_;
147  };
148
149
150  // template implementation
151
152  template<class FUNC>
153  void MultiMinimizer::operator()(yat::utility::VectorMutable& x,
154                                  FUNC& func,
155                                  MultiMinimizer::Stopper&& stopper)
156  {
157    unsigned int max_epochs = std::numeric_limits<unsigned int>::max();
158    (*this)(x, func, std::move(stopper), max_epochs);
159  }
160
161
162  template<class FUNC>
163  void MultiMinimizer::operator()(yat::utility::VectorMutable& x,
164                                  FUNC& func,
165                                  MultiMinimizer::Stopper&& stopper,
166                                  unsigned int max_epochs)
167  {
168    YAT_ASSERT(size_ == x.size());
169    gsl_multimin_function gsl_func;
170    gsl_func.n = x.size();
171    gsl_func.f = multivariable::f<FUNC>;
172    gsl_func.params = &func;
173
174    gsl_multimin_fminimizer_set(solver_.get(), &gsl_func, x.gsl_vector_p(),
175                                step_size_.gsl_vector_p());
176
177    int status = 0;
178    for (epochs_=0; epochs_<max_epochs; ++epochs_) {
179      status = gsl_multimin_fminimizer_iterate(solver_.get());
180      if (status) {
181        if (status == GSL_ENOPROG)
182          break;
183        throw GSL_error("MultiMinimizer", status);
184      }
185      if (stopper(solver_.get()))
186        break;
187      //double size = gsl_multimin_fminimizer_size(solver_.get());
188      //if (gsl_multimin_test_size(size, epsabs) != GSL_CONTINUE)
189      //break;
190    }
191
192    // copy result to passed x
193    yat::utility::VectorConstView view(solver_->x);
194    x = view;
195  }
196
197}}}
198#endif
Note: See TracBrowser for help on using the repository browser.