TheAlgorithms/C++
1.0.0
All the algorithms implemented in C++
Toggle main menu visibility
Loading...
Searching...
No Matches
integral_approximation2.cpp
Go to the documentation of this file.
1
23
24
#define _USE_MATH_DEFINES
25
#include <cmath>
26
#include <cstdint>
27
#include <ctime>
28
#include <functional>
29
#include <iostream>
30
#include <random>
31
#include <vector>
32
37
namespace
math
{
44
namespace
monte_carlo
{
45
46
using
Function = std::function<double(
47
double
&)>;
48
64
std::vector<double>
generate_samples
(
const
double
& start_point,
65
const
Function& pdf,
66
const
uint32_t& num_samples,
67
const
uint32_t& discard = 100000) {
68
std::vector<double> samples;
69
samples.reserve(num_samples);
70
71
double
x_t = start_point;
72
73
std::default_random_engine generator;
74
std::uniform_real_distribution<double> uniform(0.0, 1.0);
75
std::normal_distribution<double> normal(0.0, 1.0);
76
generator.seed(time(
nullptr
));
77
78
for
(uint32_t t = 0; t < num_samples + discard; ++t) {
79
// Generate a new proposal according to some mutation strategy.
80
// This is arbitrary and can be swapped.
81
double
x_dash = normal(generator) + x_t;
82
double
acceptance_probability = std::min(pdf(x_dash) / pdf(x_t), 1.0);
83
double
u = uniform(generator);
84
85
// Accept "new state" according to the acceptance_probability
86
if
(u <= acceptance_probability) {
87
x_t = x_dash;
88
}
89
90
if
(t >= discard) {
91
samples.push_back(x_t);
92
}
93
}
94
95
return
samples;
96
}
97
112
double
integral_monte_carlo
(
const
double
& start_point,
const
Function& function,
113
const
Function& pdf,
114
const
uint32_t& num_samples = 1000000) {
115
double
integral = 0.0;
116
std::vector<double> samples =
117
generate_samples
(start_point, pdf, num_samples);
118
119
for
(
double
sample : samples) {
120
integral += function(sample) / pdf(sample);
121
}
122
123
return
integral /
static_cast<
double
>
(samples.size());
124
}
125
126
}
// namespace monte_carlo
127
}
// namespace math
128
133
static
void
test
() {
134
std::cout <<
"Disclaimer: Because this is a randomized algorithm,"
135
<< std::endl;
136
std::cout
137
<<
"it may happen that singular samples deviate from the true result."
138
<< std::endl
139
<< std::endl;
140
;
141
142
math::monte_carlo::Function f;
143
math::monte_carlo::Function pdf;
144
double
integral = 0;
145
double
lower_bound = 0, upper_bound = 0;
146
147
/* \int_{-2}^{2} -x^2 + 4 dx */
148
f = [&](
double
& x) {
return
-x * x + 4.0; };
149
150
lower_bound = -2.0;
151
upper_bound = 2.0;
152
pdf = [&](
double
& x) {
153
if
(x >= lower_bound && x <= -1.0) {
154
return
0.1;
155
}
156
if
(x <= upper_bound && x >= 1.0) {
157
return
0.1;
158
}
159
if
(x > -1.0 && x < 1.0) {
160
return
0.4;
161
}
162
return
0.0;
163
};
164
165
integral =
math::monte_carlo::integral_monte_carlo
(
166
(upper_bound - lower_bound) / 2.0, f, pdf);
167
168
std::cout <<
"This number should be close to 10.666666: "
<< integral
169
<< std::endl;
170
171
/* \int_{0}^{1} e^x dx */
172
f = [&](
double
& x) {
return
std::exp(x); };
173
174
lower_bound = 0.0;
175
upper_bound = 1.0;
176
pdf = [&](
double
& x) {
177
if
(x >= lower_bound && x <= 0.2) {
178
return
0.1;
179
}
180
if
(x > 0.2 && x <= 0.4) {
181
return
0.4;
182
}
183
if
(x > 0.4 && x < upper_bound) {
184
return
1.5;
185
}
186
return
0.0;
187
};
188
189
integral =
math::monte_carlo::integral_monte_carlo
(
190
(upper_bound - lower_bound) / 2.0, f, pdf);
191
192
std::cout <<
"This number should be close to 1.7182818: "
<< integral
193
<< std::endl;
194
195
/* \int_{-\infty}^{\infty} sinc(x) dx, sinc(x) = sin(pi * x) / (pi * x)
196
This is a difficult integral because of its infinite domain.
197
Therefore, it may deviate largely from the expected result.
198
*/
199
f = [&](
double
& x) {
return
std::sin(M_PI * x) / (M_PI * x); };
200
201
pdf = [&](
double
& x) {
202
return
1.0 / std::sqrt(2.0 * M_PI) * std::exp(-x * x / 2.0);
203
};
204
205
integral =
math::monte_carlo::integral_monte_carlo
(0.0, f, pdf, 10000000);
206
207
std::cout <<
"This number should be close to 1.0: "
<< integral
208
<< std::endl;
209
}
210
215
int
main
() {
216
test
();
// run self-test implementations
217
return
0;
218
}
test
void test()
Definition
caesar_cipher.cpp:100
main
int main()
Main function.
Definition
generate_parentheses.cpp:110
math::monte_carlo::generate_samples
std::vector< double > generate_samples(const double &start_point, const Function &pdf, const uint32_t &num_samples, const uint32_t &discard=100000)
short-hand for std::functions used in this implementation
Definition
integral_approximation2.cpp:64
math::monte_carlo::integral_monte_carlo
double integral_monte_carlo(const double &start_point, const Function &function, const Function &pdf, const uint32_t &num_samples=1000000)
Compute an approximation of an integral using Monte Carlo integration.
Definition
integral_approximation2.cpp:112
math
for assert
monte_carlo
Functions for the Monte Carlo Integration implementation.
math
integral_approximation2.cpp
Generated by
1.18.0