Optimist  0.0.0
A C++ library for optimization
Loading...
Searching...
No Matches
Chandrupatla.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_CHANDRUPATLA_HH
14#define OPTIMIST_ROOTFINDER_CHANDRUPATLA_HH
15
17
18namespace Optimist
19{
20 namespace RootFinder
21 {
22
23 /*\
24 | ____ _ _ _ _
25 | / ___| |__ __ _ _ __ __| |_ __ _ _ _ __ __ _| |_| | __ _
26 | | | | '_ \ / _` | '_ \ / _` | '__| | | | '_ \ / _` | __| |/ _` |
27 | | |___| | | | (_| | | | | (_| | | | |_| | |_) | (_| | |_| | (_| |
28 | \____|_| |_|\__,_|_| |_|\__,_|_| \__,_| .__/ \__,_|\__|_|\__,_|
29 | |_|
30 \*/
31
41 template <typename Real>
42 class Chandrupatla : public Bracketing<Real, Chandrupatla<Real>>
43 {
44 public:
45 static constexpr bool requires_function{true};
46 static constexpr bool requires_first_derivative{false};
47 static constexpr bool requires_second_derivative{false};
48
50
51
55
60 std::string name_impl() const {return "Chandrupatla";}
61
69 template <typename FunctionLambda>
70 Real find_root_impl(FunctionLambda && function)
71 {
72 #define CMD "Optimist::ScalarRootfinder::Chandrupatla::find_root_impl(...): "
73
74 bool success;
75 Real tolerance_step{this->m_tolerance_bracketing};
76 Real tolerance_function{this->m_tolerance_bracketing};
77
78 // Check for trivial solution
79 this->m_converged = this->m_fa == 0; if (this->m_converged) {return this->m_a;}
80 this->m_converged = this->m_fb == 0; if (this->m_converged) {return this->m_b;}
81
82 // Initialize to dumb values
83 this->m_e = QUIET_NAN;
84 this->m_fe = QUIET_NAN;
85
86 // While f(left) or f(right) are infinite perform bisection
87 while (!(std::isfinite(this->m_fa) && std::isfinite(this->m_fb))) {
88 ++this->m_iterations;
89 this->m_c = (this->m_a + this->m_b)/2.0;
90 success = this->evaluate_function(std::forward<FunctionLambda>(function), this->m_c, this->m_fc);
92 CMD "function evaluation failed at iteration " << this->m_iterations << ".");
93 this->m_converged = this->m_fc == 0;
94 if (this->m_converged) {return this->m_c;}
95 if (this->m_fa*this->m_fc < 0.0) {
96 // -> [a, c]
97 this->m_b = this->m_c; this->m_fb = this->m_fc;
98 } else {
99 // -> [c, b]
100 this->m_a = this->m_c; this->m_fa = this->m_fc;
101 }
102
103 // Check for convergence
104 Real abs_fa{std::abs(this->m_fa)};
105 Real abs_fb{std::abs(this->m_fb)};
106 this->m_converged = (this->m_b - this->m_a) < tolerance_step ||
107 abs_fa < tolerance_function ||abs_fb < tolerance_function;
108 if (this->m_converged) {return abs_fb < abs_fa ? this->m_b : this->m_a;}
109 }
110
111 Real t{0.5};
112
114
115 Real direction{this->m_b - this->m_a};
116 Real tolerance{tolerance_step/(2.0*std::abs(direction))};
117 this->m_converged = tolerance >= 0.5;
118 if (this->m_converged) {break;}
119
120 Real abs_fa{std::abs(this->m_fa)};
121 Real abs_fb{std::abs(this->m_fb)};
122 this->m_converged = abs_fa < tolerance_function || abs_fb < tolerance_function;
123 if (this->m_converged) {break;}
124
125 if (t < tolerance) {t = tolerance;}
126 else if (t > 1.0 - tolerance) {t = 1.0 - tolerance;}
127
128 Real c{this->m_a + t * direction};
129 Real fc;
130 success = this->evaluate_function(std::forward<FunctionLambda>(function), c, fc);
132 CMD "function evaluation failed at iteration " << this->m_iterations << ".");
133 if (this->m_verbose) {this->info(fc);}
134
135 OPTIMIST_ASSERT(std::isfinite(fc), CMD "function is not finite.");
136
137 this->m_converged = fc == 0;
138 if (this->m_converged) {
139 this->m_a = this->m_b = c; this->m_fa = this->m_fb = 0;
140 break;
141 }
142
143 // Arrange 2-1-3: 2-1 interval, 1 middle, 3 discarded point
144 Real d, fd;
145 if ((0.0 < fc) == (0.0 < this->m_fa)) {
146 // a -> d --> [d,a,b] = [a,c,b]
147 d = this->m_a; fd = this->m_fa;
148 } else {
149 // b -> d, a -> b --> [b,a,d] = [a,c,b]
150 d = this->m_b; fd = this->m_fb;
151 this->m_b = this->m_a; this->m_fb = this->m_fa;
152 }
153 // c => a
154 this->m_a = c; this->m_fa = fc;
155
156 // If inverse quadratic interpolation holds use it
157 Real ba{this->m_b - this->m_a};
158 Real fba{this->m_fb - this->m_fa};
159 Real bd{this->m_b - d};
160 Real fbd{this->m_fb - fd};
161
162 Real xi{ba/bd};
163 Real ph{fba/fbd};
164 Real fl{1.0 - std::sqrt(1.0 - xi)};
165 Real fh{std::sqrt(xi)};
166
167 if (fl < ph && ph < fh) {
168 Real da{d - this->m_a};
169 Real fda{fd - this->m_fa};
170 t = (this->m_fa/fba) * (fd/fbd) - (this->m_fa/fda) * (this->m_fb/fbd) * (da/ba);
171 } else {
172 t = 0.5;
173 }
174 }
175 if (this->m_a > this->m_b) {std::swap(this->m_a, this->m_b); std::swap(this->m_fa, this->m_fb);}
176 return std::abs(this->m_fa) < std::abs(this->m_fb) ? this->m_a : this->m_b;;
177
178 #undef CMD
179 }
180
181 }; // class Chandrupatla
182
183 } // namespace RootFinder
184
185} // namespace Optimist
186
187#endif // OPTIMIST_ROOTFINDER_CHANDRUPATLA_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
static constexpr bool requires_second_derivative
Definition Chandrupatla.hh:47
static constexpr bool requires_first_derivative
Definition Chandrupatla.hh:46
Real find_root_impl(FunctionLambda &&function)
Definition Chandrupatla.hh:70
static constexpr bool requires_function
Definition Chandrupatla.hh:45
std::string name_impl() const
Definition Chandrupatla.hh:60
Chandrupatla()
Definition Chandrupatla.hh:54
void info(Real residuals, std::string const &notes="-")
Definition SolverBase.hh:924
Real tolerance() const
Definition SolverBase.hh:392
bool evaluate_function(FunctionLambda &&function, InputType const &x, OutputType &out)
Definition SolverBase.hh:768
Namespace for the Optimist library.
Definition Optimist.hh:88