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 and Enrico Bertolazzi. *
3 * *
4 * The Optimist project is distributed under the BSD 2-Clause License. *
5 * *
6 * Davide Stocco Enrico Bertolazzi *
7 * University of Trento University of Trento *
8 * davide.stocco@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 namespace RootFinder {
20
21 /*\
22 | ___ _ _ _ _
23 | / _ \ _ _ __ _ ___(_) \ | | _____ _| |_ ___ _ __
24 | | | | | | | |/ _` / __| | \| |/ _ \ \ /\ / / __/ _ \| '_ \
25 | | |_| | |_| | (_| \__ \ | |\ | __/\ V V /| || (_) | | | |
26 | \__\_\\__,_|\__,_|___/_|_| \_|\___| \_/\_/ \__\___/|_| |_|
27 |
28 \*/
29
38 template <typename Vector, typename DerivedSolver>
39 requires TypeTrait<Vector>::IsEigen &&
40 (!TypeTrait<Vector>::IsFixed || TypeTrait<Vector>::Dimension > 0)
41 class QuasiNewton : public RootFinder<Vector, DerivedSolver> {
42 public:
46
48
49
53
58 constexpr std::string name_impl() const {
59 return static_cast<const DerivedSolver *>(this)->name_impl();
60 }
61
74 template <typename FunctionLambda, typename JacobianLambda>
75 bool solve_impl(FunctionLambda &&function,
76 JacobianLambda &&jacobian,
77 const Vector &x_ini,
78 Vector &x_sol) {
79#define CMD "Optimist::RootFinder::QuasiNewton::solve(...): "
80
81 // Reset internal variables
82 this->reset_counters();
83
84 // Print header
85 if (this->m_verbose) {
86 this->header();
87 }
88
89 // Initialize variables
90 bool damped, success;
91 Scalar residuals, step_norm;
92 Vector x_old, x_new, function_old, function_new, step_old, step_new,
93 delta_x_old, delta_x_new, delta_function_old, delta_function_new;
94 FirstDerivative jacobian_old, jacobian_new;
95
96 // Set initial iteration
97 x_old = x_ini;
98 success =
99 this->evaluate_function(std::forward<FunctionLambda>(function),
100 x_old,
101 function_old);
102 OPTIMIST_ASSERT(success,
103 CMD "function evaluation failed at the initial point.");
104 success = this->evaluate_jacobian(jacobian, x_old, jacobian_old);
105 OPTIMIST_ASSERT(success,
106 CMD "jacobian evaluation failed at the initial point.");
107
108 // Algorithm iterations
109 Scalar tolerance_residuals{this->m_tolerance};
110 Scalar tolerance_step_norm{this->m_tolerance * this->m_tolerance};
111 for (this->m_iterations = 1;
112 this->m_iterations < this->m_max_iterations;
113 ++this->m_iterations) {
114 // Calculate step
115 step_old = -jacobian_old * function_old;
116
117 // Check convergence
118 residuals = function_old.norm();
119 step_norm = step_old.norm();
120 if (this->m_verbose) {
121 this->info(residuals);
122 }
123 if (residuals < tolerance_residuals ||
124 step_norm < tolerance_step_norm) {
125 this->m_converged = true;
126 break;
127 }
128
129 if (this->m_damped) {
130 // Relax the iteration process
131 damped = this->damp(std::forward<FunctionLambda>(function),
132 x_old,
133 function_old,
134 step_old,
135 x_new,
136 function_new,
137 step_new);
139 "Optimist::RootFinder::QuasiNewton::solve(."
140 "..): damping failed.");
141 } else {
142 // Update point
143 x_new = x_old + step_old;
144 success =
145 this->evaluate_function(std::forward<FunctionLambda>(function),
146 x_new,
147 function_new);
148 OPTIMIST_ASSERT(success,
149 CMD "function evaluation failed at iteration "
150 << this->m_iterations << ".");
151 }
152
153 // Update jacobian approximation
154 delta_x_new = x_new - x_old;
155 delta_function_new = function_new - function_old;
156 this->update(delta_x_old,
157 delta_function_old,
158 jacobian_old, // Old step data
159 delta_x_new,
160 delta_function_new,
161 function_new,
162 jacobian_new // New step data
163 );
164
165 // Update internal variables
166 x_old = x_new;
167 function_old = function_new;
168 delta_x_old = delta_x_new;
169 delta_function_old = delta_function_new;
170 step_old = step_new;
171 jacobian_old = jacobian_new;
172 }
173
174 // Print bottom
175 if (this->m_verbose) {
176 this->bottom();
177 }
178
179 // Convergence data
180 x_sol = x_old;
181 return this->m_converged;
182
183#undef CMD
184 }
185
196 void update(const Vector &delta_x_old,
197 const Vector &delta_function_old,
198 const FirstDerivative &jacobian_old,
199 const Vector &delta_x_new,
200 const Vector &delta_function_new,
201 const Vector &function_new,
202 FirstDerivative &jacobian_new) {
203 static_cast<DerivedSolver *>(this)->update_impl(
204 delta_x_old,
205 delta_function_old,
206 jacobian_old, // Old step data
207 delta_x_new,
208 delta_function_new,
209 function_new,
210 jacobian_new // New step data
211 );
212 }
213
214 }; // class QuasiNewton
215
216 } // namespace RootFinder
217
218} // namespace Optimist
219
220#endif // OPTIMIST_ROOTFINDER_QUASINEWTON_HH
#define OPTIMIST_BASIC_CONSTANTS(Scalar)
Definition Optimist.hh:70
#define OPTIMIST_ASSERT_WARNING(COND, MSG)
Definition Optimist.hh:62
#define OPTIMIST_ASSERT(COND, MSG)
Definition Optimist.hh:48
#define CMD
QuasiNewton()
Definition QuasiNewton.hh:52
void update(const Vector &delta_x_old, const Vector &delta_function_old, const FirstDerivative &jacobian_old, const Vector &delta_x_new, const Vector &delta_function_new, const Vector &function_new, FirstDerivative &jacobian_new)
Definition QuasiNewton.hh:196
constexpr std::string name_impl() const
Definition QuasiNewton.hh:58
TypeTrait< Vector > VectorTrait
Definition QuasiNewton.hh:43
typename TypeTrait< Vector >::Scalar Scalar
Definition QuasiNewton.hh:44
bool solve_impl(FunctionLambda &&function, JacobianLambda &&jacobian, const Vector &x_ini, Vector &x_sol)
Definition QuasiNewton.hh:75
bool evaluate_jacobian(JacobianLambda &&jacobian, const Input &x, FirstDerivative &out)
Definition RootFinder.hh:136
bool damp(FunctionLambda &&function, const Vector &x_old, const Vector &function_old, const Vector &step_old, Vector &x_new, Vector &function_new, Vector &step_new)
Definition SolverBase.hh:1109
void info(Scalar residuals, const std::string &notes="-")
Definition SolverBase.hh:1232
std::conditional_t< InputTrait::IsEigen||OutputTrait::IsEigen, std::conditional_t< InputTrait::IsSparse||OutputTrait::IsSparse, Eigen::SparseMatrix< Scalar >, Eigen::Matrix< Scalar, OutputTrait::Dimension, InputTrait::Dimension > >, Scalar > FirstDerivative
Definition SolverBase.hh:80
bool evaluate_function(FunctionLambda &&function, const Vector &x, Vector &out)
Definition SolverBase.hh:1040
Integer m_max_iterations
Definition SolverBase.hh:121
Scalar m_tolerance
Definition SolverBase.hh:128
void header()
Definition SolverBase.hh:1168
void reset_counters()
Definition SolverBase.hh:1022
Integer m_iterations
Definition SolverBase.hh:120
bool m_converged
Definition SolverBase.hh:136
void bottom()
Definition SolverBase.hh:1205
Namespace for the Optimist library.
Definition Optimist.hh:90
Definition Optimist.hh:114