TheAlgorithms/C++
1.0.0
All the algorithms implemented in C++
Toggle main menu visibility
Loading...
Searching...
No Matches
brent_method_extrema.cpp
Go to the documentation of this file.
1
16
#define _USE_MATH_DEFINES
17
#include <cassert>
18
#include <cmath>
19
#include <cstdint>
20
#include <functional>
21
#include <iostream>
22
#include <limits>
23
24
#define EPSILON \
25
std::sqrt( \
26
std::numeric_limits<double>::epsilon())
27
36
double
get_minima
(
const
std::function<
double
(
double
)> &f,
double
lim_a,
37
double
lim_b) {
38
uint32_t iters = 0;
39
40
if
(lim_a > lim_b) {
41
std::swap(lim_a, lim_b);
42
}
else
if
(std::abs(lim_a - lim_b) <= EPSILON) {
43
std::cerr <<
"Search range must be greater than "
<< EPSILON <<
"\n"
;
44
return
lim_a;
45
}
46
47
// golden ratio value
48
const
double
M_GOLDEN_RATIO = (3.f - std::sqrt(5.f)) / 2.f;
49
50
double
v = lim_a + M_GOLDEN_RATIO * (lim_b - lim_a);
51
double
u, w = v, x = v;
52
double
fu, fv = f(v);
53
double
fw = fv, fx = fv;
54
55
double
mid_point = (lim_a + lim_b) / 2.f;
56
double
p = 0, q = 0, r = 0;
57
58
double
d, e = 0;
59
double
tolerance, tolerance2;
60
61
do
{
62
mid_point = (lim_a + lim_b) / 2.f;
63
tolerance = EPSILON * std::abs(x);
64
tolerance2 = 2 * tolerance;
65
66
if
(std::abs(e) > tolerance2) {
67
// fit parabola
68
r = (x - w) * (fx - fv);
69
q = (x - v) * (fx - fw);
70
p = (x - v) * q - (x - w) * r;
71
q = 2.f * (q - r);
72
if
(q > 0)
73
p = -p;
74
else
75
q = -q;
76
r = e;
77
e = d;
78
}
79
80
if
(std::abs(p) < std::abs(0.5 * q * r) && p < q * (lim_b - x)) {
81
// parabolic interpolation step
82
d = p / q;
83
u = x + d;
84
if
(u - lim_a < tolerance2 || lim_b - u < tolerance2)
85
d = x < mid_point ? tolerance : -tolerance;
86
}
else
{
87
// golden section interpolation step
88
e = (x < mid_point ? lim_b : lim_a) - x;
89
d = M_GOLDEN_RATIO * e;
90
}
91
92
// evaluate not too close to x
93
if
(std::abs(d) >= tolerance)
94
u = d;
95
else
if
(d > 0)
96
u = tolerance;
97
else
98
u = -tolerance;
99
u += x;
100
fu = f(u);
101
102
// update variables
103
if
(fu <= fx) {
104
if
(u < x)
105
lim_b = x;
106
else
107
lim_a = x;
108
v = w;
109
fv = fw;
110
w = x;
111
fw = fx;
112
x = u;
113
fx = fu;
114
}
else
{
115
if
(u < x)
116
lim_a = u;
117
else
118
lim_b = u;
119
if
(fu <= fw || x == w) {
120
v = w;
121
fv = fw;
122
w = u;
123
fw = fu;
124
}
else
if
(fu <= fv || v == x || v == w) {
125
v = u;
126
fv = fu;
127
}
128
}
129
130
iters++;
131
}
while
(std::abs(x - mid_point) > (tolerance - (lim_b - lim_a) / 2.f));
132
133
std::cout <<
" (iters: "
<< iters <<
") "
;
134
135
return
x;
136
}
137
144
void
test1
() {
145
// define the function to minimize as a lambda function
146
std::function<double(
double
)> f1 = [](
double
x) {
147
return
(x - 2) * (x - 2);
148
};
149
150
std::cout <<
"Test 1.... "
;
151
152
double
minima =
get_minima
(f1, -1, 5);
153
154
std::cout << minima <<
"..."
;
155
156
assert(std::abs(minima - 2) < EPSILON);
157
std::cout <<
"passed\n"
;
158
}
159
166
void
test2
() {
167
// define the function to maximize as a lambda function
168
// since we are maximixing, we negated the function return value
169
std::function<double(
double
)> func = [](
double
x) {
170
return
-std::pow(x, 1.f / x);
171
};
172
173
std::cout <<
"Test 2.... "
;
174
175
double
minima =
get_minima
(func, -2, 5);
176
177
std::cout << minima <<
" ("
<< M_E <<
")..."
;
178
179
assert(std::abs(minima - M_E) < EPSILON);
180
std::cout <<
"passed\n"
;
181
}
182
189
void
test3
() {
190
// define the function to maximize as a lambda function
191
// since we are maximixing, we negated the function return value
192
std::function<double(
double
)> func = [](
double
x) {
return
std::cos(x); };
193
194
std::cout <<
"Test 3.... "
;
195
196
double
minima =
get_minima
(func, -4, 12);
197
198
std::cout << minima <<
" ("
<< M_PI <<
")..."
;
199
200
assert(std::abs(minima - M_PI) < EPSILON);
201
std::cout <<
"passed\n"
;
202
}
203
205
int
main
() {
206
std::cout.precision(18);
207
208
std::cout <<
"Computations performed with machine epsilon: "
<< EPSILON
209
<<
"\n"
;
210
211
test1
();
212
test2
();
213
test3
();
214
215
return
0;
216
}
get_minima
double get_minima(const std::function< double(double)> &f, double lim_a, double lim_b)
Get the real root of a function in the given interval.
Definition
brent_method_extrema.cpp:36
main
int main()
Main function.
Definition
generate_parentheses.cpp:110
test3
static void test3()
Definition
hamiltons_cycle.cpp:122
test2
void test2(const std::string &text)
Self test 2 - using 8x8 randomly generated key.
Definition
hill_cipher.cpp:505
test1
void test1(const std::string &text)
Self test 1 - using 3x3 randomly generated key.
Definition
hill_cipher.cpp:470
numerical_methods
brent_method_extrema.cpp
Generated by
1.18.0