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,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
|
+
]
|