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.
- evograd/__init__.py +67 -0
- evograd/algorithms/__init__.py +138 -0
- evograd/algorithms/cmaes.py +1365 -0
- evograd/algorithms/de.py +895 -0
- evograd/algorithms/ga.py +532 -0
- evograd/algorithms/pso.py +648 -0
- evograd/algorithms/shade.py +1165 -0
- evograd/benchmarks/functions/__init__.py +229 -0
- evograd/benchmarks/functions/base.py +217 -0
- evograd/benchmarks/functions/cec2017/__init__.py +250 -0
- evograd/benchmarks/functions/cec2017/basic.py +413 -0
- evograd/benchmarks/functions/cec2017/composition.py +580 -0
- evograd/benchmarks/functions/cec2017/data.pkl +0 -0
- evograd/benchmarks/functions/cec2017/data.py +350 -0
- evograd/benchmarks/functions/cec2017/hybrid.py +406 -0
- evograd/benchmarks/functions/cec2017/simple.py +326 -0
- evograd/benchmarks/functions/classical.py +649 -0
- evograd/benchmarks/functions/smoothed_funnel.py +476 -0
- evograd/benchmarks/functions/transforms.py +463 -0
- evograd/benchmarks/run_benchmark_functions.py +1208 -0
- evograd/core/__init__.py +73 -0
- evograd/core/algorithm.py +778 -0
- evograd/core/maximize.py +269 -0
- evograd/core/minimize.py +740 -0
- evograd/core/problem.py +444 -0
- evograd/core/result.py +571 -0
- evograd/core/termination.py +602 -0
- evograd/operators/__init__.py +178 -0
- evograd/operators/crossover.py +1117 -0
- evograd/operators/mutation.py +1098 -0
- evograd/operators/relaxations.py +175 -0
- evograd/operators/repair.py +601 -0
- evograd/operators/sampling.py +577 -0
- evograd/operators/selection.py +981 -0
- evograd/operators/survival.py +1000 -0
- evograd/tests/__init__.py +11 -0
- evograd/tests/run_all.py +78 -0
- evograd/tests/test_core.py +528 -0
- evograd/tests/test_ga.py +572 -0
- evograd/tests/test_operators.py +662 -0
- evograd/tests/test_per_individual.py +326 -0
- evograd/tests/test_utils.py +328 -0
- evograd/utils/__init__.py +97 -0
- evograd/utils/callbacks.py +926 -0
- evograd/utils/device.py +502 -0
- evograd/utils/duplicates.py +421 -0
- evograd_diff-0.1.0.dist-info/METADATA +439 -0
- evograd_diff-0.1.0.dist-info/RECORD +50 -0
- evograd_diff-0.1.0.dist-info/WHEEL +4 -0
- 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
|
+
]
|