Optimist  0.0.0
A C++ library for optimization
Loading...
Searching...
No Matches
QuasiNewton.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_ROOTFINDER_QUASINEWTON_HH
14#define OPTIMIST_ROOTFINDER_QUASINEWTON_HH
15
17
18namespace Optimist
19{
20 namespace RootFinder
21 {
22
23 /*\
24 | ___ _ _ _ _
25 | / _ \ _ _ __ _ ___(_) \ | | _____ _| |_ ___ _ __
26 | | | | | | | |/ _` / __| | \| |/ _ \ \ /\ / / __/ _ \| '_ \
27 | | |_| | |_| | (_| \__ \ | |\ | __/\ V V /| || (_) | | | |
28 | \__\_\\__,_|\__,_|___/_|_| \_|\___| \_/\_/ \__\___/|_| |_|
29 |
30 \*/
31
40 template <typename Real, Integer N, typename DerivedSolver>
41 class QuasiNewton : public RootFinder<Real, N, DerivedSolver, true>
42 {
43 public:
45
48
52 using Method = enum class Method : Integer {GOOD = 0, BAD = 1, COMBINED = 2};
53
54 private:
55 Method m_method{Method::COMBINED};
56
57 public:
62
67 std::string name_impl() const
68 {
69 return static_cast<const DerivedSolver *>(this)->name_impl();
70 }
71
83 template <typename FunctionLambda, typename JacobianLambda>
84 bool solve_impl(FunctionLambda && function, JacobianLambda && jacobian, Vector const & x_ini,
85 Vector & x_sol)
86 {
87 #define CMD "Optimist::RootFinder::QuasiNewton::solve(...): "
88
89 // Setup internal variables
90 this->reset();
91
92 // Print header
93 if (this->m_verbose) {this->header();}
94
95 // Initialize variables
96 bool damped, success;
97 Real residuals, step_norm;
98 Vector x_old, x_new, function_old, function_new, step_old, step_new, delta_x_old, delta_x_new,
99 delta_function_old, delta_function_new;
100 Matrix jacobian_old, jacobian_new;
101
102 // Set initial iteration
103 x_old = x_ini;
104 success = this->evaluate_function(std::forward<FunctionLambda>(function), x_old, function_old);
106 CMD "function evaluation failed at the initial point.");
107 success = this->evaluate_jacobian(jacobian, x_old, jacobian_old);
109 CMD "jacobian evaluation failed at the initial point.");
110
111 // Algorithm iterations
112 Real tolerance_residuals{this->m_tolerance};
113 Real tolerance_step_norm{this->m_tolerance * this->m_tolerance};
114 for (this->m_iterations = 1; this->m_iterations < this->m_max_iterations; ++this->m_iterations)
115 {
116 // Store trace
117 this->store_trace(x_old);
118
119 // Calculate step
120 step_old = -jacobian_old * function_old;
121
122 // Check convergence
123 residuals = function_old.norm();
124 step_norm = step_old.norm();
125 if (this->m_verbose) {this->info(residuals);}
126 if (residuals < tolerance_residuals || step_norm < tolerance_step_norm) {
127 this->m_converged = true;
128 break;
129 }
130
131 if (this->m_damped)
132 {
133 // Relax the iteration process
134 damped = this->damp(std::forward<FunctionLambda>(function), x_old, function_old, step_old, x_new, function_new, step_new);
136 "Optimist::RootFinder::QuasiNewton::solve(...): damping failed.");
137 } else {
138 // Update point
139 x_new = x_old + step_old;
140 success = this->evaluate_function(std::forward<FunctionLambda>(function), x_new, function_new);
142 CMD "function evaluation failed at iteration " << this->m_iterations << ".");
143 }
144
145 // Update jacobian approximation
146 delta_x_new = x_new - x_old;
147 delta_function_new = function_new - function_old;
148 this->update(
149 delta_x_old, delta_function_old, jacobian_old, // Old step data
150 delta_x_new, delta_function_new, function_new, jacobian_new // New step data
151 );
152
153 // Update internal variables
154 x_old = x_new;
155 function_old = function_new;
156 delta_x_old = delta_x_new;
157 delta_function_old = delta_function_new;
158 step_old = step_new;
159 jacobian_old = jacobian_new;
160 }
161
162 // Print bottom
163 if (this->m_verbose) {this->bottom();}
164
165 // Convergence data
166 x_sol = x_old;
167 return this->m_converged;
168
169 #undef CMD
170 }
171
182 void update(
183 Vector const & delta_x_old, Vector const & delta_function_old, Matrix const & jacobian_old,
184 Vector const & delta_x_new, Vector const & delta_function_new, Vector const & function_new,
185 Matrix & jacobian_new
186 ) {
187 static_cast<DerivedSolver *>(this)->update_impl(
188 delta_x_old, delta_function_old, jacobian_old, // Old step data
189 delta_x_new, delta_function_new, function_new, jacobian_new // New step data
190 );
191 }
192
193 }; // class QuasiNewton
194
195 } // namespace RootFinder
196
197} // namespace Optimist
198
199#endif // OPTIMIST_ROOTFINDER_QUASINEWTON_HH
#define OPTIMIST_ASSERT_WARNING(COND, MSG)
Definition Optimist.hh:61
#define OPTIMIST_BASIC_CONSTANTS(Real)
Definition Optimist.hh:71
#define CMD
void update(Vector const &delta_x_old, Vector const &delta_function_old, Matrix const &jacobian_old, Vector const &delta_x_new, Vector const &delta_function_new, Vector const &function_new, Matrix &jacobian_new)
Definition QuasiNewton.hh:182
QuasiNewton()
Definition QuasiNewton.hh:61
bool solve_impl(FunctionLambda &&function, JacobianLambda &&jacobian, Vector const &x_ini, Vector &x_sol)
Definition QuasiNewton.hh:84
Method m_method
Definition QuasiNewton.hh:55
enum class Method :Integer {GOOD=0, BAD=1, COMBINED=2} Method
Definition QuasiNewton.hh:52
std::string name_impl() const
Definition QuasiNewton.hh:67
typename SolverBase< Real, N, N, DerivedSolver, ForceEigen >::InputType Vector
Definition RootFinder.hh:61
bool evaluate_jacobian(JacobianLambda &&jacobian, Vector const &x, Matrix &out)
Definition RootFinder.hh:130
typename SolverBase< Real, N, N, DerivedSolver, ForceEigen >::FirstDerivativeType Matrix
Definition RootFinder.hh:64
void info(Real residuals, std::string const &notes="-")
Definition SolverBase.hh:924
bool damp(FunctionLambda &&function, InputType const &x_old, InputType const &function_old, InputType const &step_old, InputType &x_new, InputType &function_new, InputType &step_new)
Definition SolverBase.hh:828
void store_trace(InputType const &x)
Definition SolverBase.hh:813
bool evaluate_function(FunctionLambda &&function, InputType const &x, OutputType &out)
Definition SolverBase.hh:768
Namespace for the Optimist library.
Definition Optimist.hh:88
OPTIMIST_DEFAULT_INTEGER_TYPE Integer
The Integer type as used for the API.
Definition Optimist.hh:96