foxes 0.7.4.25__py3-none-any.whl → 0.8.1__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.
Potentially problematic release.
This version of foxes might be problematic. Click here for more details.
- foxes/VERSION +1 -1
- {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/METADATA +20 -116
- {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/RECORD +7 -33
- foxes/opt/__init__.py +0 -9
- foxes/opt/constraints/__init__.py +0 -6
- foxes/opt/constraints/area_geometry.py +0 -214
- foxes/opt/constraints/min_dist.py +0 -239
- foxes/opt/core/__init__.py +0 -9
- foxes/opt/core/farm_constraint.py +0 -96
- foxes/opt/core/farm_objective.py +0 -97
- foxes/opt/core/farm_opt_problem.py +0 -346
- foxes/opt/core/farm_vars_problem.py +0 -219
- foxes/opt/core/pop_states.py +0 -206
- foxes/opt/objectives/__init__.py +0 -6
- foxes/opt/objectives/farm_vars.py +0 -323
- foxes/opt/objectives/max_n_turbines.py +0 -142
- foxes/opt/problems/__init__.py +0 -7
- foxes/opt/problems/layout/__init__.py +0 -9
- foxes/opt/problems/layout/farm_layout.py +0 -137
- foxes/opt/problems/layout/geom_layouts/__init__.py +0 -10
- foxes/opt/problems/layout/geom_layouts/constraints.py +0 -802
- foxes/opt/problems/layout/geom_layouts/geom_layout.py +0 -290
- foxes/opt/problems/layout/geom_layouts/geom_layout_gridded.py +0 -276
- foxes/opt/problems/layout/geom_layouts/geom_reggrid.py +0 -351
- foxes/opt/problems/layout/geom_layouts/geom_reggrids.py +0 -482
- foxes/opt/problems/layout/geom_layouts/objectives.py +0 -666
- foxes/opt/problems/layout/reggrids_layout.py +0 -417
- foxes/opt/problems/layout/regular_layout.py +0 -350
- foxes/opt/problems/opt_farm_vars.py +0 -586
- {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/LICENSE +0 -0
- {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/WHEEL +0 -0
- {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/top_level.txt +0 -0
- {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/zip-safe +0 -0
|
@@ -1,666 +0,0 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
from iwopy import Objective
|
|
3
|
-
from scipy.spatial.distance import cdist
|
|
4
|
-
|
|
5
|
-
import foxes.constants as FC
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class OMaxN(Objective):
|
|
9
|
-
"""
|
|
10
|
-
Maximal number of turbines objective
|
|
11
|
-
for purely geometrical layouts problems.
|
|
12
|
-
|
|
13
|
-
:group: opt.problems.layout.geom_layouts.objectives
|
|
14
|
-
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
def __init__(self, problem, name="maxN"):
|
|
18
|
-
"""
|
|
19
|
-
Constructor.
|
|
20
|
-
|
|
21
|
-
Parameters
|
|
22
|
-
----------
|
|
23
|
-
problem: foxes.opt.FarmOptProblem
|
|
24
|
-
The underlying geometrical layout
|
|
25
|
-
optimization problem
|
|
26
|
-
name: str
|
|
27
|
-
The constraint name
|
|
28
|
-
|
|
29
|
-
"""
|
|
30
|
-
super().__init__(
|
|
31
|
-
problem,
|
|
32
|
-
name,
|
|
33
|
-
vnames_int=problem.var_names_int(),
|
|
34
|
-
vnames_float=problem.var_names_float(),
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
def n_components(self):
|
|
38
|
-
"""
|
|
39
|
-
Returns the number of components of the
|
|
40
|
-
function.
|
|
41
|
-
|
|
42
|
-
Returns
|
|
43
|
-
-------
|
|
44
|
-
int:
|
|
45
|
-
The number of components.
|
|
46
|
-
|
|
47
|
-
"""
|
|
48
|
-
return 1
|
|
49
|
-
|
|
50
|
-
def maximize(self):
|
|
51
|
-
"""
|
|
52
|
-
Returns flag for maximization of each component.
|
|
53
|
-
|
|
54
|
-
Returns
|
|
55
|
-
-------
|
|
56
|
-
flags: np.array
|
|
57
|
-
Bool array for component maximization,
|
|
58
|
-
shape: (n_components,)
|
|
59
|
-
|
|
60
|
-
"""
|
|
61
|
-
return [True]
|
|
62
|
-
|
|
63
|
-
def calc_individual(self, vars_int, vars_float, problem_results, cmpnts=None):
|
|
64
|
-
"""
|
|
65
|
-
Calculate values for a single individual of the
|
|
66
|
-
underlying problem.
|
|
67
|
-
|
|
68
|
-
Parameters
|
|
69
|
-
----------
|
|
70
|
-
vars_int : np.array
|
|
71
|
-
The integer variable values, shape: (n_vars_int,)
|
|
72
|
-
vars_float : np.array
|
|
73
|
-
The float variable values, shape: (n_vars_float,)
|
|
74
|
-
problem_results : Any
|
|
75
|
-
The results of the variable application
|
|
76
|
-
to the problem
|
|
77
|
-
components : list of int, optional
|
|
78
|
-
The selected components or None for all
|
|
79
|
-
|
|
80
|
-
Returns
|
|
81
|
-
-------
|
|
82
|
-
values : np.array
|
|
83
|
-
The component values, shape: (n_sel_components,)
|
|
84
|
-
|
|
85
|
-
"""
|
|
86
|
-
__, valid = problem_results
|
|
87
|
-
return np.sum(valid)
|
|
88
|
-
|
|
89
|
-
def calc_population(self, vars_int, vars_float, problem_results, cmpnts=None):
|
|
90
|
-
"""
|
|
91
|
-
Calculate values for all individuals of a population.
|
|
92
|
-
|
|
93
|
-
Parameters
|
|
94
|
-
----------
|
|
95
|
-
vars_int : np.array
|
|
96
|
-
The integer variable values, shape: (n_pop, n_vars_int)
|
|
97
|
-
vars_float : np.array
|
|
98
|
-
The float variable values, shape: (n_pop, n_vars_float)
|
|
99
|
-
problem_results : Any
|
|
100
|
-
The results of the variable application
|
|
101
|
-
to the problem
|
|
102
|
-
components : list of int, optional
|
|
103
|
-
The selected components or None for all
|
|
104
|
-
|
|
105
|
-
Returns
|
|
106
|
-
-------
|
|
107
|
-
values : np.array
|
|
108
|
-
The component values, shape: (n_pop, n_sel_components)
|
|
109
|
-
|
|
110
|
-
"""
|
|
111
|
-
__, valid = problem_results
|
|
112
|
-
return np.sum(valid, axis=1)[:, None]
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
class OMinN(OMaxN):
|
|
116
|
-
"""
|
|
117
|
-
Minimal number of turbines objective
|
|
118
|
-
for purely geometrical layouts problems.
|
|
119
|
-
|
|
120
|
-
:group: opt.problems.layout.geom_layouts.objectives
|
|
121
|
-
|
|
122
|
-
"""
|
|
123
|
-
|
|
124
|
-
def __init__(self, problem, name="ominN"):
|
|
125
|
-
"""
|
|
126
|
-
Constructor.
|
|
127
|
-
|
|
128
|
-
Parameters
|
|
129
|
-
----------
|
|
130
|
-
problem: foxes.opt.FarmOptProblem
|
|
131
|
-
The underlying geometrical layout
|
|
132
|
-
optimization problem
|
|
133
|
-
name: str
|
|
134
|
-
The constraint name
|
|
135
|
-
|
|
136
|
-
"""
|
|
137
|
-
super().__init__(problem, name)
|
|
138
|
-
|
|
139
|
-
def maximize(self):
|
|
140
|
-
return [False]
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
class OFixN(Objective):
|
|
144
|
-
"""
|
|
145
|
-
Fixed number of turbines objective
|
|
146
|
-
for purely geometrical layouts problems.
|
|
147
|
-
|
|
148
|
-
:group: opt.problems.layout.geom_layouts.objectives
|
|
149
|
-
|
|
150
|
-
"""
|
|
151
|
-
|
|
152
|
-
def __init__(self, problem, N, name="ofixN"):
|
|
153
|
-
"""
|
|
154
|
-
Constructor.
|
|
155
|
-
|
|
156
|
-
Parameters
|
|
157
|
-
----------
|
|
158
|
-
problem: foxes.opt.FarmOptProblem
|
|
159
|
-
The underlying geometrical layout
|
|
160
|
-
optimization problem
|
|
161
|
-
N: int
|
|
162
|
-
The number of turbines
|
|
163
|
-
name: str
|
|
164
|
-
The constraint name
|
|
165
|
-
|
|
166
|
-
"""
|
|
167
|
-
super().__init__(
|
|
168
|
-
problem,
|
|
169
|
-
name,
|
|
170
|
-
vnames_int=problem.var_names_int(),
|
|
171
|
-
vnames_float=problem.var_names_float(),
|
|
172
|
-
)
|
|
173
|
-
self.N = N
|
|
174
|
-
|
|
175
|
-
def n_components(self):
|
|
176
|
-
"""
|
|
177
|
-
Returns the number of components of the
|
|
178
|
-
function.
|
|
179
|
-
|
|
180
|
-
Returns
|
|
181
|
-
-------
|
|
182
|
-
int:
|
|
183
|
-
The number of components.
|
|
184
|
-
|
|
185
|
-
"""
|
|
186
|
-
return 1
|
|
187
|
-
|
|
188
|
-
def maximize(self):
|
|
189
|
-
"""
|
|
190
|
-
Returns flag for maximization of each component.
|
|
191
|
-
|
|
192
|
-
Returns
|
|
193
|
-
-------
|
|
194
|
-
flags: np.array
|
|
195
|
-
Bool array for component maximization,
|
|
196
|
-
shape: (n_components,)
|
|
197
|
-
|
|
198
|
-
"""
|
|
199
|
-
return [False]
|
|
200
|
-
|
|
201
|
-
def calc_individual(self, vars_int, vars_float, problem_results, cmpnts=None):
|
|
202
|
-
"""
|
|
203
|
-
Calculate values for a single individual of the
|
|
204
|
-
underlying problem.
|
|
205
|
-
|
|
206
|
-
Parameters
|
|
207
|
-
----------
|
|
208
|
-
vars_int : np.array
|
|
209
|
-
The integer variable values, shape: (n_vars_int,)
|
|
210
|
-
vars_float : np.array
|
|
211
|
-
The float variable values, shape: (n_vars_float,)
|
|
212
|
-
problem_results : Any
|
|
213
|
-
The results of the variable application
|
|
214
|
-
to the problem
|
|
215
|
-
components : list of int, optional
|
|
216
|
-
The selected components or None for all
|
|
217
|
-
|
|
218
|
-
Returns
|
|
219
|
-
-------
|
|
220
|
-
values : np.array
|
|
221
|
-
The component values, shape: (n_sel_components,)
|
|
222
|
-
|
|
223
|
-
"""
|
|
224
|
-
__, valid = problem_results
|
|
225
|
-
N = np.sum(valid, dtype=np.float64)
|
|
226
|
-
return np.maximum(N - self.N, self.N - N)
|
|
227
|
-
|
|
228
|
-
def calc_population(self, vars_int, vars_float, problem_results, cmpnts=None):
|
|
229
|
-
"""
|
|
230
|
-
Calculate values for all individuals of a population.
|
|
231
|
-
|
|
232
|
-
Parameters
|
|
233
|
-
----------
|
|
234
|
-
vars_int : np.array
|
|
235
|
-
The integer variable values, shape: (n_pop, n_vars_int)
|
|
236
|
-
vars_float : np.array
|
|
237
|
-
The float variable values, shape: (n_pop, n_vars_float)
|
|
238
|
-
problem_results : Any
|
|
239
|
-
The results of the variable application
|
|
240
|
-
to the problem
|
|
241
|
-
components : list of int, optional
|
|
242
|
-
The selected components or None for all
|
|
243
|
-
|
|
244
|
-
Returns
|
|
245
|
-
-------
|
|
246
|
-
values : np.array
|
|
247
|
-
The component values, shape: (n_pop, n_sel_components)
|
|
248
|
-
|
|
249
|
-
"""
|
|
250
|
-
__, valid = problem_results
|
|
251
|
-
N = np.sum(valid, axis=1, dtype=np.float64)[:, None]
|
|
252
|
-
return np.maximum(N - self.N, self.N - N)
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
class MaxGridSpacing(Objective):
|
|
256
|
-
"""
|
|
257
|
-
Maximal grid spacing objective
|
|
258
|
-
for purely geometrical layouts problems.
|
|
259
|
-
|
|
260
|
-
:group: opt.problems.layout.geom_layouts.objectives
|
|
261
|
-
|
|
262
|
-
"""
|
|
263
|
-
|
|
264
|
-
def __init__(self, problem, name="max_dxdy"):
|
|
265
|
-
"""
|
|
266
|
-
Constructor.
|
|
267
|
-
|
|
268
|
-
Parameters
|
|
269
|
-
----------
|
|
270
|
-
problem: foxes.opt.FarmOptProblem
|
|
271
|
-
The underlying geometrical layout
|
|
272
|
-
optimization problem
|
|
273
|
-
name: str
|
|
274
|
-
The constraint name
|
|
275
|
-
|
|
276
|
-
"""
|
|
277
|
-
super().__init__(
|
|
278
|
-
problem,
|
|
279
|
-
name,
|
|
280
|
-
vnames_int=problem.var_names_int(),
|
|
281
|
-
vnames_float=problem.var_names_float(),
|
|
282
|
-
)
|
|
283
|
-
|
|
284
|
-
def n_components(self):
|
|
285
|
-
"""
|
|
286
|
-
Returns the number of components of the
|
|
287
|
-
function.
|
|
288
|
-
|
|
289
|
-
Returns
|
|
290
|
-
-------
|
|
291
|
-
int:
|
|
292
|
-
The number of components.
|
|
293
|
-
|
|
294
|
-
"""
|
|
295
|
-
return 1
|
|
296
|
-
|
|
297
|
-
def maximize(self):
|
|
298
|
-
"""
|
|
299
|
-
Returns flag for maximization of each component.
|
|
300
|
-
|
|
301
|
-
Returns
|
|
302
|
-
-------
|
|
303
|
-
flags: np.array
|
|
304
|
-
Bool array for component maximization,
|
|
305
|
-
shape: (n_components,)
|
|
306
|
-
|
|
307
|
-
"""
|
|
308
|
-
return [True]
|
|
309
|
-
|
|
310
|
-
def calc_individual(self, vars_int, vars_float, problem_results, cmpnts=None):
|
|
311
|
-
"""
|
|
312
|
-
Calculate values for a single individual of the
|
|
313
|
-
underlying problem.
|
|
314
|
-
|
|
315
|
-
Parameters
|
|
316
|
-
----------
|
|
317
|
-
vars_int : np.array
|
|
318
|
-
The integer variable values, shape: (n_vars_int,)
|
|
319
|
-
vars_float : np.array
|
|
320
|
-
The float variable values, shape: (n_vars_float,)
|
|
321
|
-
problem_results : Any
|
|
322
|
-
The results of the variable application
|
|
323
|
-
to the problem
|
|
324
|
-
components : list of int, optional
|
|
325
|
-
The selected components or None for all
|
|
326
|
-
|
|
327
|
-
Returns
|
|
328
|
-
-------
|
|
329
|
-
values : np.array
|
|
330
|
-
The component values, shape: (n_sel_components,)
|
|
331
|
-
|
|
332
|
-
"""
|
|
333
|
-
vflt = vars_float.reshape(self.problem.n_grids, 5)
|
|
334
|
-
delta = np.minimum(vflt[:, 2], vflt[:, 3])
|
|
335
|
-
return np.nanmin(delta)
|
|
336
|
-
|
|
337
|
-
def calc_population(self, vars_int, vars_float, problem_results, cmpnts=None):
|
|
338
|
-
"""
|
|
339
|
-
Calculate values for all individuals of a population.
|
|
340
|
-
|
|
341
|
-
Parameters
|
|
342
|
-
----------
|
|
343
|
-
vars_int : np.array
|
|
344
|
-
The integer variable values, shape: (n_pop, n_vars_int)
|
|
345
|
-
vars_float : np.array
|
|
346
|
-
The float variable values, shape: (n_pop, n_vars_float)
|
|
347
|
-
problem_results : Any
|
|
348
|
-
The results of the variable application
|
|
349
|
-
to the problem
|
|
350
|
-
components : list of int, optional
|
|
351
|
-
The selected components or None for all
|
|
352
|
-
|
|
353
|
-
Returns
|
|
354
|
-
-------
|
|
355
|
-
values : np.array
|
|
356
|
-
The component values, shape: (n_pop, n_sel_components)
|
|
357
|
-
|
|
358
|
-
"""
|
|
359
|
-
n_pop = vars_float.shape[0]
|
|
360
|
-
vflt = vars_float.reshape(n_pop, self.problem.n_grids, 5)
|
|
361
|
-
delta = np.minimum(vflt[:, :, 2], vflt[:, :, 3])
|
|
362
|
-
return np.nanmin(delta, axis=1)[:, None]
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
class MaxDensity(Objective):
|
|
366
|
-
"""
|
|
367
|
-
Maximal turbine density objective
|
|
368
|
-
for purely geometrical layouts problems.
|
|
369
|
-
|
|
370
|
-
:group: opt.problems.layout.geom_layouts.objectives
|
|
371
|
-
|
|
372
|
-
"""
|
|
373
|
-
|
|
374
|
-
def __init__(self, problem, dfactor=1, min_dist=None, name="max_density"):
|
|
375
|
-
"""
|
|
376
|
-
Constructor.
|
|
377
|
-
|
|
378
|
-
Parameters
|
|
379
|
-
----------
|
|
380
|
-
problem: foxes.opt.FarmOptProblem
|
|
381
|
-
The underlying geometrical layout
|
|
382
|
-
optimization problem
|
|
383
|
-
dfactor: float
|
|
384
|
-
Delta factor for grid spacing
|
|
385
|
-
min_dist: float, optional
|
|
386
|
-
The minimal distance
|
|
387
|
-
name: str
|
|
388
|
-
The constraint name
|
|
389
|
-
|
|
390
|
-
"""
|
|
391
|
-
super().__init__(
|
|
392
|
-
problem,
|
|
393
|
-
name,
|
|
394
|
-
vnames_int=problem.var_names_int(),
|
|
395
|
-
vnames_float=problem.var_names_float(),
|
|
396
|
-
)
|
|
397
|
-
self.dfactor = dfactor
|
|
398
|
-
self.min_dist = problem.min_dist if min_dist is None else min_dist
|
|
399
|
-
|
|
400
|
-
def n_components(self):
|
|
401
|
-
"""
|
|
402
|
-
Returns the number of components of the
|
|
403
|
-
function.
|
|
404
|
-
|
|
405
|
-
Returns
|
|
406
|
-
-------
|
|
407
|
-
int:
|
|
408
|
-
The number of components.
|
|
409
|
-
|
|
410
|
-
"""
|
|
411
|
-
return 1
|
|
412
|
-
|
|
413
|
-
def maximize(self):
|
|
414
|
-
"""
|
|
415
|
-
Returns flag for maximization of each component.
|
|
416
|
-
|
|
417
|
-
Returns
|
|
418
|
-
-------
|
|
419
|
-
flags: np.array
|
|
420
|
-
Bool array for component maximization,
|
|
421
|
-
shape: (n_components,)
|
|
422
|
-
|
|
423
|
-
"""
|
|
424
|
-
return [False]
|
|
425
|
-
|
|
426
|
-
def initialize(self, verbosity):
|
|
427
|
-
"""
|
|
428
|
-
Initialize the object.
|
|
429
|
-
|
|
430
|
-
Parameters
|
|
431
|
-
----------
|
|
432
|
-
verbosity: int
|
|
433
|
-
The verbosity level, 0 = silent
|
|
434
|
-
|
|
435
|
-
"""
|
|
436
|
-
super().initialize(verbosity)
|
|
437
|
-
|
|
438
|
-
# define regular grid of probe points:
|
|
439
|
-
geom = self.problem.boundary
|
|
440
|
-
pmin = geom.p_min()
|
|
441
|
-
pmax = geom.p_max()
|
|
442
|
-
detlta = self.min_dist / self.dfactor
|
|
443
|
-
self._probes = np.stack(
|
|
444
|
-
np.meshgrid(
|
|
445
|
-
np.arange(pmin[0] - detlta, pmax[0] + 2 * detlta, detlta),
|
|
446
|
-
np.arange(pmin[1] - detlta, pmax[1] + 2 * detlta, detlta),
|
|
447
|
-
indexing="ij",
|
|
448
|
-
),
|
|
449
|
-
axis=-1,
|
|
450
|
-
)
|
|
451
|
-
nx, ny = self._probes.shape[:2]
|
|
452
|
-
n = nx * ny
|
|
453
|
-
self._probes = self._probes.reshape(n, 2)
|
|
454
|
-
|
|
455
|
-
# reduce to points within geometry:
|
|
456
|
-
valid = geom.points_inside(self._probes)
|
|
457
|
-
self._probes = self._probes[valid]
|
|
458
|
-
|
|
459
|
-
def calc_individual(self, vars_int, vars_float, problem_results, cmpnts=None):
|
|
460
|
-
"""
|
|
461
|
-
Calculate values for a single individual of the
|
|
462
|
-
underlying problem.
|
|
463
|
-
|
|
464
|
-
Parameters
|
|
465
|
-
----------
|
|
466
|
-
vars_int : np.array
|
|
467
|
-
The integer variable values, shape: (n_vars_int,)
|
|
468
|
-
vars_float : np.array
|
|
469
|
-
The float variable values, shape: (n_vars_float,)
|
|
470
|
-
problem_results : Any
|
|
471
|
-
The results of the variable application
|
|
472
|
-
to the problem
|
|
473
|
-
components : list of int, optional
|
|
474
|
-
The selected components or None for all
|
|
475
|
-
|
|
476
|
-
Returns
|
|
477
|
-
-------
|
|
478
|
-
values : np.array
|
|
479
|
-
The component values, shape: (n_sel_components,)
|
|
480
|
-
|
|
481
|
-
"""
|
|
482
|
-
xy, valid = problem_results
|
|
483
|
-
xy = xy[valid]
|
|
484
|
-
dists = cdist(self._probes, xy)
|
|
485
|
-
return np.nanmax(np.nanmin(dists, axis=1))
|
|
486
|
-
|
|
487
|
-
def calc_population(self, vars_int, vars_float, problem_results, cmpnts=None):
|
|
488
|
-
"""
|
|
489
|
-
Calculate values for all individuals of a population.
|
|
490
|
-
|
|
491
|
-
Parameters
|
|
492
|
-
----------
|
|
493
|
-
vars_int : np.array
|
|
494
|
-
The integer variable values, shape: (n_pop, n_vars_int)
|
|
495
|
-
vars_float : np.array
|
|
496
|
-
The float variable values, shape: (n_pop, n_vars_float)
|
|
497
|
-
problem_results : Any
|
|
498
|
-
The results of the variable application
|
|
499
|
-
to the problem
|
|
500
|
-
components : list of int, optional
|
|
501
|
-
The selected components or None for all
|
|
502
|
-
|
|
503
|
-
Returns
|
|
504
|
-
-------
|
|
505
|
-
values : np.array
|
|
506
|
-
The component values, shape: (n_pop, n_sel_components)
|
|
507
|
-
|
|
508
|
-
"""
|
|
509
|
-
n_pop = vars_float.shape[0]
|
|
510
|
-
xy, valid = problem_results
|
|
511
|
-
out = np.full(n_pop, 1e20, dtype=FC.DTYPE)
|
|
512
|
-
for pi in range(n_pop):
|
|
513
|
-
if np.any(valid[pi]):
|
|
514
|
-
hxy = xy[pi][valid[pi]]
|
|
515
|
-
dists = cdist(self._probes, hxy)
|
|
516
|
-
out[pi] = np.nanmax(np.nanmin(dists, axis=1))
|
|
517
|
-
return out[:, None]
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
class MeMiMaDist(Objective):
|
|
521
|
-
"""
|
|
522
|
-
Mean-min-max distance objective
|
|
523
|
-
for purely geometrical layouts problems.
|
|
524
|
-
|
|
525
|
-
:group: opt.problems.layout.geom_layouts.objectives
|
|
526
|
-
|
|
527
|
-
"""
|
|
528
|
-
|
|
529
|
-
def __init__(self, problem, scale=500.0, c1=1, c2=1, c3=1, name="MiMaMean"):
|
|
530
|
-
"""
|
|
531
|
-
Constructor.
|
|
532
|
-
|
|
533
|
-
Parameters
|
|
534
|
-
----------
|
|
535
|
-
problem: foxes.opt.FarmOptProblem
|
|
536
|
-
The underlying geometrical layout
|
|
537
|
-
optimization problem
|
|
538
|
-
scale: float
|
|
539
|
-
The distance scale
|
|
540
|
-
c1: float
|
|
541
|
-
Parameter for mean weighting
|
|
542
|
-
c2: float
|
|
543
|
-
Parameter for max diff weighting
|
|
544
|
-
c3: float
|
|
545
|
-
Parameter for min diff weighting
|
|
546
|
-
name: str
|
|
547
|
-
The constraint name
|
|
548
|
-
|
|
549
|
-
"""
|
|
550
|
-
super().__init__(
|
|
551
|
-
problem,
|
|
552
|
-
name,
|
|
553
|
-
vnames_int=problem.var_names_int(),
|
|
554
|
-
vnames_float=problem.var_names_float(),
|
|
555
|
-
)
|
|
556
|
-
self.scale = scale
|
|
557
|
-
self.c1 = c1
|
|
558
|
-
self.c2 = c2
|
|
559
|
-
self.c3 = c3
|
|
560
|
-
|
|
561
|
-
def n_components(self):
|
|
562
|
-
"""
|
|
563
|
-
Returns the number of components of the
|
|
564
|
-
function.
|
|
565
|
-
|
|
566
|
-
Returns
|
|
567
|
-
-------
|
|
568
|
-
int:
|
|
569
|
-
The number of components.
|
|
570
|
-
|
|
571
|
-
"""
|
|
572
|
-
return 1
|
|
573
|
-
|
|
574
|
-
def maximize(self):
|
|
575
|
-
"""
|
|
576
|
-
Returns flag for maximization of each component.
|
|
577
|
-
|
|
578
|
-
Returns
|
|
579
|
-
-------
|
|
580
|
-
flags: np.array
|
|
581
|
-
Bool array for component maximization,
|
|
582
|
-
shape: (n_components,)
|
|
583
|
-
|
|
584
|
-
"""
|
|
585
|
-
return [True]
|
|
586
|
-
|
|
587
|
-
def calc_individual(self, vars_int, vars_float, problem_results, cmpnts=None):
|
|
588
|
-
"""
|
|
589
|
-
Calculate values for a single individual of the
|
|
590
|
-
underlying problem.
|
|
591
|
-
|
|
592
|
-
Parameters
|
|
593
|
-
----------
|
|
594
|
-
vars_int : np.array
|
|
595
|
-
The integer variable values, shape: (n_vars_int,)
|
|
596
|
-
vars_float : np.array
|
|
597
|
-
The float variable values, shape: (n_vars_float,)
|
|
598
|
-
problem_results : Any
|
|
599
|
-
The results of the variable application
|
|
600
|
-
to the problem
|
|
601
|
-
components : list of int, optional
|
|
602
|
-
The selected components or None for all
|
|
603
|
-
|
|
604
|
-
Returns
|
|
605
|
-
-------
|
|
606
|
-
values : np.array
|
|
607
|
-
The component values, shape: (n_sel_components,)
|
|
608
|
-
|
|
609
|
-
"""
|
|
610
|
-
xy, valid = problem_results
|
|
611
|
-
# xy = xy[valid]
|
|
612
|
-
|
|
613
|
-
dists = cdist(xy, xy)
|
|
614
|
-
np.fill_diagonal(dists, np.inf)
|
|
615
|
-
dists = np.min(dists, axis=1) / self.scale / len(xy)
|
|
616
|
-
|
|
617
|
-
mean = np.average(dists)
|
|
618
|
-
mi = np.min(dists)
|
|
619
|
-
ma = np.max(dists)
|
|
620
|
-
return np.atleast_1d(
|
|
621
|
-
self.c1 * mean**2 - self.c2 * (mean - mi) ** 2 - self.c3 * (mean - ma) ** 2
|
|
622
|
-
)
|
|
623
|
-
|
|
624
|
-
def calc_population(self, vars_int, vars_float, problem_results, cmpnts=None):
|
|
625
|
-
"""
|
|
626
|
-
Calculate values for all individuals of a population.
|
|
627
|
-
|
|
628
|
-
Parameters
|
|
629
|
-
----------
|
|
630
|
-
vars_int : np.array
|
|
631
|
-
The integer variable values, shape: (n_pop, n_vars_int)
|
|
632
|
-
vars_float : np.array
|
|
633
|
-
The float variable values, shape: (n_pop, n_vars_float)
|
|
634
|
-
problem_results : Any
|
|
635
|
-
The results of the variable application
|
|
636
|
-
to the problem
|
|
637
|
-
components : list of int, optional
|
|
638
|
-
The selected components or None for all
|
|
639
|
-
|
|
640
|
-
Returns
|
|
641
|
-
-------
|
|
642
|
-
values : np.array
|
|
643
|
-
The component values, shape: (n_pop, n_sel_components)
|
|
644
|
-
|
|
645
|
-
"""
|
|
646
|
-
xy, valid = problem_results
|
|
647
|
-
n_pop, n_xy = xy.shape[:2]
|
|
648
|
-
|
|
649
|
-
out = np.zeros((n_pop, 1), dtype=FC.DTYPE)
|
|
650
|
-
for pi in range(n_pop):
|
|
651
|
-
hxy = xy[pi] # , valid[pi]]
|
|
652
|
-
|
|
653
|
-
dists = cdist(hxy, hxy)
|
|
654
|
-
np.fill_diagonal(dists, np.inf)
|
|
655
|
-
dists = np.min(dists, axis=1) / self.scale / n_xy
|
|
656
|
-
|
|
657
|
-
mean = np.average(dists)
|
|
658
|
-
mi = np.min(dists)
|
|
659
|
-
ma = np.max(dists)
|
|
660
|
-
out[pi, 0] = (
|
|
661
|
-
self.c1 * mean**2
|
|
662
|
-
- self.c2 * (mean - mi) ** 2
|
|
663
|
-
- self.c3 * (mean - ma) ** 2
|
|
664
|
-
)
|
|
665
|
-
|
|
666
|
-
return out
|