Optimist  0.0.0
A C++ library for optimization
Loading...
Searching...
No Matches
PatternSearch.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
2 * Copyright (c) 2025, Davide Stocco, Mattia Piazza and Enrico Bertolazzi. *
3 * *
4 * The Optimist project is distributed under the BSD 2-Clause License. *
5 * *
6 * Davide Stocco Mattia Piazza Enrico Bertolazzi *
7 * University of Trento University of Trento University of Trento *
8 * davide.stocco@unitn.it mattia.piazza@unitn.it enrico.bertolazzi@unitn.it *
9\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10
11#pragma once
12
13#ifndef OPTIMIST_OPTIMIZER_HJ_PATTERN_SEARCH_HH
14#define OPTIMIST_OPTIMIZER_HJ_PATTERN_SEARCH_HH
15
16#include "Optimist/Optimizer.hh"
17
18namespace Optimist
19{
20 namespace Optimizer
21 {
22
23
24 /*\
25 | ____ _ _ ____ _
26 | | _ \ __ _| |_| |_ ___ _ __ _ __ / ___| ___ __ _ _ __ ___| |__
27 | | |_) / _` | __| __/ _ \ '__| '_ \\___ \ / _ \/ _` | '__/ __| '_ \
28 | | __/ (_| | |_| || __/ | | | | |___) | __/ (_| | | | (__| | | |
29 | |_| \__,_|\__|\__\___|_| |_| |_|____/ \___|\__,_|_| \___|_| |_|
30 |
31 \*/
32
41 template <typename Real>
42 template <Integer N>
43 class PatternSearch : public Optimizer<Real, N, PatternSearch<Real, N>>
44 {
45 public:
46 static constexpr bool requires_function{true};
47 static constexpr bool requires_first_derivative{false};
48 static constexpr bool requires_second_derivative{false};
49
54
55 using Simplex = std::vector<Vector>;
56
57 private:
58 Real m_rho{0.9}; // stencil step decreasing factor (must be 0 < rho < 1)
59 Real m_h{0.1};
60 bool m_stencil_failure{false}; // stencil failure flag - used to shrink h,
61 // stencil_failure = true means failure
62
63 public:
68
73 std::string name_impl() const {return "PatternSearch";}
74
75 void set_max_num_stagnation( integer nstg ) {
76 UTILS_ASSERT(
77 nstg > 0,
78 "set_max_num_stagnation({}) argument must be >0\n", nstg
79 );
80 m_max_num_stagnation = nstg;
81 }
82
83 // SEARCH This method call the explore method on the first
84 // iteration and then continue to call explore until a stencil
85 // fails. In the case of a stencil failure, it tries once to go
86 // back of half a step along the search direction by setting x_center
87 // equal to the base point x_best.
88 // If the stencil fails again, it exits the while loop and stencil_failure
89 // is set to zero in order to signal that a reduction of h is necessary.
90 void
92 ++m_iteration_count; // augment counter
93
94 this->best_nearby();
95
96 while ( m_stencil_failure ) {
97 // reduce the scale
98 m_h *= m_rho;
99 this->best_nearby();
100 if ( m_h <= m_tolerance ) return;
101 if ( m_fun_evaluation_count >= m_max_fun_evaluation ) return;
102 }
103
104 search_dir.noalias() = x_best - x_old; // Compute search direction
105
106 // Continue exploring until stencil failure or exceed of
107 Real lambda = 1;
108 Real max_der = 0;
109 while ( m_fun_evaluation_count < m_max_fun_evaluation && lambda > 0.1 ) {
110 x_new.noalias() = x_best + lambda*search_dir;
111 Real new_f = eval_function(x_new);
112 if ( new_f < f_best-(0.25*lambda)*max_der ) {
113 Real der = (f_best-new_f)/lambda;
114 if ( der > max_der ) max_der = der;
115 x_best.noalias() = x_new;
116 f_best = new_f;
117 //lambda *= 2;
118 }
119 lambda *= 0.5;
120 }
121 }
122
123 // This method explore all points on the stencil center at
124 // x_temporary = x_center and updates the current iteration x to the current
125 // best point x_current_best. If the current best point x_current_best is worse than the
126 // base point x_best, the current iteration x will remain constant
127 // (x = x_best) and stencil failure flag stencil_failure will be set to zero.
129 {
130 /*
131 */
132 // Initialize
133 m_stencil_failure = true;
134
135 // ----------------------------------------------------------------------------------------
136 // Cycle on all stencil directions
137
138 for ( integer j = 0; j < N; ++j ) {
139 Real s_dirh = search_sign(j) * m_h;
140 m_p.noalias() = x_best; m_p(j) += s_dirh;
141 Real fp = eval_function( m_p );
142 if ( fp >= f_best ) {
143 m_p1.noalias() = x_best; m_p1(j) -= s_dirh; // try the opposite direction
144 Real fp1 = eval_function( m_p1 );
145 if ( fp1 < fp ) {
146 m_p.noalias() = m_p1; fp = fp1;
147 // change priority of search direction to the opposite verse
148 search_sign(j) = -search_sign(j);
149 }
150 }
151 // Update temporary and current best point before checking
152 // the remaining directions j
153 if ( fp < f_best ) {
154 x_best.noalias() = m_p; // move temporary point
155 f_best = fp; // new current best point
156 m_stencil_failure = false; // update stencil failure flag
157 }
158 }
159 }
160
169 bool solve_impl(FunctionWrapper function, Vector const & x_ini, Vector & x_sol)
170 {
171 // Setup internal variables
172 this->reset();
173 this->m_stencil_failure = false;
174
175 // Print header
176 if (this->m_verbose) {this->header();}
177
178 // Set initial iteration
179 Vector x_best(x_ini);
180 Real f_best;
181 this->evaluate_function(function, x_best, f_best);
182 search_sign.setOnes(); // First direction will be positive for each direction
183 this->m_h = h;
184
185 // Algorithm iterations
186 integer stagnations{0};
187 for (this->m_iterations = static_cast<Integer>(0); this->m_iterations < this->m_max_iterations; ++this->m_iterations)
188 {
189
190 x_old = x_best;
191 f_old = f_best;
192
193 this->search();
194 if (this->m_stencil_failure) {break;}
195
196 // Check convergence
197 if (this->m_verbose) {this->info(residuals);}
198 if (this->m_h < this->m_tolerance) {
199 this->m_converged = true;
200 break;
201 }
202
203 // Reduce the scale
204 this->m_h *= this->m_rho;
205
206 // Check for stagnation
207 if (f_old <= f_best) {
208 ++stagnations;
209 if (stagnations > this->m_max_stagnations) {break;}
210 } else {
211 stagnations = 0;
212 }
213 }
214
215 // Print bottom
216 if (this->m_verbose) {this->bottom();}
217
218 // Convergence data
219 x_sol =
220 return this->m_converged;
221 }
222
223 }; // class PatternSearch
224
225 } // namespace Optimizer
226
227} // namespace Optimist
228
229#endif // OPTIMIST_OPTIMIZER_HJ_PATTERN_SEARCH_HH
bool solve(FunctionWrapper function, Vector const &x_ini, Vector &x_sol)
Definition Optimizer.hh:160
void set_max_num_stagnation(integer nstg)
Definition PatternSearch.hh:75
Real m_rho
Definition PatternSearch.hh:58
void search()
Definition PatternSearch.hh:91
static constexpr bool requires_second_derivative
Definition PatternSearch.hh:48
std::vector< Vector > Simplex
Definition PatternSearch.hh:55
typename Optimizer< Real, N, PatternSearch< Real, N > >::Matrix Matrix
Definition PatternSearch.hh:51
typename Optimizer< Real, N, PatternSearch< Real, N > >::Vector Vector
Definition PatternSearch.hh:50
bool m_stencil_failure
Definition PatternSearch.hh:60
bool solve_impl(FunctionWrapper function, Vector const &x_ini, Vector &x_sol)
Definition PatternSearch.hh:169
Real m_h
Definition PatternSearch.hh:59
static constexpr bool requires_function
Definition PatternSearch.hh:46
void best_nearby()
Definition PatternSearch.hh:128
PatternSearch()
Definition PatternSearch.hh:67
typename Optimizer< Real, N, PatternSearch< Real, N > >::FunctionWrapper FunctionWrapper
Definition PatternSearch.hh:52
static constexpr bool requires_first_derivative
Definition PatternSearch.hh:47
std::string name_impl() const
Definition PatternSearch.hh:73
void evaluate_function(FunctionWrapper function, const InputType &x, OutputType &out)
Definition Solver.hh:710
void info(Real residuals, std::string const &notes="-")
Definition Solver.hh:853
Namespace for the Optimist library.
Definition Optimist.hh:87
OPTIMIST_DEFAULT_INTEGER_TYPE Integer
The Integer type as used for the API.
Definition Optimist.hh:95