38 const std::vector<double> &lower_bounds,
39 const std::vector<double> &upper_bounds)
const {
40 if (lower_bounds.size() != upper_bounds.size()) {
41 throw std::invalid_argument(
42 "Lower and upper bounds must have the same dimension.");
45 std::vector<double> point;
46 for (
size_t i = 0; i < lower_bounds.size(); ++i) {
48 lower_bounds[i] +
static_cast<double>(rand()) / RAND_MAX *
49 (upper_bounds[i] - lower_bounds[i]);
50 point.push_back(random_value);
58 std::vector<double> sequence;
61 double fibonacci_prev = 0.0;
62 double fibonacci_curr = 1.0;
63 for (
size_t i = 0; i < length; ++i) {
64 sequence.push_back(fibonacci_prev);
65 double fibonacci_next = fibonacci_curr + fibonacci_prev;
66 fibonacci_prev = fibonacci_curr;
67 fibonacci_curr = fibonacci_next;
75 const std::vector<double> &b)
const {
76 if (a.size() != b.size()) {
77 throw std::invalid_argument(
78 "Vector dimensions do not match for addition.");
81 std::vector<double> result;
82 for (
size_t i = 0; i < a.size(); ++i) {
83 result.push_back(a[i] + b[i]);
91 const std::vector<double> &b)
const {
92 if (a.size() != b.size()) {
93 throw std::invalid_argument(
94 "Vector dimensions do not match for subtraction.");
97 std::vector<double> result;
98 for (
size_t i = 0; i < a.size(); ++i) {
99 result.push_back(a[i] - b[i]);
107 const std::vector<double> &vec)
const {
108 std::vector<double> result;
109 for (
double value : vec) {
110 result.push_back(scalar * value);
118 double fraction)
const {
119 return a + fraction * (b - a);
123 const std::function<
double(
double)> &func,
127 if (!is_valid_interval(a, b)) {
128 throw std::invalid_argument(
129 "Invalid interval: lower bound must be less than upper bound.");
132 const double inv_phi = (std::sqrt(5.0) - 1.0) / 2.0;
133 double x1 = b - inv_phi * (b - a);
134 double x2 = a + inv_phi * (b - a);
136 return golden_section_search_minimize(func, a, b, tol, x1, x2);
144 return y0 + (y1 - y0) / (x1 - x0) * (x - x0);
155 double t = (x - x0) / h;
159 double a = 2 * t3 - 3 * t2 + 1;
160 double b = t3 - 2 * t2 + t;
162 double d = -2 * t3 + 3 * t2;
164 return a * y0 + b * (h * y0_prime) + c * (h * y1_prime) + d * y1;
168 const std::function<
double(
double)> &func,
174 double f1 = func(x1);
175 double f2 = func(x2);
177 while ((b - a) > tol) {
193 return (f1 < f2) ? x1 : x2;
201 const std::function<
double(
const std::vector<double> &)> &func,
202 const std::vector<double> &lower_bounds,
203 const std::vector<double> &upper_bounds,
205 if (lower_bounds.size() != upper_bounds.size()) {
206 throw std::invalid_argument(
207 "Lower and upper bounds must have the same dimension.");
211 std::vector<double> x1(lower_bounds.size());
212 std::vector<double> x2(lower_bounds.size());
214 for (
size_t i = 0; i < lower_bounds.size(); ++i) {
215 if (!is_valid_interval(lower_bounds[i], upper_bounds[i])) {
216 throw std::invalid_argument(
"Invalid interval for dimension " +
220 const double inv_phi = (std::sqrt(5.0) - 1.0) / 2.0;
221 x1[i] = upper_bounds[i] - inv_phi * (upper_bounds[i] - lower_bounds[i]);
222 x2[i] = lower_bounds[i] + inv_phi * (upper_bounds[i] - lower_bounds[i]);
225 return golden_section_search_minimize_multivariate(func,
234 const std::function<
double(
const std::vector<double> &)> &func,
235 const std::vector<double> &lower_bounds,
236 const std::vector<double> &upper_bounds,
237 size_t max_iterations) {
238 if (lower_bounds.size() != upper_bounds.size()) {
239 throw std::invalid_argument(
240 "Lower and upper bounds must have the same dimension.");
243 size_t dimension = lower_bounds.size();
244 std::vector<double> best_point(dimension);
245 double best_value = std::numeric_limits<double>::infinity();
247 for (
size_t iteration = 0; iteration < max_iterations; ++iteration) {
248 std::vector<double> random_point =
249 generate_random_point(lower_bounds, upper_bounds);
250 double value = func(random_point);
252 if (value < best_value) {
254 best_point = random_point;
265 const std::vector<double> &y) {
268 if (n != y.size() || n < 2) {
269 throw std::invalid_argument(
270 "Invalid input dimensions for linear curve fitting.");
273 double sum_x = 0.0, sum_y = 0.0, sum_xy = 0.0, sum_x_squared = 0.0;
275 for (
size_t i = 0; i < n; ++i) {
278 sum_xy += x[i] * y[i];
279 sum_x_squared += x[i] * x[i];
283 (n * sum_xy - sum_x * sum_y) / (n * sum_x_squared - sum_x * sum_x);
284 double b = (sum_y - a * sum_x) / n;
290 const std::function<
double(
const std::vector<double> &)> &func,
291 const std::vector<double> &lower_bounds,
292 const std::vector<double> &upper_bounds,
293 size_t max_iterations) {
295 if (lower_bounds.size() != upper_bounds.size()) {
296 throw std::invalid_argument(
297 "Lower and upper bounds must have the same dimension.");
300 size_t dimension = lower_bounds.size();
301 std::vector<double> fib_sequence = generate_fibonacci_sequence(
305 std::vector<double> a = lower_bounds;
306 std::vector<double> b = upper_bounds;
308 for (
size_t k = 0; k < max_iterations; ++k) {
309 double lambda = (fib_sequence[max_iterations - k + 1] /
310 fib_sequence[max_iterations - k +
313 std::vector<double> x1(dimension);
314 std::vector<double> x2(dimension);
316 for (
size_t i = 0; i < dimension; ++i) {
317 x1[i] = a[i] + lambda * (b[i] - a[i]);
318 x2[i] = b[i] + lambda * (a[i] - b[i]);
321 if (func(x1) < func(x2)) {
332 const std::function<
double(
const std::vector<double> &)> &func,
333 const std::vector<double> &lower_bounds,
334 const std::vector<double> &upper_bounds,
335 size_t max_iterations)
const {
336 double a = lower_bounds[0];
337 double b = upper_bounds[0];
339 if (lower_bounds >= upper_bounds) {
340 throw std::invalid_argument(
"Invalid bounds for ternary search method");
343 for (
size_t iteration = 0; iteration < max_iterations; ++iteration) {
344 double m1 = calculate_midpoint(a, b, 1.0 / 3.0);
345 double m2 = calculate_midpoint(a, b, 2.0 / 3.0);
347 double f_m1 = func({m1});
348 double f_m2 = func({m2});
357 return calculate_midpoint(a, b, 0.5);
363 const std::function<
double(
const std::vector<double> &)> &func,
366 size_t max_iterations) {
367 if (lower_bound >= upper_bound) {
368 throw std::invalid_argument(
"Invalid bounds for bisection method.");
371 double a = lower_bound;
372 double b = upper_bound;
374 for (
size_t iteration = 0; iteration < max_iterations; ++iteration) {
375 double midpoint = (a + b) / 2.0;
378 if (fabs(func({midpoint}) - 0.0f) <
379 std::numeric_limits<double>::epsilon()) {
381 }
else if (func({midpoint}) * func({a}) < 0) {
388 return {(a + b) / 2.0};
394 const std::function<
double(
const std::vector<double> &)> &func,
395 const std::function<
double(
const std::vector<double> &)> &derivative,
396 double initial_guess,
397 size_t max_iterations) {
398 double x = initial_guess;
400 for (
size_t iteration = 0; iteration < max_iterations; ++iteration) {
401 double fx = func({x});
402 double dfx = derivative({x});
404 if ((fabs(dfx) - 0.0f) < std::numeric_limits<double>::epsilon()) {
405 throw std::runtime_error(
"Newton's method: Derivative is zero.");
415 const std::function<
double(
const std::vector<double> &)> &func,
418 size_t max_iterations) {
419 if (func({lower_bound}) * func({upper_bound}) >= 0.0) {
420 throw std::invalid_argument(
"Invalid bounds for regula falsi method.");
423 double a = lower_bound;
424 double b = upper_bound;
426 for (
size_t iteration = 0; iteration < max_iterations; ++iteration) {
427 double fa = func({a});
428 double fb = func({b});
430 if (fa * fb >= 0.0) {
431 throw std::runtime_error(
"Regula falsi method: Function values at "
432 "the bounds have the same sign.");
435 double c = (a * fb - b * fa) / (fb - fa);
437 if (fabs(func({c}) - 0.0f) < std::numeric_limits<double>::epsilon()) {
439 }
else if (fa * func({c}) < 0.0) {
446 return {(a + b) / 2.0};
450 const std::vector<double> &y) {
453 if (n != y.size() || n < 4) {
454 throw std::invalid_argument(
455 "Invalid input dimensions for cubic curve fitting.");
458 double sum_x = 0.0, sum_y = 0.0, sum_x_squared = 0.0, sum_x_cubed = 0.0,
459 sum_xy = 0.0, sum_x_squared_y = 0.0, sum_squared = 0.0;
461 for (
size_t i = 0; i < n; ++i) {
462 double xi_squared = x[i] * x[i];
463 double xi_cubed = xi_squared * x[i];
467 sum_x_squared += xi_squared;
468 sum_x_cubed += xi_cubed;
469 sum_xy += x[i] * y[i];
470 sum_x_squared_y += xi_squared * y[i];
473 double determinant = n * sum_x_squared * sum_x_squared * sum_x_squared -
474 sum_x_squared * sum_x_squared * sum_x * sum_x_squared -
475 sum_x * sum_x * sum_x_squared * sum_x_squared +
476 sum_x_squared * sum_x * sum_x * sum_x_squared +
477 sum_x * sum_x * sum_x * sum_x_squared -
478 n * sum_x * sum_x * sum_x * sum_x;
480 double a = (n * sum_x_squared * sum_x_squared_y -
481 sum_x_squared * sum_x * sum_xy * sum_x_squared -
482 sum_x * sum_x_squared_y * sum_x_squared +
483 sum_x_squared * sum_x * sum_x * sum_xy +
484 sum_x * sum_x * sum_x_squared * sum_x * sum_y -
485 n * sum_x * sum_x * sum_x * sum_xy) /
488 double b = (n * sum_x_squared * sum_x_squared * sum_xy -
489 sum_x_squared_y * sum_x_squared * sum_x_squared +
490 sum_x * sum_x * sum_x_squared_y * sum_x_squared -
491 sum_x_squared * sum_x * sum_x * sum_x * sum_xy -
492 sum_x_squared * sum_x_squared * sum_x * sum_y +
493 n * sum_x * sum_x * sum_x * sum_x * sum_xy) /
497 (n * sum_x_squared * sum_x_squared * sum_x * sum_xy -
498 sum_x_squared * sum_x_squared_y * sum_x_squared * sum_x +
499 sum_x * sum_x * sum_x_squared_y * sum_x_squared * sum_x_squared -
500 sum_x_squared * sum_x * sum_x * sum_x * sum_x_squared -
501 sum_x * sum_x_squared * sum_x_squared * sum_x * sum_y +
502 n * sum_x * sum_x * sum_x * sum_squared * sum_x * sum_y) /
506 (n * sum_x_squared * sum_x_squared * sum_x * sum_x * sum_xy -
507 sum_x_squared * sum_x_squared_y * sum_x_squared * sum_x_squared *
509 sum_x_squared * sum_x * sum_x_squared_y * sum_x_squared *
511 sum_x_squared * sum_x * sum_x * sum_x * sum_x_squared -
512 sum_x * sum_x_squared * sum_x_squared * sum_x * sum_x_squared +
513 n * sum_x * sum_x * sum_x * sum_squared * sum_x * sum_x_squared) /
520 const std::function<
double(
const std::vector<double> &)> &func,
521 std::vector<double> initial_point,
523 size_t max_iterations) {
524 size_t n = initial_point.size();
525 std::vector<std::vector<double>> simplex(n + 1, initial_point);
527 for (
size_t i = 0; i < n; ++i) {
528 simplex[i][i] += 1.0;
531 std::vector<double> values(n + 1);
532 for (
size_t i = 0; i <= n; ++i) {
533 values[i] = func(simplex[i]);
536 for (
size_t iteration = 0; iteration < max_iterations; ++iteration) {
537 size_t highest_index =
538 std::distance(values.begin(),
539 std::max_element(values.begin(), values.end()));
540 size_t lowest_index =
541 std::distance(values.begin(),
542 std::min_element(values.begin(), values.end()));
544 std::vector<double> centroid =
545 calculate_centroid(simplex, highest_index);
548 std::vector<double> reflected_point =
549 reflect(simplex[highest_index], centroid, 1.0);
550 double reflected_value = func(reflected_point);
552 if (reflected_value < values[lowest_index]) {
554 std::vector<double> expanded_point =
555 reflect(simplex[highest_index], centroid, 2.0);
556 double expanded_value = func(expanded_point);
558 if (expanded_value < reflected_value) {
559 simplex[highest_index] = expanded_point;
560 values[highest_index] = expanded_value;
562 simplex[highest_index] = reflected_point;
563 values[highest_index] = reflected_value;
565 }
else if (reflected_value >= values[lowest_index] &&
566 reflected_value < values[highest_index]) {
567 simplex[highest_index] = reflected_point;
568 values[highest_index] = reflected_value;
571 std::vector<double> contracted_point =
572 reflect(simplex[highest_index], centroid, 0.5);
573 double contracted_value = func(contracted_point);
575 if (contracted_value < values[highest_index]) {
576 simplex[highest_index] = contracted_point;
577 values[highest_index] = contracted_value;
580 for (
size_t i = 0; i <= n; ++i) {
581 if (i != lowest_index) {
582 for (
size_t j = 0; j < n; ++j) {
583 simplex[i][j] = 0.5 * (simplex[i][j] +
584 simplex[lowest_index][j]);
586 values[i] = func(simplex[i]);
593 double range = calculate_range(values);
594 if (range < tolerance) {
595 return simplex[lowest_index];
599 return simplex[std::distance(
601 std::min_element(values.begin(), values.end()))];
607 const std::vector<std::vector<double>> &simplex,
608 size_t exclude_index) {
609 size_t n = simplex[0].size();
610 std::vector<double> centroid(n, 0.0);
612 for (
size_t i = 0; i < simplex.size(); ++i) {
613 if (i != exclude_index) {
614 for (
size_t j = 0; j < n; ++j) {
615 centroid[j] += simplex[i][j];
620 for (
size_t j = 0; j < n; ++j) {
621 centroid[j] /= (simplex.size() - 1);
629 const std::vector<double> ¢roid,
630 double reflection_coefficient) {
631 size_t n = point.size();
632 std::vector<double> reflected_point(n);
634 for (
size_t i = 0; i < n; ++i) {
636 centroid[i] + reflection_coefficient * (centroid[i] - point[i]);
639 return reflected_point;
643 double max_value = *std::max_element(values.begin(), values.end());
644 double min_value = *std::min_element(values.begin(), values.end());
646 return max_value - min_value;
651 const std::function<
double(
const std::vector<double> &)> &func,
652 const std::vector<double> &lower_bounds,
653 const std::vector<double> &upper_bounds,
655 const std::vector<double> &x1,
656 const std::vector<double> &x2) {
658 std::vector<double> best_point;
659 double best_value = std::numeric_limits<double>::infinity();
662 for (
size_t i = 0; i < lower_bounds.size(); ++i) {
663 double a = lower_bounds[i];
664 double b = upper_bounds[i];
668 double result = golden_section_search_minimize(
670 std::vector<double> point(x1);
671 point[i] = calculate_midpoint(x1_i, x2_i, t);
680 if (result < best_value) {
683 best_point[i] = calculate_midpoint(x1_i, x2_i, result);
double cubic_interpolation(double x, double x0, double x1, double y0, double y1, double y0_prime, double y1_prime)
Interpolates a univariate function using cubic interpolation.
double fibonacci_search(const std::function< double(const std::vector< double > &)> &func, const std::vector< double > &lower_bounds, const std::vector< double > &upper_bounds, size_t max_iterations)
Performs Fibonacci search for function optimization.
std::vector< double > regula_falsi(const std::function< double(const std::vector< double > &)> &func, double lower_bound, double upper_bound, size_t max_iterations)
Performs Regula Falsi (False Position) method for function optimization.
std::vector< double > generate_random_point(const std::vector< double > &lower_bounds, const std::vector< double > &upper_bounds) const
Generates a random point within specified bounds.
double random_search(const std::function< double(const std::vector< double > &)> &func, const std::vector< double > &lower_bounds, const std::vector< double > &upper_bounds, size_t max_iterations)
Performs random search for function optimization.
std::vector< double > bisection_method(const std::function< double(const std::vector< double > &)> &func, double lower_bound, double upper_bound, size_t max_iterations)
Performs the bisection method for function optimization.
std::vector< double > vector_subtraction(const std::vector< double > &a, const std::vector< double > &b) const
Performs vector subtraction.
std::vector< double > fit_linear(const std::vector< double > &x, const std::vector< double > &y)
Fits a linear function to given data points.
std::vector< double > reflect(const std::vector< double > &point, const std::vector< double > ¢roid, double reflection_coefficient)
Reflects a point with respect to a centroid.
double ternary_search(const std::function< double(const std::vector< double > &)> &func, const std::vector< double > &lower_bounds, const std::vector< double > &upper_bounds, size_t max_iterations) const
Performs ternary search for function optimization.
std::vector< double > cubic_fit(const std::vector< double > &x, const std::vector< double > &y)
Fits a cubic function to given data points.
std::vector< double > golden_section_search_minimize_multivariate(const std::function< double(const std::vector< double > &)> &func, const std::vector< double > &lower_bounds, const std::vector< double > &upper_bounds, double tol, const std::vector< double > &x1, const std::vector< double > &x2)
Finds the minimum of a multivariate function using Golden-section search (Internal helper function)
std::vector< double > newton_method(const std::function< double(const std::vector< double > &)> &func, const std::function< double(const std::vector< double > &)> &derivative, double initial_guess, size_t max_iterations)
Performs Newton's method for function optimization.
double calculate_midpoint(double a, double b, double fraction) const
Calculates the midpoint between two values.
std::vector< double > nelder_mead(const std::function< double(const std::vector< double > &)> &func, std::vector< double > initial_point, double tolerance, size_t max_iterations)
Finds the minimum of a multivariate function using the Nelder–Mead method.
double calculate_range(const std::vector< double > &values)
Calculates the range of values.
bool is_valid_interval(double a, double b)
Checks if a given interval is valid (lower bound < upper bound)
double golden_section_search(const std::function< double(double)> &func, double a, double b, double tol)
Finds the minimum of a univariate function using Golden-section search.
double linear_interpolation(double x, double x0, double x1, double y0, double y1)
Interpolates a univariate function using linear interpolation.
std::vector< double > vector_scalar_multiply(double scalar, const std::vector< double > &vec) const
Performs vector scalar multiplication.
std::vector< double > calculate_centroid(const std::vector< std::vector< double >> &simplex, size_t exclude_index)
Calculates the centroid of a simplex excluding a specific point.
double golden_section_search_minimize(const std::function< double(double)> &func, double a, double b, double tol, double x1, double x2)
Finds the minimum of a univariate function using Golden-section search (Internal helper function)
std::vector< double > vector_addition(const std::vector< double > &a, const std::vector< double > &b) const
Performs vector addition.
std::vector< double > generate_fibonacci_sequence(size_t length) const
Generates a Fibonacci sequence up to a specified length.
std::vector< double > golden_section_search_multivariate(const std::function< double(const std::vector< double > &)> &func, const std::vector< double > &lower_bounds, const std::vector< double > &upper_bounds, double tol)
Finds the minimum of a multivariate function using Golden-section search.