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,586 +0,0 @@
1
- import numpy as np
2
- import pandas as pd
3
-
4
- from foxes.opt.core import FarmVarsProblem
5
- from foxes.models.turbine_models import SetFarmVars
6
- import foxes.constants as FC
7
-
8
-
9
- class OptFarmVars(FarmVarsProblem):
10
- """
11
- Optimize a selection of farm variables.
12
-
13
- :group: opt.problems
14
-
15
- """
16
-
17
- def __init__(self, *args, **kwargs):
18
- """
19
- Constructor.
20
-
21
- Parameters
22
- ----------
23
- args: tuple, optional
24
- Arguments for `FarmVarsProblem`
25
- kwargs: dict, optional
26
- Keyword arguments for `FarmVarsProblem`
27
-
28
- """
29
- super().__init__(*args, **kwargs)
30
- self._vars = None
31
-
32
- def add_var(
33
- self,
34
- name,
35
- typ,
36
- init,
37
- min,
38
- max,
39
- level="uniform",
40
- sel=None,
41
- pre_rotor=False,
42
- model_key=None,
43
- ):
44
- """
45
- Add a variable.
46
-
47
- Parameters
48
- ----------
49
- name: str
50
- The foxes farm variable name
51
- typ: type
52
- The variable type, either float or int
53
- init: float or int
54
- The initial value
55
- min: float or int
56
- The min value
57
- max: float or int
58
- The max value
59
- level: str
60
- Choices: uniform, state, turbine, state-turbine
61
- sel: numpy.ndarray, optional
62
- States/turbines/state-turbine selection,
63
- depending on the level
64
- pre_rotor: bool
65
- Apply this variable before rotor model
66
- model_key: str, optional
67
- Creates sub-model which can then be placed in the
68
- turbine model list. Repeated keys are added to the
69
- same turbine model
70
-
71
- """
72
- if typ is not float and typ is not int:
73
- raise TypeError(
74
- f"Problem '{self.name}': Expecting float or int, got type '{type(typ).__name__}'"
75
- )
76
-
77
- mname = self.name if model_key is None else model_key
78
- if mname in self.algo.mbook.turbine_models:
79
- m = self.algo.mbook.turbine_models[mname]
80
- if not isinstance(m, SetFarmVars):
81
- raise KeyError(
82
- f"Problem '{self.name}': Turbine model entry '{mname}' already exists in model book, and is not of type SetFarmVars"
83
- )
84
- elif m.pre_rotor != pre_rotor:
85
- raise ValueError(
86
- f"Problem '{self.name}': Turbine model entry '{mname}' exists in model book, and disagrees on pre_rotor = {pre_rotor}"
87
- )
88
- else:
89
- self.algo.mbook.turbine_models[mname] = SetFarmVars(pre_rotor=pre_rotor)
90
-
91
- if self._vars is None:
92
- i0 = 0
93
- i0i = 0
94
- i0f = 0
95
- else:
96
- if name in self._vars["var"].tolist():
97
- raise ValueError(
98
- f"Problem '{self.name}': Attempt to add variable '{name}' twice"
99
- )
100
- i0 = len(self._vars.index)
101
- grps = self._vars.groupby("type")
102
- i0i = len(grps.get_group("int").index) if "int" in grps.groups.keys() else 0
103
- i0f = (
104
- len(grps.get_group("float").index)
105
- if "float" in grps.groups.keys()
106
- else 0
107
- )
108
- del grps
109
-
110
- if level == "uniform":
111
- hdata = pd.DataFrame(index=[i0])
112
- hdata.loc[i0, "name"] = name
113
- hdata.loc[i0, "var"] = name
114
- hdata.loc[i0, "type"] = "int" if typ is int else "float"
115
- hdata.loc[i0, "index"] = i0i if typ is int else i0f
116
- hdata.loc[i0, "level"] = level
117
- hdata.loc[i0, "state"] = -1
118
- hdata.loc[i0, "turbine"] = -1
119
- hdata.loc[i0, "sel_turbine"] = -1
120
- hdata.loc[i0, "init"] = np.array([init], dtype=FC.DTYPE)
121
- hdata.loc[i0, "min"] = np.array([min], dtype=FC.DTYPE)
122
- hdata.loc[i0, "max"] = np.array([max], dtype=FC.DTYPE)
123
- hdata.loc[i0, "pre_rotor"] = pre_rotor
124
- hdata.loc[i0, "model_key"] = mname
125
-
126
- elif level == "state":
127
- if not self.algo.initialized:
128
- self.algo.initialize()
129
-
130
- states = np.arange(self.algo.n_states)
131
- if sel is not None:
132
- states = states[sel]
133
- inds = i0 + np.arange(len(states))
134
- tinds = inds - i0 + i0i if typ is int else inds - i0 + i0f
135
-
136
- hdata = pd.DataFrame(index=inds)
137
- hdata.loc[inds, "name"] = [f"{name}_{i:05d}" for i in range(len(states))]
138
- hdata.loc[inds, "var"] = name
139
- hdata.loc[inds, "type"] = "int" if typ is int else "float"
140
- hdata.loc[inds, "index"] = tinds
141
- hdata.loc[inds, "level"] = level
142
- hdata.loc[inds, "state"] = states
143
- hdata.loc[inds, "turbine"] = -1
144
- hdata.loc[inds, "sel_turbine"] = -1
145
-
146
- for c, d in [("init", init), ("min", min), ("max", max)]:
147
- data = np.full(len(inds), np.nan, dtype=FC.DTYPE)
148
- data[:] = d
149
- hdata.loc[inds, c] = data
150
-
151
- hdata.loc[inds, "pre_rotor"] = pre_rotor
152
- hdata.loc[inds, "model_key"] = mname
153
-
154
- elif level == "turbine":
155
- if sel is None:
156
- turbines = self.sel_turbines
157
- else:
158
- turbines = np.arange(self.algo.n_turbines)[sel]
159
- inds = i0 + np.arange(len(turbines))
160
- tinds = inds - i0 + i0i if typ is int else inds - i0 + i0f
161
-
162
- hdata = pd.DataFrame(index=inds)
163
- hdata.loc[inds, "name"] = [f"{name}_{i:04d}" for i in range(len(turbines))]
164
- hdata.loc[inds, "var"] = name
165
- hdata.loc[inds, "type"] = "int" if typ is int else "float"
166
- hdata.loc[inds, "index"] = tinds
167
- hdata.loc[inds, "level"] = level
168
- hdata.loc[inds, "state"] = -1
169
- hdata.loc[inds, "turbine"] = turbines
170
- hdata.loc[inds, "sel_turbine"] = [
171
- self.sel_turbines.index(ti) for ti in turbines
172
- ]
173
-
174
- for c, d in [("init", init), ("min", min), ("max", max)]:
175
- data = np.full(len(inds), np.nan, dtype=FC.DTYPE)
176
- data[:] = d
177
- hdata.loc[inds, c] = data
178
-
179
- hdata.loc[inds, "pre_rotor"] = pre_rotor
180
- hdata.loc[inds, "model_key"] = mname
181
-
182
- elif level == "state-turbine":
183
- if not self.algo.initialized:
184
- self.algo.initialize()
185
-
186
- n_states = self.algo.n_states
187
- n_turbines = self.algo.n_turbines
188
- if sel is None:
189
- sel = np.zeros((n_states, n_turbines), dtype=bool)
190
- sel[:, self.sel_turbines] = True
191
- else:
192
- sel = np.array(sel, dtype=bool)
193
- st = np.arange(n_states * n_turbines).reshape(n_states, n_turbines)[sel]
194
- whr = np.where(sel)
195
- n_inds = len(st)
196
- inds = i0 + np.arange(n_inds)
197
- tinds = inds - i0 + i0i if typ is int else inds - i0 + i0f
198
-
199
- hdata = pd.DataFrame(index=inds)
200
- hdata.loc[inds, "name"] = [
201
- f"{name}_{whr[0][i]:05d}_{whr[1][i]:04d}" for i in range(len(st))
202
- ]
203
- hdata.loc[inds, "var"] = name
204
- hdata.loc[inds, "type"] = "int" if typ is int else "float"
205
- hdata.loc[inds, "index"] = tinds
206
- hdata.loc[inds, "level"] = level
207
- hdata.loc[inds, "state"] = whr[0]
208
- hdata.loc[inds, "turbine"] = whr[1]
209
- hdata.loc[inds, "sel_turbine"] = [
210
- self.sel_turbines.index(ti) for ti in whr[1]
211
- ]
212
-
213
- for c, d in [("init", init), ("min", min), ("max", max)]:
214
- data = np.full(n_inds, np.nan, dtype=FC.DTYPE)
215
- if isinstance(d, np.ndarray) and len(d.shape) > 1:
216
- data[:] = d[sel]
217
- else:
218
- data[:] = d
219
- hdata.loc[inds, c] = data
220
-
221
- hdata.loc[inds, "pre_rotor"] = pre_rotor
222
- hdata.loc[inds, "model_key"] = mname
223
-
224
- else:
225
- raise ValueError(
226
- f"Problem '{self.name}': Unknown level '{level}'. Choices: uniform, state, turbine, state-turbine"
227
- )
228
-
229
- if self._vars is None:
230
- self._vars = hdata
231
- else:
232
- self._vars = pd.concat([self._vars, hdata], axis=0)
233
-
234
- icols = ["index", "state", "turbine", "sel_turbine"]
235
- for c in icols:
236
- self._vars[c] = self._vars[c].astype(FC.ITYPE)
237
-
238
- def initialize(self, verbosity=1, **kwargs):
239
- """
240
- Initialize the object.
241
-
242
- Parameters
243
- ----------
244
- verbosity: int
245
- The verbosity level, 0 = silent
246
- kwargs: dict, optional
247
- Additional parameters for super class init
248
-
249
- """
250
- if self._vars is None:
251
- raise ValueError(
252
- f"Problem '{self.name}': No variables added for optimization."
253
- )
254
-
255
- if verbosity > 0:
256
- print(f"Problem '{self.name}': Optimization variable list")
257
- print()
258
- print(self._vars)
259
- print()
260
-
261
- prev = {}
262
- postv = {}
263
- for (mname, pre), g in self._vars.groupby(["model_key", "pre_rotor"]):
264
- if (pre and mname in postv) or (not pre and mname in prev):
265
- raise ValueError(
266
- f"Problem '{self.name}': Model '{mname}' reveived both pre_rotor and non-pre_rotor variables"
267
- )
268
- tg = prev if pre else postv
269
- if mname not in tg:
270
- tg[mname] = set(g["var"].tolist())
271
- else:
272
- tg[mname] = tg[mname].update(g["var"].tolist())
273
-
274
- super().initialize(
275
- pre_rotor_vars={mname: list(vrs) for mname, vrs in prev.items()},
276
- post_rotor_vars={mname: list(vrs) for mname, vrs in postv.items()},
277
- verbosity=verbosity,
278
- **kwargs,
279
- )
280
-
281
- def var_names_int(self):
282
- """
283
- The names of int variables.
284
-
285
- Returns
286
- -------
287
- names: list of str
288
- The names of the int variables
289
-
290
- """
291
- if self._vars is None:
292
- raise ValueError(
293
- f"Problem '{self.name}': No variables added for optimization."
294
- )
295
-
296
- grps = self._vars.groupby("type")
297
- if "int" not in grps.groups.keys():
298
- return []
299
- else:
300
- return grps.get_group("int")["name"].tolist()
301
-
302
- def initial_values_int(self):
303
- """
304
- The initial values of the int variables.
305
-
306
- Returns
307
- -------
308
- values: numpy.ndarray
309
- Initial int values, shape: (n_vars_int,)
310
-
311
- """
312
- if self._vars is None:
313
- raise ValueError(
314
- f"Problem '{self.name}': No variables added for optimization."
315
- )
316
-
317
- grps = self._vars.groupby("type")
318
- if "int" not in grps.groups.keys():
319
- return []
320
- else:
321
- return grps.get_group("int")["init"].to_numpy(FC.ITYPE)
322
-
323
- def min_values_int(self):
324
- """
325
- The minimal values of the integer variables.
326
-
327
- Use -self.INT_INF for unbounded.
328
-
329
- Returns
330
- -------
331
- values: numpy.ndarray
332
- Minimal int values, shape: (n_vars_int,)
333
-
334
- """
335
- if self._vars is None:
336
- raise ValueError(
337
- f"Problem '{self.name}': No variables added for optimization."
338
- )
339
-
340
- grps = self._vars.groupby("type")
341
- if "int" not in grps.groups.keys():
342
- return []
343
- else:
344
- return grps.get_group("int")["min"].to_numpy(FC.ITYPE)
345
-
346
- def max_values_int(self):
347
- """
348
- The maximal values of the integer variables.
349
-
350
- Use self.INT_INF for unbounded.
351
-
352
- Returns
353
- -------
354
- values: numpy.ndarray
355
- Maximal int values, shape: (n_vars_int,)
356
-
357
- """
358
- if self._vars is None:
359
- raise ValueError(
360
- f"Problem '{self.name}': No variables added for optimization."
361
- )
362
-
363
- grps = self._vars.groupby("type")
364
- if "int" not in grps.groups.keys():
365
- return []
366
- else:
367
- return grps.get_group("int")["max"].to_numpy(FC.ITYPE)
368
-
369
- def var_names_float(self):
370
- """
371
- The names of float variables.
372
-
373
- Returns
374
- -------
375
- names: list of str
376
- The names of the float variables
377
-
378
- """
379
- if self._vars is None:
380
- raise ValueError(
381
- f"Problem '{self.name}': No variables added for optimization."
382
- )
383
-
384
- grps = self._vars.groupby("type")
385
- if "float" not in grps.groups.keys():
386
- return []
387
- else:
388
- return grps.get_group("float")["name"].tolist()
389
-
390
- def initial_values_float(self):
391
- """
392
- The initial values of the float variables.
393
-
394
- Returns
395
- -------
396
- values: numpy.ndarray
397
- Initial float values, shape: (n_vars_float,)
398
-
399
- """
400
- if self._vars is None:
401
- raise ValueError(
402
- f"Problem '{self.name}': No variables added for optimization."
403
- )
404
-
405
- grps = self._vars.groupby("type")
406
- if "float" not in grps.groups.keys():
407
- return []
408
- else:
409
- return grps.get_group("float")["init"].to_numpy(FC.DTYPE)
410
-
411
- def min_values_float(self):
412
- """
413
- The minimal values of the float variables.
414
-
415
- Use -numpy.inf for unbounded.
416
-
417
- Returns
418
- -------
419
- values: numpy.ndarray
420
- Minimal float values, shape: (n_vars_float,)
421
-
422
- """
423
- if self._vars is None:
424
- raise ValueError(
425
- f"Problem '{self.name}': No variables added for optimization."
426
- )
427
-
428
- grps = self._vars.groupby("type")
429
- if "float" not in grps.groups.keys():
430
- return []
431
- else:
432
- return grps.get_group("float")["min"].to_numpy(FC.DTYPE)
433
-
434
- def max_values_float(self):
435
- """
436
- The maximal values of the float variables.
437
-
438
- Use numpy.inf for unbounded.
439
-
440
- Returns
441
- -------
442
- values: numpy.ndarray
443
- Maximal float values, shape: (n_vars_float,)
444
-
445
- """
446
- if self._vars is None:
447
- raise ValueError(
448
- f"Problem '{self.name}': No variables added for optimization."
449
- )
450
-
451
- grps = self._vars.groupby("type")
452
- if "float" not in grps.groups.keys():
453
- return []
454
- else:
455
- return grps.get_group("float")["max"].to_numpy(FC.DTYPE)
456
-
457
- def opt2farm_vars_individual(self, vars_int, vars_float):
458
- """
459
- Translates optimization variables to farm variables
460
-
461
- Parameters
462
- ----------
463
- vars_int: numpy.ndarray
464
- The integer optimization variable values,
465
- shape: (n_vars_int,)
466
- vars_float: numpy.ndarray
467
- The float optimization variable values,
468
- shape: (n_vars_float,)
469
-
470
- Returns
471
- -------
472
- farm_vars: dict
473
- The foxes farm variables. Key: var name,
474
- value: numpy.ndarray with values, shape:
475
- (n_states, n_sel_turbines)
476
-
477
- """
478
- n_states = self.algo.n_states
479
- n_sturb = self.n_sel_turbines
480
-
481
- farm_vars = {}
482
- grps = self._vars.groupby(["type", "var", "level"])
483
- for (typ, var, level), g in grps:
484
- src = vars_int if typ == "int" else vars_float
485
- i0 = g.index[0]
486
- i1 = g.index[-1]
487
- data = src[np.s_[i0 : i1 + 1]]
488
-
489
- if level == "uniform":
490
- farm_vars[var] = np.full((n_states, n_sturb), data[0], dtype=FC.DTYPE)
491
-
492
- elif level == "state":
493
- farm_vars[var] = np.full((n_states, n_sturb), np.nan, dtype=FC.DTYPE)
494
- if np.all(g["state"] == np.arange(n_states)):
495
- farm_vars[var][:] = data[:, None]
496
- else:
497
- farm_vars[var][g["state"]] = data[:, None]
498
-
499
- elif level == "turbine":
500
- farm_vars[var] = np.full((n_states, n_sturb), np.nan, dtype=FC.DTYPE)
501
- if np.all(g["sel_turbine"] == np.arange(n_sturb)):
502
- farm_vars[var][:] = data[None, :]
503
- else:
504
- farm_vars[var][:, g["sel_turbine"]] = data[None, :]
505
-
506
- elif level == "state-turbine":
507
- farm_vars[var] = np.full((n_states, n_sturb), np.nan, dtype=FC.DTYPE)
508
- farm_vars[var][g["state"], g["sel_turbine"]] = data
509
-
510
- else:
511
- raise ValueError(
512
- f"Problem '{self.name}': Unknown level '{level}' encountered for variable '{var}'. Valid choices: uniform, state, turbine, state-turbine"
513
- )
514
-
515
- return farm_vars
516
-
517
- def opt2farm_vars_population(self, vars_int, vars_float, n_states):
518
- """
519
- Translates optimization variables to farm variables
520
-
521
- Parameters
522
- ----------
523
- vars_int: numpy.ndarray
524
- The integer optimization variable values,
525
- shape: (n_pop, n_vars_int)
526
- vars_float: numpy.ndarray
527
- The float optimization variable values,
528
- shape: (n_pop, n_vars_float)
529
- n_states: int
530
- The number of original (non-pop) states
531
-
532
- Returns
533
- -------
534
- farm_vars: dict
535
- The foxes farm variables. Key: var name,
536
- value: numpy.ndarray with values, shape:
537
- (n_pop, n_states, n_sel_turbines)
538
-
539
- """
540
- n_pop = vars_float.shape[0]
541
- n_sturb = self.n_sel_turbines
542
-
543
- farm_vars = {}
544
- grps = self._vars.groupby(["type", "var", "level"])
545
- for (typ, var, level), g in grps:
546
- src = vars_int if typ == "int" else vars_float
547
- i0 = g.index[0]
548
- i1 = g.index[-1]
549
- data = src[:, np.s_[i0 : i1 + 1]]
550
-
551
- if level == "uniform":
552
- farm_vars[var] = np.full(
553
- (n_pop, n_states, n_sturb), np.nan, dtype=FC.DTYPE
554
- )
555
- farm_vars[var][:] = data[:, 0, None, None]
556
-
557
- elif level == "state":
558
- farm_vars[var] = np.full(
559
- (n_pop, n_states, n_sturb), np.nan, dtype=FC.DTYPE
560
- )
561
- if np.all(g["state"] == np.arange(n_states)):
562
- farm_vars[var][:] = data[:, :, None]
563
- else:
564
- farm_vars[var][:, g["state"]] = data[:, :, None]
565
-
566
- elif level == "turbine":
567
- farm_vars[var] = np.full(
568
- (n_pop, n_states, n_sturb), np.nan, dtype=FC.DTYPE
569
- )
570
- if np.all(g["sel_turbine"] == np.arange(n_sturb)):
571
- farm_vars[var][:] = data[:, None, :]
572
- else:
573
- farm_vars[var][:, :, g["sel_turbine"]] = data[:, None, :]
574
-
575
- elif level == "state-turbine":
576
- farm_vars[var] = np.full(
577
- (n_pop, n_states, n_sturb), np.nan, dtype=FC.DTYPE
578
- )
579
- farm_vars[var][:, g["state"], g["sel_turbine"]] = data
580
-
581
- else:
582
- raise ValueError(
583
- f"Problem '{self.name}': Unknown level '{level}' encountered for variable '{var}'. Valid choices: uniform, state, turbine, state-turbine"
584
- )
585
-
586
- return farm_vars