openGPMP
Open Source Mathematics Package
function.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  *
3  * Project
4  * _____ _____ __ __ _____
5  * / ____| __ \| \/ | __ \
6  * ___ _ __ ___ _ __ | | __| |__) | \ / | |__) |
7  * / _ \| '_ \ / _ \ '_ \| | |_ | ___/| |\/| | ___/
8  *| (_) | |_) | __/ | | | |__| | | | | | | |
9  * \___/| .__/ \___|_| |_|\_____|_| |_| |_|_|
10  * | |
11  * |_|
12  *
13  * Copyright (C) Akiel Aries, <akiel@akiel.org>, et al.
14  *
15  * This software is licensed as described in the file LICENSE, which
16  * you should have received as part of this distribution. The terms
17  * among other details are referenced in the official documentation
18  * seen here : https://akielaries.github.io/openGPMP/ along with
19  * important files seen in this project.
20  *
21  * You may opt to use, copy, modify, merge, publish, distribute
22  * and/or sell copies of the Software, and permit persons to whom
23  * the Software is furnished to do so, under the terms of the
24  * LICENSE file. As this is an Open Source effort, all implementations
25  * must be of the same methodology.
26  *
27  *
28  *
29  * This software is distributed on an AS IS basis, WITHOUT
30  * WARRANTY OF ANY KIND, either express or implied.
31  *
32  ************************************************************************/
33 #include <iostream>
35 #include <vector>
36 
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.");
43  }
44 
45  std::vector<double> point;
46  for (size_t i = 0; i < lower_bounds.size(); ++i) {
47  double random_value =
48  lower_bounds[i] + static_cast<double>(rand()) / RAND_MAX *
49  (upper_bounds[i] - lower_bounds[i]);
50  point.push_back(random_value);
51  }
52 
53  return point;
54 }
55 
56 std::vector<double>
58  std::vector<double> sequence;
59 
60  // double golden_ratio = (1.0 + std::sqrt(5.0)) / 2.0;
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;
68  }
69 
70  return sequence;
71 }
72 
73 std::vector<double>
74 gpmp::optim::Func::vector_addition(const std::vector<double> &a,
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.");
79  }
80 
81  std::vector<double> result;
82  for (size_t i = 0; i < a.size(); ++i) {
83  result.push_back(a[i] + b[i]);
84  }
85 
86  return result;
87 }
88 
89 std::vector<double>
90 gpmp::optim::Func::vector_subtraction(const std::vector<double> &a,
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.");
95  }
96 
97  std::vector<double> result;
98  for (size_t i = 0; i < a.size(); ++i) {
99  result.push_back(a[i] - b[i]);
100  }
101 
102  return result;
103 }
104 
106  double scalar,
107  const std::vector<double> &vec) const {
108  std::vector<double> result;
109  for (double value : vec) {
110  result.push_back(scalar * value);
111  }
112 
113  return result;
114 }
115 
117  double b,
118  double fraction) const {
119  return a + fraction * (b - a);
120 }
121 
123  const std::function<double(double)> &func,
124  double a,
125  double b,
126  double tol) {
127  if (!is_valid_interval(a, b)) {
128  throw std::invalid_argument(
129  "Invalid interval: lower bound must be less than upper bound.");
130  }
131 
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);
135 
136  return golden_section_search_minimize(func, a, b, tol, x1, x2);
137 }
138 
140  double x0,
141  double x1,
142  double y0,
143  double y1) {
144  return y0 + (y1 - y0) / (x1 - x0) * (x - x0);
145 }
146 
148  double x0,
149  double x1,
150  double y0,
151  double y1,
152  double y0_prime,
153  double y1_prime) {
154  double h = x1 - x0;
155  double t = (x - x0) / h;
156  double t2 = t * t;
157  double t3 = t2 * t;
158 
159  double a = 2 * t3 - 3 * t2 + 1;
160  double b = t3 - 2 * t2 + t;
161  double c = t3 - t2;
162  double d = -2 * t3 + 3 * t2;
163 
164  return a * y0 + b * (h * y0_prime) + c * (h * y1_prime) + d * y1;
165 }
166 
168  const std::function<double(double)> &func,
169  double a,
170  double b,
171  double tol,
172  double x1,
173  double x2) {
174  double f1 = func(x1);
175  double f2 = func(x2);
176 
177  while ((b - a) > tol) {
178  if (f1 < f2) {
179  b = x2;
180  x2 = x1;
181  x1 = a + b - x2;
182  f2 = f1;
183  f1 = func(x1);
184  } else {
185  a = x1;
186  x1 = x2;
187  x2 = a + b - x1;
188  f1 = f2;
189  f2 = func(x2);
190  }
191  }
192 
193  return (f1 < f2) ? x1 : x2;
194 }
195 
196 // Helper methods for multivariate golden section search
197 // (Implementation of these methods requires more details about the multivariate
198 // function)
199 
201  const std::function<double(const std::vector<double> &)> &func,
202  const std::vector<double> &lower_bounds,
203  const std::vector<double> &upper_bounds,
204  double tol) {
205  if (lower_bounds.size() != upper_bounds.size()) {
206  throw std::invalid_argument(
207  "Lower and upper bounds must have the same dimension.");
208  }
209 
210  // Initialize x1 and x2 based on the golden section ratio for each dimension
211  std::vector<double> x1(lower_bounds.size());
212  std::vector<double> x2(lower_bounds.size());
213 
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 " +
217  std::to_string(i));
218  }
219 
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]);
223  }
224 
225  return golden_section_search_minimize_multivariate(func,
226  lower_bounds,
227  upper_bounds,
228  tol,
229  x1,
230  x2);
231 }
232 
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.");
241  }
242 
243  size_t dimension = lower_bounds.size();
244  std::vector<double> best_point(dimension);
245  double best_value = std::numeric_limits<double>::infinity();
246 
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);
251 
252  if (value < best_value) {
253  best_value = value;
254  best_point = random_point;
255  }
256  }
257 
258  return best_value;
259 }
260 
261 // Curve-fitting methods
262 
263 std::vector<double>
264 gpmp::optim::Func::fit_linear(const std::vector<double> &x,
265  const std::vector<double> &y) {
266  size_t n = x.size();
267 
268  if (n != y.size() || n < 2) {
269  throw std::invalid_argument(
270  "Invalid input dimensions for linear curve fitting.");
271  }
272 
273  double sum_x = 0.0, sum_y = 0.0, sum_xy = 0.0, sum_x_squared = 0.0;
274 
275  for (size_t i = 0; i < n; ++i) {
276  sum_x += x[i];
277  sum_y += y[i];
278  sum_xy += x[i] * y[i];
279  sum_x_squared += x[i] * x[i];
280  }
281 
282  double a =
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;
285 
286  return {a, b};
287 }
288 
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) {
294 
295  if (lower_bounds.size() != upper_bounds.size()) {
296  throw std::invalid_argument(
297  "Lower and upper bounds must have the same dimension.");
298  }
299 
300  size_t dimension = lower_bounds.size();
301  std::vector<double> fib_sequence = generate_fibonacci_sequence(
302  max_iterations + 2); // Adjusted for proper Fibonacci generation
303 
304  // Print Fibonacci sequence for debugging
305  std::vector<double> a = lower_bounds;
306  std::vector<double> b = upper_bounds;
307 
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 +
311  2]); // Corrected lambda calculation
312 
313  std::vector<double> x1(dimension);
314  std::vector<double> x2(dimension);
315 
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]);
319  }
320 
321  if (func(x1) < func(x2)) {
322  b = x2;
323  } else {
324  a = x1;
325  }
326  }
327 
328  return func(a);
329 }
330 
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];
338 
339  if (lower_bounds >= upper_bounds) {
340  throw std::invalid_argument("Invalid bounds for ternary search method");
341  }
342 
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);
346 
347  double f_m1 = func({m1});
348  double f_m2 = func({m2});
349 
350  if (f_m1 < f_m2) {
351  b = m2;
352  } else {
353  a = m1;
354  }
355  }
356 
357  return calculate_midpoint(a, b, 0.5);
358 }
359 
360 // First-order methods
361 
363  const std::function<double(const std::vector<double> &)> &func,
364  double lower_bound,
365  double upper_bound,
366  size_t max_iterations) {
367  if (lower_bound >= upper_bound) {
368  throw std::invalid_argument("Invalid bounds for bisection method.");
369  }
370 
371  double a = lower_bound;
372  double b = upper_bound;
373 
374  for (size_t iteration = 0; iteration < max_iterations; ++iteration) {
375  double midpoint = (a + b) / 2.0;
376 
377  // if (func({midpoint}) == 0.0) {
378  if (fabs(func({midpoint}) - 0.0f) <
379  std::numeric_limits<double>::epsilon()) {
380  return {midpoint};
381  } else if (func({midpoint}) * func({a}) < 0) {
382  b = midpoint;
383  } else {
384  a = midpoint;
385  }
386  }
387 
388  return {(a + b) / 2.0};
389 }
390 
391 // Curve-fitting methods
392 
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;
399 
400  for (size_t iteration = 0; iteration < max_iterations; ++iteration) {
401  double fx = func({x});
402  double dfx = derivative({x});
403 
404  if ((fabs(dfx) - 0.0f) < std::numeric_limits<double>::epsilon()) {
405  throw std::runtime_error("Newton's method: Derivative is zero.");
406  }
407 
408  x = x - fx / dfx;
409  }
410 
411  return {x};
412 }
413 
415  const std::function<double(const std::vector<double> &)> &func,
416  double lower_bound,
417  double upper_bound,
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.");
421  }
422 
423  double a = lower_bound;
424  double b = upper_bound;
425 
426  for (size_t iteration = 0; iteration < max_iterations; ++iteration) {
427  double fa = func({a});
428  double fb = func({b});
429 
430  if (fa * fb >= 0.0) {
431  throw std::runtime_error("Regula falsi method: Function values at "
432  "the bounds have the same sign.");
433  }
434 
435  double c = (a * fb - b * fa) / (fb - fa);
436 
437  if (fabs(func({c}) - 0.0f) < std::numeric_limits<double>::epsilon()) {
438  return {c};
439  } else if (fa * func({c}) < 0.0) {
440  b = c;
441  } else {
442  a = c;
443  }
444  }
445 
446  return {(a + b) / 2.0};
447 }
448 
449 std::vector<double> gpmp::optim::Func::cubic_fit(const std::vector<double> &x,
450  const std::vector<double> &y) {
451  size_t n = x.size();
452 
453  if (n != y.size() || n < 4) {
454  throw std::invalid_argument(
455  "Invalid input dimensions for cubic curve fitting.");
456  }
457 
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;
460 
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];
464 
465  sum_x += x[i];
466  sum_y += y[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];
471  }
472 
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;
479 
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) /
486  determinant;
487 
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) /
494  determinant;
495 
496  double c =
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) /
503  determinant;
504 
505  double d =
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 *
508  sum_x +
509  sum_x_squared * sum_x * sum_x_squared_y * sum_x_squared *
510  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) /
514  determinant;
515 
516  return {a, b, c, d};
517 }
518 
519 std::vector<double> gpmp::optim::Func::nelder_mead(
520  const std::function<double(const std::vector<double> &)> &func,
521  std::vector<double> initial_point,
522  double tolerance,
523  size_t max_iterations) {
524  size_t n = initial_point.size();
525  std::vector<std::vector<double>> simplex(n + 1, initial_point);
526 
527  for (size_t i = 0; i < n; ++i) {
528  simplex[i][i] += 1.0;
529  }
530 
531  std::vector<double> values(n + 1);
532  for (size_t i = 0; i <= n; ++i) {
533  values[i] = func(simplex[i]);
534  }
535 
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()));
543 
544  std::vector<double> centroid =
545  calculate_centroid(simplex, highest_index);
546 
547  // Reflect
548  std::vector<double> reflected_point =
549  reflect(simplex[highest_index], centroid, 1.0);
550  double reflected_value = func(reflected_point);
551 
552  if (reflected_value < values[lowest_index]) {
553  // Expand
554  std::vector<double> expanded_point =
555  reflect(simplex[highest_index], centroid, 2.0);
556  double expanded_value = func(expanded_point);
557 
558  if (expanded_value < reflected_value) {
559  simplex[highest_index] = expanded_point;
560  values[highest_index] = expanded_value;
561  } else {
562  simplex[highest_index] = reflected_point;
563  values[highest_index] = reflected_value;
564  }
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;
569  } else {
570  // Contract
571  std::vector<double> contracted_point =
572  reflect(simplex[highest_index], centroid, 0.5);
573  double contracted_value = func(contracted_point);
574 
575  if (contracted_value < values[highest_index]) {
576  simplex[highest_index] = contracted_point;
577  values[highest_index] = contracted_value;
578  } else {
579  // Shrink
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]);
585  }
586  values[i] = func(simplex[i]);
587  }
588  }
589  }
590  }
591 
592  // Check convergence
593  double range = calculate_range(values);
594  if (range < tolerance) {
595  return simplex[lowest_index];
596  }
597  }
598 
599  return simplex[std::distance(
600  values.begin(),
601  std::min_element(values.begin(), values.end()))];
602 }
603 
604 // Helper methods for Nelder–Mead
605 
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);
611 
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];
616  }
617  }
618  }
619 
620  for (size_t j = 0; j < n; ++j) {
621  centroid[j] /= (simplex.size() - 1);
622  }
623 
624  return centroid;
625 }
626 
627 std::vector<double>
628 gpmp::optim::Func::reflect(const std::vector<double> &point,
629  const std::vector<double> &centroid,
630  double reflection_coefficient) {
631  size_t n = point.size();
632  std::vector<double> reflected_point(n);
633 
634  for (size_t i = 0; i < n; ++i) {
635  reflected_point[i] =
636  centroid[i] + reflection_coefficient * (centroid[i] - point[i]);
637  }
638 
639  return reflected_point;
640 }
641 
642 double gpmp::optim::Func::calculate_range(const std::vector<double> &values) {
643  double max_value = *std::max_element(values.begin(), values.end());
644  double min_value = *std::min_element(values.begin(), values.end());
645 
646  return max_value - min_value;
647 }
648 
649 std::vector<double>
651  const std::function<double(const std::vector<double> &)> &func,
652  const std::vector<double> &lower_bounds,
653  const std::vector<double> &upper_bounds,
654  double tol,
655  const std::vector<double> &x1,
656  const std::vector<double> &x2) {
657 
658  std::vector<double> best_point;
659  double best_value = std::numeric_limits<double>::infinity();
660 
661  // Perform golden section search for each dimension
662  for (size_t i = 0; i < lower_bounds.size(); ++i) {
663  double a = lower_bounds[i];
664  double b = upper_bounds[i];
665  double x1_i = x1[i];
666  double x2_i = x2[i];
667 
668  double result = golden_section_search_minimize(
669  [&](double t) {
670  std::vector<double> point(x1);
671  point[i] = calculate_midpoint(x1_i, x2_i, t);
672  return func(point);
673  },
674  a,
675  b,
676  tol,
677  0.382,
678  0.618);
679 
680  if (result < best_value) {
681  best_value = result;
682  best_point = x1;
683  best_point[i] = calculate_midpoint(x1_i, x2_i, result);
684  }
685  }
686 
687  return best_point;
688 }
689 
690 bool gpmp::optim::Func::is_valid_interval(double a, double b) {
691  return a < b;
692 }
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.
Definition: function.cpp:147
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.
Definition: function.cpp:289
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.
Definition: function.cpp:414
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.
Definition: function.cpp:37
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.
Definition: function.cpp:233
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.
Definition: function.cpp:362
std::vector< double > vector_subtraction(const std::vector< double > &a, const std::vector< double > &b) const
Performs vector subtraction.
Definition: function.cpp:90
std::vector< double > fit_linear(const std::vector< double > &x, const std::vector< double > &y)
Fits a linear function to given data points.
Definition: function.cpp:264
std::vector< double > reflect(const std::vector< double > &point, const std::vector< double > &centroid, double reflection_coefficient)
Reflects a point with respect to a centroid.
Definition: function.cpp:628
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.
Definition: function.cpp:331
std::vector< double > cubic_fit(const std::vector< double > &x, const std::vector< double > &y)
Fits a cubic function to given data points.
Definition: function.cpp:449
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)
Definition: function.cpp:650
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.
Definition: function.cpp:393
double calculate_midpoint(double a, double b, double fraction) const
Calculates the midpoint between two values.
Definition: function.cpp:116
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.
Definition: function.cpp:519
double calculate_range(const std::vector< double > &values)
Calculates the range of values.
Definition: function.cpp:642
bool is_valid_interval(double a, double b)
Checks if a given interval is valid (lower bound < upper bound)
Definition: function.cpp:690
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.
Definition: function.cpp:122
double linear_interpolation(double x, double x0, double x1, double y0, double y1)
Interpolates a univariate function using linear interpolation.
Definition: function.cpp:139
std::vector< double > vector_scalar_multiply(double scalar, const std::vector< double > &vec) const
Performs vector scalar multiplication.
Definition: function.cpp:105
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.
Definition: function.cpp:606
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)
Definition: function.cpp:167
std::vector< double > vector_addition(const std::vector< double > &a, const std::vector< double > &b) const
Performs vector addition.
Definition: function.cpp:74
std::vector< double > generate_fibonacci_sequence(size_t length) const
Generates a Fibonacci sequence up to a specified length.
Definition: function.cpp:57
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.
Definition: function.cpp:200