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,326 @@
1
+ """
2
+ CEC 2017 Simple Functions (F1-F10).
3
+
4
+ Shifted and rotated versions of basic benchmark functions.
5
+
6
+ Reference: CEC 2017 Competition on Real-Parameter Single Objective Optimization
7
+
8
+ F1: Shifted and Rotated Bent Cigar Function
9
+ F2: (Deprecated) Shifted and Rotated Sum of Different Powers Function
10
+ F3: Shifted and Rotated Zakharov Function
11
+ F4: Shifted and Rotated Rosenbrock's Function
12
+ F5: Shifted and Rotated Rastrigin's Function
13
+ F6: Shifted and Rotated Schaffer's F7 Function
14
+ F7: Shifted and Rotated Lunacek Bi-Rastrigin's Function
15
+ F8: Shifted and Rotated Non-Continuous Rastrigin's Function
16
+ F9: Shifted and Rotated Levy Function
17
+ F10: Shifted and Rotated Schwefel's Function
18
+ """
19
+
20
+ from typing import Optional, Tuple
21
+ import warnings
22
+
23
+ import torch
24
+ from torch import Tensor
25
+
26
+ from ..base import BenchmarkFunction
27
+ from . import basic
28
+ from . import data as cec_data
29
+
30
+
31
+ class CEC2017Function(BenchmarkFunction):
32
+ """Base class for CEC 2017 functions with shift and rotation support."""
33
+
34
+ def __init__(
35
+ self,
36
+ func_num: int,
37
+ n_var: int = 10,
38
+ rotation: Optional[Tensor] = None,
39
+ shift: Optional[Tensor] = None,
40
+ seed: Optional[int] = None,
41
+ ):
42
+ """
43
+ Initialize CEC 2017 function.
44
+
45
+ Args:
46
+ func_num: Function number (1-30).
47
+ n_var: Number of variables (2, 10, 20, 30, 50, or 100 for official data).
48
+ rotation: Optional rotation matrix. If None, loads from data or generates.
49
+ shift: Optional shift vector. If None, loads from data or generates.
50
+ seed: Random seed for generating transforms if not provided.
51
+ """
52
+ super().__init__(n_var=n_var, xl=-100.0, xu=100.0)
53
+
54
+ self.func_num = func_num
55
+ self.bias = func_num * 100.0 # F_i* = i * 100
56
+
57
+ # Load or generate rotation matrix
58
+ if rotation is not None:
59
+ self.rotation = rotation
60
+ else:
61
+ self.rotation = cec_data.get_rotation(func_num, n_var, seed=seed)
62
+
63
+ # Load or generate shift vector
64
+ if shift is not None:
65
+ self.shift = shift
66
+ else:
67
+ self.shift = cec_data.get_shift(func_num, n_var, seed=seed)
68
+
69
+ def default_bounds(self) -> Tuple[float, float]:
70
+ return (-100.0, 100.0)
71
+
72
+ def _shift_rotate(self, x: Tensor) -> Tensor:
73
+ """Apply shift and rotation transformation."""
74
+ shift = self.shift.to(x.device, x.dtype)
75
+ rotation = self.rotation.to(x.device, x.dtype)
76
+ return cec_data.shift_rotate(x, shift, rotation)
77
+
78
+
79
+ class CEC2017_F1(CEC2017Function):
80
+ """
81
+ F1: Shifted and Rotated Bent Cigar Function
82
+
83
+ Properties:
84
+ - Unimodal
85
+ - Non-separable
86
+ - Ill-conditioned
87
+ - Optimal value: F1* = 100
88
+ """
89
+ name = "cec2017_f1"
90
+ optimal_value = 100.0
91
+
92
+ def __init__(self, n_var: int = 10, **kwargs):
93
+ super().__init__(func_num=1, n_var=n_var, **kwargs)
94
+
95
+ def __call__(self, x: Tensor) -> Tensor:
96
+ z = self._shift_rotate(x)
97
+ return basic.bent_cigar(z) + self.bias
98
+
99
+
100
+ class CEC2017_F2(CEC2017Function):
101
+ """
102
+ F2: (DEPRECATED) Shifted and Rotated Sum of Different Powers Function
103
+
104
+ Note: This function was deprecated from the CEC 2017 benchmark suite
105
+ due to numerical instability. It is included for completeness.
106
+
107
+ Properties:
108
+ - Unimodal
109
+ - Non-separable
110
+ - Optimal value: F2* = 200
111
+ """
112
+ name = "cec2017_f2"
113
+ optimal_value = 200.0
114
+ _warned = False
115
+
116
+ def __init__(self, n_var: int = 10, **kwargs):
117
+ if not CEC2017_F2._warned:
118
+ warnings.warn(
119
+ "F2 has been deprecated from the CEC 2017 benchmark suite "
120
+ "due to numerical instability.",
121
+ DeprecationWarning,
122
+ )
123
+ CEC2017_F2._warned = True
124
+ super().__init__(func_num=2, n_var=n_var, **kwargs)
125
+
126
+ def __call__(self, x: Tensor) -> Tensor:
127
+ z = self._shift_rotate(x)
128
+ return basic.sum_diff_pow(z) + self.bias
129
+
130
+
131
+ class CEC2017_F3(CEC2017Function):
132
+ """
133
+ F3: Shifted and Rotated Zakharov Function
134
+
135
+ Properties:
136
+ - Unimodal
137
+ - Non-separable
138
+ - Optimal value: F3* = 300
139
+ """
140
+ name = "cec2017_f3"
141
+ optimal_value = 300.0
142
+
143
+ def __init__(self, n_var: int = 10, **kwargs):
144
+ super().__init__(func_num=3, n_var=n_var, **kwargs)
145
+
146
+ def __call__(self, x: Tensor) -> Tensor:
147
+ z = self._shift_rotate(x)
148
+ return basic.zakharov(z) + self.bias
149
+
150
+
151
+ class CEC2017_F4(CEC2017Function):
152
+ """
153
+ F4: Shifted and Rotated Rosenbrock's Function
154
+
155
+ Properties:
156
+ - Multimodal (for high dimensions)
157
+ - Non-separable
158
+ - Optimal value: F4* = 400
159
+ """
160
+ name = "cec2017_f4"
161
+ optimal_value = 400.0
162
+
163
+ def __init__(self, n_var: int = 10, **kwargs):
164
+ super().__init__(func_num=4, n_var=n_var, **kwargs)
165
+
166
+ def __call__(self, x: Tensor) -> Tensor:
167
+ z = self._shift_rotate(x)
168
+ return basic.rosenbrock(z) + self.bias
169
+
170
+
171
+ class CEC2017_F5(CEC2017Function):
172
+ """
173
+ F5: Shifted and Rotated Rastrigin's Function
174
+
175
+ Properties:
176
+ - Highly multimodal
177
+ - Non-separable (after rotation)
178
+ - Optimal value: F5* = 500
179
+ """
180
+ name = "cec2017_f5"
181
+ optimal_value = 500.0
182
+
183
+ def __init__(self, n_var: int = 10, **kwargs):
184
+ super().__init__(func_num=5, n_var=n_var, **kwargs)
185
+
186
+ def __call__(self, x: Tensor) -> Tensor:
187
+ z = self._shift_rotate(x)
188
+ return basic.rastrigin(z) + self.bias
189
+
190
+
191
+ class CEC2017_F6(CEC2017Function):
192
+ """
193
+ F6: Shifted and Rotated Schaffer's F7 Function
194
+
195
+ Properties:
196
+ - Multimodal
197
+ - Non-separable
198
+ - Optimal value: F6* = 600
199
+ """
200
+ name = "cec2017_f6"
201
+ optimal_value = 600.0
202
+
203
+ def __init__(self, n_var: int = 10, **kwargs):
204
+ super().__init__(func_num=6, n_var=n_var, **kwargs)
205
+
206
+ def __call__(self, x: Tensor) -> Tensor:
207
+ z = self._shift_rotate(x)
208
+ return basic.schaffers_f7(z) + self.bias
209
+
210
+
211
+ class CEC2017_F7(CEC2017Function):
212
+ """
213
+ F7: Shifted and Rotated Lunacek Bi-Rastrigin's Function
214
+
215
+ Properties:
216
+ - Multimodal with two global optima regions
217
+ - Non-separable
218
+ - Optimal value: F7* = 700
219
+ """
220
+ name = "cec2017_f7"
221
+ optimal_value = 700.0
222
+
223
+ def __init__(self, n_var: int = 10, **kwargs):
224
+ super().__init__(func_num=7, n_var=n_var, **kwargs)
225
+
226
+ def __call__(self, x: Tensor) -> Tensor:
227
+ # Special case: pass shift and rotation directly to function
228
+ shift = self.shift.to(x.device, x.dtype)
229
+ rotation = self.rotation.to(x.device, x.dtype)
230
+ return basic.lunacek_bi_rastrigin(x, shift, rotation) + self.bias
231
+
232
+
233
+ class CEC2017_F8(CEC2017Function):
234
+ """
235
+ F8: Shifted and Rotated Non-Continuous Rastrigin's Function
236
+
237
+ Properties:
238
+ - Multimodal
239
+ - Non-separable
240
+ - Non-continuous
241
+ - Optimal value: F8* = 800
242
+ """
243
+ name = "cec2017_f8"
244
+ optimal_value = 800.0
245
+
246
+ def __init__(self, n_var: int = 10, **kwargs):
247
+ super().__init__(func_num=8, n_var=n_var, **kwargs)
248
+
249
+ def __call__(self, x: Tensor) -> Tensor:
250
+ # Special case: pass shift and rotation directly to function
251
+ shift = self.shift.to(x.device, x.dtype)
252
+ rotation = self.rotation.to(x.device, x.dtype)
253
+ return basic.non_cont_rastrigin(x, shift, rotation) + self.bias
254
+
255
+
256
+ class CEC2017_F9(CEC2017Function):
257
+ """
258
+ F9: Shifted and Rotated Levy Function
259
+
260
+ Properties:
261
+ - Multimodal
262
+ - Non-separable
263
+ - Optimal value: F9* = 900
264
+ """
265
+ name = "cec2017_f9"
266
+ optimal_value = 900.0
267
+
268
+ def __init__(self, n_var: int = 10, **kwargs):
269
+ super().__init__(func_num=9, n_var=n_var, **kwargs)
270
+
271
+ def __call__(self, x: Tensor) -> Tensor:
272
+ z = self._shift_rotate(x)
273
+ return basic.levy(z) + self.bias
274
+
275
+
276
+ class CEC2017_F10(CEC2017Function):
277
+ """
278
+ F10: Shifted and Rotated Schwefel's Function
279
+
280
+ Properties:
281
+ - Multimodal
282
+ - Non-separable
283
+ - Optimal far from origin
284
+ - Optimal value: F10* = 1000
285
+ """
286
+ name = "cec2017_f10"
287
+ optimal_value = 1000.0
288
+
289
+ def __init__(self, n_var: int = 10, **kwargs):
290
+ super().__init__(func_num=10, n_var=n_var, **kwargs)
291
+
292
+ def __call__(self, x: Tensor) -> Tensor:
293
+ z = self._shift_rotate(x)
294
+ return basic.modified_schwefel(z) + self.bias
295
+
296
+
297
+ # =============================================================================
298
+ # FUNCTION REGISTRY
299
+ # =============================================================================
300
+
301
+ SIMPLE_FUNCTIONS = {
302
+ "cec2017_f1": CEC2017_F1,
303
+ "cec2017_f2": CEC2017_F2,
304
+ "cec2017_f3": CEC2017_F3,
305
+ "cec2017_f4": CEC2017_F4,
306
+ "cec2017_f5": CEC2017_F5,
307
+ "cec2017_f6": CEC2017_F6,
308
+ "cec2017_f7": CEC2017_F7,
309
+ "cec2017_f8": CEC2017_F8,
310
+ "cec2017_f9": CEC2017_F9,
311
+ "cec2017_f10": CEC2017_F10,
312
+ }
313
+
314
+ # List for iteration
315
+ all_functions = [
316
+ CEC2017_F1,
317
+ CEC2017_F2,
318
+ CEC2017_F3,
319
+ CEC2017_F4,
320
+ CEC2017_F5,
321
+ CEC2017_F6,
322
+ CEC2017_F7,
323
+ CEC2017_F8,
324
+ CEC2017_F9,
325
+ CEC2017_F10,
326
+ ]