Optimist  0.0.0
A C++ library for optimization
Loading...
Searching...
No Matches
Halley.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_HALLEY_HH
14#define OPTIMIST_ROOTFINDER_HALLEY_HH
15
17
18namespace Optimist
19{
20 namespace RootFinder
21 {
22
23 /*\
24 | _ _ _ _
25 | | | | | __ _| | | ___ _ _
26 | | |_| |/ _` | | |/ _ \ | | |
27 | | _ | (_| | | | __/ |_| |
28 | |_| |_|\__,_|_|_|\___|\__, |
29 | |___/
30 \*/
31
39 template <typename Real>
40 class Halley : public RootFinder<Real, 1, Halley<Real>>
41 {
42 public:
43 static constexpr bool requires_function{true};
44 static constexpr bool requires_first_derivative{true};
45 static constexpr bool requires_second_derivative{true};
46
48
49
52 Halley() {}
53
58 std::string name_impl() const {return "Halley";}
59
72 template <typename FunctionLambda, typename FirstDerivativeLambda, typename SecondDerivativeLambda>
73 bool solve_impl(FunctionLambda && function, FirstDerivativeLambda && first_derivative,
74 SecondDerivativeLambda && second_derivative, Real x_ini, Real & x_sol)
75 {
76 #define CMD "Optimist::RootFinder::Halley::solve(...): "
77
78 // Setup internal variables
79 this->reset();
80
81 // Print header
82 if (this->m_verbose) {this->header();}
83
84 // Initialize variables
85 bool damped, success;
86 Real residuals, step_norm;
87 Real x_old, x_new, function_old, function_new, step_old, step_new;
88 Real first_derivative_old, second_derivative_old;
89
90 // Set initial iteration
91 x_old = x_ini;
92 success = this->evaluate_function(std::forward<FunctionLambda>(function), x_old, function_old);
94 CMD "function evaluation failed at the initial point.");
95
96 // Algorithm iterations
97 Real tolerance_residuals{this->m_tolerance};
98 Real tolerance_step_norm{this->m_tolerance * this->m_tolerance};
99 for (this->m_iterations = 1; this->m_iterations < this->m_max_iterations; ++this->m_iterations)
100 {
101 // Store trace
102 this->store_trace(x_old);
103
104 // Evaluate derivatives
105 success = this->evaluate_first_derivative(std::forward<FirstDerivativeLambda>(first_derivative), x_old, first_derivative_old);
107 CMD "first derivative evaluation failed at iteration " << this->m_iterations << ".");
108 success = this->evaluate_second_derivative(std::forward<SecondDerivativeLambda>(second_derivative), x_old, second_derivative_old);
110 CMD "second derivative evaluation failed at iteration " << this->m_iterations << ".");
111
112 // Calculate step
113 if (std::abs(first_derivative_old) < EPSILON_LOW) {
114 OPTIMIST_WARNING( CMD "singular first derivative detected.");
115 first_derivative_old = (first_derivative_old > 0.0) ? EPSILON_LOW : -EPSILON_LOW;
116 }
117 if (std::abs(second_derivative_old) < EPSILON_LOW) {
118 OPTIMIST_WARNING( CMD "singular second derivative detected.");
119 second_derivative_old = (second_derivative_old > 0.0) ? EPSILON_LOW : -EPSILON_LOW;
120 }
121 step_old = -(function_old / first_derivative_old) * (1.0 - (function_old * second_derivative_old) /
122 (first_derivative_old * first_derivative_old));
123 OPTIMIST_ASSERT(std::isfinite(step_old), CMD "step " << this->m_iterations << " is not finite.");
124
125 // Check convergence
126 residuals = std::abs(function_old);
127 step_norm = std::abs(step_old);
128 if (this->m_verbose) {this->info(residuals);}
129 if (residuals < tolerance_residuals || step_norm < tolerance_step_norm) {
130 this->m_converged = true;
131 break;
132 }
133
134 if (this->m_damped) {
135 // Relax the iteration process
136 damped = this->damp(std::forward<FunctionLambda>(function), x_old, function_old, step_old, x_new, function_new, step_new);
137 OPTIMIST_ASSERT_WARNING(damped, CMD "damping failed.");
138 } else {
139 // Update point
140 x_new = x_old + step_old;
141 success = this->evaluate_function(std::forward<FunctionLambda>(function), x_new, function_new);
143 CMD "function evaluation failed at iteration " << this->m_iterations << ".");
144 }
145
146 // Update internal variables
147 x_old = x_new;
148 function_old = function_new;
149 step_old = step_new;
150 }
151
152 // Print bottom
153 if (this->m_verbose) {this->bottom();}
154
155 // Convergence data
156 x_sol = x_old;
157 return this->m_converged;
158
159 #undef CMD
160 }
161
162 }; // class Halley
163
164 } // namespace RootFinder
165
166} // namespace Optimist
167
168#endif // OPTIMIST_ROOTFINDER_HALLEY_HH
#define OPTIMIST_WARNING(MSG)
Definition Optimist.hh:53
#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
static constexpr bool requires_function
Definition Halley.hh:43
static constexpr bool requires_first_derivative
Definition Halley.hh:44
std::string name_impl() const
Definition Halley.hh:58
Halley()
Definition Halley.hh:52
bool solve_impl(FunctionLambda &&function, FirstDerivativeLambda &&first_derivative, SecondDerivativeLambda &&second_derivative, Real x_ini, Real &x_sol)
Definition Halley.hh:73
static constexpr bool requires_second_derivative
Definition Halley.hh:45
bool evaluate_second_derivative(SecondDerivativeLambda &&function, InputType const &x, SecondDerivativeType &out)
Definition SolverBase.hh:801
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
Integer m_max_iterations
Definition SolverBase.hh:85
void store_trace(InputType const &x)
Definition SolverBase.hh:813
bool evaluate_function(FunctionLambda &&function, InputType const &x, OutputType &out)
Definition SolverBase.hh:768
bool evaluate_first_derivative(FirstDerivativeLambda &&function, InputType const &x, FirstDerivativeType &out)
Definition SolverBase.hh:785
Namespace for the Optimist library.
Definition Optimist.hh:88