Monte Carlo Integration Library 1.0
High-performance Monte Carlo methods for numerical integration and optimization
main.cpp
Go to the documentation of this file.
1
16#include <iostream>
17#include <string>
18#include <fstream>
19#include <limits>
20#include <array>
21#include <vector>
22#include <stdexcept>
23#include <cstdint>
24
25#include "apps/benchmarks.hpp"
31
33#define FUNCTION_FILE "../function.txt"
34
36constexpr int dim = 2;
37
38
39// --- FUNCTION PROTOTYPES ---
40std::string readFunctionFromFile(const std::string& filename);
41
42template <int dim>
43std::vector<mc::geom::Point<dim>> read_points_from_file(const std::string& filename);
44
45template <int dim>
47 const std::string& filename,
48 std::vector<std::array<double, dim>>& normals,
49 std::vector<double>& offsets);
50
51
52// --- MAIN ---
53
54int main(int argc, char* argv[]) {
55 // Default seed value
56 std::uint32_t seed = 12345;
57
58 // Check if user provided a seed as argument
59 if (argc > 1) {
60 try {
61 seed = static_cast<std::uint32_t>(std::stoul(argv[1]));
62 std::cout << "Using custom seed: " << seed << std::endl;
63 } catch (const std::exception& e) {
64 std::cerr << "Invalid seed argument. Using default seed: " << seed << std::endl;
65 }
66 } else {
67 std::cout << "Using default seed: " << seed << std::endl;
68 std::cout << "(To use a different seed, run: ./program <seed>)" << std::endl;
69 }
70
71 // Set the global seed for all library components
73 std::cout << std::endl;
74
75 // Closes already open gnuplot windows
77
78 std::cout << "===========================================" << std::endl;
79 std::cout << " Monte Carlo Integration Benchmarks" << std::endl;
80 std::cout << "===========================================" << std::endl;
81
82 enum Proposal {
83 Zero,
84 Parser,
85 UnifHard,
86 MeHaHard,
87 Polytope,
88 PSO,
89 GA
90 };
91
92 // Mode choice
93 std::cout << "Select mode:" << std::endl;
94 std::cout << Parser << ". Use function from file (function.txt) - Uses Parser (Slower)" << std::endl;
95 std::cout << UnifHard << ". Use hardcoded function with Uniform distribution - Uses C++ Lambda (Faster)" << std::endl;
96 std::cout << MeHaHard << ". Use hardcoded function with Metropolis-Hastings distribution - Uses C++ Lambda (Faster)" << std::endl;
97 std::cout << Polytope << ". Do you want to use a polytope con covex hull (IT: Inviluppo Convesso)" << std::endl;
98 std::cout << PSO << ". Run Optimizer Benchmarks (PSO)" << std::endl;
99 std::cout << GA << ". Run Optimizer Benchmarks (GA)" << std::endl;
100 std::cout << "Choice: ";
101
102 int choice;
103 if (!(std::cin >> choice)) {
104 std::cerr << "Invalid input." << std::endl;
105 return 1;
106 }
107 // Clear buffer until next line
108 std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
109
110 bool useGnuplot = false;
111 if (choice >= 1 && choice <= 2) {
112 std::cout << "Enable Gnuplot visualization for results? (y/n): ";
113 char gpChoice;
114 std::cin >> gpChoice;
115 std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
116 useGnuplot = (gpChoice == 'y' || gpChoice == 'Y');
117 }
118
119 if (choice == Parser) {
120 try {
121 std::string expression = readFunctionFromFile(FUNCTION_FILE);
122 std::cout << "\nLoaded expression: " << expression << std::endl;
123 std::cout << "Starting PARSER benchmarks..." << std::endl;
124 runBenchmarks(expression, useGnuplot);
125 } catch (const std::exception& e) {
126 std::cerr << "Error: " << e.what() << std::endl;
127 return 1;
128 }
129 } else if (choice == UnifHard) {
130 std::cout << "\nStarting HARDCODED benchmarks..." << std::endl;
131 // Sends file to gnuPlot
132 runBenchmarks(useGnuplot);
133 }else if (choice == MeHaHard) {
134 std::cout << "\nStarting HARDCODED benchmarks with Metropolis-Hastings distribution..." << std::endl;
135 // Sends file to gnuPlot
137 }else if (choice == Polytope) {
138 std::cout << "\nReading Points, Normals and Offsets..." << std::endl;
139
140 std::vector<mc::geom::Point<dim>> points = read_points_from_file<dim>("../points.txt");
141
142
143 std::vector<std::array<double, dim>> normals;
144 std::vector<double> offsets;
145
146 read_normals_and_offsets_from_qhull_n<dim>("../hull.txt", normals, offsets);
147
148 mc::domains::PolyTope<dim> polytope(points, normals, offsets);
150 /*
151 auto f_const = [](const mc::geom::Point<3>& p) {
152 return 1.0;
153 };
154
155 auto f_linear = [](const mc::geom::Point<3>& p) {
156 return p[0] + p[1] + p[2]; // x + y + z
157 };
158
159 auto f_quad = [](const mc::geom::Point<3>& p) {
160 return p[0]*p[0] + p[1]*p[1] + p[2]*p[2];
161 };
162 std::cout << integrator.integrate(f_const, 1000000) << std::endl;
163 std::cout << "Expected: 1.0" << std::endl;
164 std::cout << integrator.integrate(f_quad, 1000000) << std::endl;
165 std::cout << "Expected: 1.0" << std::endl;
166 std::cout << integrator.integrate(f_linear, 1000000) << std::endl;
167 std::cout << "Expected: 1.5" << std::endl;
168 */
169
170
171 // f(x,y) = 1
172 auto f_const = [](const mc::geom::Point<2>& p) {
173 return 1.0;
174 };
175
176 // f(x,y) = x
177 auto f_x = [](const mc::geom::Point<2>& p) {
178 return p[0];
179 };
180
181 // f(x,y) = y
182 auto f_y = [](const mc::geom::Point<2>& p) {
183 return p[1];
184 };
185
186 double I_const = integrator.OLDintegrate(f_const, 1000000);
187 double I_x = integrator.OLDintegrate(f_x, 1000000);
188 double I_y = integrator.OLDintegrate(f_y, 1000000);
189
190 std::cout << "Integral f=1 ≈ " << I_const << " (exact: " << 3*std::sqrt(3)/2 << ")\n";
191 std::cout << "Integral f=x ≈ " << I_x << " (exact: 0)\n";
192 std::cout << "Integral f=y ≈ " << I_y << " (exact: 0)\n";
193
194 } else if (choice == PSO) {
196 } else if (choice == GA) {
198 }else {
199 std::cerr << "Invalid choice selected." << std::endl;
200 return 1;
201 }
202
203 std::cout << "\nAll benchmarks completed." << std::endl;
204 if (useGnuplot) {
205 std::cout << "Check opened Gnuplot windows. Press Enter in console or close windows to finish fully if needed." << std::endl;
206 }
207
208 return 0;
209}
210
211// --- FUNCTION IMPLEMENTATIONS ---
212
213std::string readFunctionFromFile(const std::string& filename) {
214 std::ifstream file(filename);
215
216 if (!file.is_open()) {
217 throw std::runtime_error("Could not open function file at: " + filename +
218 "\nMake sure the file exists in the repository root.");
219 }
220
221 std::string expression;
222 if (!std::getline(file, expression)) {
223 throw std::runtime_error("File is empty: " + filename);
224 }
225
226 if (!expression.empty() && expression.back() == '\r') {
227 expression.pop_back();
228 }
229
230 file.close();
231
232 if (expression.empty()) {
233 throw std::runtime_error("Expression in file is empty: " + filename);
234 }
235
236 return expression;
237}
238
239template <int dim>
240std::vector<mc::geom::Point<dim>> read_points_from_file(const std::string& filename)
241{
242 std::ifstream in(filename);
243 if (!in.is_open()) {
244 throw std::runtime_error("Cannot open file: " + filename);
245 }
246
247 std::size_t num_points = 0;
248 std::size_t file_dim = 0;
249
250 // Prima riga: <num_points> <dim>
251 in >> num_points >> file_dim;
252
253 if (!in.good()) {
254 throw std::runtime_error("Error reading header from file: " + filename);
255 }
256
257 if (file_dim != static_cast<std::size_t>(dim)) {
258 throw std::runtime_error(
259 "Dimension mismatch: file has dim = " + std::to_string(file_dim) +
260 " but template expects dim = " + std::to_string(dim));
261 }
262
263 std::vector<mc::geom::Point<dim>> points;
264 points.reserve(num_points);
265
266 for (std::size_t i = 0; i < num_points; ++i) {
268 for (int k = 0; k < dim; ++k) {
269 if (!(in >> p[k])) {
270 throw std::runtime_error(
271 "Error reading coordinate " + std::to_string(k) +
272 " of point " + std::to_string(i) +
273 " from file: " + filename);
274 }
275 }
276 points.push_back(p);
277 }
278
279 return points;
280}
281
282template <int dim>
284 const std::string& filename,
285 std::vector<std::array<double, dim>>& normals,
286 std::vector<double>& offsets)
287{
288 std::ifstream in(filename);
289 if (!in.is_open()) {
290 throw std::runtime_error("Cannot open normals file: " + filename);
291 }
292
293 std::size_t file_dim = 0;
294 std::size_t num_facets = 0;
295
296 // Legge dimensione e numero di facce (possono essere sulla stessa riga o su due righe)
297 in >> file_dim >> num_facets;
298 if (!in.good()) {
299 throw std::runtime_error("Error reading header (dim, num_facets) from: " + filename);
300 }
301
302 if (file_dim != dim + 1) {
303 throw std::runtime_error(
304 "Dimension mismatch in normals file: file has dim = " +
305 std::to_string(file_dim) + " but template expects dim = " +
306 std::to_string(dim));
307 }
308
309 normals.clear();
310 offsets.clear();
311 normals.reserve(num_facets);
312 offsets.reserve(num_facets);
313
314 for (std::size_t f = 0; f < num_facets; ++f) {
315 std::array<double, dim> n{};
316 double d = 0.0;
317
318 // Legge i componenti della normale
319 for (std::size_t k = 0; k < dim; ++k) {
320 if (!(in >> n[k])) {
321 throw std::runtime_error(
322 "Error reading normal component " + std::to_string(k) +
323 " for facet " + std::to_string(f) +
324 " from: " + filename);
325 }
326 }
327
328 // Legge l'offset d (nel piano n·x + d = 0)
329 if (!(in >> d)) {
330 throw std::runtime_error(
331 "Error reading offset d for facet " + std::to_string(f) +
332 " from: " + filename);
333 }
334
335 double b = -d;
336
337 normals.push_back(n);
338 offsets.push_back(b);
339 }
340}
Classic Monte Carlo integration engine.
Benchmarking framework for Monte Carlo integration algorithms.
void runBenchmarks(bool useGnuplot)
Run integration benchmarks with hardcoded integrands.
void runOptimizationBenchmarksGA()
void runBenchmarksMH()
Run Metropolis-Hastings MCMC integration benchmarks.
void runOptimizationBenchmarksPSO()
Convex polytope (convex polyhedron) integration domain.
Definition polytope.hpp:34
N-dimensional point representation.
Definition geometry.hpp:32
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).
Core geometric types for Monte Carlo integration.
constexpr int dim
Default dimensionality for integration.
Definition main.cpp:36
std::vector< mc::geom::Point< dim > > read_points_from_file(const std::string &filename)
Definition main.cpp:240
void read_normals_and_offsets_from_qhull_n(const std::string &filename, std::vector< std::array< double, dim > > &normals, std::vector< double > &offsets)
Definition main.cpp:283
#define FUNCTION_FILE
Path to user-defined integrand function.
Definition main.cpp:33
std::string readFunctionFromFile(const std::string &filename)
Definition main.cpp:213
bool set_global_seed(std::uint32_t s)
Set the global seed used by all library RNG components.
void closeGnuplotWindows()
Utility to close all currently open Gnuplot windows.
Definition plotter.hpp:22
N-dimensional polytope (convex polyhedron) domain for Monte Carlo integration.