evograd-diff 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. evograd/__init__.py +67 -0
  2. evograd/algorithms/__init__.py +138 -0
  3. evograd/algorithms/cmaes.py +1365 -0
  4. evograd/algorithms/de.py +895 -0
  5. evograd/algorithms/ga.py +532 -0
  6. evograd/algorithms/pso.py +648 -0
  7. evograd/algorithms/shade.py +1165 -0
  8. evograd/benchmarks/functions/__init__.py +229 -0
  9. evograd/benchmarks/functions/base.py +217 -0
  10. evograd/benchmarks/functions/cec2017/__init__.py +250 -0
  11. evograd/benchmarks/functions/cec2017/basic.py +413 -0
  12. evograd/benchmarks/functions/cec2017/composition.py +580 -0
  13. evograd/benchmarks/functions/cec2017/data.pkl +0 -0
  14. evograd/benchmarks/functions/cec2017/data.py +350 -0
  15. evograd/benchmarks/functions/cec2017/hybrid.py +406 -0
  16. evograd/benchmarks/functions/cec2017/simple.py +326 -0
  17. evograd/benchmarks/functions/classical.py +649 -0
  18. evograd/benchmarks/functions/smoothed_funnel.py +476 -0
  19. evograd/benchmarks/functions/transforms.py +463 -0
  20. evograd/benchmarks/run_benchmark_functions.py +1208 -0
  21. evograd/core/__init__.py +73 -0
  22. evograd/core/algorithm.py +778 -0
  23. evograd/core/maximize.py +269 -0
  24. evograd/core/minimize.py +740 -0
  25. evograd/core/problem.py +444 -0
  26. evograd/core/result.py +571 -0
  27. evograd/core/termination.py +602 -0
  28. evograd/operators/__init__.py +178 -0
  29. evograd/operators/crossover.py +1117 -0
  30. evograd/operators/mutation.py +1098 -0
  31. evograd/operators/relaxations.py +175 -0
  32. evograd/operators/repair.py +601 -0
  33. evograd/operators/sampling.py +577 -0
  34. evograd/operators/selection.py +981 -0
  35. evograd/operators/survival.py +1000 -0
  36. evograd/tests/__init__.py +11 -0
  37. evograd/tests/run_all.py +78 -0
  38. evograd/tests/test_core.py +528 -0
  39. evograd/tests/test_ga.py +572 -0
  40. evograd/tests/test_operators.py +662 -0
  41. evograd/tests/test_per_individual.py +326 -0
  42. evograd/tests/test_utils.py +328 -0
  43. evograd/utils/__init__.py +97 -0
  44. evograd/utils/callbacks.py +926 -0
  45. evograd/utils/device.py +502 -0
  46. evograd/utils/duplicates.py +421 -0
  47. evograd_diff-0.1.0.dist-info/METADATA +439 -0
  48. evograd_diff-0.1.0.dist-info/RECORD +50 -0
  49. evograd_diff-0.1.0.dist-info/WHEEL +4 -0
  50. evograd_diff-0.1.0.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,229 @@
1
+ """
2
+ EvoGrad Benchmark Functions.
3
+
4
+ This package provides a comprehensive set of benchmark functions for
5
+ testing and comparing optimization algorithms.
6
+
7
+ Categories:
8
+ - Classical: Standard test functions (Sphere, Rosenbrock, Rastrigin, etc.)
9
+ - CEC 2017: Competition benchmark suite (F1-F30)
10
+ - Smoothed Funnel: Multi-basin problems designed for differentiable EAs
11
+ - Transforms: Wrappers for creating shifted/rotated variants
12
+
13
+ Usage:
14
+ >>> from evograd.benchmarks.functions import Sphere, Rastrigin
15
+ >>> from evograd.benchmarks.functions import CEC2017_F1, get_cec2017_function
16
+ >>> from evograd.benchmarks.functions import SmoothedMultiFunnel
17
+ >>>
18
+ >>> # Create function with default bounds
19
+ >>> sphere = Sphere(n_var=30)
20
+ >>>
21
+ >>> # Create function with custom bounds
22
+ >>> sphere = Sphere(n_var=30, xl=-5.0, xu=5.0)
23
+ >>>
24
+ >>> # Evaluate population
25
+ >>> x = torch.randn(100, 30)
26
+ >>> f = sphere(x) # Shape: [100]
27
+ >>>
28
+ >>> # Get bounds
29
+ >>> lb, ub = sphere.bounds
30
+ >>>
31
+ >>> # CEC 2017 functions
32
+ >>> f1 = CEC2017_F1(n_var=10)
33
+ >>> f15 = get_cec2017_function(15, n_var=10)
34
+ >>>
35
+ >>> # Smoothed multi-funnel (designed for differentiable EAs)
36
+ >>> funnel = SmoothedMultiFunnel(n_var=10, tau=1.0, delta=10.0)
37
+ """
38
+
39
+ from .base import BenchmarkFunction, CompositeFunction
40
+
41
+ from .classical import (
42
+ # Unimodal
43
+ Sphere,
44
+ Ellipsoid,
45
+ SumOfDifferentPowers,
46
+ Schwefel222,
47
+ Cigar,
48
+ Discus,
49
+ BentCigar,
50
+ Rosenbrock,
51
+ DixonPrice,
52
+ Powell,
53
+ Trid,
54
+ # Multimodal
55
+ Rastrigin,
56
+ Ackley,
57
+ Griewank,
58
+ Schwefel,
59
+ Levy,
60
+ Michalewicz,
61
+ Zakharov,
62
+ Weierstrass,
63
+ Alpine,
64
+ Salomon,
65
+ StyblinskiTang,
66
+ # Registry
67
+ CLASSICAL_FUNCTIONS,
68
+ )
69
+
70
+ from .transforms import (
71
+ ShiftedFunction,
72
+ RotatedFunction,
73
+ ShiftedRotatedFunction,
74
+ ScaledFunction,
75
+ AsymmetricFunction,
76
+ OscillatedFunction,
77
+ BiasedFunction,
78
+ generate_rotation_matrix,
79
+ generate_shift_vector,
80
+ )
81
+
82
+ # CEC 2017 Benchmark Suite
83
+ from .cec2017 import (
84
+ # Simple functions (F1-F10)
85
+ CEC2017_F1,
86
+ CEC2017_F2,
87
+ CEC2017_F3,
88
+ CEC2017_F4,
89
+ CEC2017_F5,
90
+ CEC2017_F6,
91
+ CEC2017_F7,
92
+ CEC2017_F8,
93
+ CEC2017_F9,
94
+ CEC2017_F10,
95
+ # Hybrid functions (F11-F20)
96
+ CEC2017_F11,
97
+ CEC2017_F12,
98
+ CEC2017_F13,
99
+ CEC2017_F14,
100
+ CEC2017_F15,
101
+ CEC2017_F16,
102
+ CEC2017_F17,
103
+ CEC2017_F18,
104
+ CEC2017_F19,
105
+ CEC2017_F20,
106
+ # Composition functions (F21-F30)
107
+ CEC2017_F21,
108
+ CEC2017_F22,
109
+ CEC2017_F23,
110
+ CEC2017_F24,
111
+ CEC2017_F25,
112
+ CEC2017_F26,
113
+ CEC2017_F27,
114
+ CEC2017_F28,
115
+ CEC2017_F29,
116
+ CEC2017_F30,
117
+ # Registries
118
+ CEC2017_FUNCTIONS,
119
+ ALL_CEC2017_CLASSES,
120
+ # Utilities
121
+ get_function as get_cec2017_function,
122
+ )
123
+
124
+ # Smoothed Multi-Funnel Functions (designed for differentiable EAs)
125
+ from .smoothed_funnel import (
126
+ # Core utilities
127
+ log_sum_exp_min,
128
+ random_orthogonal_matrix,
129
+ # Benchmark functions
130
+ MultiBasinRastrigin,
131
+ MultiBasinRosenbrock,
132
+ DeceptiveLandscape,
133
+ # Registry
134
+ SMOOTHED_FUNNEL_FUNCTIONS,
135
+ )
136
+
137
+ # Combined registry of all functions
138
+ ALL_FUNCTIONS = {
139
+ **CLASSICAL_FUNCTIONS,
140
+ **CEC2017_FUNCTIONS,
141
+ **SMOOTHED_FUNNEL_FUNCTIONS,
142
+ }
143
+
144
+ __all__ = [
145
+ # Base
146
+ "BenchmarkFunction",
147
+ "CompositeFunction",
148
+ # Classical - Unimodal
149
+ "Sphere",
150
+ "Ellipsoid",
151
+ "SumOfDifferentPowers",
152
+ "Schwefel222",
153
+ "Cigar",
154
+ "Discus",
155
+ "BentCigar",
156
+ "Rosenbrock",
157
+ "DixonPrice",
158
+ "Powell",
159
+ "Trid",
160
+ # Classical - Multimodal
161
+ "Rastrigin",
162
+ "Ackley",
163
+ "Griewank",
164
+ "Schwefel",
165
+ "Levy",
166
+ "Michalewicz",
167
+ "Zakharov",
168
+ "Weierstrass",
169
+ "Alpine",
170
+ "Salomon",
171
+ "StyblinskiTang",
172
+ # Transforms
173
+ "ShiftedFunction",
174
+ "RotatedFunction",
175
+ "ShiftedRotatedFunction",
176
+ "ScaledFunction",
177
+ "AsymmetricFunction",
178
+ "OscillatedFunction",
179
+ "BiasedFunction",
180
+ "generate_rotation_matrix",
181
+ "generate_shift_vector",
182
+ # CEC 2017 - Simple (F1-F10)
183
+ "CEC2017_F1",
184
+ "CEC2017_F2",
185
+ "CEC2017_F3",
186
+ "CEC2017_F4",
187
+ "CEC2017_F5",
188
+ "CEC2017_F6",
189
+ "CEC2017_F7",
190
+ "CEC2017_F8",
191
+ "CEC2017_F9",
192
+ "CEC2017_F10",
193
+ # CEC 2017 - Hybrid (F11-F20)
194
+ "CEC2017_F11",
195
+ "CEC2017_F12",
196
+ "CEC2017_F13",
197
+ "CEC2017_F14",
198
+ "CEC2017_F15",
199
+ "CEC2017_F16",
200
+ "CEC2017_F17",
201
+ "CEC2017_F18",
202
+ "CEC2017_F19",
203
+ "CEC2017_F20",
204
+ # CEC 2017 - Composition (F21-F30)
205
+ "CEC2017_F21",
206
+ "CEC2017_F22",
207
+ "CEC2017_F23",
208
+ "CEC2017_F24",
209
+ "CEC2017_F25",
210
+ "CEC2017_F26",
211
+ "CEC2017_F27",
212
+ "CEC2017_F28",
213
+ "CEC2017_F29",
214
+ "CEC2017_F30",
215
+ # CEC 2017 utilities
216
+ "CEC2017_FUNCTIONS",
217
+ "ALL_CEC2017_CLASSES",
218
+ "get_cec2017_function",
219
+ # Smoothed Multi-Funnel (for differentiable EAs)
220
+ "log_sum_exp_min",
221
+ "random_orthogonal_matrix",
222
+ "MultiBasinRastrigin",
223
+ "MultiBasinRosenbrock",
224
+ "DeceptiveLandscape",
225
+ "SMOOTHED_FUNNEL_FUNCTIONS",
226
+ # Registries
227
+ "CLASSICAL_FUNCTIONS",
228
+ "ALL_FUNCTIONS",
229
+ ]
@@ -0,0 +1,217 @@
1
+ """
2
+ Base class for benchmark functions.
3
+
4
+ All benchmark functions inherit from BenchmarkFunction and implement
5
+ the __call__ method for evaluation. Bounds can be specified per-function
6
+ or overridden at instantiation.
7
+ """
8
+
9
+ from abc import ABC, abstractmethod
10
+ from typing import Optional, Tuple, Union
11
+
12
+ import torch
13
+ from torch import Tensor
14
+
15
+
16
+ class BenchmarkFunction(ABC):
17
+ """
18
+ Abstract base class for benchmark optimization functions.
19
+
20
+ All benchmark functions support:
21
+ - Configurable dimensionality (n_var)
22
+ - Configurable bounds (xl, xu) - can be scalar or per-dimension
23
+ - Known optimal value and location
24
+ - Batch evaluation for populations
25
+
26
+ Args:
27
+ n_var: Number of decision variables (dimensions).
28
+ xl: Lower bound(s). Scalar or tensor of shape [n_var].
29
+ xu: Upper bound(s). Scalar or tensor of shape [n_var].
30
+
31
+ Example:
32
+ >>> sphere = Sphere(n_var=10)
33
+ >>> x = torch.randn(100, 10) # Population of 100 individuals
34
+ >>> f = sphere(x) # Shape: [100]
35
+
36
+ >>> # Custom bounds
37
+ >>> sphere = Sphere(n_var=10, xl=-5.0, xu=5.0)
38
+ """
39
+
40
+ # Class attributes (can be overridden in subclasses)
41
+ name: str = "base_function"
42
+ optimal_value: float = 0.0
43
+
44
+ def __init__(
45
+ self,
46
+ n_var: int = 30,
47
+ xl: Optional[Union[float, Tensor]] = None,
48
+ xu: Optional[Union[float, Tensor]] = None,
49
+ ):
50
+ """
51
+ Initialize benchmark function.
52
+
53
+ Args:
54
+ n_var: Number of decision variables.
55
+ xl: Lower bound(s). If None, uses default_bounds().
56
+ xu: Upper bound(s). If None, uses default_bounds().
57
+ """
58
+ self.n_var = n_var
59
+
60
+ # Get default bounds
61
+ default_lb, default_ub = self.default_bounds()
62
+
63
+ # Set lower bounds
64
+ if xl is None:
65
+ xl = default_lb
66
+ if isinstance(xl, (int, float)):
67
+ self._xl = torch.full((n_var,), float(xl))
68
+ else:
69
+ self._xl = xl.clone() if isinstance(xl, Tensor) else torch.tensor(xl)
70
+ if self._xl.numel() == 1:
71
+ self._xl = self._xl.expand(n_var).clone()
72
+
73
+ # Set upper bounds
74
+ if xu is None:
75
+ xu = default_ub
76
+ if isinstance(xu, (int, float)):
77
+ self._xu = torch.full((n_var,), float(xu))
78
+ else:
79
+ self._xu = xu.clone() if isinstance(xu, Tensor) else torch.tensor(xu)
80
+ if self._xu.numel() == 1:
81
+ self._xu = self._xu.expand(n_var).clone()
82
+
83
+ # Compute optimal location (default: origin)
84
+ self._optimal_x = self._compute_optimal_x()
85
+
86
+ @property
87
+ def xl(self) -> Tensor:
88
+ """Lower bounds as tensor of shape [n_var]."""
89
+ return self._xl
90
+
91
+ @property
92
+ def xu(self) -> Tensor:
93
+ """Upper bounds as tensor of shape [n_var]."""
94
+ return self._xu
95
+
96
+ @property
97
+ def bounds(self) -> Tuple[Tensor, Tensor]:
98
+ """Return (lower_bounds, upper_bounds) tuple."""
99
+ return (self._xl, self._xu)
100
+
101
+ @property
102
+ def optimal_x(self) -> Tensor:
103
+ """Optimal solution location."""
104
+ return self._optimal_x
105
+
106
+ def _compute_optimal_x(self) -> Tensor:
107
+ """
108
+ Compute the optimal solution location.
109
+
110
+ Override in subclasses if optimal is not at origin.
111
+ """
112
+ return torch.zeros(self.n_var)
113
+
114
+ @abstractmethod
115
+ def default_bounds(self) -> Tuple[float, float]:
116
+ """
117
+ Return default (lower, upper) bounds for this function.
118
+
119
+ Returns:
120
+ Tuple of (lower_bound, upper_bound) scalars.
121
+ """
122
+ pass
123
+
124
+ @abstractmethod
125
+ def __call__(self, x: Tensor) -> Tensor:
126
+ """
127
+ Evaluate the function at point(s) x.
128
+
129
+ Args:
130
+ x: Decision variables of shape [..., n_var].
131
+ Can be single point [n_var] or batch [N, n_var].
132
+
133
+ Returns:
134
+ Function values of shape [...] (same batch dimensions as input).
135
+ """
136
+ pass
137
+
138
+ def to(self, device: torch.device) -> "BenchmarkFunction":
139
+ """Move bounds to specified device."""
140
+ self._xl = self._xl.to(device)
141
+ self._xu = self._xu.to(device)
142
+ self._optimal_x = self._optimal_x.to(device)
143
+ return self
144
+
145
+ def __repr__(self) -> str:
146
+ return (
147
+ f"{self.__class__.__name__}("
148
+ f"n_var={self.n_var}, "
149
+ f"xl={self._xl[0].item():.2f}, "
150
+ f"xu={self._xu[0].item():.2f})"
151
+ )
152
+
153
+ def info(self) -> str:
154
+ """Return detailed information about the function."""
155
+ return (
156
+ f"Function: {self.name}\n"
157
+ f" Dimensions: {self.n_var}\n"
158
+ f" Bounds: [{self._xl[0].item():.2f}, {self._xu[0].item():.2f}]\n"
159
+ f" Optimal value: {self.optimal_value}\n"
160
+ f" Optimal location: {self._optimal_x[:3].tolist()}..."
161
+ )
162
+
163
+
164
+ class CompositeFunction(BenchmarkFunction):
165
+ """
166
+ Composite function combining multiple base functions.
167
+
168
+ Used for creating CEC-style hybrid and composition functions.
169
+ """
170
+
171
+ def __init__(
172
+ self,
173
+ functions: list,
174
+ weights: Optional[Tensor] = None,
175
+ n_var: int = 30,
176
+ xl: Optional[Union[float, Tensor]] = None,
177
+ xu: Optional[Union[float, Tensor]] = None,
178
+ ):
179
+ """
180
+ Initialize composite function.
181
+
182
+ Args:
183
+ functions: List of BenchmarkFunction instances.
184
+ weights: Weights for combining functions. If None, equal weights.
185
+ n_var: Number of decision variables.
186
+ xl: Lower bounds.
187
+ xu: Upper bounds.
188
+ """
189
+ self.functions = functions
190
+ self.n_functions = len(functions)
191
+
192
+ if weights is None:
193
+ self.weights = torch.ones(self.n_functions) / self.n_functions
194
+ else:
195
+ self.weights = weights / weights.sum()
196
+
197
+ # Use first function's bounds as default
198
+ if xl is None and functions:
199
+ xl = functions[0]._xl[0].item()
200
+ if xu is None and functions:
201
+ xu = functions[0]._xu[0].item()
202
+
203
+ super().__init__(n_var=n_var, xl=xl, xu=xu)
204
+ self.name = "composite"
205
+
206
+ def default_bounds(self) -> Tuple[float, float]:
207
+ return (-100.0, 100.0)
208
+
209
+ def __call__(self, x: Tensor) -> Tensor:
210
+ """Weighted sum of component functions."""
211
+ result = torch.zeros(x.shape[:-1], device=x.device, dtype=x.dtype)
212
+ weights = self.weights.to(x.device, x.dtype)
213
+
214
+ for i, func in enumerate(self.functions):
215
+ result = result + weights[i] * func(x)
216
+
217
+ return result
@@ -0,0 +1,250 @@
1
+ """
2
+ CEC 2017 Benchmark Functions for PyTorch.
3
+
4
+ This package provides a comprehensive implementation of the CEC 2017
5
+ benchmark suite for real-parameter single objective optimization.
6
+
7
+ The suite consists of 30 functions:
8
+ - F1-F10: Simple functions (shifted and rotated basic functions)
9
+ - F11-F20: Hybrid functions (combinations of basic functions)
10
+ - F21-F30: Composition functions (weighted combinations)
11
+
12
+ All functions:
13
+ - Accept PyTorch tensors
14
+ - Support batch evaluation
15
+ - Have bounds of [-100, 100]
16
+ - Have optimal values of F_i* = i * 100
17
+
18
+ Usage:
19
+ >>> from evograd.benchmarks.functions.cec2017 import CEC2017_F1, CEC2017_F10
20
+ >>>
21
+ >>> # Create function with default settings
22
+ >>> f1 = CEC2017_F1(n_var=10)
23
+ >>>
24
+ >>> # Evaluate population
25
+ >>> x = torch.randn(100, 10)
26
+ >>> fitness = f1(x) # Shape: [100]
27
+ >>>
28
+ >>> # Get optimal value
29
+ >>> print(f"Optimal value: {f1.optimal_value}") # 100.0
30
+
31
+ Supported dimensions: 2, 10, 20, 30, 50, 100 (for official data)
32
+ Other dimensions will use randomly generated transforms.
33
+
34
+ Reference:
35
+ N. H. Awad, M. Z. Ali, J. J. Liang, B. Y. Qu, and P. N. Suganthan,
36
+ "Problem Definitions and Evaluation Criteria for the CEC 2017
37
+ Special Session and Competition on Single Objective Real-Parameter
38
+ Numerical Optimization," Technical Report, 2016.
39
+ """
40
+
41
+ # Basic functions (stateless, for internal use)
42
+ from .basic import (
43
+ bent_cigar,
44
+ sum_diff_pow,
45
+ zakharov,
46
+ rosenbrock,
47
+ rastrigin,
48
+ expanded_schaffers_f6,
49
+ lunacek_bi_rastrigin,
50
+ non_cont_rastrigin,
51
+ levy,
52
+ modified_schwefel,
53
+ high_conditioned_elliptic,
54
+ discus,
55
+ ackley,
56
+ weierstrass,
57
+ griewank,
58
+ katsuura,
59
+ happy_cat,
60
+ h_g_bat,
61
+ expanded_griewanks_plus_rosenbrock,
62
+ schaffers_f7,
63
+ BASIC_FUNCTIONS,
64
+ )
65
+
66
+ # Simple functions (F1-F10)
67
+ from .simple import (
68
+ CEC2017_F1,
69
+ CEC2017_F2,
70
+ CEC2017_F3,
71
+ CEC2017_F4,
72
+ CEC2017_F5,
73
+ CEC2017_F6,
74
+ CEC2017_F7,
75
+ CEC2017_F8,
76
+ CEC2017_F9,
77
+ CEC2017_F10,
78
+ SIMPLE_FUNCTIONS,
79
+ )
80
+
81
+ # Hybrid functions (F11-F20)
82
+ from .hybrid import (
83
+ CEC2017_F11,
84
+ CEC2017_F12,
85
+ CEC2017_F13,
86
+ CEC2017_F14,
87
+ CEC2017_F15,
88
+ CEC2017_F16,
89
+ CEC2017_F17,
90
+ CEC2017_F18,
91
+ CEC2017_F19,
92
+ CEC2017_F20,
93
+ HYBRID_FUNCTIONS,
94
+ )
95
+
96
+ # Composition functions (F21-F30)
97
+ from .composition import (
98
+ CEC2017_F21,
99
+ CEC2017_F22,
100
+ CEC2017_F23,
101
+ CEC2017_F24,
102
+ CEC2017_F25,
103
+ CEC2017_F26,
104
+ CEC2017_F27,
105
+ CEC2017_F28,
106
+ CEC2017_F29,
107
+ CEC2017_F30,
108
+ COMPOSITION_FUNCTIONS,
109
+ )
110
+
111
+ # Data utilities
112
+ from .data import (
113
+ data_available,
114
+ get_rotation,
115
+ get_rotation_cf,
116
+ get_shift,
117
+ get_shift_cf,
118
+ get_shuffle,
119
+ get_shuffle_cf,
120
+ generate_rotation_matrix,
121
+ generate_shift_vector,
122
+ generate_shuffle,
123
+ shift_rotate,
124
+ shuffle_and_partition,
125
+ SUPPORTED_DIMS,
126
+ )
127
+
128
+
129
+ # Combined registry of all CEC 2017 functions
130
+ CEC2017_FUNCTIONS = {
131
+ **SIMPLE_FUNCTIONS,
132
+ **HYBRID_FUNCTIONS,
133
+ **COMPOSITION_FUNCTIONS,
134
+ }
135
+
136
+ # List of all function classes for iteration
137
+ ALL_CEC2017_CLASSES = [
138
+ # Simple (F1-F10)
139
+ CEC2017_F1, CEC2017_F2, CEC2017_F3, CEC2017_F4, CEC2017_F5,
140
+ CEC2017_F6, CEC2017_F7, CEC2017_F8, CEC2017_F9, CEC2017_F10,
141
+ # Hybrid (F11-F20)
142
+ CEC2017_F11, CEC2017_F12, CEC2017_F13, CEC2017_F14, CEC2017_F15,
143
+ CEC2017_F16, CEC2017_F17, CEC2017_F18, CEC2017_F19, CEC2017_F20,
144
+ # Composition (F21-F30)
145
+ CEC2017_F21, CEC2017_F22, CEC2017_F23, CEC2017_F24, CEC2017_F25,
146
+ CEC2017_F26, CEC2017_F27, CEC2017_F28, CEC2017_F29, CEC2017_F30,
147
+ ]
148
+
149
+
150
+ def get_function(func_num: int, n_var: int = 10, **kwargs):
151
+ """
152
+ Get CEC 2017 function by number.
153
+
154
+ Args:
155
+ func_num: Function number (1-30).
156
+ n_var: Number of variables.
157
+ **kwargs: Additional arguments passed to the function constructor.
158
+
159
+ Returns:
160
+ BenchmarkFunction instance.
161
+
162
+ Example:
163
+ >>> f1 = get_function(1, n_var=10)
164
+ >>> f15 = get_function(15, n_var=30)
165
+ """
166
+ if func_num < 1 or func_num > 30:
167
+ raise ValueError(f"Function number must be 1-30, got {func_num}")
168
+
169
+ func_class = ALL_CEC2017_CLASSES[func_num - 1]
170
+ return func_class(n_var=n_var, **kwargs)
171
+
172
+
173
+ __all__ = [
174
+ # Basic functions
175
+ "bent_cigar",
176
+ "sum_diff_pow",
177
+ "zakharov",
178
+ "rosenbrock",
179
+ "rastrigin",
180
+ "expanded_schaffers_f6",
181
+ "lunacek_bi_rastrigin",
182
+ "non_cont_rastrigin",
183
+ "levy",
184
+ "modified_schwefel",
185
+ "high_conditioned_elliptic",
186
+ "discus",
187
+ "ackley",
188
+ "weierstrass",
189
+ "griewank",
190
+ "katsuura",
191
+ "happy_cat",
192
+ "h_g_bat",
193
+ "expanded_griewanks_plus_rosenbrock",
194
+ "schaffers_f7",
195
+ "BASIC_FUNCTIONS",
196
+ # Simple functions (F1-F10)
197
+ "CEC2017_F1",
198
+ "CEC2017_F2",
199
+ "CEC2017_F3",
200
+ "CEC2017_F4",
201
+ "CEC2017_F5",
202
+ "CEC2017_F6",
203
+ "CEC2017_F7",
204
+ "CEC2017_F8",
205
+ "CEC2017_F9",
206
+ "CEC2017_F10",
207
+ "SIMPLE_FUNCTIONS",
208
+ # Hybrid functions (F11-F20)
209
+ "CEC2017_F11",
210
+ "CEC2017_F12",
211
+ "CEC2017_F13",
212
+ "CEC2017_F14",
213
+ "CEC2017_F15",
214
+ "CEC2017_F16",
215
+ "CEC2017_F17",
216
+ "CEC2017_F18",
217
+ "CEC2017_F19",
218
+ "CEC2017_F20",
219
+ "HYBRID_FUNCTIONS",
220
+ # Composition functions (F21-F30)
221
+ "CEC2017_F21",
222
+ "CEC2017_F22",
223
+ "CEC2017_F23",
224
+ "CEC2017_F24",
225
+ "CEC2017_F25",
226
+ "CEC2017_F26",
227
+ "CEC2017_F27",
228
+ "CEC2017_F28",
229
+ "CEC2017_F29",
230
+ "CEC2017_F30",
231
+ "COMPOSITION_FUNCTIONS",
232
+ # Combined registries
233
+ "CEC2017_FUNCTIONS",
234
+ "ALL_CEC2017_CLASSES",
235
+ # Utilities
236
+ "get_function",
237
+ "data_available",
238
+ "get_rotation",
239
+ "get_rotation_cf",
240
+ "get_shift",
241
+ "get_shift_cf",
242
+ "get_shuffle",
243
+ "get_shuffle_cf",
244
+ "generate_rotation_matrix",
245
+ "generate_shift_vector",
246
+ "generate_shuffle",
247
+ "shift_rotate",
248
+ "shuffle_and_partition",
249
+ "SUPPORTED_DIMS",
250
+ ]