Optimist  0.0.0
A C++ library for optimization
Loading...
Searching...
No Matches
Chebyshev.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_CHEBYSHEV_HH
14#define OPTIMIST_ROOTFINDER_CHEBYSHEV_HH
15
17
18namespace Optimist {
19 namespace RootFinder {
20
21 /*\
22 | ____ _ _ _
23 | / ___| |__ ___| |__ _ _ ___| |__ _____ __
24 | | | | '_ \ / _ \ '_ \| | | / __| '_ \ / _ \ \ / /
25 | | |___| | | | __/ |_) | |_| \__ \ | | | __/\ V /
26 | \____|_| |_|\___|_.__/ \__, |___/_| |_|\___| \_/
27 | |___/
28 \*/
29
37 template <typename Scalar>
38 class Chebyshev : public RootFinder<Scalar, Chebyshev<Scalar>> {
39 public:
40 static constexpr bool RequiresFunction{true};
41 static constexpr bool RequiresFirstDerivative{true};
42 static constexpr bool RequiresSecondDerivative{true};
43
45
46
50
55 constexpr std::string name_impl() const {
56 return "Chebyshev";
57 }
58
72 template <typename FunctionLambda,
73 typename FirstDerivativeLambda,
74 typename SecondDerivativeLambda>
75 bool solve_impl(FunctionLambda &&function,
76 FirstDerivativeLambda &&first_derivative,
77 SecondDerivativeLambda &&second_derivative,
78 Scalar x_ini,
79 Scalar &x_sol) {
80#define CMD "Optimist::RootFinder::Chebyshev::solve(...): "
81
82 // Reset internal variables
83 this->reset_counters();
84
85 // Print header
86 if (this->m_verbose) {
87 this->header();
88 }
89
90 // Initialize variables
91 bool damped, success;
92 Scalar residuals, step_norm;
93 Scalar x_old, x_new, function_old, function_new, step_old, step_new;
94 Scalar first_derivative_old, second_derivative_old;
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 iteration "
104 << this->m_iterations << ".");
105
106 // Algorithm iterations
107 Scalar tolerance_residuals{this->m_tolerance};
108 Scalar tolerance_step_norm{this->m_tolerance * this->m_tolerance};
109 for (this->m_iterations = 1;
110 this->m_iterations < this->m_max_iterations;
111 ++this->m_iterations) {
112 // Evaluate derivatives
113 success = this->evaluate_first_derivative(
114 std::forward<FirstDerivativeLambda>(first_derivative),
115 x_old,
116 first_derivative_old);
117 OPTIMIST_ASSERT(success,
118 CMD "first derivative evaluation failed at iteration "
119 << this->m_iterations << ".");
120 success = this->evaluate_second_derivative(
121 std::forward<SecondDerivativeLambda>(second_derivative),
122 x_old,
123 second_derivative_old);
125 success,
126 CMD "second derivative evaluation failed at iteration "
127 << this->m_iterations << ".");
128
129 // Calculate step
130 if (std::abs(first_derivative_old) < Chebyshev::SQRT_EPSILON) {
132 "close-to-singular first derivative detected.");
133 first_derivative_old = (first_derivative_old > 0)
134 ? Chebyshev::SQRT_EPSILON
135 : -Chebyshev::SQRT_EPSILON;
136 }
137 if (std::abs(second_derivative_old) < Chebyshev::SQRT_EPSILON) {
139 "close-to-singular second derivative detected.");
140 second_derivative_old = (second_derivative_old > 0)
141 ? Chebyshev::SQRT_EPSILON
142 : -Chebyshev::SQRT_EPSILON;
143 }
144 step_old = -(function_old / first_derivative_old) *
145 (1.0 + (function_old * second_derivative_old) /
146 (first_derivative_old * first_derivative_old));
148 std::isfinite(step_old),
149 CMD "step " << this->m_iterations << " is not finite.");
150
151 // Check convergence
152 residuals = std::abs(function_old);
153 step_norm = std::abs(step_old);
154 if (this->m_verbose) {
155 this->info(residuals);
156 }
157 if (residuals < tolerance_residuals ||
158 step_norm < tolerance_step_norm) {
159 this->m_converged = true;
160 break;
161 }
162
163 if (this->m_damped) {
164 // Relax the iteration process
165 damped = this->damp(std::forward<FunctionLambda>(function),
166 x_old,
167 function_old,
168 step_old,
169 x_new,
170 function_new,
171 step_new);
172 OPTIMIST_ASSERT_WARNING(damped, CMD "damping failed.");
173 } else {
174 // Update point
175 x_new = x_old + step_old;
176 success =
177 this->evaluate_function(std::forward<FunctionLambda>(function),
178 x_new,
179 function_new);
180 OPTIMIST_ASSERT(success,
181 CMD "function evaluation failed at iteration "
182 << this->m_iterations << ".");
183 }
184
185 // Update internal variables
186 x_old = x_new;
187 function_old = function_new;
188 step_old = step_new;
189 }
190
191 // Print bottom
192 if (this->m_verbose) {
193 this->bottom();
194 }
195
196 // Convergence data
197 x_sol = x_old;
198 return this->m_converged;
199
200#undef CMD
201 }
202
203 }; // class Chebyshev
204
205 } // namespace RootFinder
206
207} // namespace Optimist
208
209#endif // OPTIMIST_ROOTFINDER_CHEBYSHEV_HH
#define OPTIMIST_WARNING(MSG)
Definition Optimist.hh:55
#define OPTIMIST_BASIC_CONSTANTS(Scalar)
Definition Optimist.hh:69
#define OPTIMIST_ASSERT_WARNING(COND, MSG)
Definition Optimist.hh:61
#define OPTIMIST_ASSERT(COND, MSG)
Definition Optimist.hh:47
#define CMD
static constexpr bool RequiresFunction
Definition Chebyshev.hh:40
static constexpr bool RequiresSecondDerivative
Definition Chebyshev.hh:42
Chebyshev()
Definition Chebyshev.hh:49
constexpr std::string name_impl() const
Definition Chebyshev.hh:55
bool solve_impl(FunctionLambda &&function, FirstDerivativeLambda &&first_derivative, SecondDerivativeLambda &&second_derivative, Scalar x_ini, Scalar &x_sol)
Definition Chebyshev.hh:75
static constexpr bool RequiresFirstDerivative
Definition Chebyshev.hh:41
typename TypeTrait< Scalar >::Scalar Scalar
Definition RootFinder.hh:53
bool damp(FunctionLambda &&function, const Scalar &x_old, const Scalar &function_old, const Scalar &step_old, Scalar &x_new, Scalar &function_new, Scalar &step_new)
Definition SolverBase.hh:1109
void info(Scalar residuals, const std::string &notes="-")
Definition SolverBase.hh:1230
bool evaluate_function(FunctionLambda &&function, const Scalar &x, Scalar &out)
Definition SolverBase.hh:1040
bool evaluate_first_derivative(FirstDerivativeLambda &&function, const Scalar &x, FirstDerivative &out)
Definition SolverBase.hh:1061
bool evaluate_second_derivative(SecondDerivativeLambda &&function, const Scalar &x, SecondDerivative &out)
Definition SolverBase.hh:1082
Integer m_max_iterations
Definition SolverBase.hh:121
void reset_counters()
Definition SolverBase.hh:1022
Namespace for the Optimist library.
Definition Optimist.hh:89