56template <
size_t dim,
typename Func>
58 const std::string& filename,
63 const std::string& rawDataFile,
64 const std::string& functionExpr)
67 auto printLine = [&](std::size_t n,
68 const std::string& label,
72 std::cout << std::setw(8) << n <<
" | "
73 << std::setw(30) << label <<
" | "
74 << std::setw(20) << std::fixed << std::setprecision(6) << result <<
" | "
75 << std::setw(5) << time_ms <<
" ms\n";
78 std::cout <<
"------------------------------------------------" << std::endl;
79 std::cout << title <<
":" << std::endl;
80 std::cout <<
"Integrating Function: " << functionExpr << std::endl << std::endl;
82 std::vector<results> testResults;
86 std::vector<double> init_mean(
dim, 0.0);
87 std::vector<double> init_sigma(
dim, 2.5);
89 for (
size_t i = 0; i <
dim; ++i) {
90 init_mean[i] = 0.5 * (bounds[i].first + bounds[i].second);
91 init_sigma[i] = (bounds[i].second - bounds[i].first) / 3.0;
97 std::cout << std::string(107,
'-') <<
'\n';
98 std::cout << std::setw(8) <<
"Samples" <<
" | "
99 << std::setw(30) <<
"Method" <<
" | "
100 << std::setw(20) <<
"Result" <<
" | "
101 << std::setw(6) <<
"Time" <<
'\n';
102 std::cout << std::string(107,
'-') <<
'\n';
106 auto startTimer1 = std::chrono::high_resolution_clock::now();
108 auto endTimer1 = std::chrono::high_resolution_clock::now();
109 auto duration1 = std::chrono::duration_cast<std::chrono::milliseconds>(endTimer1 - startTimer1);
112 auto startTimer2 = std::chrono::high_resolution_clock::now();
114 auto endTimer2 = std::chrono::high_resolution_clock::now();
115 auto duration2 = std::chrono::duration_cast<std::chrono::milliseconds>(endTimer2 - startTimer2);
118 auto startTimer3 = std::chrono::high_resolution_clock::now();
120 auto endTimer3 = std::chrono::high_resolution_clock::now();
121 auto duration3 = std::chrono::duration_cast<std::chrono::milliseconds>(endTimer3 - startTimer3);
124 auto startTimer4 = std::chrono::high_resolution_clock::now();
126 auto endTimer4 = std::chrono::high_resolution_clock::now();
127 auto duration4 = std::chrono::duration_cast<std::chrono::milliseconds>(endTimer4 - startTimer4);
133 newLine.
duration = std::to_string(duration1.count());
134 testResults.push_back(newLine);
137 printLine(n_i,
"Normal Sampling", result1, duration1.count());
138 printLine(n_i,
"Uniform Importance Sampling", result2, duration2.count());
139 printLine(n_i,
"Gaussian Importance Sampling", result3, duration3.count());
140 printLine(n_i,
"Mixture Importance Sampling", result4, duration4.count());
141 std::cout << std::string(107,
'-') <<
'\n';
153 std::cout <<
"\nSaved txt file: " << filename <<
"\n";
159template <
typename Func>
160void runCircleBenchmark(Func f,
const std::string& modeLabel,
bool useGnuplot,
const std::string& funcStr) {
163 std::string title =
"2D Circle Integration (Radius 5) [" + modeLabel +
"]";
164 std::string filename =
"resultsCircle_" + modeLabel +
".txt";
165 std::string dataFile =
"hsphere_samples.dat";
167 executeBenchmark(title, filename, integrator, circle, f, useGnuplot, dataFile, funcStr);
170template <
typename Func>
171void runSphereBenchmark(Func f,
const std::string& modeLabel,
bool useGnuplot,
const std::string& funcStr) {
172 double radius = 10.0;
175 std::string title =
"4D Hypersphere Integration [" + modeLabel +
"]";
176 std::string filename =
"resultsSphere4D_" + modeLabel +
".txt";
177 std::string dataFile =
"hsphere_samples.dat";
179 executeBenchmark(title, filename, integrator, sphere, f, useGnuplot, dataFile, funcStr);
182template <
typename Func>
183void runRectBenchmark(Func f,
const std::string& modeLabel,
bool useGnuplot,
const std::string& funcStr) {
184 std::array<double, 4> sides = {10.0, 5.0, 10.0, 5.0};
187 std::string title =
"4D HyperRectangle Integration [" + modeLabel +
"]";
188 std::string filename =
"resultsRectangle4D_" + modeLabel +
".txt";
189 std::string dataFile =
"hrectangle_samples.dat";
191 executeBenchmark(title, filename, integrator, rectangle, f, useGnuplot, dataFile, funcStr);
194template <
typename Func>
197 double height = 10.0;
200 std::string title =
"4D HyperCylinder Integration [" + modeLabel +
"]";
201 std::string filename =
"resultsCylinder4D_" + modeLabel +
".txt";
202 std::string dataFile =
"cylinder_samples.dat";
204 executeBenchmark(title, filename, integrator, cylinder, f, useGnuplot, dataFile, funcStr);
215 std::string funcStr =
"x[0]^2 - x[1]^2";
220 auto f = [](
const mc::geom::Point<4> &x) {
return x[0]*x[0] + x[1]*x[1] + x[2]*x[2] + x[3]*x[3]; };
221 std::string funcStr =
"x[0]^2 + x[1]^2 + x[2]^2 + x[3]^2";
226 auto f = [](
const mc::geom::Point<4> &x) {
return x[0]*x[0] + x[1]*x[1] + x[2]*x[2] + x[3]*x[3]; };
227 std::string funcStr =
"x[0]^2 + x[1]^2 + x[2]^2 + x[3]^2";
232 auto f = [](
const mc::geom::Point<4> &x) {
return x[0]*x[0] + x[1]*x[1] + x[2]*x[2] + x[3]*x[3]; };
233 std::string funcStr =
"x[0]^2 + x[1]^2 + x[2]^2 + x[3]^2";
247 thread_local Parser p = base;
259 thread_local Parser p = base;
271 thread_local Parser p = base;
283 thread_local Parser p = base;
293 n_threads = std::thread::hardware_concurrency();
310 n_threads = std::thread::hardware_concurrency();
313 constexpr double R = 10.0;
318 return domain.
isInside(x) ? 1.0 : 0.0;
321 const double deviation = 0.15;
322 const std::size_t burn_in = 20'000;
323 const std::size_t thinning = 10;
324 const std::size_t n_samples = 1'000'000;
325 const std::size_t n_samples_volume = 200'000;
342 auto run_case = [&](
const std::string& name,
348 const double mh_est = mhintegrator.
integrate(
349 f,
static_cast<int>(n_samples), dummy_proposal, seed);
351 const double mc_est = integrator.
OLDintegrate(f, n_samples);
353 auto print_line = [&](
const std::string& method,
double est) {
354 std::cout <<
" " << method <<
": " << est;
355 if (!std::isnan(exact_or_nan)) {
356 const double abs_err = std::abs(est - exact_or_nan);
357 const double rel_err = abs_err / (std::abs(exact_or_nan) + 1e-30);
358 std::cout <<
" | abs_err=" << abs_err <<
" | rel_err=" << rel_err;
363 std::cout <<
"\n===========================================\n";
364 std::cout <<
"Case: " << name <<
"\n";
365 if (!std::isnan(exact_or_nan))
366 std::cout <<
"Exact: " << exact_or_nan <<
"\n";
368 std::cout <<
"Exact: (no closed form used here)\n";
370 print_line(
"MH", mh_est);
371 print_line(
"MC", mc_est);
374 std::cout <<
"Running Benchmarks (MC vs MH) on disk R=" << R <<
"\n";
375 std::cout <<
"Config: n_samples=" << n_samples
376 <<
" burn_in=" << burn_in
377 <<
" thinning=" << thinning
378 <<
" deviation=" << deviation
379 <<
" n_samples_volume=" << n_samples_volume
388 return x[0]*x[0] + x[1]*x[1];
390 const double exactA = 0.5 * M_PI * std::pow(R, 4);
391 run_case(
"A) f=r^2 (sanity check)", fA, exactA);
400 const double exactB = M_PI * R * R;
401 run_case(
"B) f=1 (volume)", fB, exactB);
409 const double alpha = 1.0;
411 const double r2 = x[0]*x[0] + x[1]*x[1];
412 return std::exp(-alpha * r2);
414 const double exactC = (M_PI/alpha) * (1.0 - std::exp(-alpha * R * R));
415 run_case(
"C) f=exp(-alpha r^2), alpha=1", fC, exactC);
423 const double r0 = 8.0;
424 const double beta = 50.0;
426 const double r = std::sqrt(x[0]*x[0] + x[1]*x[1]);
427 const double d = r - r0;
428 return std::exp(-beta * d * d);
430 run_case(
"D) f=exp(-beta (r-r0)^2) (thin ring)", fD,
431 std::numeric_limits<double>::quiet_NaN());
439 const double eps = 1e-3;
441 const double r = std::sqrt(x[0]*x[0] + x[1]*x[1]);
442 return 1.0 / std::sqrt((R - r) + eps);
444 run_case(
"E) f=1/sqrt((R-r)+eps) (boundary layer)", fE,
445 std::numeric_limits<double>::quiet_NaN());
450 n_threads = std::thread::hardware_concurrency();
Importance sampling Monte Carlo integration engine.
void saveResults(const std::string &filename, const std::vector< results > &results, const std::string &function_expr)
Export benchmark results to CSV file for analysis.
const std::vector< size_t > n_samples_vector
Global sample count vector used across all benchmarks for convergence testing.
unsigned int n_threads
Global OpenMP thread count (set at runtime)
Benchmarking framework for Monte Carlo integration algorithms.
void cylinderIntegration()
3D cylindrical integration: hypercylinder base with height
void sphereIntegration()
3D spherical integration: f(x,y,z) = x²+y²+z² over unit ball
void rectangularIntegration()
2D rectangular integration over axis-aligned box
void circleIntegration()
2D circular integration: f(x,y) = x²+y² over unit disk
N-dimensional hypercylinder.
Axis-aligned hyperrectangular domain.
N-dimensional ball (solid sphere).
bool isInside(const mc::geom::Point< dim > &point) const override
Test if a point is inside the hypersphere.
Abstract base class for N-dimensional integration domains.
virtual mc::geom::Bounds< dim > getBounds() const =0
Get the axis-aligned bounding box of the domain.
N-dimensional point representation.
Importance sampling Monte Carlo integrator.
double integrate(const std::function< double(const mc::geom::Point< dim > &)> &f, int n_samples, const mc::proposals::Proposal< dim > &proposal, std::uint32_t seed) override
Compute the integral using importance sampling.
Metropolis-Hastings MCMC integrator for complex domains.
void setConfig(std::size_t burn_in_, std::size_t thinning_, std::size_t n_samples_volume_, double deviation_, Func p_, Point x0_)
Configure the MCMC sampler parameters.
double integrate(const Func &f, int n_samples, const mc::proposals::Proposal< dim > &proposal, std::uint32_t seed) override
Compute the integral using MH sampling combined with volume estimation.
Uniform-sampling Monte Carlo integrator for N-dimensional domains.
double OLDintegrate(const std::function< double(const mc::geom::Point< dim > &)> &f, int n_samples)
Legacy integration routine (deprecated).
void cylinderIntegrationParser(const std::string &expr, bool useGnuplot)
void runBenchmarks(bool useGnuplot)
Run integration benchmarks with hardcoded integrands.
void runRectBenchmark(Func f, const std::string &modeLabel, bool useGnuplot, const std::string &funcStr)
void runSphereBenchmark(Func f, const std::string &modeLabel, bool useGnuplot, const std::string &funcStr)
void rectangularIntegrationParser(const std::string &expr, bool useGnuplot)
void executeBenchmark(const std::string &title, const std::string &filename, mc::integrators::MontecarloIntegrator< dim > &integrator, const mc::domains::IntegrationDomain< dim > &domain, Func &&f, bool useGnuplot, const std::string &rawDataFile, const std::string &functionExpr)
Generic execution loop for integration benchmarks.
void runCylinderBenchmark(Func f, const std::string &modeLabel, bool useGnuplot, const std::string &funcStr)
void runBenchmarksMH()
Run Metropolis-Hastings MCMC integration benchmarks.
void sphereIntegrationParser(const std::string &expr, bool useGnuplot)
void runCircleBenchmark(Func f, const std::string &modeLabel, bool useGnuplot, const std::string &funcStr)
void circleIntegrationParser(const std::string &expr, bool useGnuplot)
constexpr int dim
Default dimensionality for integration.
std::uint32_t get_global_seed()
Get the current global seed.
void createFunctionGnuplotScript(const std::string &tempRawDataFile, const mc::domains::IntegrationDomain< dim > &domain, const Func &func, size_t currentSamples)
void createGnuplotScript(const std::string &tempRawDataFile, const mc::domains::IntegrationDomain< dim > &domain, size_t currentSamples)
Stores benchmark result for a single sample count.
std::string integration_result