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,406 @@
1
+ """
2
+ CEC 2017 Hybrid Functions (F11-F20).
3
+
4
+ Hybrid functions combine multiple basic functions applied to different
5
+ partitions of the input vector after shuffling.
6
+
7
+ Reference: CEC 2017 Competition on Real-Parameter Single Objective Optimization
8
+
9
+ F11: Hybrid Function 1 (N=3)
10
+ F12: Hybrid Function 2 (N=3)
11
+ F13: Hybrid Function 3 (N=3)
12
+ F14: Hybrid Function 4 (N=4)
13
+ F15: Hybrid Function 5 (N=4)
14
+ F16: Hybrid Function 6 (N=4)
15
+ F17: Hybrid Function 7 (N=5)
16
+ F18: Hybrid Function 8 (N=5)
17
+ F19: Hybrid Function 9 (N=5)
18
+ F20: Hybrid Function 10 (N=6)
19
+ """
20
+
21
+ from typing import List, Optional, Tuple, Callable
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 CEC2017HybridFunction(BenchmarkFunction):
32
+ """Base class for CEC 2017 hybrid functions."""
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
+ shuffle: Optional[Tensor] = None,
41
+ seed: Optional[int] = None,
42
+ ):
43
+ """
44
+ Initialize CEC 2017 hybrid function.
45
+
46
+ Args:
47
+ func_num: Function number (11-20).
48
+ n_var: Number of variables.
49
+ rotation: Optional rotation matrix.
50
+ shift: Optional shift vector.
51
+ shuffle: Optional shuffle permutation.
52
+ seed: Random seed for generating transforms if not provided.
53
+ """
54
+ super().__init__(n_var=n_var, xl=-100.0, xu=100.0)
55
+
56
+ self.func_num = func_num
57
+ self.bias = func_num * 100.0
58
+
59
+ # Load or generate transforms
60
+ if rotation is not None:
61
+ self.rotation = rotation
62
+ else:
63
+ self.rotation = cec_data.get_rotation(func_num, n_var, seed=seed)
64
+
65
+ if shift is not None:
66
+ self.shift = shift
67
+ else:
68
+ self.shift = cec_data.get_shift(func_num, n_var, seed=seed)
69
+
70
+ if shuffle is not None:
71
+ self.shuffle = shuffle
72
+ else:
73
+ self.shuffle = cec_data.get_shuffle(func_num, n_var, seed=seed)
74
+
75
+ def default_bounds(self) -> Tuple[float, float]:
76
+ return (-100.0, 100.0)
77
+
78
+ def _shift_rotate(self, x: Tensor) -> Tensor:
79
+ """Apply shift and rotation transformation."""
80
+ shift = self.shift.to(x.device, x.dtype)
81
+ rotation = self.rotation.to(x.device, x.dtype)
82
+ return cec_data.shift_rotate(x, shift, rotation)
83
+
84
+ def _shuffle_and_partition(self, x: Tensor, partitions: List[float]) -> List[Tensor]:
85
+ """Apply shuffle and partition."""
86
+ shuffle = self.shuffle.to(x.device)
87
+ return cec_data.shuffle_and_partition(x, shuffle, partitions)
88
+
89
+ def _evaluate_hybrid(
90
+ self,
91
+ x: Tensor,
92
+ partitions: List[float],
93
+ funcs: List[Callable],
94
+ ) -> Tensor:
95
+ """
96
+ Evaluate hybrid function.
97
+
98
+ Args:
99
+ x: Input tensor of shape [..., n_var].
100
+ partitions: List of partition fractions.
101
+ funcs: List of basic functions to apply to each partition.
102
+
103
+ Returns:
104
+ Function values.
105
+ """
106
+ z = self._shift_rotate(x)
107
+ parts = self._shuffle_and_partition(z, partitions)
108
+
109
+ result = torch.zeros(x.shape[:-1], device=x.device, dtype=x.dtype)
110
+ for part, func in zip(parts, funcs):
111
+ result = result + func(part)
112
+
113
+ return result + self.bias
114
+
115
+
116
+ class CEC2017_F11(CEC2017HybridFunction):
117
+ """
118
+ F11: Hybrid Function 1 (N=3)
119
+
120
+ Components: Zakharov, Rosenbrock, Rastrigin
121
+ Partitions: 0.2, 0.4, 0.4
122
+
123
+ Optimal value: F11* = 1100
124
+ """
125
+ name = "cec2017_f11"
126
+ optimal_value = 1100.0
127
+
128
+ def __init__(self, n_var: int = 10, **kwargs):
129
+ super().__init__(func_num=11, n_var=n_var, **kwargs)
130
+ self.partitions = [0.2, 0.4, 0.4]
131
+ self.funcs = [basic.zakharov, basic.rosenbrock, basic.rastrigin]
132
+
133
+ def __call__(self, x: Tensor) -> Tensor:
134
+ return self._evaluate_hybrid(x, self.partitions, self.funcs)
135
+
136
+
137
+ class CEC2017_F12(CEC2017HybridFunction):
138
+ """
139
+ F12: Hybrid Function 2 (N=3)
140
+
141
+ Components: High Conditioned Elliptic, Modified Schwefel, Bent Cigar
142
+ Partitions: 0.3, 0.3, 0.4
143
+
144
+ Optimal value: F12* = 1200
145
+ """
146
+ name = "cec2017_f12"
147
+ optimal_value = 1200.0
148
+
149
+ def __init__(self, n_var: int = 10, **kwargs):
150
+ super().__init__(func_num=12, n_var=n_var, **kwargs)
151
+ self.partitions = [0.3, 0.3, 0.4]
152
+ self.funcs = [
153
+ basic.high_conditioned_elliptic,
154
+ basic.modified_schwefel,
155
+ basic.bent_cigar,
156
+ ]
157
+
158
+ def __call__(self, x: Tensor) -> Tensor:
159
+ return self._evaluate_hybrid(x, self.partitions, self.funcs)
160
+
161
+
162
+ class CEC2017_F13(CEC2017HybridFunction):
163
+ """
164
+ F13: Hybrid Function 3 (N=3)
165
+
166
+ Components: Bent Cigar, Rosenbrock, Lunacek Bi-Rastrigin
167
+ Partitions: 0.3, 0.3, 0.4
168
+
169
+ Optimal value: F13* = 1300
170
+ """
171
+ name = "cec2017_f13"
172
+ optimal_value = 1300.0
173
+
174
+ def __init__(self, n_var: int = 10, **kwargs):
175
+ super().__init__(func_num=13, n_var=n_var, **kwargs)
176
+ self.partitions = [0.3, 0.3, 0.4]
177
+ self.funcs = [
178
+ basic.bent_cigar,
179
+ basic.rosenbrock,
180
+ basic.lunacek_bi_rastrigin,
181
+ ]
182
+
183
+ def __call__(self, x: Tensor) -> Tensor:
184
+ return self._evaluate_hybrid(x, self.partitions, self.funcs)
185
+
186
+
187
+ class CEC2017_F14(CEC2017HybridFunction):
188
+ """
189
+ F14: Hybrid Function 4 (N=4)
190
+
191
+ Components: High Conditioned Elliptic, Ackley, Schaffer's F7, Rastrigin
192
+ Partitions: 0.2, 0.2, 0.2, 0.4
193
+
194
+ Optimal value: F14* = 1400
195
+ """
196
+ name = "cec2017_f14"
197
+ optimal_value = 1400.0
198
+
199
+ def __init__(self, n_var: int = 10, **kwargs):
200
+ super().__init__(func_num=14, n_var=n_var, **kwargs)
201
+ self.partitions = [0.2, 0.2, 0.2, 0.4]
202
+ self.funcs = [
203
+ basic.high_conditioned_elliptic,
204
+ basic.ackley,
205
+ basic.schaffers_f7,
206
+ basic.rastrigin,
207
+ ]
208
+
209
+ def __call__(self, x: Tensor) -> Tensor:
210
+ return self._evaluate_hybrid(x, self.partitions, self.funcs)
211
+
212
+
213
+ class CEC2017_F15(CEC2017HybridFunction):
214
+ """
215
+ F15: Hybrid Function 5 (N=4)
216
+
217
+ Components: Bent Cigar, HGBat, Rastrigin, Rosenbrock
218
+ Partitions: 0.2, 0.2, 0.3, 0.3
219
+
220
+ Optimal value: F15* = 1500
221
+ """
222
+ name = "cec2017_f15"
223
+ optimal_value = 1500.0
224
+
225
+ def __init__(self, n_var: int = 10, **kwargs):
226
+ super().__init__(func_num=15, n_var=n_var, **kwargs)
227
+ self.partitions = [0.2, 0.2, 0.3, 0.3]
228
+ self.funcs = [
229
+ basic.bent_cigar,
230
+ basic.h_g_bat,
231
+ basic.rastrigin,
232
+ basic.rosenbrock,
233
+ ]
234
+
235
+ def __call__(self, x: Tensor) -> Tensor:
236
+ return self._evaluate_hybrid(x, self.partitions, self.funcs)
237
+
238
+
239
+ class CEC2017_F16(CEC2017HybridFunction):
240
+ """
241
+ F16: Hybrid Function 6 (N=4)
242
+
243
+ Components: Expanded Schaffer's F6, HGBat, Rosenbrock, Modified Schwefel
244
+ Partitions: 0.2, 0.2, 0.3, 0.3
245
+
246
+ Optimal value: F16* = 1600
247
+ """
248
+ name = "cec2017_f16"
249
+ optimal_value = 1600.0
250
+
251
+ def __init__(self, n_var: int = 10, **kwargs):
252
+ super().__init__(func_num=16, n_var=n_var, **kwargs)
253
+ self.partitions = [0.2, 0.2, 0.3, 0.3]
254
+ self.funcs = [
255
+ basic.expanded_schaffers_f6,
256
+ basic.h_g_bat,
257
+ basic.rosenbrock,
258
+ basic.modified_schwefel,
259
+ ]
260
+
261
+ def __call__(self, x: Tensor) -> Tensor:
262
+ return self._evaluate_hybrid(x, self.partitions, self.funcs)
263
+
264
+
265
+ class CEC2017_F17(CEC2017HybridFunction):
266
+ """
267
+ F17: Hybrid Function 7 (N=5)
268
+
269
+ Components: Katsuura, Ackley, Expanded Griewank's plus Rosenbrock,
270
+ Modified Schwefel, Rastrigin
271
+ Partitions: 0.1, 0.2, 0.2, 0.2, 0.3
272
+
273
+ Optimal value: F17* = 1700
274
+ """
275
+ name = "cec2017_f17"
276
+ optimal_value = 1700.0
277
+
278
+ def __init__(self, n_var: int = 10, **kwargs):
279
+ super().__init__(func_num=17, n_var=n_var, **kwargs)
280
+ self.partitions = [0.1, 0.2, 0.2, 0.2, 0.3]
281
+ self.funcs = [
282
+ basic.katsuura,
283
+ basic.ackley,
284
+ basic.expanded_griewanks_plus_rosenbrock,
285
+ basic.modified_schwefel,
286
+ basic.rastrigin,
287
+ ]
288
+
289
+ def __call__(self, x: Tensor) -> Tensor:
290
+ return self._evaluate_hybrid(x, self.partitions, self.funcs)
291
+
292
+
293
+ class CEC2017_F18(CEC2017HybridFunction):
294
+ """
295
+ F18: Hybrid Function 8 (N=5)
296
+
297
+ Components: High Conditioned Elliptic, Ackley, Rastrigin, HGBat, Discus
298
+ Partitions: 0.2, 0.2, 0.2, 0.2, 0.2
299
+
300
+ Optimal value: F18* = 1800
301
+ """
302
+ name = "cec2017_f18"
303
+ optimal_value = 1800.0
304
+
305
+ def __init__(self, n_var: int = 10, **kwargs):
306
+ super().__init__(func_num=18, n_var=n_var, **kwargs)
307
+ self.partitions = [0.2, 0.2, 0.2, 0.2, 0.2]
308
+ self.funcs = [
309
+ basic.high_conditioned_elliptic,
310
+ basic.ackley,
311
+ basic.rastrigin,
312
+ basic.h_g_bat,
313
+ basic.discus,
314
+ ]
315
+
316
+ def __call__(self, x: Tensor) -> Tensor:
317
+ return self._evaluate_hybrid(x, self.partitions, self.funcs)
318
+
319
+
320
+ class CEC2017_F19(CEC2017HybridFunction):
321
+ """
322
+ F19: Hybrid Function 9 (N=5)
323
+
324
+ Components: Bent Cigar, Rastrigin, Expanded Griewank's plus Rosenbrock,
325
+ Weierstrass, Expanded Schaffer's F6
326
+ Partitions: 0.2, 0.2, 0.2, 0.2, 0.2
327
+
328
+ Optimal value: F19* = 1900
329
+ """
330
+ name = "cec2017_f19"
331
+ optimal_value = 1900.0
332
+
333
+ def __init__(self, n_var: int = 10, **kwargs):
334
+ super().__init__(func_num=19, n_var=n_var, **kwargs)
335
+ self.partitions = [0.2, 0.2, 0.2, 0.2, 0.2]
336
+ self.funcs = [
337
+ basic.bent_cigar,
338
+ basic.rastrigin,
339
+ basic.expanded_griewanks_plus_rosenbrock,
340
+ basic.weierstrass,
341
+ basic.expanded_schaffers_f6,
342
+ ]
343
+
344
+ def __call__(self, x: Tensor) -> Tensor:
345
+ return self._evaluate_hybrid(x, self.partitions, self.funcs)
346
+
347
+
348
+ class CEC2017_F20(CEC2017HybridFunction):
349
+ """
350
+ F20: Hybrid Function 10 (N=6)
351
+
352
+ Components: Happy Cat, Katsuura, Ackley, Rastrigin, Modified Schwefel,
353
+ Schaffer's F7
354
+ Partitions: 0.1, 0.1, 0.2, 0.2, 0.2, 0.2
355
+
356
+ Optimal value: F20* = 2000
357
+ """
358
+ name = "cec2017_f20"
359
+ optimal_value = 2000.0
360
+
361
+ def __init__(self, n_var: int = 10, **kwargs):
362
+ super().__init__(func_num=20, n_var=n_var, **kwargs)
363
+ self.partitions = [0.1, 0.1, 0.2, 0.2, 0.2, 0.2]
364
+ self.funcs = [
365
+ basic.happy_cat,
366
+ basic.katsuura,
367
+ basic.ackley,
368
+ basic.rastrigin,
369
+ basic.modified_schwefel,
370
+ basic.schaffers_f7,
371
+ ]
372
+
373
+ def __call__(self, x: Tensor) -> Tensor:
374
+ return self._evaluate_hybrid(x, self.partitions, self.funcs)
375
+
376
+
377
+ # =============================================================================
378
+ # FUNCTION REGISTRY
379
+ # =============================================================================
380
+
381
+ HYBRID_FUNCTIONS = {
382
+ "cec2017_f11": CEC2017_F11,
383
+ "cec2017_f12": CEC2017_F12,
384
+ "cec2017_f13": CEC2017_F13,
385
+ "cec2017_f14": CEC2017_F14,
386
+ "cec2017_f15": CEC2017_F15,
387
+ "cec2017_f16": CEC2017_F16,
388
+ "cec2017_f17": CEC2017_F17,
389
+ "cec2017_f18": CEC2017_F18,
390
+ "cec2017_f19": CEC2017_F19,
391
+ "cec2017_f20": CEC2017_F20,
392
+ }
393
+
394
+ # List for iteration
395
+ all_functions = [
396
+ CEC2017_F11,
397
+ CEC2017_F12,
398
+ CEC2017_F13,
399
+ CEC2017_F14,
400
+ CEC2017_F15,
401
+ CEC2017_F16,
402
+ CEC2017_F17,
403
+ CEC2017_F18,
404
+ CEC2017_F19,
405
+ CEC2017_F20,
406
+ ]