Optimist  0.0.0
A C++ library for optimization
Loading...
Searching...
No Matches
Newton.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_NEWTON_HH
14#define OPTIMIST_ROOTFINDER_NEWTON_HH
15
17
18namespace Optimist {
19 namespace RootFinder {
20
21 /*\
22 | _ _ _
23 | | \ | | _____ _| |_ ___ _ __
24 | | \| |/ _ \ \ /\ / / __/ _ \| '_ \
25 | | |\ | __/\ V V /| || (_) | | | |
26 | |_| \_|\___| \_/\_/ \__\___/|_| |_|
27 |
28 \*/
29
37 template <typename Vector>
38 requires TypeTrait<Vector>::IsEigen &&
39 (!TypeTrait<Vector>::IsFixed || TypeTrait<Vector>::Dimension > 0)
40 class Newton : public RootFinder<Vector, Newton<Vector>> {
41 public:
42 static constexpr bool RequiresFunction{true};
43 static constexpr bool RequiresFirstDerivative{true};
44 static constexpr bool RequiresSecondDerivative{false};
45
50 std::conditional_t<VectorTrait::IsSparse,
51 Eigen::SparseLU<FirstDerivative>,
52 Eigen::FullPivLU<FirstDerivative>>;
53
55
56 private:
58
59 public:
63 Newton() {}
64
69 constexpr std::string name_impl() const {
70 return "Newton";
71 }
72
85 template <typename FunctionLambda, typename JacobianLambda>
86 bool solve_impl(FunctionLambda &&function,
87 JacobianLambda &&jacobian,
88 const Vector &x_ini,
89 Vector &x_sol) {
90#define CMD "Optimist::RootFinder::Newton::solve(...): "
91
92 // Reset internal variables
93 this->reset_counters();
94
95 // Print header
96 if (this->m_verbose) {
97 this->header();
98 }
99
100 // Initialize variables
101 bool damped, success;
102 Scalar residuals, step_norm;
103 Vector x_old, x_new, function_old, function_new, step_old, step_new;
104 FirstDerivative jacobian_old;
105
106 // Set initial iteration
107 x_old = x_ini;
108 success =
109 this->evaluate_function(std::forward<FunctionLambda>(function),
110 x_old,
111 function_old);
112 OPTIMIST_ASSERT(success,
113 CMD "function evaluation failed at the initial point.");
114
115 // Algorithm iterations
116 Scalar tolerance_residuals{this->m_tolerance};
117 Scalar tolerance_step_norm{this->m_tolerance * this->m_tolerance};
118 for (this->m_iterations = 1;
119 this->m_iterations < this->m_max_iterations;
120 ++this->m_iterations) {
121 // Calculate step
122 success = this->evaluate_jacobian(jacobian, x_old, jacobian_old);
123 OPTIMIST_ASSERT(success,
124 CMD "jacobian evaluation failed at iteration "
125 << this->m_iterations << ".");
126 this->m_lu.compute(jacobian_old);
127 if constexpr (VectorTrait::IsSparse) {
128 OPTIMIST_ASSERT_WARNING(this->m_lu.info() == Eigen::Success,
129 CMD "jacobian factorization failed.");
130 step_old = -this->m_lu.solve(function_old).eval();
131 } else {
132 OPTIMIST_ASSERT(this->m_lu.isInvertible(),
133 CMD "singular Jacobian detected.");
134 step_old = -this->m_lu.solve(function_old);
135 }
136
137 // Check convergence
138 residuals = function_old.norm();
139 step_norm = step_old.norm();
140 if (this->m_verbose) {
141 this->info(residuals);
142 }
143 if (residuals < tolerance_residuals ||
144 step_norm < tolerance_step_norm) {
145 this->m_converged = true;
146 break;
147 }
148
149 if (this->m_damped) {
150 // Relax the iteration process
151 damped = this->damp(std::forward<FunctionLambda>(function),
152 x_old,
153 function_old,
154 step_old,
155 x_new,
156 function_new,
157 step_new);
159 damped,
160 "Optimist::RootFinder::Newton::solve(...): damping failed.");
161 } else {
162 // Update point
163 x_new = x_old + step_old;
164 success =
165 this->evaluate_function(std::forward<FunctionLambda>(function),
166 x_new,
167 function_new);
168 OPTIMIST_ASSERT(success,
169 CMD "function evaluation failed at iteration "
170 << this->m_iterations << ".");
171 }
172
173 // Update internal variables
174 x_old = x_new;
175 function_old = function_new;
176 step_old = step_new;
177 }
178
179 // Print bottom
180 if (this->m_verbose) {
181 this->bottom();
182 }
183
184 // Convergence data
185 x_sol = x_old;
186 return this->m_converged;
187
188#undef CMD
189 }
190
191 }; // class Newton
192
193 } // namespace RootFinder
194
195} // namespace Optimist
196
197#endif // OPTIMIST_ROOTFINDER_NEWTON_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
TypeTrait< Vector > VectorTrait
Definition Newton.hh:46
static constexpr bool RequiresFirstDerivative
Definition Newton.hh:43
typename TypeTrait< Vector >::Scalar Scalar
Definition Newton.hh:47
Factorization m_lu
Definition Newton.hh:57
bool solve_impl(FunctionLambda &&function, JacobianLambda &&jacobian, const Vector &x_ini, Vector &x_sol)
Definition Newton.hh:86
constexpr std::string name_impl() const
Definition Newton.hh:69
static constexpr bool RequiresSecondDerivative
Definition Newton.hh:44
Newton()
Definition Newton.hh:63
std::conditional_t< VectorTrait::IsSparse, Eigen::SparseLU< FirstDerivative >, Eigen::FullPivLU< FirstDerivative > > Factorization
Definition Newton.hh:49
static constexpr bool RequiresFunction
Definition Newton.hh:42
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 reset_counters()
Definition SolverBase.hh:1022
Integer m_iterations
Definition SolverBase.hh:120
Namespace for the Optimist library.
Definition Optimist.hh:90
Definition Optimist.hh:114