Optimist  0.0.0
A C++ library for optimization
Loading...
Searching...
No Matches
RootFinder.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_HH
14#define OPTIMIST_ROOTFINDER_HH
15
17
18namespace Optimist
19{
20
24 namespace RootFinder
25 {
26
27 /*\
28 | ____ _ _____ _ _
29 | | _ \ ___ ___ | |_| ___(_)_ __ __| | ___ _ __
30 | | |_) / _ \ / _ \| __| |_ | | '_ \ / _` |/ _ \ '__|
31 | | _ < (_) | (_) | |_| _| | | | | | (_| | __/ |
32 | |_| \_\___/ \___/ \__|_| |_|_| |_|\__,_|\___|_|
33 |
34 \*/
35
46 template <typename Real, Integer N, typename DerivedSolver, bool ForceEigen = false>
47 class RootFinder : public SolverBase<Real, N, N, DerivedSolver, ForceEigen>
48 {
49 public:
50 // Fancy static assertions (just for fun, don't take it too seriously)
51 static_assert(N != 0, "Are you sure you want to solve a zero-dimensional system of equations?");
52
53 friend class SolverBase<Real, N, N, RootFinder<Real, N, DerivedSolver, ForceEigen>>;
54
55 static constexpr bool is_rootfinder{true};
56 static constexpr bool is_optimizer{false};
57
59
60 // I/O types
61 using Vector = typename SolverBase<Real, N, N, DerivedSolver, ForceEigen>::InputType;
62
63 // Derivative types
64 using Matrix = typename SolverBase<Real, N, N, DerivedSolver, ForceEigen>::FirstDerivativeType;
65 using Tensor = typename SolverBase<Real, N, N, DerivedSolver, ForceEigen>::SecondDerivativeType;
66
71
76 std::string name() const {return static_cast<const DerivedSolver *>(this)->name_impl();}
77
83
89
94 void max_jacobian_evaluations(Integer t_jacobian_evaluations)
95 {
96 this->max_first_derivative_evaluations(t_jacobian_evaluations);
97 }
98
104
110
115 void max_hessian_evaluations(Integer t_hessian_evaluations)
116 {
117 this->max_first_derivative_evaluations(t_hessian_evaluations);
118 }
119
120 protected:
129 template <typename JacobianLambda>
130 bool evaluate_jacobian(JacobianLambda && jacobian, Vector const & x, Matrix & out)
131 {
132 return this->evaluate_first_derivative(std::forward<JacobianLambda>(jacobian), x, out);
133 }
134
143 template <typename HessianLambda>
144 bool evaluate_hessian(HessianLambda && hessian, Vector const & x, Matrix & out)
145 {
146 return this->evaluate_second_derivative(std::forward<HessianLambda>(hessian), x, out);
147 }
148
149 public:
158 template <typename FunctionLambda>
159 bool solve(FunctionLambda && function, Vector const & x_ini, Vector & x_sol)
160 {
161 #define CMD "Optimist::RootFinder::solve(...): "
162
163 static_assert(DerivedSolver::requires_function,
164 CMD "the solver requires a function.");
165 return static_cast<DerivedSolver *>(this)->solve_impl(
166 std::forward<FunctionLambda>(function),
167 x_ini, x_sol);
168
169 #undef CMD
170 }
171
182 template <typename FunctionLambda, typename JacobianLambda>
183 bool solve(FunctionLambda && function, JacobianLambda && jacobian, Vector const & x_ini,
184 Vector & x_sol)
185 {
186 #define CMD "Optimist::RootFinder::solve(...): "
187
188 static_assert(DerivedSolver::requires_function,
189 CMD "the solver requires a function.");
190 static_assert(DerivedSolver::requires_first_derivative,
191 CMD "the solver requires the first derivative.");
192 return static_cast<DerivedSolver *>(this)->solve_impl(
193 std::forward<FunctionLambda>(function),
194 std::forward<JacobianLambda>(jacobian),
195 x_ini, x_sol);
196
197 #undef CMD
198 }
199
212 template <typename FunctionLambda, typename JacobianLambda, typename HessianLambda>
213 bool solve(FunctionLambda && function, JacobianLambda && jacobian, HessianLambda && hessian,
214 Vector const & x_ini, Vector & x_sol)
215 {
216 #define CMD "Optimist::RootFinder::solve(...): "
217
218 static_assert(DerivedSolver::requires_function,
219 CMD "the solver requires the function.");
220 static_assert(DerivedSolver::requires_first_derivative,
221 CMD "the solver requires the first derivative.");
222 static_assert(DerivedSolver::requires_second_derivative,
223 CMD "the solver requires the second derivative.");
224 return static_cast<DerivedSolver *>(this)->solve_impl(
225 std::forward<FunctionLambda>(function),
226 std::forward<JacobianLambda>(jacobian),
227 std::forward<HessianLambda>(hessian),
228 x_ini, x_sol);
229
230 #undef CMD
231 }
232
233 }; // class RootFinder
234
235 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
236
245 template <typename Real, typename DerivedSolver>
246 class RootFinder<Real, 1, DerivedSolver> : public SolverBase<Real, 1, 1, DerivedSolver>
247 {
248 public:
249 friend class SolverBase<Real, 1, 1, RootFinder<Real, 1, DerivedSolver>>;
250
251 static constexpr bool is_rootfinder{true};
252 static constexpr bool is_optimizer{false};
253
255
256
260
265 std::string name() const {return static_cast<const DerivedSolver *>(this)->name_impl();}
266
275 template <typename FunctionLambda>
276 bool solve(FunctionLambda && function, Real x_ini, Real & x_sol)
277 {
278 return static_cast<DerivedSolver *>(this)->solve_impl(
279 std::forward<FunctionLambda>(function),
280 x_ini, x_sol);
281 }
282
293 template <typename FunctionLambda, typename FirstDerivativeLambda>
294 bool solve(FunctionLambda && function, FirstDerivativeLambda && first_derivative, Real x_ini,
295 Real & x_sol)
296 {
297 return static_cast<DerivedSolver *>(this)->solve_impl(
298 std::forward<FunctionLambda>(function),
299 std::forward<FirstDerivativeLambda>(first_derivative),
300 x_ini, x_sol);
301 }
302
315 template <typename FunctionLambda, typename FirstDerivativeLambda, typename SecondDerivativeLambda>
316 bool solve(FunctionLambda && function, FirstDerivativeLambda && first_derivative, SecondDerivativeLambda
317 && second_derivate, Real x_ini, Real & x_sol)
318 {
319 return static_cast<DerivedSolver *>(this)->solve_impl(
320 std::forward<FunctionLambda>(function),
321 std::forward<FirstDerivativeLambda>(first_derivative),
322 std::forward<SecondDerivativeLambda>(second_derivate),
323 x_ini, x_sol);
324 }
325
326 }; // class RootFinder
327
328 } // namespace RootFinder
329
330} // namespace Optimist
331
332#endif // OPTIMIST_ROOTFINDER_HH
#define OPTIMIST_BASIC_CONSTANTS(Real)
Definition Optimist.hh:71
#define CMD
bool solve(FunctionLambda &&function, Real x_ini, Real &x_sol)
Definition RootFinder.hh:276
bool solve(FunctionLambda &&function, FirstDerivativeLambda &&first_derivative, SecondDerivativeLambda &&second_derivate, Real x_ini, Real &x_sol)
Definition RootFinder.hh:316
static constexpr bool is_optimizer
Definition RootFinder.hh:252
std::string name() const
Definition RootFinder.hh:265
static constexpr bool is_rootfinder
Definition RootFinder.hh:251
bool solve(FunctionLambda &&function, FirstDerivativeLambda &&first_derivative, Real x_ini, Real &x_sol)
Definition RootFinder.hh:294
Class container for the multi-dimensional root finder.
Definition RootFinder.hh:48
bool solve(FunctionLambda &&function, Vector const &x_ini, Vector &x_sol)
Definition RootFinder.hh:159
bool solve(FunctionLambda &&function, JacobianLambda &&jacobian, HessianLambda &&hessian, Vector const &x_ini, Vector &x_sol)
Definition RootFinder.hh:213
static constexpr bool is_optimizer
Definition RootFinder.hh:56
void max_jacobian_evaluations(Integer t_jacobian_evaluations)
Definition RootFinder.hh:94
std::string name() const
Definition RootFinder.hh:76
typename SolverBase< Real, N, N, DerivedSolver, ForceEigen >::InputType Vector
Definition RootFinder.hh:61
void max_hessian_evaluations(Integer t_hessian_evaluations)
Definition RootFinder.hh:115
bool evaluate_hessian(HessianLambda &&hessian, Vector const &x, Matrix &out)
Definition RootFinder.hh:144
typename SolverBase< Real, N, N, DerivedSolver, ForceEigen >::SecondDerivativeType Tensor
Definition RootFinder.hh:65
RootFinder()
Definition RootFinder.hh:70
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
Integer hessian_evaluations() const
Definition RootFinder.hh:103
Integer jacobian_evaluations() const
Definition RootFinder.hh:82
static constexpr bool is_rootfinder
Definition RootFinder.hh:55
bool solve(FunctionLambda &&function, JacobianLambda &&jacobian, Vector const &x_ini, Vector &x_sol)
Definition RootFinder.hh:183
Integer max_jacobian_evaluations() const
Definition RootFinder.hh:88
Integer max_hessian_evaluations() const
Definition RootFinder.hh:109
bool evaluate_second_derivative(SecondDerivativeLambda &&function, InputType const &x, SecondDerivativeType &out)
Definition SolverBase.hh:801
Integer max_first_derivative_evaluations() const
Definition SolverBase.hh:289
std::conditional_t< ForceEigen||(SolInDim > 1)||(SolOutDim > 1), std::conditional_t< SolInDim==1||SolOutDim==1, Eigen::Matrix< Real, SolInDim, SolInDim >, std::vector< Eigen::Matrix< Real, SolInDim, SolInDim > > >, Real > SecondDerivativeType
Definition SolverBase.hh:64
typename std::conditional_t< ForceEigen||(SolInDim > 1), Eigen::Vector< Real, SolInDim >, Real > InputType
Definition SolverBase.hh:53
std::conditional_t< ForceEigen||(SolInDim > 1)||(SolOutDim > 1), Eigen::Matrix< Real, SolOutDim, SolInDim >, Real > FirstDerivativeType
Definition SolverBase.hh:62
Integer first_derivative_evaluations() const
Definition SolverBase.hh:283
bool evaluate_first_derivative(FirstDerivativeLambda &&function, InputType const &x, FirstDerivativeType &out)
Definition SolverBase.hh:785
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