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.

Files changed (33) hide show
  1. foxes/VERSION +1 -1
  2. {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/METADATA +20 -116
  3. {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/RECORD +7 -33
  4. foxes/opt/__init__.py +0 -9
  5. foxes/opt/constraints/__init__.py +0 -6
  6. foxes/opt/constraints/area_geometry.py +0 -214
  7. foxes/opt/constraints/min_dist.py +0 -239
  8. foxes/opt/core/__init__.py +0 -9
  9. foxes/opt/core/farm_constraint.py +0 -96
  10. foxes/opt/core/farm_objective.py +0 -97
  11. foxes/opt/core/farm_opt_problem.py +0 -346
  12. foxes/opt/core/farm_vars_problem.py +0 -219
  13. foxes/opt/core/pop_states.py +0 -206
  14. foxes/opt/objectives/__init__.py +0 -6
  15. foxes/opt/objectives/farm_vars.py +0 -323
  16. foxes/opt/objectives/max_n_turbines.py +0 -142
  17. foxes/opt/problems/__init__.py +0 -7
  18. foxes/opt/problems/layout/__init__.py +0 -9
  19. foxes/opt/problems/layout/farm_layout.py +0 -137
  20. foxes/opt/problems/layout/geom_layouts/__init__.py +0 -10
  21. foxes/opt/problems/layout/geom_layouts/constraints.py +0 -802
  22. foxes/opt/problems/layout/geom_layouts/geom_layout.py +0 -290
  23. foxes/opt/problems/layout/geom_layouts/geom_layout_gridded.py +0 -276
  24. foxes/opt/problems/layout/geom_layouts/geom_reggrid.py +0 -351
  25. foxes/opt/problems/layout/geom_layouts/geom_reggrids.py +0 -482
  26. foxes/opt/problems/layout/geom_layouts/objectives.py +0 -666
  27. foxes/opt/problems/layout/reggrids_layout.py +0 -417
  28. foxes/opt/problems/layout/regular_layout.py +0 -350
  29. foxes/opt/problems/opt_farm_vars.py +0 -586
  30. {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/LICENSE +0 -0
  31. {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/WHEEL +0 -0
  32. {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/top_level.txt +0 -0
  33. {foxes-0.7.4.25.dist-info → foxes-0.8.1.dist-info}/zip-safe +0 -0
@@ -1,802 +0,0 @@
1
- import numpy as np
2
- from scipy.spatial.distance import cdist
3
- from iwopy import Constraint
4
-
5
- import foxes.constants as FC
6
-
7
-
8
- class Valid(Constraint):
9
- """
10
- Validity constraint for purely geometrical layouts problems.
11
-
12
- :group: opt.problems.layout.geom_layouts.constraints
13
-
14
- """
15
-
16
- def __init__(self, problem, name="valid", **kwargs):
17
- """
18
- Constructor.
19
-
20
- Parameters
21
- ----------
22
- problem: foxes.opt.FarmOptProblem
23
- The underlying geometrical layout
24
- optimization problem
25
- name: str
26
- The constraint name
27
- kwargs: dict, optional
28
- Additioal parameters for the base class
29
-
30
- """
31
- super().__init__(
32
- problem,
33
- name,
34
- vnames_int=problem.var_names_int(),
35
- vnames_float=problem.var_names_float(),
36
- **kwargs,
37
- )
38
-
39
- def n_components(self):
40
- """
41
- Returns the number of components of the
42
- function.
43
-
44
- Returns
45
- -------
46
- int:
47
- The number of components.
48
-
49
- """
50
- return 1
51
-
52
- def calc_individual(self, vars_int, vars_float, problem_results, cmpnts=None):
53
- """
54
- Calculate values for a single individual of the
55
- underlying problem.
56
-
57
- Parameters
58
- ----------
59
- vars_int : np.array
60
- The integer variable values, shape: (n_vars_int,)
61
- vars_float : np.array
62
- The float variable values, shape: (n_vars_float,)
63
- problem_results : Any
64
- The results of the variable application
65
- to the problem
66
- components : list of int, optional
67
- The selected components or None for all
68
-
69
- Returns
70
- -------
71
- values : np.array
72
- The component values, shape: (n_sel_components,)
73
-
74
- """
75
- __, valid = problem_results
76
- return np.sum(~valid)
77
-
78
- def calc_population(self, vars_int, vars_float, problem_results, cmpnts=None):
79
- """
80
- Calculate values for all individuals of a population.
81
-
82
- Parameters
83
- ----------
84
- vars_int : np.array
85
- The integer variable values, shape: (n_pop, n_vars_int)
86
- vars_float : np.array
87
- The float variable values, shape: (n_pop, n_vars_float)
88
- problem_results : Any
89
- The results of the variable application
90
- to the problem
91
- components : list of int, optional
92
- The selected components or None for all
93
-
94
- Returns
95
- -------
96
- values : np.array
97
- The component values, shape: (n_pop, n_sel_components)
98
-
99
- """
100
- __, valid = problem_results
101
- return np.sum(~valid, axis=1)[:, None]
102
-
103
-
104
- class Boundary(Constraint):
105
- """
106
- Boundary constraint for purely geometrical layouts problems.
107
-
108
- :group: opt.problems.layout.geom_layouts.constraints
109
-
110
- """
111
-
112
- def __init__(self, problem, n_turbines=None, D=None, name="boundary", **kwargs):
113
- """
114
- Constructor.
115
-
116
- Parameters
117
- ----------
118
- problem: foxes.opt.FarmOptProblem
119
- The underlying geometrical layout
120
- optimization problem
121
- n_turbines: int, optional
122
- The number of turbines
123
- D: float, optional
124
- The rotor diameter
125
- name: str
126
- The constraint name
127
- kwargs: dict, optional
128
- Additioal parameters for the base class
129
-
130
- """
131
- super().__init__(
132
- problem,
133
- name,
134
- vnames_int=problem.var_names_int(),
135
- vnames_float=problem.var_names_float(),
136
- **kwargs,
137
- )
138
- self.n_turbines = problem.n_turbines if n_turbines is None else n_turbines
139
- self.D = problem.D if D is None else D
140
-
141
- def n_components(self):
142
- """
143
- Returns the number of components of the
144
- function.
145
-
146
- Returns
147
- -------
148
- int:
149
- The number of components.
150
-
151
- """
152
- return self.n_turbines
153
-
154
- def calc_individual(self, vars_int, vars_float, problem_results, cmpnts=None):
155
- """
156
- Calculate values for a single individual of the
157
- underlying problem.
158
-
159
- Parameters
160
- ----------
161
- vars_int : np.array
162
- The integer variable values, shape: (n_vars_int,)
163
- vars_float : np.array
164
- The float variable values, shape: (n_vars_float,)
165
- problem_results : Any
166
- The results of the variable application
167
- to the problem
168
- components : list of int, optional
169
- The selected components or None for all
170
-
171
- Returns
172
- -------
173
- values : np.array
174
- The component values, shape: (n_sel_components,)
175
-
176
- """
177
- xy, __ = problem_results
178
-
179
- dists = self.problem.boundary.points_distance(xy)
180
- dists[self.problem.boundary.points_inside(xy)] *= -1
181
-
182
- if self.D is not None:
183
- dists += self.D / 2
184
-
185
- return dists
186
-
187
- def calc_population(self, vars_int, vars_float, problem_results, cmpnts=None):
188
- """
189
- Calculate values for all individuals of a population.
190
-
191
- Parameters
192
- ----------
193
- vars_int : np.array
194
- The integer variable values, shape: (n_pop, n_vars_int)
195
- vars_float : np.array
196
- The float variable values, shape: (n_pop, n_vars_float)
197
- problem_results : Any
198
- The results of the variable application
199
- to the problem
200
- components : list of int, optional
201
- The selected components or None for all
202
-
203
- Returns
204
- -------
205
- values : np.array
206
- The component values, shape: (n_pop, n_sel_components)
207
-
208
- """
209
- xy, __ = problem_results
210
- n_pop, n_xy = xy.shape[:2]
211
-
212
- xy = xy.reshape(n_pop * n_xy, 2)
213
- dists = self.problem.boundary.points_distance(xy)
214
- dists[self.problem.boundary.points_inside(xy)] *= -1
215
- dists = dists.reshape(n_pop, n_xy)
216
-
217
- if self.D is not None:
218
- dists += self.D / 2
219
-
220
- return dists
221
-
222
-
223
- class MinDist(Constraint):
224
- """
225
- Minimal distance constraint for purely geometrical layouts problems.
226
-
227
- :group: opt.problems.layout.geom_layouts.constraints
228
-
229
- """
230
-
231
- def __init__(
232
- self, problem, min_dist=None, n_turbines=None, name="min_dist", **kwargs
233
- ):
234
- """
235
- Constructor.
236
-
237
- Parameters
238
- ----------
239
- problem: foxes.opt.FarmOptProblem
240
- The underlying geometrical layout
241
- optimization problem
242
- min_dist: float, optional
243
- The minimal distance between turbines
244
- n_turbines: int, optional
245
- The number of turbines
246
- name: str
247
- The constraint name
248
- kwargs: dict, optional
249
- Additioal parameters for the base class
250
-
251
- """
252
- super().__init__(
253
- problem,
254
- name,
255
- vnames_int=problem.var_names_int(),
256
- vnames_float=problem.var_names_float(),
257
- **kwargs,
258
- )
259
- self.min_dist = problem.min_dist if min_dist is None else min_dist
260
- self.n_turbines = problem.n_turbines if n_turbines is None else n_turbines
261
-
262
- def initialize(self, verbosity=0):
263
- """
264
- Initialize the constaint.
265
-
266
- Parameters
267
- ----------
268
- verbosity: int
269
- The verbosity level, 0 = silent
270
-
271
- """
272
- N = self.n_turbines
273
- self._i2t = [] # i --> (ti, tj)
274
- self._t2i = np.full([N, N], -1) # (ti, tj) --> i
275
- i = 0
276
- for ti in range(N):
277
- for tj in range(N):
278
- if ti != tj and self._t2i[ti, tj] < 0:
279
- self._i2t.append([ti, tj])
280
- self._t2i[ti, tj] = i
281
- self._t2i[tj, ti] = i
282
- i += 1
283
- self._i2t = np.array(self._i2t)
284
- self._cnames = [f"{self.name}_{ti}_{tj}" for ti, tj in self._i2t]
285
- super().initialize(verbosity)
286
-
287
- def n_components(self):
288
- """
289
- Returns the number of components of the
290
- function.
291
-
292
- Returns
293
- -------
294
- int:
295
- The number of components.
296
-
297
- """
298
- return len(self._i2t)
299
-
300
- def calc_individual(self, vars_int, vars_float, problem_results, cmpnts=None):
301
- """
302
- Calculate values for a single individual of the
303
- underlying problem.
304
-
305
- Parameters
306
- ----------
307
- vars_int : np.array
308
- The integer variable values, shape: (n_vars_int,)
309
- vars_float : np.array
310
- The float variable values, shape: (n_vars_float,)
311
- problem_results : Any
312
- The results of the variable application
313
- to the problem
314
- components : list of int, optional
315
- The selected components or None for all
316
-
317
- Returns
318
- -------
319
- values : np.array
320
- The component values, shape: (n_sel_components,)
321
-
322
- """
323
- xy, __ = problem_results
324
-
325
- a = np.take_along_axis(xy, self._i2t[:, 0, None], axis=0)
326
- b = np.take_along_axis(xy, self._i2t[:, 1, None], axis=0)
327
- d = np.linalg.norm(a - b, axis=-1)
328
-
329
- return self.min_dist - d
330
-
331
- def calc_population(self, vars_int, vars_float, problem_results, cmpnts=None):
332
- """
333
- Calculate values for all individuals of a population.
334
-
335
- Parameters
336
- ----------
337
- vars_int : np.array
338
- The integer variable values, shape: (n_pop, n_vars_int)
339
- vars_float : np.array
340
- The float variable values, shape: (n_pop, n_vars_float)
341
- problem_results : Any
342
- The results of the variable application
343
- to the problem
344
- components : list of int, optional
345
- The selected components or None for all
346
-
347
- Returns
348
- -------
349
- values : np.array
350
- The component values, shape: (n_pop, n_sel_components)
351
-
352
- """
353
- xy, __ = problem_results
354
-
355
- a = np.take_along_axis(xy, self._i2t[None, :, 0, None], axis=1)
356
- b = np.take_along_axis(xy, self._i2t[None, :, 1, None], axis=1)
357
- d = np.linalg.norm(a - b, axis=-1)
358
-
359
- return self.min_dist - d
360
-
361
-
362
- class CMinN(Constraint):
363
- """
364
- Minimal number of turbines constraint for purely geometrical layouts problems.
365
-
366
- :group: opt.problems.layout.geom_layouts.constraints
367
-
368
- """
369
-
370
- def __init__(self, problem, N, name="cminN", **kwargs):
371
- super().__init__(
372
- problem,
373
- name,
374
- vnames_int=problem.var_names_int(),
375
- vnames_float=problem.var_names_float(),
376
- **kwargs,
377
- )
378
- """
379
- Constructor.
380
-
381
- Parameters
382
- ----------
383
- problem: foxes.opt.FarmOptProblem
384
- The underlying geometrical layout
385
- optimization problem
386
- N: int
387
- The minimal number of turbines
388
- name: str
389
- The constraint name
390
- kwargs: dict, optional
391
- Additioal parameters for the base class
392
-
393
- """
394
- self.N = N
395
-
396
- def n_components(self):
397
- """
398
- Returns the number of components of the
399
- function.
400
-
401
- Returns
402
- -------
403
- int:
404
- The number of components.
405
-
406
- """
407
- return 1
408
-
409
- def calc_individual(self, vars_int, vars_float, problem_results, cmpnts=None):
410
- """
411
- Calculate values for a single individual of the
412
- underlying problem.
413
-
414
- Parameters
415
- ----------
416
- vars_int : np.array
417
- The integer variable values, shape: (n_vars_int,)
418
- vars_float : np.array
419
- The float variable values, shape: (n_vars_float,)
420
- problem_results : Any
421
- The results of the variable application
422
- to the problem
423
- components : list of int, optional
424
- The selected components or None for all
425
-
426
- Returns
427
- -------
428
- values : np.array
429
- The component values, shape: (n_sel_components,)
430
-
431
- """
432
- __, valid = problem_results
433
- return self.N - np.sum(valid)
434
-
435
- def calc_population(self, vars_int, vars_float, problem_results, cmpnts=None):
436
- """
437
- Calculate values for all individuals of a population.
438
-
439
- Parameters
440
- ----------
441
- vars_int : np.array
442
- The integer variable values, shape: (n_pop, n_vars_int)
443
- vars_float : np.array
444
- The float variable values, shape: (n_pop, n_vars_float)
445
- problem_results : Any
446
- The results of the variable application
447
- to the problem
448
- components : list of int, optional
449
- The selected components or None for all
450
-
451
- Returns
452
- -------
453
- values : np.array
454
- The component values, shape: (n_pop, n_sel_components)
455
-
456
- """
457
- __, valid = problem_results
458
- return self.N - np.sum(valid, axis=1)[:, None]
459
-
460
-
461
- class CMaxN(Constraint):
462
- """
463
- Maximal number of turbines constraint for purely geometrical layouts problems.
464
-
465
- :group: opt.problems.layout.geom_layouts.constraints
466
-
467
- """
468
-
469
- def __init__(self, problem, N, name="cmaxN", **kwargs):
470
- """
471
- Constructor.
472
-
473
- Parameters
474
- ----------
475
- problem: foxes.opt.FarmOptProblem
476
- The underlying geometrical layout
477
- optimization problem
478
- N: int
479
- The maximal number of turbines
480
- name: str
481
- The constraint name
482
- kwargs: dict, optional
483
- Additioal parameters for the base class
484
-
485
- """
486
- super().__init__(
487
- problem,
488
- name,
489
- vnames_int=problem.var_names_int(),
490
- vnames_float=problem.var_names_float(),
491
- **kwargs,
492
- )
493
- self.N = N
494
-
495
- def n_components(self):
496
- """
497
- Returns the number of components of the
498
- function.
499
-
500
- Returns
501
- -------
502
- int:
503
- The number of components.
504
-
505
- """
506
- return 1
507
-
508
- def calc_individual(self, vars_int, vars_float, problem_results, cmpnts=None):
509
- """
510
- Calculate values for a single individual of the
511
- underlying problem.
512
-
513
- Parameters
514
- ----------
515
- vars_int : np.array
516
- The integer variable values, shape: (n_vars_int,)
517
- vars_float : np.array
518
- The float variable values, shape: (n_vars_float,)
519
- problem_results : Any
520
- The results of the variable application
521
- to the problem
522
- components : list of int, optional
523
- The selected components or None for all
524
-
525
- Returns
526
- -------
527
- values : np.array
528
- The component values, shape: (n_sel_components,)
529
-
530
- """
531
- __, valid = problem_results
532
- return np.sum(valid) - self.N
533
-
534
- def calc_population(self, vars_int, vars_float, problem_results, cmpnts=None):
535
- """
536
- Calculate values for all individuals of a population.
537
-
538
- Parameters
539
- ----------
540
- vars_int : np.array
541
- The integer variable values, shape: (n_pop, n_vars_int)
542
- vars_float : np.array
543
- The float variable values, shape: (n_pop, n_vars_float)
544
- problem_results : Any
545
- The results of the variable application
546
- to the problem
547
- components : list of int, optional
548
- The selected components or None for all
549
-
550
- Returns
551
- -------
552
- values : np.array
553
- The component values, shape: (n_pop, n_sel_components)
554
-
555
- """
556
- __, valid = problem_results
557
- return np.sum(valid, axis=1)[:, None] - self.N
558
-
559
-
560
- class CFixN(Constraint):
561
- """
562
- Fixed number of turbines constraint for purely geometrical layouts problems.
563
-
564
- :group: opt.problems.layout.geom_layouts.constraints
565
-
566
- """
567
-
568
- def __init__(self, problem, N, name="cfixN", **kwargs):
569
- """
570
- Constructor.
571
-
572
- Parameters
573
- ----------
574
- problem: foxes.opt.FarmOptProblem
575
- The underlying geometrical layout
576
- optimization problem
577
- N: int
578
- The number of turbines
579
- name: str
580
- The constraint name
581
- kwargs: dict, optional
582
- Additioal parameters for the base class
583
-
584
- """
585
- super().__init__(
586
- problem,
587
- name,
588
- vnames_int=problem.var_names_int(),
589
- vnames_float=problem.var_names_float(),
590
- tol=0.1,
591
- **kwargs,
592
- )
593
- self.N = N
594
-
595
- def n_components(self):
596
- """
597
- Returns the number of components of the
598
- function.
599
-
600
- Returns
601
- -------
602
- int:
603
- The number of components.
604
-
605
- """
606
- return 2
607
-
608
- def calc_individual(self, vars_int, vars_float, problem_results, cmpnts=None):
609
- """
610
- Calculate values for a single individual of the
611
- underlying problem.
612
-
613
- Parameters
614
- ----------
615
- vars_int : np.array
616
- The integer variable values, shape: (n_vars_int,)
617
- vars_float : np.array
618
- The float variable values, shape: (n_vars_float,)
619
- problem_results : Any
620
- The results of the variable application
621
- to the problem
622
- components : list of int, optional
623
- The selected components or None for all
624
-
625
- Returns
626
- -------
627
- values : np.array
628
- The component values, shape: (n_sel_components,)
629
-
630
- """
631
- __, valid = problem_results
632
- vld = np.sum(valid)
633
- return np.array([self.N - vld, vld - self.N])
634
-
635
- def calc_population(self, vars_int, vars_float, problem_results, cmpnts=None):
636
- """
637
- Calculate values for all individuals of a population.
638
-
639
- Parameters
640
- ----------
641
- vars_int : np.array
642
- The integer variable values, shape: (n_pop, n_vars_int)
643
- vars_float : np.array
644
- The float variable values, shape: (n_pop, n_vars_float)
645
- problem_results : Any
646
- The results of the variable application
647
- to the problem
648
- components : list of int, optional
649
- The selected components or None for all
650
-
651
- Returns
652
- -------
653
- values : np.array
654
- The component values, shape: (n_pop, n_sel_components)
655
-
656
- """
657
- __, valid = problem_results
658
- vld = np.sum(valid, axis=1)
659
- return np.stack([self.N - vld, vld - self.N], axis=-1)
660
-
661
-
662
- class CMinDensity(Constraint):
663
- """
664
- Minimal turbine density constraint for purely geometrical layouts problems.
665
-
666
- :group: opt.problems.layout.geom_layouts.constraints
667
-
668
- """
669
-
670
- def __init__(self, problem, min_value, dfactor=1, name="min_density"):
671
- """
672
- Constructor.
673
-
674
- Parameters
675
- ----------
676
- problem: foxes.opt.FarmOptProblem
677
- The underlying geometrical layout
678
- optimization problem
679
- min_value: float
680
- The minimal turbine density
681
- dfactor: float
682
- Delta factor for grid spacing
683
- name: str
684
- The constraint name
685
- kwargs: dict, optional
686
- Additioal parameters for the base class
687
-
688
- """
689
- super().__init__(
690
- problem,
691
- name,
692
- vnames_int=problem.var_names_int(),
693
- vnames_float=problem.var_names_float(),
694
- )
695
- self.min_value = min_value
696
- self.dfactor = dfactor
697
-
698
- def n_components(self):
699
- """
700
- Returns the number of components of the
701
- function.
702
-
703
- Returns
704
- -------
705
- int:
706
- The number of components.
707
-
708
- """
709
- return 1
710
-
711
- def initialize(self, verbosity):
712
- """
713
- Initialize the object.
714
-
715
- Parameters
716
- ----------
717
- verbosity: int
718
- The verbosity level, 0 = silent
719
-
720
- """
721
- super().initialize(verbosity)
722
-
723
- # define regular grid of probe points:
724
- geom = self.problem.boundary
725
- pmin = geom.p_min()
726
- pmax = geom.p_max()
727
- detlta = self.problem.min_dist / self.dfactor
728
- self._probes = np.stack(
729
- np.meshgrid(
730
- np.arange(pmin[0] - detlta, pmax[0] + 2 * detlta, detlta),
731
- np.arange(pmin[1] - detlta, pmax[1] + 2 * detlta, detlta),
732
- indexing="ij",
733
- ),
734
- axis=-1,
735
- )
736
- nx, ny = self._probes.shape[:2]
737
- n = nx * ny
738
- self._probes = self._probes.reshape(n, 2)
739
-
740
- # reduce to points within geometry:
741
- valid = geom.points_inside(self._probes)
742
- self._probes = self._probes[valid]
743
-
744
- def calc_individual(self, vars_int, vars_float, problem_results, cmpnts=None):
745
- """
746
- Calculate values for a single individual of the
747
- underlying problem.
748
-
749
- Parameters
750
- ----------
751
- vars_int : np.array
752
- The integer variable values, shape: (n_vars_int,)
753
- vars_float : np.array
754
- The float variable values, shape: (n_vars_float,)
755
- problem_results : Any
756
- The results of the variable application
757
- to the problem
758
- components : list of int, optional
759
- The selected components or None for all
760
-
761
- Returns
762
- -------
763
- values : np.array
764
- The component values, shape: (n_sel_components,)
765
-
766
- """
767
- xy, valid = problem_results
768
- xy = xy[valid]
769
- dists = cdist(self._probes, xy)
770
- return np.nanmax(np.nanmin(dists, axis=1)) - self.min_value
771
-
772
- def calc_population(self, vars_int, vars_float, problem_results, cmpnts=None):
773
- """
774
- Calculate values for all individuals of a population.
775
-
776
- Parameters
777
- ----------
778
- vars_int : np.array
779
- The integer variable values, shape: (n_pop, n_vars_int)
780
- vars_float : np.array
781
- The float variable values, shape: (n_pop, n_vars_float)
782
- problem_results : Any
783
- The results of the variable application
784
- to the problem
785
- components : list of int, optional
786
- The selected components or None for all
787
-
788
- Returns
789
- -------
790
- values : np.array
791
- The component values, shape: (n_pop, n_sel_components)
792
-
793
- """
794
- n_pop = vars_float.shape[0]
795
- xy, valid = problem_results
796
- out = np.full(n_pop, 1e20, dtype=FC.DTYPE)
797
- for pi in range(n_pop):
798
- if np.any(valid[pi]):
799
- hxy = xy[pi][valid[pi]]
800
- dists = cdist(self._probes, hxy)
801
- out[pi] = np.nanmax(np.nanmin(dists, axis=1)) - self.min_value
802
- return out[:, None]