Optimist  0.0.0
A C++ library for optimization
Loading...
Searching...
No Matches
ParticleSwarm.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_PARTICLE_SWARM_HH
14#define OPTIMIST_OPTIMIZER_PARTICLE_SWARM_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, Integer N>
42 class PatternSearch : public Optimizer<Real, N, PatternSearch<Real, N>, true>
43 {
44 public:
45 static constexpr bool requires_function{true};
46 static constexpr bool requires_first_derivative{false};
47 static constexpr bool requires_second_derivative{false};
48
51
52 using Simplex = std::vector<Vector>;
53
54 private:
55 Real m_rho{0.9}; // stencil step decreasing factor (must be 0 < rho < 1)
56 Real m_h{0.1};
57 bool m_stencil_failure{false}; // stencil failure flag - used to shrink h,
58 // stencil_failure = true means failure
59
60 public:
65
70 std::string name_impl() const {return "PatternSearch";}
71
72 void set_max_num_stagnation( integer nstg ) {
73 UTILS_ASSERT(
74 nstg > 0,
75 "set_max_num_stagnation({}) argument must be >0\n", nstg
76 );
77 m_max_num_stagnation = nstg;
78 }
79
80 // SEARCH This method call the explore method on the first
81 // iteration and then continue to call explore until a stencil
82 // fails. In the case of a stencil failure, it tries once to go
83 // back of half a step along the search direction by setting x_center
84 // equal to the base point x_best.
85 // If the stencil fails again, it exits the while loop and stencil_failure
86 // is set to zero in order to signal that a reduction of h is necessary.
87 void
89 ++m_iteration_count; // augment counter
90
91 this->best_nearby();
92
93 while ( m_stencil_failure ) {
94 // reduce the scale
95 m_h *= m_rho;
96 this->best_nearby();
97 if ( m_h <= m_tolerance ) return;
98 if ( m_fun_evaluation_count >= m_max_fun_evaluation ) return;
99 }
100
101 search_dir.noalias() = x_best - x_old; // Compute search direction
102
103 // Continue exploring until stencil failure or exceed of
104 Real lambda = 1;
105 Real max_der = 0;
106 while ( m_fun_evaluation_count < m_max_fun_evaluation && lambda > 0.1 ) {
107 x_new.noalias() = x_best + lambda*search_dir;
108 Real new_f = eval_function(x_new);
109 if ( new_f < f_best-(0.25*lambda)*max_der ) {
110 Real der = (f_best-new_f)/lambda;
111 if ( der > max_der ) max_der = der;
112 x_best.noalias() = x_new;
113 f_best = new_f;
114 //lambda *= 2;
115 }
116 lambda *= 0.5;
117 }
118 }
119
120 // This method explore all points on the stencil center at
121 // x_temporary = x_center and updates the current iteration x to the current
122 // best point x_current_best. If the current best point x_current_best is worse than the
123 // base point x_best, the current iteration x will remain constant
124 // (x = x_best) and stencil failure flag stencil_failure will be set to zero.
126 {
127 /*
128 */
129 // Initialize
130 m_stencil_failure = true;
131
132 // ----------------------------------------------------------------------------------------
133 // Cycle on all stencil directions
134
135 for ( integer j = 0; j < N; ++j ) {
136 Real s_dirh = search_sign(j) * m_h;
137 m_p.noalias() = x_best; m_p(j) += s_dirh;
138 Real fp = eval_function( m_p );
139 if ( fp >= f_best ) {
140 m_p1.noalias() = x_best; m_p1(j) -= s_dirh; // try the opposite direction
141 Real fp1 = eval_function( m_p1 );
142 if ( fp1 < fp ) {
143 m_p.noalias() = m_p1; fp = fp1;
144 // change priority of search direction to the opposite verse
145 search_sign(j) = -search_sign(j);
146 }
147 }
148 // Update temporary and current best point before checking
149 // the remaining directions j
150 if ( fp < f_best ) {
151 x_best.noalias() = m_p; // move temporary point
152 f_best = fp; // new current best point
153 m_stencil_failure = false; // update stencil failure flag
154 }
155 }
156 }
157
167 template <typename FunctionLambda>
168 bool solve_impl(FunctionLambda && function, Vector const & x_ini, Vector & x_sol)
169 {
170 // Setup internal variables
171 this->reset();
172 this->m_stencil_failure = false;
173
174 // Print header
175 if (this->m_verbose) {this->header();}
176
177 // Set initial iteration
178 Vector x_best(x_ini);
179 Real f_best;
180 this->evaluate_function(std::forward<FunctionLambda>(function), x_best, f_best);
181 search_sign.setOnes(); // First direction will be positive for each direction
182 this->m_h = h;
183
184 // Algorithm iterations
185 integer stagnations{0};
186 for (this->m_iterations = 0; this->m_iterations < this->m_max_iterations; ++this->m_iterations)
187 {
188
189 x_old = x_best;
190 f_old = f_best;
191
192 this->search();
193 if (this->m_stencil_failure) {break;}
194
195 // Check convergence
196 if (this->m_verbose) {this->info(residuals);}
197 if (this->m_h < this->m_tolerance) {
198 this->m_converged = true;
199 break;
200 }
201
202 // Reduce the scale
203 this->m_h *= this->m_rho;
204
205 // Check for stagnation
206 if (f_old <= f_best) {
207 ++stagnations;
208 if (stagnations > this->m_max_stagnations) {break;}
209 } else {
210 stagnations = 0;
211 }
212 }
213
214 // Print bottom
215 if (this->m_verbose) {this->bottom();}
216
217 // Convergence data
218 x_sol =
219 return this->m_converged;
220 }
221
222 }; // class PatternSearch
223
224 } // namespace Optimizer
225
226} // namespace Optimist
227
228#endif // OPTIMIST_OPTIMIZER_HJ_PATTERN_SEARCH_HH
229
230
231#endif /* A07D533D_899A_43DD_BCBC_2CAC21A8A0FC */
Class container for the multi-dimensional optimizer.
Definition Optimizer.hh:47
typename SolverBase< Real, N, 1, PatternSearch< Real, N >, ForceEigen >::InputType Vector
Definition Optimizer.hh:60
typename SolverBase< Real, N, 1, PatternSearch< Real, N >, ForceEigen >::SecondDerivativeType Matrix
Definition Optimizer.hh:64
std::vector< Vector > Simplex
Definition ParticleSwarm.hh:52
bool solve_impl(FunctionLambda &&function, Vector const &x_ini, Vector &x_sol)
Definition ParticleSwarm.hh:168
bool m_stencil_failure
Definition ParticleSwarm.hh:57
Real m_rho
Definition ParticleSwarm.hh:55
static constexpr bool requires_function
Definition ParticleSwarm.hh:45
void search()
Definition ParticleSwarm.hh:88
static constexpr bool requires_first_derivative
Definition ParticleSwarm.hh:46
void set_max_num_stagnation(integer nstg)
Definition ParticleSwarm.hh:72
static constexpr bool requires_second_derivative
Definition ParticleSwarm.hh:47
void best_nearby()
Definition ParticleSwarm.hh:125
Real m_h
Definition ParticleSwarm.hh:56
std::string name_impl() const
Definition ParticleSwarm.hh:70
PatternSearch()
Definition ParticleSwarm.hh:64
void info(Real residuals, std::string const &notes="-")
Definition SolverBase.hh:924
bool evaluate_function(FunctionLambda &&function, InputType const &x, OutputType &out)
Definition SolverBase.hh:768
Namespace for the Optimist library.
Definition Optimist.hh:88