Skip to main content

math_audio_test_functions/
lib.rs

1#![doc = include_str!("../README.md")]
2#![doc = include_str!("../REFERENCES.md")]
3#![allow(unused)]
4
5use ndarray::{Array1, Array2};
6use std::collections::HashMap;
7
8// Import all function modules
9pub mod functions;
10pub use functions::*;
11
12/// Metadata for a test function including bounds, constraints, and other properties
13#[derive(Debug, Clone)]
14pub struct FunctionMetadata {
15    /// Function name
16    pub name: String,
17    /// Bounds for each dimension (min, max)
18    pub bounds: Vec<(f64, f64)>,
19    /// Global minima locations and values
20    pub global_minima: Vec<(Vec<f64>, f64)>,
21    /// Inequality constraint functions (should be <= 0 when satisfied)
22    pub inequality_constraints: Vec<fn(&Array1<f64>) -> f64>,
23    /// Equality constraint functions (should be = 0 when satisfied)
24    pub equality_constraints: Vec<fn(&Array1<f64>) -> f64>,
25    /// Description of the function
26    pub description: String,
27    /// Whether the function is multimodal
28    pub multimodal: bool,
29    /// Typical dimension(s) for the function
30    pub dimensions: Vec<usize>,
31}
32
33/// Create bounds matrix for optimization (2 x n matrix)
34/// bounds[[0, i]] = lower bound, bounds[[1, i]] = upper bound
35pub fn create_bounds(n: usize, lower: f64, upper: f64) -> Array2<f64> {
36    Array2::from_shape_fn((2, n), |(i, _)| if i == 0 { lower } else { upper })
37}
38
39/// Get metadata for all available test functions (explicit definitions)
40pub fn get_function_metadata() -> HashMap<String, FunctionMetadata> {
41    let mut metadata = HashMap::new();
42
43    // Explicit metadata definitions for all functions, sorted alphabetically
44
45    metadata.insert(
46        "ackley".to_string(),
47        FunctionMetadata {
48            name: "ackley".to_string(),
49            bounds: vec![(-32.768, 32.768); 2],
50            global_minima: vec![(vec![0.0, 0.0], 0.0)],
51            inequality_constraints: vec![],
52            equality_constraints: vec![],
53            description: "Multimodal Ackley function with many local minima".to_string(),
54            multimodal: true,
55            dimensions: vec![2],
56        },
57    );
58
59    metadata.insert(
60        "ackley_n2".to_string(),
61        FunctionMetadata {
62            name: "ackley_n2".to_string(),
63            bounds: vec![(-32.768, 32.768); 2],
64            global_minima: vec![(vec![-1.0, -1.0], -200.0)],
65            inequality_constraints: vec![],
66            equality_constraints: vec![],
67            description: "Modified Ackley N.2 function".to_string(),
68            multimodal: true,
69            dimensions: vec![2],
70        },
71    );
72
73    metadata.insert(
74        "ackley_n3".to_string(),
75        FunctionMetadata {
76            name: "ackley_n3".to_string(),
77            bounds: vec![(-32.768, 32.768); 2],
78            global_minima: vec![(vec![0.682584, -0.36075], -195.629)],
79            inequality_constraints: vec![],
80            equality_constraints: vec![],
81            description: "Modified Ackley N.3 function".to_string(),
82            multimodal: true,
83            dimensions: vec![2],
84        },
85    );
86
87    metadata.insert(
88        "alpine_n1".to_string(),
89        FunctionMetadata {
90            name: "alpine_n1".to_string(),
91            bounds: vec![(-10.0, 10.0); 2],
92            global_minima: vec![(vec![0.0, 0.0], 0.0)],
93            inequality_constraints: vec![],
94            equality_constraints: vec![],
95            description: "Alpine N.1 function".to_string(),
96            multimodal: true,
97            dimensions: vec![2],
98        },
99    );
100
101    metadata.insert(
102        "alpine_n2".to_string(),
103        FunctionMetadata {
104            name: "alpine_n2".to_string(),
105            bounds: vec![(0.0, 10.0); 2],
106            global_minima: vec![(vec![7.917, 7.917], -12.259)],
107            inequality_constraints: vec![],
108            equality_constraints: vec![],
109            description: "Alpine N.2 function".to_string(),
110            multimodal: true,
111            dimensions: vec![2],
112        },
113    );
114
115    metadata.insert(
116        "beale".to_string(),
117        FunctionMetadata {
118            name: "beale".to_string(),
119            bounds: vec![(-10.0, 10.0); 2],
120            global_minima: vec![(vec![3.0, 0.5], 0.0)],
121            inequality_constraints: vec![],
122            equality_constraints: vec![],
123            description: "Beale function".to_string(),
124            multimodal: false,
125            dimensions: vec![2],
126        },
127    );
128
129    metadata.insert(
130        "bent_cigar".to_string(),
131        FunctionMetadata {
132            name: "bent_cigar".to_string(),
133            bounds: vec![(-100.0, 100.0); 2],
134            global_minima: vec![(vec![0.0, 0.0], 0.0)],
135            inequality_constraints: vec![],
136            equality_constraints: vec![],
137            description: "Bent Cigar function".to_string(),
138            multimodal: false,
139            dimensions: vec![2],
140        },
141    );
142
143    metadata.insert(
144        "bent_cigar_alt".to_string(),
145        FunctionMetadata {
146            name: "bent_cigar_alt".to_string(),
147            bounds: vec![(-100.0, 100.0); 2],
148            global_minima: vec![(vec![0.0, 0.0], 0.0)],
149            inequality_constraints: vec![],
150            equality_constraints: vec![],
151            description: "Alternative Bent Cigar function".to_string(),
152            multimodal: false,
153            dimensions: vec![2],
154        },
155    );
156
157    metadata.insert(
158        "binh_korn_constraint1".to_string(),
159        FunctionMetadata {
160            name: "binh_korn_constraint1".to_string(),
161            bounds: vec![(0.0, 5.0), (0.0, 3.0)],
162            global_minima: vec![(vec![0.0, 0.0], 0.0)],
163            inequality_constraints: vec![binh_korn_constraint1, binh_korn_constraint2],
164            equality_constraints: vec![],
165            description: "Binh-Korn constraints: x1^2 + x2^2 <= 25 and (x1-8)^2 + (x2+3)^2 >= 7.7"
166                .to_string(),
167            multimodal: false,
168            dimensions: vec![2],
169        },
170    );
171
172    metadata.insert(
173        "binh_korn_constraint2".to_string(),
174        FunctionMetadata {
175            name: "binh_korn_constraint2".to_string(),
176            bounds: vec![(0.0, 5.0), (0.0, 3.0)],
177            global_minima: vec![],
178            inequality_constraints: vec![],
179            equality_constraints: vec![],
180            description: "Binh-Korn constraint 2 function".to_string(),
181            multimodal: false,
182            dimensions: vec![2],
183        },
184    );
185
186    metadata.insert(
187        "binh_korn_weighted".to_string(),
188        FunctionMetadata {
189            name: "binh_korn_weighted".to_string(),
190            bounds: vec![(0.0, 5.0), (0.0, 3.0)],
191            global_minima: vec![],
192            inequality_constraints: vec![],
193            equality_constraints: vec![],
194            description: "Binh-Korn weighted function".to_string(),
195            multimodal: false,
196            dimensions: vec![2],
197        },
198    );
199
200    metadata.insert(
201        "bird".to_string(),
202        FunctionMetadata {
203            name: "bird".to_string(),
204            bounds: vec![(-2.0 * std::f64::consts::PI, 2.0 * std::f64::consts::PI); 2],
205            global_minima: vec![
206                (vec![4.70104, 3.15294], -106.764537),
207                (vec![-1.58214, -3.13024], -106.764537),
208            ],
209            inequality_constraints: vec![],
210            equality_constraints: vec![],
211            description: "Bird function".to_string(),
212            multimodal: true,
213            dimensions: vec![2],
214        },
215    );
216
217    metadata.insert(
218        "bohachevsky1".to_string(),
219        FunctionMetadata {
220            name: "bohachevsky1".to_string(),
221            bounds: vec![(-15.0, 15.0); 2],
222            global_minima: vec![(vec![0.0, 0.0], 0.0)],
223            inequality_constraints: vec![],
224            equality_constraints: vec![],
225            description: "Bohachevsky N.1 function".to_string(),
226            multimodal: false,
227            dimensions: vec![2],
228        },
229    );
230
231    metadata.insert(
232        "bohachevsky2".to_string(),
233        FunctionMetadata {
234            name: "bohachevsky2".to_string(),
235            bounds: vec![(-15.0, 15.0); 2],
236            global_minima: vec![(vec![0.0, 0.0], 0.0)],
237            inequality_constraints: vec![],
238            equality_constraints: vec![],
239            description: "Bohachevsky N.2 function".to_string(),
240            multimodal: false,
241            dimensions: vec![2],
242        },
243    );
244
245    metadata.insert(
246        "bohachevsky3".to_string(),
247        FunctionMetadata {
248            name: "bohachevsky3".to_string(),
249            bounds: vec![(-15.0, 15.0); 2],
250            global_minima: vec![(vec![0.0, 0.0], 0.0)],
251            inequality_constraints: vec![],
252            equality_constraints: vec![],
253            description: "Bohachevsky N.3 function".to_string(),
254            multimodal: false,
255            dimensions: vec![2],
256        },
257    );
258
259    metadata.insert(
260        "booth".to_string(),
261        FunctionMetadata {
262            name: "booth".to_string(),
263            bounds: vec![(-10.0, 10.0); 2],
264            global_minima: vec![(vec![1.0, 3.0], 0.0)],
265            inequality_constraints: vec![],
266            equality_constraints: vec![],
267            description: "Booth function".to_string(),
268            multimodal: false,
269            dimensions: vec![2],
270        },
271    );
272
273    metadata.insert(
274        "branin".to_string(),
275        FunctionMetadata {
276            name: "branin".to_string(),
277            bounds: vec![(-5.0, 10.0), (0.0, 15.0)],
278            global_minima: vec![
279                (vec![-std::f64::consts::PI, 12.275], 0.397887),
280                (vec![std::f64::consts::PI, 2.275], 0.397887),
281                (vec![9.42478, 2.475], 0.397887),
282            ],
283            inequality_constraints: vec![],
284            equality_constraints: vec![],
285            description: "Branin function".to_string(),
286            multimodal: true,
287            dimensions: vec![2],
288        },
289    );
290
291    metadata.insert(
292        "brown".to_string(),
293        FunctionMetadata {
294            name: "brown".to_string(),
295            bounds: vec![(-1.0, 4.0); 2],
296            global_minima: vec![(vec![0.0, 0.0], 0.0)],
297            inequality_constraints: vec![],
298            equality_constraints: vec![],
299            description: "Brown function".to_string(),
300            multimodal: false,
301            dimensions: vec![2],
302        },
303    );
304
305    metadata.insert(
306        "bukin_n6".to_string(),
307        FunctionMetadata {
308            name: "bukin_n6".to_string(),
309            bounds: vec![(-15.0, -5.0), (-3.0, 3.0)],
310            global_minima: vec![(vec![-10.0, 1.0], 0.0)],
311            inequality_constraints: vec![],
312            equality_constraints: vec![],
313            description: "Bukin N.6 function".to_string(),
314            multimodal: true,
315            dimensions: vec![2],
316        },
317    );
318
319    metadata.insert(
320        "chung_reynolds".to_string(),
321        FunctionMetadata {
322            name: "chung_reynolds".to_string(),
323            bounds: vec![(-100.0, 100.0); 2],
324            global_minima: vec![(vec![0.0, 0.0], 0.0)],
325            inequality_constraints: vec![],
326            equality_constraints: vec![],
327            description: "Chung Reynolds function".to_string(),
328            multimodal: false,
329            dimensions: vec![2],
330        },
331    );
332
333    metadata.insert(
334        "cigar".to_string(),
335        FunctionMetadata {
336            name: "cigar".to_string(),
337            bounds: vec![(-100.0, 100.0); 2],
338            global_minima: vec![(vec![0.0, 0.0], 0.0)],
339            inequality_constraints: vec![],
340            equality_constraints: vec![],
341            description: "Cigar function".to_string(),
342            multimodal: false,
343            dimensions: vec![2],
344        },
345    );
346
347    metadata.insert(
348        "colville".to_string(),
349        FunctionMetadata {
350            name: "colville".to_string(),
351            bounds: vec![(-10.0, 10.0); 4],
352            global_minima: vec![(vec![1.0, 1.0, 1.0, 1.0], 0.0)],
353            inequality_constraints: vec![],
354            equality_constraints: vec![],
355            description: "Colville function (4D)".to_string(),
356            multimodal: false,
357            dimensions: vec![4],
358        },
359    );
360
361    metadata.insert(
362        "cosine_mixture".to_string(),
363        FunctionMetadata {
364            name: "cosine_mixture".to_string(),
365            bounds: vec![(-1.0, 1.0); 2],
366            global_minima: vec![(vec![0.0, 0.0], -0.2)],
367            inequality_constraints: vec![],
368            equality_constraints: vec![],
369            description: "Cosine Mixture function".to_string(),
370            multimodal: true,
371            dimensions: vec![2],
372        },
373    );
374
375    metadata.insert(
376        "cross_in_tray".to_string(),
377        FunctionMetadata {
378            name: "cross_in_tray".to_string(),
379            bounds: vec![(-15.0, 15.0); 2],
380            global_minima: vec![
381                (vec![1.3491, -1.3491], -2.06261),
382                (vec![1.3491, 1.3491], -2.06261),
383                (vec![-1.3491, 1.3491], -2.06261),
384                (vec![-1.3491, -1.3491], -2.06261),
385            ],
386            inequality_constraints: vec![],
387            equality_constraints: vec![],
388            description: "Cross-in-Tray function".to_string(),
389            multimodal: true,
390            dimensions: vec![2],
391        },
392    );
393
394    metadata.insert(
395        "de_jong_step2".to_string(),
396        FunctionMetadata {
397            name: "de_jong_step2".to_string(),
398            bounds: vec![(-100.0, 100.0); 2],
399            global_minima: vec![(vec![0.0, 0.0], 0.0)],
400            inequality_constraints: vec![],
401            equality_constraints: vec![],
402            description: "De Jong Step 2 function".to_string(),
403            multimodal: false,
404            dimensions: vec![2],
405        },
406    );
407
408    metadata.insert(
409        "dejong_f5_foxholes".to_string(),
410        FunctionMetadata {
411            name: "dejong_f5_foxholes".to_string(),
412            bounds: vec![(-65.536, 65.536); 2],
413            global_minima: vec![(vec![-32.0, -32.0], 0.998003838)],
414            inequality_constraints: vec![],
415            equality_constraints: vec![],
416            description: "De Jong F5 (Foxholes) function".to_string(),
417            multimodal: true,
418            dimensions: vec![2],
419        },
420    );
421
422    metadata.insert(
423        "different_powers".to_string(),
424        FunctionMetadata {
425            name: "different_powers".to_string(),
426            bounds: vec![(-1.0, 1.0); 2],
427            global_minima: vec![(vec![0.0, 0.0], 0.0)],
428            inequality_constraints: vec![],
429            equality_constraints: vec![],
430            description: "Different Powers function".to_string(),
431            multimodal: false,
432            dimensions: vec![2],
433        },
434    );
435
436    metadata.insert(
437        "discus".to_string(),
438        FunctionMetadata {
439            name: "discus".to_string(),
440            bounds: vec![(-100.0, 100.0); 2],
441            global_minima: vec![(vec![0.0, 0.0], 0.0)],
442            inequality_constraints: vec![],
443            equality_constraints: vec![],
444            description: "Discus function".to_string(),
445            multimodal: false,
446            dimensions: vec![2],
447        },
448    );
449
450    metadata.insert(
451        "dixons_price".to_string(),
452        FunctionMetadata {
453            name: "dixons_price".to_string(),
454            bounds: vec![(-10.0, 10.0); 2],
455            global_minima: vec![(vec![1.0, 0.5], 0.0)],
456            inequality_constraints: vec![],
457            equality_constraints: vec![],
458            description: "Dixon's Price function".to_string(),
459            multimodal: false,
460            dimensions: vec![2],
461        },
462    );
463
464    metadata.insert(
465        "drop_wave".to_string(),
466        FunctionMetadata {
467            name: "drop_wave".to_string(),
468            bounds: vec![(-5.12, 5.12); 2],
469            global_minima: vec![(vec![0.0, 0.0], -1.0)],
470            inequality_constraints: vec![],
471            equality_constraints: vec![],
472            description: "Drop-Wave function".to_string(),
473            multimodal: true,
474            dimensions: vec![2],
475        },
476    );
477
478    metadata.insert(
479        "easom".to_string(),
480        FunctionMetadata {
481            name: "easom".to_string(),
482            bounds: vec![(-100.0, 100.0); 2],
483            global_minima: vec![(vec![std::f64::consts::PI, std::f64::consts::PI], -1.0)],
484            inequality_constraints: vec![],
485            equality_constraints: vec![],
486            description: "Easom function".to_string(),
487            multimodal: false,
488            dimensions: vec![2],
489        },
490    );
491
492    metadata.insert(
493        "eggholder".to_string(),
494        FunctionMetadata {
495            name: "eggholder".to_string(),
496            bounds: vec![(-512.0, 512.0); 2],
497            global_minima: vec![(vec![512.0, 404.2319], -959.6407)],
498            inequality_constraints: vec![],
499            equality_constraints: vec![],
500            description: "Eggholder function".to_string(),
501            multimodal: true,
502            dimensions: vec![2],
503        },
504    );
505
506    metadata.insert(
507        "elliptic".to_string(),
508        FunctionMetadata {
509            name: "elliptic".to_string(),
510            bounds: vec![(-100.0, 100.0); 2],
511            global_minima: vec![(vec![0.0, 0.0], 0.0)],
512            inequality_constraints: vec![],
513            equality_constraints: vec![],
514            description: "Elliptic function".to_string(),
515            multimodal: false,
516            dimensions: vec![2],
517        },
518    );
519
520    metadata.insert(
521        "epistatic_michalewicz".to_string(),
522        FunctionMetadata {
523            name: "epistatic_michalewicz".to_string(),
524            bounds: vec![(0.0, std::f64::consts::PI); 2],
525            global_minima: vec![],
526            inequality_constraints: vec![],
527            equality_constraints: vec![],
528            description: "Epistatic Michalewicz function".to_string(),
529            multimodal: true,
530            dimensions: vec![2],
531        },
532    );
533
534    metadata.insert(
535        "expanded_griewank_rosenbrock".to_string(),
536        FunctionMetadata {
537            name: "expanded_griewank_rosenbrock".to_string(),
538            bounds: vec![(-100.0, 100.0); 2],
539            global_minima: vec![(vec![1.0, 1.0], 0.0)],
540            inequality_constraints: vec![],
541            equality_constraints: vec![],
542            description: "Expanded Griewank + Rosenbrock function".to_string(),
543            multimodal: true,
544            dimensions: vec![2],
545        },
546    );
547
548    metadata.insert(
549        "exponential".to_string(),
550        FunctionMetadata {
551            name: "exponential".to_string(),
552            bounds: vec![(-1.0, 1.0); 2],
553            global_minima: vec![(vec![0.0, 0.0], -1.0)],
554            inequality_constraints: vec![],
555            equality_constraints: vec![],
556            description: "Exponential function".to_string(),
557            multimodal: false,
558            dimensions: vec![2],
559        },
560    );
561
562    metadata.insert(
563        "forrester_2008".to_string(),
564        FunctionMetadata {
565            name: "forrester_2008".to_string(),
566            bounds: vec![(0.0, 1.0)],
567            global_minima: vec![(vec![0.757249], -6.02074)],
568            inequality_constraints: vec![],
569            equality_constraints: vec![],
570            description: "Forrester et al. (2008) function (1D)".to_string(),
571            multimodal: true,
572            dimensions: vec![1],
573        },
574    );
575
576    metadata.insert(
577        "freudenstein_roth".to_string(),
578        FunctionMetadata {
579            name: "freudenstein_roth".to_string(),
580            bounds: vec![(-10.0, 10.0); 2],
581            global_minima: vec![(vec![5.0, 4.0], 0.0), (vec![11.41, -0.8968], 48.9842)],
582            inequality_constraints: vec![],
583            equality_constraints: vec![],
584            description: "Freudenstein and Roth function".to_string(),
585            multimodal: true,
586            dimensions: vec![2],
587        },
588    );
589
590    metadata.insert(
591        "goldstein_price".to_string(),
592        FunctionMetadata {
593            name: "goldstein_price".to_string(),
594            bounds: vec![(-2.0, 2.0); 2],
595            global_minima: vec![(vec![0.0, -1.0], 3.0)],
596            inequality_constraints: vec![],
597            equality_constraints: vec![],
598            description: "Goldstein-Price function".to_string(),
599            multimodal: true,
600            dimensions: vec![2],
601        },
602    );
603
604    metadata.insert(
605        "gramacy_lee_2012".to_string(),
606        FunctionMetadata {
607            name: "gramacy_lee_2012".to_string(),
608            bounds: vec![(0.5, 2.5)],
609            global_minima: vec![(vec![0.548563], -0.869011)],
610            inequality_constraints: vec![],
611            equality_constraints: vec![],
612            description: "Gramacy & Lee (2012) function (1D)".to_string(),
613            multimodal: false,
614            dimensions: vec![1],
615        },
616    );
617
618    metadata.insert(
619        "gramacy_lee_function".to_string(),
620        FunctionMetadata {
621            name: "gramacy_lee_function".to_string(),
622            bounds: vec![(0.0, 6.0)],
623            global_minima: vec![],
624            inequality_constraints: vec![],
625            equality_constraints: vec![],
626            description: "Gramacy & Lee function (1D)".to_string(),
627            multimodal: true,
628            dimensions: vec![1],
629        },
630    );
631
632    metadata.insert(
633        "griewank".to_string(),
634        FunctionMetadata {
635            name: "griewank".to_string(),
636            bounds: vec![(-600.0, 600.0); 2],
637            global_minima: vec![(vec![0.0, 0.0], 0.0)],
638            inequality_constraints: vec![],
639            equality_constraints: vec![],
640            description: "Griewank function".to_string(),
641            multimodal: true,
642            dimensions: vec![2],
643        },
644    );
645
646    metadata.insert(
647        "griewank2".to_string(),
648        FunctionMetadata {
649            name: "griewank2".to_string(),
650            bounds: vec![(-600.0, 600.0); 2],
651            global_minima: vec![(vec![0.0, 0.0], 0.0)],
652            inequality_constraints: vec![],
653            equality_constraints: vec![],
654            description: "Griewank function variant 2".to_string(),
655            multimodal: true,
656            dimensions: vec![2],
657        },
658    );
659
660    metadata.insert(
661        "happy_cat".to_string(),
662        FunctionMetadata {
663            name: "happy_cat".to_string(),
664            bounds: vec![(-2.0, 2.0); 2],
665            global_minima: vec![(vec![-1.0, -1.0], 0.0)],
666            inequality_constraints: vec![],
667            equality_constraints: vec![],
668            description: "Happy Cat function".to_string(),
669            multimodal: false,
670            dimensions: vec![2],
671        },
672    );
673
674    metadata.insert(
675        "happycat".to_string(),
676        FunctionMetadata {
677            name: "happycat".to_string(),
678            bounds: vec![(-2.0, 2.0); 2],
679            global_minima: vec![(vec![-1.0, -1.0], 0.0)],
680            inequality_constraints: vec![],
681            equality_constraints: vec![],
682            description: "HappyCat function".to_string(),
683            multimodal: false,
684            dimensions: vec![2],
685        },
686    );
687
688    metadata.insert(
689        "hartman_3d".to_string(),
690        FunctionMetadata {
691            name: "hartman_3d".to_string(),
692            bounds: vec![(0.0, 1.0); 3],
693            global_minima: vec![(vec![0.114614, 0.555649, 0.852547], -3.86278)],
694            inequality_constraints: vec![],
695            equality_constraints: vec![],
696            description: "Hartmann 3D function".to_string(),
697            multimodal: true,
698            dimensions: vec![3],
699        },
700    );
701
702    metadata.insert(
703        "hartman_4d".to_string(),
704        FunctionMetadata {
705            name: "hartman_4d".to_string(),
706            bounds: vec![(0.0, 1.0); 4],
707            global_minima: vec![(vec![0.1873, 0.1936, 0.5576, 0.2647], -3.72983)],
708            inequality_constraints: vec![],
709            equality_constraints: vec![],
710            description: "Hartmann 4D function".to_string(),
711            multimodal: true,
712            dimensions: vec![4],
713        },
714    );
715
716    metadata.insert(
717        "hartman_6d".to_string(),
718        FunctionMetadata {
719            name: "hartman_6d".to_string(),
720            bounds: vec![(0.0, 1.0); 6],
721            global_minima: vec![(
722                vec![0.20169, 0.150011, 0.476874, 0.275332, 0.311652, 0.6573],
723                -3.32237,
724            )],
725            inequality_constraints: vec![],
726            equality_constraints: vec![],
727            description: "Hartmann 6D function".to_string(),
728            multimodal: true,
729            dimensions: vec![6],
730        },
731    );
732
733    metadata.insert(
734        "himmelblau".to_string(),
735        FunctionMetadata {
736            name: "himmelblau".to_string(),
737            bounds: vec![(-6.0, 6.0); 2],
738            global_minima: vec![
739                (vec![3.0, 2.0], 0.0),
740                (vec![-2.805118, 3.131312], 0.0),
741                (vec![-3.779310, -3.283186], 0.0),
742                (vec![3.584428, -1.848126], 0.0),
743            ],
744            inequality_constraints: vec![],
745            equality_constraints: vec![],
746            description: "Himmelblau's function".to_string(),
747            multimodal: true,
748            dimensions: vec![2],
749        },
750    );
751
752    metadata.insert(
753        "holder_table".to_string(),
754        FunctionMetadata {
755            name: "holder_table".to_string(),
756            bounds: vec![(-10.0, 10.0); 2],
757            global_minima: vec![
758                (vec![8.05502, 9.66459], -19.2085),
759                (vec![-8.05502, 9.66459], -19.2085),
760                (vec![8.05502, -9.66459], -19.2085),
761                (vec![-8.05502, -9.66459], -19.2085),
762            ],
763            inequality_constraints: vec![],
764            equality_constraints: vec![],
765            description: "Holder Table function".to_string(),
766            multimodal: true,
767            dimensions: vec![2],
768        },
769    );
770
771    metadata.insert(
772        "katsuura".to_string(),
773        FunctionMetadata {
774            name: "katsuura".to_string(),
775            bounds: vec![(0.0, 100.0); 2],
776            global_minima: vec![(vec![0.0, 0.0], 0.0)],
777            inequality_constraints: vec![],
778            equality_constraints: vec![],
779            description: "Katsuura function".to_string(),
780            multimodal: true,
781            dimensions: vec![2],
782        },
783    );
784
785    metadata.insert(
786        "keanes_bump_constraint1".to_string(),
787        FunctionMetadata {
788            name: "keanes_bump_constraint1".to_string(),
789            bounds: vec![(0.0, 10.0); 2],
790            global_minima: vec![],
791            inequality_constraints: vec![],
792            equality_constraints: vec![],
793            description: "Keane's Bump constraint 1 function".to_string(),
794            multimodal: false,
795            dimensions: vec![2],
796        },
797    );
798
799    metadata.insert(
800        "keanes_bump_constraint2".to_string(),
801        FunctionMetadata {
802            name: "keanes_bump_constraint2".to_string(),
803            bounds: vec![(0.0, 10.0); 2],
804            global_minima: vec![],
805            inequality_constraints: vec![],
806            equality_constraints: vec![],
807            description: "Keane's Bump constraint 2 function".to_string(),
808            multimodal: false,
809            dimensions: vec![2],
810        },
811    );
812
813    metadata.insert(
814        "keanes_bump_objective".to_string(),
815        FunctionMetadata {
816            name: "keanes_bump_objective".to_string(),
817            bounds: vec![(0.0, 10.0); 2],
818            global_minima: vec![(vec![1.393249, 0.0], 0.673668)],
819            inequality_constraints: vec![],
820            equality_constraints: vec![],
821            description: "Keane's Bump objective function".to_string(),
822            multimodal: true,
823            dimensions: vec![2],
824        },
825    );
826
827    metadata.insert(
828        "lampinen_simplified".to_string(),
829        FunctionMetadata {
830            name: "lampinen_simplified".to_string(),
831            bounds: vec![(0.0, 6.0); 2],
832            global_minima: vec![],
833            inequality_constraints: vec![],
834            equality_constraints: vec![],
835            description: "Lampinen simplified function".to_string(),
836            multimodal: false,
837            dimensions: vec![2],
838        },
839    );
840
841    metadata.insert(
842        "langermann".to_string(),
843        FunctionMetadata {
844            name: "langermann".to_string(),
845            bounds: vec![(0.0, 10.0); 2],
846            global_minima: vec![(vec![2.00299219, 1.006096], -5.1621259)],
847            inequality_constraints: vec![],
848            equality_constraints: vec![],
849            description: "Langermann function".to_string(),
850            multimodal: true,
851            dimensions: vec![2],
852        },
853    );
854
855    metadata.insert(
856        "levi13".to_string(),
857        FunctionMetadata {
858            name: "levi13".to_string(),
859            bounds: vec![(-10.0, 10.0); 2],
860            global_minima: vec![(vec![1.0, 1.0], 0.0)],
861            inequality_constraints: vec![],
862            equality_constraints: vec![],
863            description: "LƩvi N.13 function".to_string(),
864            multimodal: true,
865            dimensions: vec![2],
866        },
867    );
868
869    metadata.insert(
870        "levy".to_string(),
871        FunctionMetadata {
872            name: "levy".to_string(),
873            bounds: vec![(-10.0, 10.0); 2],
874            global_minima: vec![(vec![1.0, 1.0], 0.0)],
875            inequality_constraints: vec![],
876            equality_constraints: vec![],
877            description: "LƩvy function".to_string(),
878            multimodal: true,
879            dimensions: vec![2],
880        },
881    );
882
883    metadata.insert(
884        "levy_n13".to_string(),
885        FunctionMetadata {
886            name: "levy_n13".to_string(),
887            bounds: vec![(-10.0, 10.0); 2],
888            global_minima: vec![(vec![1.0, 1.0], 0.0)],
889            inequality_constraints: vec![],
890            equality_constraints: vec![],
891            description: "LƩvy N.13 function".to_string(),
892            multimodal: true,
893            dimensions: vec![2],
894        },
895    );
896
897    metadata.insert(
898        "matyas".to_string(),
899        FunctionMetadata {
900            name: "matyas".to_string(),
901            bounds: vec![(-10.0, 10.0); 2],
902            global_minima: vec![(vec![0.0, 0.0], 0.0)],
903            inequality_constraints: vec![],
904            equality_constraints: vec![],
905            description: "Matyas function".to_string(),
906            multimodal: false,
907            dimensions: vec![2],
908        },
909    );
910
911    metadata.insert(
912        "mccormick".to_string(),
913        FunctionMetadata {
914            name: "mccormick".to_string(),
915            bounds: vec![(-1.5, 4.0), (-3.0, 4.0)],
916            global_minima: vec![(vec![-0.54719, -1.54719], -1.9133)],
917            inequality_constraints: vec![],
918            equality_constraints: vec![],
919            description: "McCormick function".to_string(),
920            multimodal: true,
921            dimensions: vec![2],
922        },
923    );
924
925    metadata.insert(
926        "michalewicz".to_string(),
927        FunctionMetadata {
928            name: "michalewicz".to_string(),
929            bounds: vec![(0.0, std::f64::consts::PI); 2],
930            global_minima: vec![(vec![2.20, 1.57], -1.8013)],
931            inequality_constraints: vec![],
932            equality_constraints: vec![],
933            description: "Michalewicz function".to_string(),
934            multimodal: true,
935            dimensions: vec![2],
936        },
937    );
938
939    metadata.insert(
940        "mishras_bird_constraint".to_string(),
941        FunctionMetadata {
942            name: "mishras_bird_constraint".to_string(),
943            bounds: vec![(-10.0, 0.0); 2],
944            global_minima: vec![],
945            inequality_constraints: vec![],
946            equality_constraints: vec![],
947            description: "Mishra's Bird constraint function".to_string(),
948            multimodal: false,
949            dimensions: vec![2],
950        },
951    );
952
953    metadata.insert(
954        "mishras_bird_objective".to_string(),
955        FunctionMetadata {
956            name: "mishras_bird_objective".to_string(),
957            bounds: vec![(-10.0, 0.0); 2],
958            global_minima: vec![(vec![-3.1302468, -1.5821422], -106.7645367)],
959            inequality_constraints: vec![],
960            equality_constraints: vec![],
961            description: "Mishra's Bird objective function".to_string(),
962            multimodal: true,
963            dimensions: vec![2],
964        },
965    );
966
967    metadata.insert(
968        "periodic".to_string(),
969        FunctionMetadata {
970            name: "periodic".to_string(),
971            bounds: vec![(-10.0, 10.0); 2],
972            global_minima: vec![(vec![0.0, 0.0], 0.9)],
973            inequality_constraints: vec![],
974            equality_constraints: vec![],
975            description: "Periodic function".to_string(),
976            multimodal: true,
977            dimensions: vec![2],
978        },
979    );
980
981    metadata.insert(
982        "perm_0_d_beta".to_string(),
983        FunctionMetadata {
984            name: "perm_0_d_beta".to_string(),
985            bounds: vec![(-2.0, 2.0); 2],
986            global_minima: vec![(vec![1.0, 0.5], 0.0)],
987            inequality_constraints: vec![],
988            equality_constraints: vec![],
989            description: "Perm 0,d,β function".to_string(),
990            multimodal: false,
991            dimensions: vec![2],
992        },
993    );
994
995    metadata.insert(
996        "perm_d_beta".to_string(),
997        FunctionMetadata {
998            name: "perm_d_beta".to_string(),
999            bounds: vec![(-2.0, 2.0); 2],
1000            global_minima: vec![(vec![1.0, 0.5], 0.0)],
1001            inequality_constraints: vec![],
1002            equality_constraints: vec![],
1003            description: "Perm d,β function".to_string(),
1004            multimodal: false,
1005            dimensions: vec![2],
1006        },
1007    );
1008
1009    metadata.insert(
1010        "pinter".to_string(),
1011        FunctionMetadata {
1012            name: "pinter".to_string(),
1013            bounds: vec![(-10.0, 10.0); 2],
1014            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1015            inequality_constraints: vec![],
1016            equality_constraints: vec![],
1017            description: "Pinter function".to_string(),
1018            multimodal: false,
1019            dimensions: vec![2],
1020        },
1021    );
1022
1023    metadata.insert(
1024        "powell".to_string(),
1025        FunctionMetadata {
1026            name: "powell".to_string(),
1027            bounds: vec![(-4.0, 5.0); 4],
1028            global_minima: vec![(vec![0.0, 0.0, 0.0, 0.0], 0.0)],
1029            inequality_constraints: vec![],
1030            equality_constraints: vec![],
1031            description: "Powell function (4D)".to_string(),
1032            multimodal: false,
1033            dimensions: vec![4],
1034        },
1035    );
1036
1037    metadata.insert(
1038        "power_sum".to_string(),
1039        FunctionMetadata {
1040            name: "power_sum".to_string(),
1041            bounds: vec![(0.0, 4.0); 4],
1042            global_minima: vec![(vec![1.0, 2.0, 2.0, 3.0], 0.0)],
1043            inequality_constraints: vec![],
1044            equality_constraints: vec![],
1045            description: "Power Sum function (4D)".to_string(),
1046            multimodal: false,
1047            dimensions: vec![4],
1048        },
1049    );
1050
1051    metadata.insert(
1052        "qing".to_string(),
1053        FunctionMetadata {
1054            name: "qing".to_string(),
1055            bounds: vec![(-500.0, 500.0); 2],
1056            global_minima: vec![(vec![std::f64::consts::SQRT_2, 2.0], 0.0)],
1057            inequality_constraints: vec![],
1058            equality_constraints: vec![],
1059            description: "Qing function".to_string(),
1060            multimodal: false,
1061            dimensions: vec![2],
1062        },
1063    );
1064
1065    metadata.insert(
1066        "quadratic".to_string(),
1067        FunctionMetadata {
1068            name: "quadratic".to_string(),
1069            bounds: vec![(-10.0, 10.0); 2],
1070            global_minima: vec![(vec![0.19388, 0.48513], -3873.7243)],
1071            inequality_constraints: vec![],
1072            equality_constraints: vec![],
1073            description: "Quadratic function".to_string(),
1074            multimodal: false,
1075            dimensions: vec![2],
1076        },
1077    );
1078
1079    metadata.insert(
1080        "quartic".to_string(),
1081        FunctionMetadata {
1082            name: "quartic".to_string(),
1083            bounds: vec![(-1.28, 1.28); 2],
1084            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1085            inequality_constraints: vec![],
1086            equality_constraints: vec![],
1087            description: "Quartic function with noise".to_string(),
1088            multimodal: false,
1089            dimensions: vec![2],
1090        },
1091    );
1092
1093    metadata.insert(
1094        "rastrigin".to_string(),
1095        FunctionMetadata {
1096            name: "rastrigin".to_string(),
1097            bounds: vec![(-5.12, 5.12); 2],
1098            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1099            inequality_constraints: vec![],
1100            equality_constraints: vec![],
1101            description: "Highly multimodal Rastrigin function".to_string(),
1102            multimodal: true,
1103            dimensions: vec![2],
1104        },
1105    );
1106
1107    metadata.insert(
1108        "ridge".to_string(),
1109        FunctionMetadata {
1110            name: "ridge".to_string(),
1111            bounds: vec![(-5.0, 5.0); 2],
1112            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1113            inequality_constraints: vec![],
1114            equality_constraints: vec![],
1115            description: "Ridge function".to_string(),
1116            multimodal: false,
1117            dimensions: vec![2],
1118        },
1119    );
1120
1121    metadata.insert(
1122        "rosenbrock".to_string(),
1123        FunctionMetadata {
1124            name: "rosenbrock".to_string(),
1125            bounds: vec![(-2.048, 2.048); 2],
1126            global_minima: vec![(vec![1.0, 1.0], 0.0)],
1127            inequality_constraints: vec![],
1128            equality_constraints: vec![],
1129            description: "Classic Rosenbrock banana function".to_string(),
1130            multimodal: false,
1131            dimensions: vec![2],
1132        },
1133    );
1134
1135    metadata.insert(
1136        "rosenbrock_disk_constraint".to_string(),
1137        FunctionMetadata {
1138            name: "rosenbrock_disk_constraint".to_string(),
1139            bounds: vec![(-1.5, 1.5); 2],
1140            global_minima: vec![(vec![1.0, 1.0], 0.0)],
1141            inequality_constraints: vec![rosenbrock_disk_constraint],
1142            equality_constraints: vec![],
1143            description: "Disk constraint: x^2 + y^2 <= 2".to_string(),
1144            multimodal: false,
1145            dimensions: vec![2],
1146        },
1147    );
1148
1149    metadata.insert(
1150        "rosenbrock_objective".to_string(),
1151        FunctionMetadata {
1152            name: "rosenbrock_objective".to_string(),
1153            bounds: vec![(-2.048, 2.048); 2],
1154            global_minima: vec![(vec![1.0, 1.0], 0.0)],
1155            inequality_constraints: vec![],
1156            equality_constraints: vec![],
1157            description: "Rosenbrock objective function".to_string(),
1158            multimodal: false,
1159            dimensions: vec![2],
1160        },
1161    );
1162
1163    metadata.insert(
1164        "rotated_hyper_ellipsoid".to_string(),
1165        FunctionMetadata {
1166            name: "rotated_hyper_ellipsoid".to_string(),
1167            bounds: vec![(-65.536, 65.536); 2],
1168            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1169            inequality_constraints: vec![],
1170            equality_constraints: vec![],
1171            description: "Rotated Hyper-ellipsoid function".to_string(),
1172            multimodal: false,
1173            dimensions: vec![2],
1174        },
1175    );
1176
1177    metadata.insert(
1178        "salomon".to_string(),
1179        FunctionMetadata {
1180            name: "salomon".to_string(),
1181            bounds: vec![(-100.0, 100.0); 2],
1182            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1183            inequality_constraints: vec![],
1184            equality_constraints: vec![],
1185            description: "Salomon function".to_string(),
1186            multimodal: true,
1187            dimensions: vec![2],
1188        },
1189    );
1190
1191    metadata.insert(
1192        "salomon_corrected".to_string(),
1193        FunctionMetadata {
1194            name: "salomon_corrected".to_string(),
1195            bounds: vec![(-100.0, 100.0); 2],
1196            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1197            inequality_constraints: vec![],
1198            equality_constraints: vec![],
1199            description: "Salomon corrected function".to_string(),
1200            multimodal: true,
1201            dimensions: vec![2],
1202        },
1203    );
1204
1205    metadata.insert(
1206        "schaffer_n2".to_string(),
1207        FunctionMetadata {
1208            name: "schaffer_n2".to_string(),
1209            bounds: vec![(-100.0, 100.0); 2],
1210            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1211            inequality_constraints: vec![],
1212            equality_constraints: vec![],
1213            description: "Schaffer N.2 function".to_string(),
1214            multimodal: true,
1215            dimensions: vec![2],
1216        },
1217    );
1218
1219    metadata.insert(
1220        "schaffer_n4".to_string(),
1221        FunctionMetadata {
1222            name: "schaffer_n4".to_string(),
1223            bounds: vec![(-100.0, 100.0); 2],
1224            global_minima: vec![
1225                (vec![0.0, 1.25313], 0.292579),
1226                (vec![0.0, -1.25313], 0.292579),
1227            ],
1228            inequality_constraints: vec![],
1229            equality_constraints: vec![],
1230            description: "Schaffer N.4 function".to_string(),
1231            multimodal: true,
1232            dimensions: vec![2],
1233        },
1234    );
1235
1236    metadata.insert(
1237        "schwefel".to_string(),
1238        FunctionMetadata {
1239            name: "schwefel".to_string(),
1240            bounds: vec![(-500.0, 500.0); 2],
1241            global_minima: vec![(vec![420.9687, 420.9687], 0.0)],
1242            inequality_constraints: vec![],
1243            equality_constraints: vec![],
1244            description: "Schwefel function".to_string(),
1245            multimodal: true,
1246            dimensions: vec![2],
1247        },
1248    );
1249
1250    metadata.insert(
1251        "schwefel2".to_string(),
1252        FunctionMetadata {
1253            name: "schwefel2".to_string(),
1254            bounds: vec![(-100.0, 100.0); 2],
1255            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1256            inequality_constraints: vec![],
1257            equality_constraints: vec![],
1258            description: "Schwefel 2 function".to_string(),
1259            multimodal: false,
1260            dimensions: vec![2],
1261        },
1262    );
1263
1264    metadata.insert(
1265        "sharp_ridge".to_string(),
1266        FunctionMetadata {
1267            name: "sharp_ridge".to_string(),
1268            bounds: vec![(-5.0, 5.0); 2],
1269            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1270            inequality_constraints: vec![],
1271            equality_constraints: vec![],
1272            description: "Sharp Ridge function".to_string(),
1273            multimodal: false,
1274            dimensions: vec![2],
1275        },
1276    );
1277
1278    metadata.insert(
1279        "shekel".to_string(),
1280        FunctionMetadata {
1281            name: "shekel".to_string(),
1282            bounds: vec![(0.0, 10.0); 4],
1283            global_minima: vec![(vec![4.0, 4.0, 4.0, 4.0], -10.5364)],
1284            inequality_constraints: vec![],
1285            equality_constraints: vec![],
1286            description: "Shekel function (4D)".to_string(),
1287            multimodal: true,
1288            dimensions: vec![4],
1289        },
1290    );
1291
1292    metadata.insert(
1293        "shubert".to_string(),
1294        FunctionMetadata {
1295            name: "shubert".to_string(),
1296            bounds: vec![(-10.0, 10.0); 2],
1297            global_minima: vec![(vec![-7.0835, 4.8580], -186.7309)],
1298            inequality_constraints: vec![],
1299            equality_constraints: vec![],
1300            description: "Shubert function".to_string(),
1301            multimodal: true,
1302            dimensions: vec![2],
1303        },
1304    );
1305
1306    metadata.insert(
1307        "six_hump_camel".to_string(),
1308        FunctionMetadata {
1309            name: "six_hump_camel".to_string(),
1310            bounds: vec![(-3.0, 3.0), (-2.0, 2.0)],
1311            global_minima: vec![
1312                (vec![0.0898, -0.7126], -1.0316),
1313                (vec![-0.0898, 0.7126], -1.0316),
1314            ],
1315            inequality_constraints: vec![],
1316            equality_constraints: vec![],
1317            description: "Six-hump Camel function".to_string(),
1318            multimodal: true,
1319            dimensions: vec![2],
1320        },
1321    );
1322
1323    metadata.insert(
1324        "sphere".to_string(),
1325        FunctionMetadata {
1326            name: "sphere".to_string(),
1327            bounds: vec![(-5.0, 5.0); 2],
1328            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1329            inequality_constraints: vec![],
1330            equality_constraints: vec![],
1331            description: "Simple quadratic sphere function".to_string(),
1332            multimodal: false,
1333            dimensions: vec![2],
1334        },
1335    );
1336
1337    metadata.insert(
1338        "step".to_string(),
1339        FunctionMetadata {
1340            name: "step".to_string(),
1341            bounds: vec![(-100.0, 100.0); 2],
1342            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1343            inequality_constraints: vec![],
1344            equality_constraints: vec![],
1345            description: "Step function".to_string(),
1346            multimodal: false,
1347            dimensions: vec![2],
1348        },
1349    );
1350
1351    metadata.insert(
1352        "styblinski_tang2".to_string(),
1353        FunctionMetadata {
1354            name: "styblinski_tang2".to_string(),
1355            bounds: vec![(-5.0, 5.0); 2],
1356            global_minima: vec![(vec![-2.903534, -2.903534], -78.332)],
1357            inequality_constraints: vec![],
1358            equality_constraints: vec![],
1359            description: "Styblinski-Tang function (2D)".to_string(),
1360            multimodal: true,
1361            dimensions: vec![2],
1362        },
1363    );
1364
1365    metadata.insert(
1366        "sum_of_different_powers".to_string(),
1367        FunctionMetadata {
1368            name: "sum_of_different_powers".to_string(),
1369            bounds: vec![(-1.0, 1.0); 2],
1370            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1371            inequality_constraints: vec![],
1372            equality_constraints: vec![],
1373            description: "Sum of Different Powers function".to_string(),
1374            multimodal: false,
1375            dimensions: vec![2],
1376        },
1377    );
1378
1379    metadata.insert(
1380        "sum_squares".to_string(),
1381        FunctionMetadata {
1382            name: "sum_squares".to_string(),
1383            bounds: vec![(-10.0, 10.0); 2],
1384            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1385            inequality_constraints: vec![],
1386            equality_constraints: vec![],
1387            description: "Sum Squares function".to_string(),
1388            multimodal: false,
1389            dimensions: vec![2],
1390        },
1391    );
1392
1393    metadata.insert(
1394        "tablet".to_string(),
1395        FunctionMetadata {
1396            name: "tablet".to_string(),
1397            bounds: vec![(-100.0, 100.0); 2],
1398            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1399            inequality_constraints: vec![],
1400            equality_constraints: vec![],
1401            description: "Tablet function".to_string(),
1402            multimodal: false,
1403            dimensions: vec![2],
1404        },
1405    );
1406
1407    metadata.insert(
1408        "three_hump_camel".to_string(),
1409        FunctionMetadata {
1410            name: "three_hump_camel".to_string(),
1411            bounds: vec![(-5.0, 5.0); 2],
1412            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1413            inequality_constraints: vec![],
1414            equality_constraints: vec![],
1415            description: "Three-hump Camel function".to_string(),
1416            multimodal: true,
1417            dimensions: vec![2],
1418        },
1419    );
1420
1421    metadata.insert(
1422        "trid".to_string(),
1423        FunctionMetadata {
1424            name: "trid".to_string(),
1425            bounds: vec![(-4.0, 4.0); 2],
1426            global_minima: vec![(vec![1.0, 2.0], -2.0)],
1427            inequality_constraints: vec![],
1428            equality_constraints: vec![],
1429            description: "Trid function".to_string(),
1430            multimodal: false,
1431            dimensions: vec![2],
1432        },
1433    );
1434
1435    metadata.insert(
1436        "vincent".to_string(),
1437        FunctionMetadata {
1438            name: "vincent".to_string(),
1439            bounds: vec![(0.25, 10.0); 2],
1440            global_minima: vec![(vec![7.70628, 7.70628], -2.0)],
1441            inequality_constraints: vec![],
1442            equality_constraints: vec![],
1443            description: "Vincent function".to_string(),
1444            multimodal: true,
1445            dimensions: vec![2],
1446        },
1447    );
1448
1449    metadata.insert(
1450        "whitley".to_string(),
1451        FunctionMetadata {
1452            name: "whitley".to_string(),
1453            bounds: vec![(-10.24, 10.24); 2],
1454            global_minima: vec![(vec![1.0, 1.0], 0.0)],
1455            inequality_constraints: vec![],
1456            equality_constraints: vec![],
1457            description: "Whitley function".to_string(),
1458            multimodal: true,
1459            dimensions: vec![2],
1460        },
1461    );
1462
1463    metadata.insert(
1464        "xin_she_yang_n1".to_string(),
1465        FunctionMetadata {
1466            name: "xin_she_yang_n1".to_string(),
1467            bounds: vec![(-2.0 * std::f64::consts::PI, 2.0 * std::f64::consts::PI); 2],
1468            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1469            inequality_constraints: vec![],
1470            equality_constraints: vec![],
1471            description: "Xin-She Yang N.1 function".to_string(),
1472            multimodal: true,
1473            dimensions: vec![2],
1474        },
1475    );
1476
1477    metadata.insert(
1478        "xin_she_yang_n2".to_string(),
1479        FunctionMetadata {
1480            name: "xin_she_yang_n2".to_string(),
1481            bounds: vec![(-2.0 * std::f64::consts::PI, 2.0 * std::f64::consts::PI); 2],
1482            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1483            inequality_constraints: vec![],
1484            equality_constraints: vec![],
1485            description: "Xin-She Yang N.2 function".to_string(),
1486            multimodal: true,
1487            dimensions: vec![2],
1488        },
1489    );
1490
1491    metadata.insert(
1492        "xin_she_yang_n3".to_string(),
1493        FunctionMetadata {
1494            name: "xin_she_yang_n3".to_string(),
1495            bounds: vec![(-20.0, 20.0); 2],
1496            global_minima: vec![(vec![0.0, 0.0], -1.0)],
1497            inequality_constraints: vec![],
1498            equality_constraints: vec![],
1499            description: "Xin-She Yang N.3 function".to_string(),
1500            multimodal: true,
1501            dimensions: vec![2],
1502        },
1503    );
1504
1505    metadata.insert(
1506        "xin_she_yang_n4".to_string(),
1507        FunctionMetadata {
1508            name: "xin_she_yang_n4".to_string(),
1509            bounds: vec![(-10.0, 10.0); 2],
1510            global_minima: vec![(vec![0.0, 0.0], -1.0)],
1511            inequality_constraints: vec![],
1512            equality_constraints: vec![],
1513            description: "Xin-She Yang N.4 function".to_string(),
1514            multimodal: true,
1515            dimensions: vec![2],
1516        },
1517    );
1518
1519    metadata.insert(
1520        "zakharov".to_string(),
1521        FunctionMetadata {
1522            name: "zakharov".to_string(),
1523            bounds: vec![(-5.0, 10.0); 2],
1524            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1525            inequality_constraints: vec![],
1526            equality_constraints: vec![],
1527            description: "Zakharov function".to_string(),
1528            multimodal: false,
1529            dimensions: vec![2],
1530        },
1531    );
1532
1533    metadata.insert(
1534        "zakharov2".to_string(),
1535        FunctionMetadata {
1536            name: "zakharov2".to_string(),
1537            bounds: vec![(-5.0, 10.0); 2],
1538            global_minima: vec![(vec![0.0, 0.0], 0.0)],
1539            inequality_constraints: vec![],
1540            equality_constraints: vec![],
1541            description: "Zakharov function variant 2".to_string(),
1542            multimodal: false,
1543            dimensions: vec![2],
1544        },
1545    );
1546
1547    println!(
1548        "šŸ“Š Loaded metadata for {} test functions (explicit definitions)",
1549        metadata.len()
1550    );
1551    metadata
1552}
1553
1554/// Helper function to get bounds for a specific function from metadata
1555/// Returns None if function is not found in metadata
1556pub fn get_function_bounds(function_name: &str) -> Option<Vec<(f64, f64)>> {
1557    let metadata = get_function_metadata();
1558    metadata.get(function_name).map(|meta| meta.bounds.clone())
1559}
1560
1561/// Helper function to get bounds as a 2D array for optimization (compatible with existing tests)
1562/// Returns default bounds if function is not found
1563pub fn get_function_bounds_2d(function_name: &str, default_bounds: (f64, f64)) -> [(f64, f64); 2] {
1564    if let Some(bounds) = get_function_bounds(function_name) {
1565        if bounds.len() >= 2 {
1566            [bounds[0], bounds[1]]
1567        } else {
1568            [default_bounds; 2]
1569        }
1570    } else {
1571        [default_bounds; 2]
1572    }
1573}
1574
1575/// Helper function to get bounds as a Vec for optimization (compatible with recorded tests)
1576/// Returns default bounds if function is not found
1577pub fn get_function_bounds_vec(function_name: &str, default_bounds: (f64, f64)) -> Vec<(f64, f64)> {
1578    if let Some(bounds) = get_function_bounds(function_name) {
1579        if bounds.len() >= 2 {
1580            bounds
1581        } else {
1582            vec![default_bounds; 2]
1583        }
1584    } else {
1585        vec![default_bounds; 2]
1586    }
1587}
1588
1589#[cfg(test)]
1590mod tests {
1591    use super::*;
1592    use ndarray::Array1;
1593
1594    /// Helper function to get a function by name and call it
1595    /// This uses a match statement to map function names to actual function calls
1596    fn call_function(name: &str, x: &Array1<f64>) -> Option<f64> {
1597        match name {
1598            // Unimodal functions
1599            "sphere" => Some(sphere(x)),
1600            "rosenbrock" => Some(rosenbrock(x)),
1601            "booth" => Some(booth(x)),
1602            "matyas" => Some(matyas(x)),
1603            "beale" => Some(beale(x)),
1604            "himmelblau" => Some(himmelblau(x)),
1605            "sum_squares" => Some(sum_squares(x)),
1606            "different_powers" => Some(different_powers(x)),
1607            "elliptic" => Some(elliptic(x)),
1608            "cigar" => Some(cigar(x)),
1609            "tablet" => Some(tablet(x)),
1610            "discus" => Some(discus(x)),
1611            "ridge" => Some(ridge(x)),
1612            "sharp_ridge" => Some(sharp_ridge(x)),
1613            "perm_0_d_beta" => Some(perm_0_d_beta(x)),
1614            "perm_d_beta" => Some(perm_d_beta(x)),
1615
1616            // Multimodal functions
1617            "ackley" => Some(ackley(x)),
1618            "rastrigin" => Some(rastrigin(x)),
1619            "griewank" => Some(griewank(x)),
1620            "schwefel" => Some(schwefel(x)),
1621            "branin" => Some(branin(x)),
1622            "goldstein_price" => Some(goldstein_price(x)),
1623            "six_hump_camel" => Some(six_hump_camel(x)),
1624            "hartman_4d" => Some(hartman_4d(x)),
1625            "xin_she_yang_n1" => Some(xin_she_yang_n1(x)),
1626            "katsuura" => Some(katsuura(x)),
1627            "happycat" => Some(happycat(x)),
1628
1629            // Modern functions
1630            "gramacy_lee_2012" => Some(gramacy_lee_2012(x)),
1631            "forrester_2008" => Some(forrester_2008(x)),
1632            "power_sum" => Some(power_sum(x)),
1633            "shekel" => Some(shekel(x)),
1634            "gramacy_lee_function" => Some(gramacy_lee_function(x)),
1635
1636            // Composite functions
1637            "expanded_griewank_rosenbrock" => Some(expanded_griewank_rosenbrock(x)),
1638
1639            // Constrained functions (skip constraint tests for now)
1640            "rosenbrock_disk_constraint" | "binh_korn_constraint1" => None,
1641
1642            _ => None,
1643        }
1644    }
1645
1646    #[test]
1647    fn test_all_function_minima() {
1648        let metadata = get_function_metadata();
1649        let tolerance = 1e-10; // Very small tolerance for exact matches
1650        let loose_tolerance = 1e-3; // Looser tolerance for approximate matches
1651
1652        for (func_name, meta) in metadata.iter() {
1653            // Skip constrained functions as they require special handling
1654            if !meta.inequality_constraints.is_empty() || !meta.equality_constraints.is_empty() {
1655                continue;
1656            }
1657
1658            println!("Testing function: {}", func_name);
1659
1660            // Test each global minimum
1661            for (minimum_location, expected_value) in &meta.global_minima {
1662                let x = Array1::from_vec(minimum_location.clone());
1663
1664                if let Some(actual_value) = call_function(func_name, &x) {
1665                    let error = (actual_value - expected_value).abs();
1666
1667                    // Use different tolerances based on the expected value magnitude
1668                    let test_tolerance = if expected_value.abs() > 1.0 {
1669                        loose_tolerance * expected_value.abs()
1670                    } else {
1671                        loose_tolerance
1672                    };
1673
1674                    println!(
1675                        "  {} at {:?}: expected {:.6}, got {:.6}, error {:.2e}",
1676                        func_name, minimum_location, expected_value, actual_value, error
1677                    );
1678
1679                    assert!(
1680                        error <= test_tolerance,
1681                        "Function {} failed: at {:?}, expected {:.10}, got {:.10}, error {:.2e} > tolerance {:.2e}",
1682                        func_name,
1683                        minimum_location,
1684                        expected_value,
1685                        actual_value,
1686                        error,
1687                        test_tolerance
1688                    );
1689
1690                    println!("  āœ“ {} passed with error {:.2e}", func_name, error);
1691                } else {
1692                    println!(
1693                        "  ⚠ Skipped {} (not implemented in test dispatcher)",
1694                        func_name
1695                    );
1696                }
1697            }
1698        }
1699
1700        println!("\nšŸŽ‰ All function minima tests completed!");
1701    }
1702
1703    #[test]
1704    fn test_specific_challenging_functions() {
1705        let tolerance = 1e-5;
1706
1707        // Test some particularly challenging functions with known good values
1708
1709        // Gramacy & Lee 2012 - should be very precise
1710        let x = Array1::from_vec(vec![0.548563444114526]);
1711        let result = gramacy_lee_2012(&x);
1712        let expected = -0.869011134989500;
1713        assert!(
1714            (result - expected).abs() < tolerance,
1715            "Gramacy & Lee 2012: expected {}, got {}",
1716            expected,
1717            result
1718        );
1719
1720        // Forrester 2008 - should be very precise
1721        let x = Array1::from_vec(vec![0.757249]);
1722        let result = forrester_2008(&x);
1723        let expected = -6.02074;
1724        assert!(
1725            (result - expected).abs() < tolerance,
1726            "Forrester 2008: expected {}, got {}",
1727            expected,
1728            result
1729        );
1730
1731        // Hartmann 4D - should be close
1732        let x = Array1::from_vec(vec![0.1873, 0.1936, 0.5576, 0.2647]);
1733        let result = hartman_4d(&x);
1734        let expected = -3.72983;
1735        assert!(
1736            (result - expected).abs() < tolerance,
1737            "Hartmann 4D: expected {}, got {}",
1738            expected,
1739            result
1740        );
1741
1742        // Shekel - should be close (looser tolerance due to numerical precision)
1743        let x = Array1::from_vec(vec![4.0, 4.0, 4.0, 4.0]);
1744        let result = shekel(&x);
1745        let expected = -10.5364;
1746        let shekel_tolerance = 1e-3; // Looser tolerance for Shekel
1747        assert!(
1748            (result - expected).abs() < shekel_tolerance,
1749            "Shekel: expected {}, got {}",
1750            expected,
1751            result
1752        );
1753    }
1754
1755    #[test]
1756    fn test_simple_unimodal_functions() {
1757        let tolerance = 1e-12;
1758
1759        // Test functions that should have exact zeros
1760        let x = Array1::from_vec(vec![0.0, 0.0]);
1761
1762        assert_eq!(sphere(&x), 0.0);
1763        assert_eq!(sum_squares(&x), 0.0);
1764        assert_eq!(different_powers(&x), 0.0);
1765        assert_eq!(elliptic(&x), 0.0);
1766        assert_eq!(cigar(&x), 0.0);
1767        assert_eq!(tablet(&x), 0.0);
1768        assert_eq!(discus(&x), 0.0);
1769        assert_eq!(ridge(&x), 0.0);
1770        assert_eq!(sharp_ridge(&x), 0.0);
1771        assert_eq!(xin_she_yang_n1(&x), 0.0);
1772
1773        // Test functions with specific minima
1774        let x = Array1::from_vec(vec![1.0, 1.0]);
1775        assert!((rosenbrock(&x) - 0.0).abs() < tolerance);
1776        assert!((expanded_griewank_rosenbrock(&x) - 0.0).abs() < tolerance);
1777
1778        let x = Array1::from_vec(vec![1.0, 3.0]);
1779        assert!((booth(&x) - 0.0).abs() < tolerance);
1780
1781        let x = Array1::from_vec(vec![0.0, 0.0]);
1782        assert!((matyas(&x) - 0.0).abs() < tolerance);
1783
1784        let x = Array1::from_vec(vec![3.0, 0.5]);
1785        assert!((beale(&x) - 0.0).abs() < tolerance);
1786    }
1787
1788    #[test]
1789    fn test_multimodal_functions() {
1790        let tolerance = 1e-10;
1791
1792        // Test functions that should be zero at origin
1793        let x = Array1::from_vec(vec![0.0, 0.0]);
1794
1795        assert!((ackley(&x) - 0.0).abs() < tolerance);
1796        assert!((rastrigin(&x) - 0.0).abs() < tolerance);
1797        assert!((griewank(&x) - 0.0).abs() < tolerance);
1798
1799        // Test Schwefel at its known minimum
1800        let x = Array1::from_vec(vec![420.9687, 420.9687]);
1801        assert!((schwefel(&x) - 0.0).abs() < 1e-3); // Schwefel is less precise
1802    }
1803
1804    #[test]
1805    fn test_perm_functions() {
1806        let tolerance = 1e-12;
1807
1808        // Test Perm 0,d,β at (1, 1/2)
1809        let x = Array1::from_vec(vec![1.0, 0.5]);
1810        assert!((perm_0_d_beta(&x) - 0.0).abs() < tolerance);
1811        assert!((perm_d_beta(&x) - 0.0).abs() < tolerance);
1812    }
1813
1814    #[test]
1815    fn test_function_metadata_completeness() {
1816        let metadata = get_function_metadata();
1817
1818        // Ensure all functions have proper metadata
1819        for (name, meta) in metadata.iter() {
1820            assert!(!meta.name.is_empty(), "Function {} has empty name", name);
1821            assert!(!meta.bounds.is_empty(), "Function {} has no bounds", name);
1822            // Allow functions with no global minima (e.g., power_sum with inconsistent constraints)
1823            // assert!(!meta.global_minima.is_empty(), "Function {} has no global minima", name);
1824            assert!(
1825                !meta.description.is_empty(),
1826                "Function {} has no description",
1827                name
1828            );
1829            assert!(
1830                !meta.dimensions.is_empty(),
1831                "Function {} has no dimensions",
1832                name
1833            );
1834
1835            // Check that bounds make sense
1836            for (lower, upper) in &meta.bounds {
1837                assert!(
1838                    lower < upper,
1839                    "Function {} has invalid bounds: {} >= {}",
1840                    name,
1841                    lower,
1842                    upper
1843                );
1844            }
1845
1846            // Check that global minima have correct dimensionality
1847            for (location, _value) in &meta.global_minima {
1848                if !meta.bounds.is_empty() {
1849                    // Allow some flexibility: bounds should match the global minima dimensions
1850                    // If they don't match exactly, print a warning instead of failing
1851                    if location.len() != meta.bounds.len() {
1852                        println!(
1853                            "āš ļø  Function {} has dimension mismatch: global minimum {}D vs bounds {}D",
1854                            name,
1855                            location.len(),
1856                            meta.bounds.len()
1857                        );
1858                        // Only fail if the mismatch is severe (not just 2D vs 4D for example)
1859                        if location.len() > meta.bounds.len() * 2 {
1860                            panic!(
1861                                "Function {} has severe dimension mismatch: {} vs bounds {}",
1862                                name,
1863                                location.len(),
1864                                meta.bounds.len()
1865                            );
1866                        }
1867                    }
1868                }
1869            }
1870        }
1871
1872        println!("āœ“ All {} functions have complete metadata", metadata.len());
1873    }
1874}