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, 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_NEWTON_HH
14#define OPTIMIST_ROOTFINDER_NEWTON_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>
41 class Newton : public RootFinder<Real, N, Newton<Real, N>, true>
42 {
43 public:
44 static constexpr bool requires_function{true};
45 static constexpr bool requires_first_derivative{true};
46 static constexpr bool requires_second_derivative{false};
47
49
52
53 private:
54 Eigen::FullPivLU<Matrix> m_lu;
55
56 public:
60 Newton() {}
61
66 std::string name_impl() const {return "Newton";}
67
79 template <typename FunctionLambda, typename JacobianLambda>
80 bool solve_impl(FunctionLambda && function, JacobianLambda && jacobian, Vector const & x_ini,
81 Vector & x_sol)
82 {
83 #define CMD "Optimist::RootFinder::Newton::solve(...): "
84
85 // Setup internal variables
86 this->reset();
87
88 // Print header
89 if (this->m_verbose) {this->header();}
90
91 // Initialize variables
92 bool damped, success;
93 Real residuals, step_norm;
94 Vector x_old, x_new, function_old, function_new, step_old, step_new;
95 Matrix jacobian_old;
96
97 // Set initial iteration
98 x_old = x_ini;
99 success = this->evaluate_function(std::forward<FunctionLambda>(function), x_old, function_old);
101 CMD "function evaluation failed at the initial point.");
102
103 // Algorithm iterations
104 Real tolerance_residuals{this->m_tolerance};
105 Real tolerance_step_norm{this->m_tolerance * this->m_tolerance};
106 for (this->m_iterations = 1; this->m_iterations < this->m_max_iterations; ++this->m_iterations)
107 {
108 // Store trace
109 this->store_trace(x_old);
110
111 // Calculate step
112 success = this->evaluate_jacobian(jacobian, x_old, jacobian_old);
114 CMD "jacobian evaluation failed at iteration " << this->m_iterations << ".");
115 this->m_lu.compute(jacobian_old);
116 OPTIMIST_ASSERT(this->m_lu.rank() == N,
117 "Optimist::RootFinder::Newton::solve(...): singular Jacobian detected.");
118 step_old = -this->m_lu.solve(function_old);
119
120 // Check convergence
121 residuals = function_old.norm();
122 step_norm = step_old.norm();
123 if (this->m_verbose) {this->info(residuals);}
124 if (residuals < tolerance_residuals || step_norm < tolerance_step_norm) {
125 this->m_converged = true;
126 break;
127 }
128
129 if (this->m_damped)
130 {
131 // Relax the iteration process
132 damped = this->damp(std::forward<FunctionLambda>(function), x_old, function_old, step_old, x_new, function_new, step_new);
134 "Optimist::RootFinder::Newton::solve(...): damping failed.");
135 } else {
136 // Update point
137 x_new = x_old + step_old;
138 success = this->evaluate_function(std::forward<FunctionLambda>(function), x_new, function_new);
140 CMD "function evaluation failed at iteration " << this->m_iterations << ".");
141 }
142
143 // Update internal variables
144 x_old = x_new;
145 function_old = function_new;
146 step_old = step_new;
147 }
148
149 // Print bottom
150 if (this->m_verbose) {this->bottom();}
151
152 // Convergence data
153 x_sol = x_old;
154 return this->m_converged;
155
156 #undef CMD
157 }
158
159 }; // class Newton
160
161 } // namespace RootFinder
162
163} // namespace Optimist
164
165#endif // OPTIMIST_ROOTFINDER_NEWTON_HH
#define OPTIMIST_ASSERT_WARNING(COND, MSG)
Definition Optimist.hh:61
#define OPTIMIST_BASIC_CONSTANTS(Real)
Definition Optimist.hh:71
#define OPTIMIST_ASSERT(COND, MSG)
Definition Optimist.hh:44
#define CMD
Newton()
Definition Newton.hh:60
static constexpr bool requires_function
Definition Newton.hh:44
static constexpr bool requires_first_derivative
Definition Newton.hh:45
std::string name_impl() const
Definition Newton.hh:66
Eigen::FullPivLU< Matrix > m_lu
Definition Newton.hh:54
static constexpr bool requires_second_derivative
Definition Newton.hh:46
bool solve_impl(FunctionLambda &&function, JacobianLambda &&jacobian, Vector const &x_ini, Vector &x_sol)
Definition Newton.hh:80
Class container for the multi-dimensional root finder.
Definition RootFinder.hh:48
typename SolverBase< Real, N, N, Newton< Real, N >, 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, Newton< Real, N >, 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