pymoo 0.6.1__cp311-cp311-win_amd64.whl → 0.6.1.2__cp311-cp311-win_amd64.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 pymoo might be problematic. Click here for more details.

Files changed (38) hide show
  1. pymoo/algorithms/moo/age.py +3 -2
  2. pymoo/algorithms/moo/nsga3.py +1 -2
  3. pymoo/algorithms/moo/sms.py +4 -1
  4. pymoo/algorithms/soo/nonconvex/cmaes.py +1 -1
  5. pymoo/algorithms/soo/nonconvex/es.py +1 -1
  6. pymoo/algorithms/soo/nonconvex/optuna.py +1 -4
  7. pymoo/algorithms/soo/nonconvex/pattern.py +1 -1
  8. pymoo/constraints/adaptive.py +2 -2
  9. pymoo/constraints/eps.py +1 -1
  10. pymoo/core/algorithm.py +1 -0
  11. pymoo/core/individual.py +512 -49
  12. pymoo/core/plot.py +1 -1
  13. pymoo/core/result.py +3 -0
  14. pymoo/core/variable.py +310 -16
  15. pymoo/cython/calc_perpendicular_distance.cp311-win_amd64.pyd +0 -0
  16. pymoo/cython/decomposition.cp311-win_amd64.pyd +0 -0
  17. pymoo/cython/hv.cp311-win_amd64.pyd +0 -0
  18. pymoo/cython/info.cp311-win_amd64.pyd +0 -0
  19. pymoo/cython/mnn.cp311-win_amd64.pyd +0 -0
  20. pymoo/cython/non_dominated_sorting.cp311-win_amd64.pyd +0 -0
  21. pymoo/cython/pruning_cd.cp311-win_amd64.pyd +0 -0
  22. pymoo/cython/stochastic_ranking.cp311-win_amd64.pyd +0 -0
  23. pymoo/gradient/__init__.py +3 -1
  24. pymoo/gradient/grad_autograd.py +28 -4
  25. pymoo/operators/crossover/sbx.py +1 -1
  26. pymoo/util/display/single.py +1 -2
  27. pymoo/util/function_loader.py +31 -21
  28. pymoo/util/nds/dominance_degree_non_dominated_sort.py +159 -0
  29. pymoo/util/ref_dirs/__init__.py +2 -0
  30. pymoo/util/ref_dirs/energy.py +4 -5
  31. pymoo/util/ref_dirs/energy_layer.py +5 -4
  32. pymoo/util/ref_dirs/incremental.py +68 -0
  33. pymoo/version.py +1 -1
  34. {pymoo-0.6.1.dist-info → pymoo-0.6.1.2.dist-info}/METADATA +2 -3
  35. {pymoo-0.6.1.dist-info → pymoo-0.6.1.2.dist-info}/RECORD +38 -36
  36. {pymoo-0.6.1.dist-info → pymoo-0.6.1.2.dist-info}/WHEEL +1 -1
  37. {pymoo-0.6.1.dist-info → pymoo-0.6.1.2.dist-info}/LICENSE +0 -0
  38. {pymoo-0.6.1.dist-info → pymoo-0.6.1.2.dist-info}/top_level.txt +0 -0
pymoo/core/individual.py CHANGED
@@ -1,23 +1,91 @@
1
- import copy
1
+ """
2
+ Module containing infrastructure for representing individuals in
3
+ population-based optimization algorithms.
4
+ """
5
+
6
+ # public API for when using ``from pymoo.core.individual import *``
7
+ __all__ = [
8
+ "default_config",
9
+ "Individual",
10
+ "calc_cv",
11
+ "constr_to_cv",
12
+ ]
2
13
 
14
+ import copy
15
+ from typing import Optional
16
+ from typing import Tuple
17
+ from typing import Union
18
+ from warnings import warn
3
19
  import numpy as np
4
20
 
5
21
 
6
- def default_config():
7
- return dict(cache=True,
8
- cv_eps=0.0,
9
- cv_ieq=dict(scale=None, eps=0.0, pow=None, func=np.sum),
10
- cv_eq=dict(scale=None, eps=1e-4, pow=None, func=np.sum)
11
- )
22
+ def default_config() -> dict:
23
+ """
24
+ Get default constraint violation configuration settings.
25
+
26
+ Returns
27
+ -------
28
+ out : dict
29
+ A dictionary of default constraint violation settings.
30
+ """
31
+ return dict(
32
+ cache = True,
33
+ cv_eps = 0.0,
34
+ cv_ieq = dict(scale=None, eps=0.0, pow=None, func=np.sum),
35
+ cv_eq = dict(scale=None, eps=1e-4, pow=None, func=np.sum),
36
+ )
12
37
 
13
38
 
14
39
  class Individual:
40
+ """
41
+ Base class for representing an individual in a population-based
42
+ optimization algorithm.
43
+ """
44
+
45
+ # function: function to generate default configuration settings
15
46
  default_config = default_config
16
47
 
17
- def __init__(self, config=None, **kwargs) -> None:
48
+ def __init__(
49
+ self,
50
+ config: Optional[dict] = None,
51
+ **kwargs: dict,
52
+ ) -> None:
53
+ """
54
+ Constructor for the ``Invididual`` class.
55
+
56
+ Parameters
57
+ ----------
58
+ config : dict, None
59
+ A dictionary of configuration metadata.
60
+ If ``None``, use a class-dependent default configuration.
61
+ kwargs : dict
62
+ Additional keyword arguments containing data which is to be stored
63
+ in the ``Individual``.
64
+ """
65
+ # set decision variable vector to None
66
+ self._X = None
67
+
68
+ # set values objective(s), inequality constraint(s), equality
69
+ # contstraint(s) to None
70
+ self._F = None
71
+ self._G = None
72
+ self._H = None
73
+
74
+ # set first derivatives of objective(s), inequality constraint(s),
75
+ # equality contstraint(s) to None
76
+ self._dF = None
77
+ self._dG = None
78
+ self._dH = None
79
+
80
+ # set second derivatives of objective(s), inequality constraint(s),
81
+ # equality contstraint(s) to None
82
+ self._ddF = None
83
+ self._ddG = None
84
+ self._ddH = None
85
+
86
+ # set constraint violation value to None
87
+ self._CV = None
18
88
 
19
- self._X, self._F, self._G, self._H, self._dF, self._dG, self._dH = None, None, None, None, None, None, None
20
- self._ddF, self._ddG, self._ddH, self._CV, = None, None, None, None
21
89
  self.evaluated = None
22
90
 
23
91
  # initialize all the local variables
@@ -39,8 +107,21 @@ class Individual:
39
107
  else:
40
108
  self.data[k] = v
41
109
 
42
- def reset(self, data=True):
43
-
110
+ def reset(
111
+ self,
112
+ data: bool = True,
113
+ ) -> None:
114
+ """
115
+ Reset the value of objective(s), inequality constraint(s), equality
116
+ constraint(s), their first and second derivatives, the constraint
117
+ violation, and the metadata to empty values.
118
+
119
+ Parameters
120
+ ----------
121
+ data : bool
122
+ Whether to reset metadata associated with the ``Individiual``.
123
+ """
124
+ # create an empty array to share
44
125
  empty = np.array([])
45
126
 
46
127
  # design variables
@@ -70,7 +151,23 @@ class Individual:
70
151
  # a set storing what has been evaluated
71
152
  self.evaluated = set()
72
153
 
73
- def has(self, key):
154
+ def has(
155
+ self,
156
+ key: str,
157
+ ) -> bool:
158
+ """
159
+ Determine whether an individual has a provided key or not.
160
+
161
+ Parameters
162
+ ----------
163
+ key : str
164
+ The key for which to test.
165
+
166
+ Returns
167
+ -------
168
+ out : bool
169
+ Whether the ``Individual`` has the provided key.
170
+ """
74
171
  return hasattr(self.__class__, key) or key in self.data
75
172
 
76
173
  # -------------------------------------------------------
@@ -78,39 +175,112 @@ class Individual:
78
175
  # -------------------------------------------------------
79
176
 
80
177
  @property
81
- def X(self):
178
+ def X(self) -> np.ndarray:
179
+ """
180
+ Get the decision vector for an individual.
181
+
182
+ Returns
183
+ -------
184
+ out : np.ndarray
185
+ The decision variable for the individual.
186
+ """
82
187
  return self._X
83
188
 
84
189
  @X.setter
85
- def X(self, value):
190
+ def X(self, value: np.ndarray) -> None:
191
+ """
192
+ Set the decision vector for an individual.
193
+
194
+ Parameters
195
+ ----------
196
+ value : np.ndarray
197
+ The decision variable for the individual.
198
+ """
86
199
  self._X = value
87
200
 
88
201
  @property
89
- def F(self):
202
+ def F(self) -> np.ndarray:
203
+ """
204
+ Get the objective function vector for an individual.
205
+
206
+ Returns
207
+ -------
208
+ out : np.ndarray
209
+ The objective function vector for the individual.
210
+ """
90
211
  return self._F
91
212
 
92
213
  @F.setter
93
- def F(self, value):
214
+ def F(self, value: np.ndarray) -> None:
215
+ """
216
+ Set the objective function vector for an individual.
217
+
218
+ Parameters
219
+ ----------
220
+ value : np.ndarray
221
+ The objective function vector for the individual.
222
+ """
94
223
  self._F = value
95
224
 
96
225
  @property
97
- def G(self):
226
+ def G(self) -> np.ndarray:
227
+ """
228
+ Get the inequality constraint vector for an individual.
229
+
230
+ Returns
231
+ -------
232
+ out : np.ndarray
233
+ The inequality constraint vector for the individual.
234
+ """
98
235
  return self._G
99
236
 
100
237
  @G.setter
101
- def G(self, value):
238
+ def G(self, value: np.ndarray) -> None:
239
+ """
240
+ Set the inequality constraint vector for an individual.
241
+
242
+ Parameters
243
+ ----------
244
+ value : np.ndarray
245
+ The inequality constraint vector for the individual.
246
+ """
102
247
  self._G = value
103
248
 
104
249
  @property
105
- def H(self):
250
+ def H(self) -> np.ndarray:
251
+ """
252
+ Get the equality constraint vector for an individual.
253
+
254
+ Returns
255
+ -------
256
+ out : np.ndarray
257
+ The equality constraint vector for the individual.
258
+ """
106
259
  return self._H
107
260
 
108
261
  @H.setter
109
- def H(self, value):
262
+ def H(self, value: np.ndarray) -> None:
263
+ """
264
+ Get the equality constraint vector for an individual.
265
+
266
+ Parameters
267
+ ----------
268
+ value : np.ndarray
269
+ The equality constraint vector for the individual.
270
+ """
110
271
  self._H = value
111
272
 
112
273
  @property
113
- def CV(self):
274
+ def CV(self) -> np.ndarray:
275
+ """
276
+ Get the constraint violation vector for an individual by either reading
277
+ it from the cache or calculating it.
278
+
279
+ Returns
280
+ -------
281
+ out : np.ndarray
282
+ The constraint violation vector for an individual.
283
+ """
114
284
  config = self.config
115
285
  cache = config["cache"]
116
286
 
@@ -121,11 +291,28 @@ class Individual:
121
291
  return self._CV
122
292
 
123
293
  @CV.setter
124
- def CV(self, value):
294
+ def CV(self, value: np.ndarray) -> None:
295
+ """
296
+ Set the constraint violation vector for an individual.
297
+
298
+ Parameters
299
+ ----------
300
+ value : np.ndarray
301
+ The constraint violation vector for the individual.
302
+ """
125
303
  self._CV = value
126
304
 
127
305
  @property
128
- def FEAS(self):
306
+ def FEAS(self) -> np.ndarray:
307
+ """
308
+ Get whether an individual is feasible for each constraint.
309
+
310
+ Returns
311
+ -------
312
+ out : np.ndarray
313
+ An array containing whether each constraint is feasible for an
314
+ individual.
315
+ """
129
316
  eps = self.config.get("cv_eps", 0.0)
130
317
  return self.CV <= eps
131
318
 
@@ -134,27 +321,75 @@ class Individual:
134
321
  # -------------------------------------------------------
135
322
 
136
323
  @property
137
- def dF(self):
324
+ def dF(self) -> np.ndarray:
325
+ """
326
+ Get the objective function vector first derivatives for an individual.
327
+
328
+ Returns
329
+ -------
330
+ out : np.ndarray
331
+ The objective function vector first derivatives for the individual.
332
+ """
138
333
  return self._dF
139
334
 
140
335
  @dF.setter
141
- def dF(self, value):
336
+ def dF(self, value: np.ndarray) -> None:
337
+ """
338
+ Set the objective function vector first derivatives for an individual.
339
+
340
+ Parameters
341
+ ----------
342
+ value : np.ndarray
343
+ The objective function vector first derivatives for the individual.
344
+ """
142
345
  self._dF = value
143
346
 
144
347
  @property
145
- def dG(self):
348
+ def dG(self) -> np.ndarray:
349
+ """
350
+ Get the inequality constraint(s) first derivatives for an individual.
351
+
352
+ Returns
353
+ -------
354
+ out : np.ndarray
355
+ The inequality constraint(s) first derivatives for the individual.
356
+ """
146
357
  return self._dG
147
358
 
148
359
  @dG.setter
149
- def dG(self, value):
360
+ def dG(self, value: np.ndarray) -> None:
361
+ """
362
+ Set the inequality constraint(s) first derivatives for an individual.
363
+
364
+ Parameters
365
+ ----------
366
+ value : np.ndarray
367
+ The inequality constraint(s) first derivatives for the individual.
368
+ """
150
369
  self._dG = value
151
370
 
152
371
  @property
153
- def dH(self):
372
+ def dH(self) -> np.ndarray:
373
+ """
374
+ Get the equality constraint(s) first derivatives for an individual.
375
+
376
+ Returns
377
+ -------
378
+ out : np.ndarray
379
+ The equality constraint(s) first derivatives for the individual.
380
+ """
154
381
  return self._dH
155
382
 
156
383
  @dH.setter
157
- def dH(self, value):
384
+ def dH(self, value: np.ndarray) -> None:
385
+ """
386
+ Set the equality constraint(s) first derivatives for an individual.
387
+
388
+ Parameters
389
+ ----------
390
+ value : np.ndarray
391
+ The equality constraint(s) first derivatives for the individual.
392
+ """
158
393
  self._dH = value
159
394
 
160
395
  # -------------------------------------------------------
@@ -162,27 +397,75 @@ class Individual:
162
397
  # -------------------------------------------------------
163
398
 
164
399
  @property
165
- def ddF(self):
400
+ def ddF(self) -> np.ndarray:
401
+ """
402
+ Get the objective function vector second derivatives for an individual.
403
+
404
+ Returns
405
+ -------
406
+ out : np.ndarray
407
+ The objective function vector second derivatives for the individual.
408
+ """
166
409
  return self._ddF
167
410
 
168
411
  @ddF.setter
169
- def ddF(self, value):
412
+ def ddF(self, value: np.ndarray) -> None:
413
+ """
414
+ Set the objective function vector second derivatives for an individual.
415
+
416
+ Parameters
417
+ ----------
418
+ value : np.ndarray
419
+ The objective function vector second derivatives for the individual.
420
+ """
170
421
  self._ddF = value
171
422
 
172
423
  @property
173
- def ddG(self):
424
+ def ddG(self) -> np.ndarray:
425
+ """
426
+ Get the inequality constraint(s) second derivatives for an individual.
427
+
428
+ Returns
429
+ -------
430
+ out : np.ndarray
431
+ The inequality constraint(s) second derivatives for the individual.
432
+ """
174
433
  return self._ddG
175
434
 
176
435
  @ddG.setter
177
- def ddG(self, value):
436
+ def ddG(self, value: np.ndarray) -> None:
437
+ """
438
+ Set the inequality constraint(s) second derivatives for an individual.
439
+
440
+ Parameters
441
+ ----------
442
+ value : np.ndarray
443
+ The inequality constraint(s) second derivatives for the individual.
444
+ """
178
445
  self._ddG = value
179
446
 
180
447
  @property
181
- def ddH(self):
448
+ def ddH(self) -> np.ndarray:
449
+ """
450
+ Get the equality constraint(s) second derivatives for an individual.
451
+
452
+ Returns
453
+ -------
454
+ out : np.ndarray
455
+ The equality constraint(s) second derivatives for the individual.
456
+ """
182
457
  return self._ddH
183
458
 
184
459
  @ddH.setter
185
- def ddH(self, value):
460
+ def ddH(self, value: np.ndarray) -> None:
461
+ """
462
+ Set the equality constraint(s) second derivatives for an individual.
463
+
464
+ Parameters
465
+ ----------
466
+ value : np.ndarray
467
+ The equality constraint(s) second derivatives for the individual.
468
+ """
186
469
  self._ddH = value
187
470
 
188
471
  # -------------------------------------------------------
@@ -190,22 +473,56 @@ class Individual:
190
473
  # -------------------------------------------------------
191
474
 
192
475
  @property
193
- def x(self):
476
+ def x(self) -> np.ndarray:
477
+ """
478
+ Convenience property. Get the decision vector for an individual.
479
+
480
+ Returns
481
+ -------
482
+ out : np.ndarray
483
+ The decision variable for the individual.
484
+ """
194
485
  return self.X
195
486
 
196
487
  @property
197
- def f(self):
488
+ def f(self) -> float:
489
+ """
490
+ Convenience property. Get the first objective function value for an individual.
491
+
492
+ Returns
493
+ -------
494
+ out : float
495
+ The first objective function value for the individual.
496
+ """
198
497
  return self.F[0]
199
498
 
200
499
  @property
201
- def cv(self):
500
+ def cv(self) -> Union[float,None]:
501
+ """
502
+ Convenience property. Get the first constraint violation value for an
503
+ individual by either reading it from the cache or calculating it.
504
+
505
+ Returns
506
+ -------
507
+ out : float, None
508
+ The constraint violation vector for an individual.
509
+ """
202
510
  if self.CV is None:
203
511
  return None
204
512
  else:
205
513
  return self.CV[0]
206
514
 
207
515
  @property
208
- def feas(self):
516
+ def feas(self) -> bool:
517
+ """
518
+ Convenience property. Get whether an individual is feasible for the
519
+ first constraint.
520
+
521
+ Returns
522
+ -------
523
+ out : bool
524
+ Whether an individual is feasible for the first constraint.
525
+ """
209
526
  return self.FEAS[0]
210
527
 
211
528
  # -------------------------------------------------------
@@ -213,25 +530,86 @@ class Individual:
213
530
  # -------------------------------------------------------
214
531
 
215
532
  @property
216
- def feasible(self):
533
+ def feasible(self) -> np.ndarray:
534
+ """
535
+ Deprecated. Get whether an individual is feasible for each constraint.
536
+
537
+ Returns
538
+ -------
539
+ out : np.ndarray
540
+ An array containing whether each constraint is feasible for an
541
+ individual.
542
+ """
543
+ warn(
544
+ "The ``feasible`` property for ``pymoo.core.individual.Individual`` is deprecated",
545
+ DeprecationWarning,
546
+ stacklevel = 2,
547
+ )
217
548
  return self.FEAS
218
549
 
219
550
  # -------------------------------------------------------
220
551
  # Other Functions
221
552
  # -------------------------------------------------------
222
553
 
223
- def set_by_dict(self, **kwargs):
554
+ def set_by_dict(
555
+ self,
556
+ **kwargs: dict
557
+ ) -> None:
558
+ """
559
+ Set an individual's data or metadata using values in a dictionary.
560
+
561
+ Parameters
562
+ ----------
563
+ kwargs : dict
564
+ Keyword arguments defining the data to set.
565
+ """
224
566
  for k, v in kwargs.items():
225
567
  self.set(k, v)
226
568
 
227
- def set(self, key, value):
569
+ def set(
570
+ self,
571
+ key: str,
572
+ value: object,
573
+ ) -> 'Individual':
574
+ """
575
+ Set an individual's data or metadata based on a key and value.
576
+
577
+ Parameters
578
+ ----------
579
+ key : str
580
+ Key of the data for which to set.
581
+ value : object
582
+ Value of the data for which to set.
583
+
584
+ Returns
585
+ -------
586
+ out : Individual
587
+ A reference to the ``Individual`` for which values were set.
588
+ """
228
589
  if hasattr(self, key):
229
590
  setattr(self, key, value)
230
591
  else:
231
592
  self.data[key] = value
232
593
  return self
233
594
 
234
- def get(self, *keys):
595
+ def get(
596
+ self,
597
+ *keys: Tuple[str,...],
598
+ ) -> Union[tuple,object]:
599
+ """
600
+ Get the values for one or more keys for an individual.
601
+
602
+ Parameters
603
+ ----------
604
+ keys : tuple
605
+ A tuple of keys for which to get values.
606
+
607
+ Returns
608
+ -------
609
+ out : tuple, object
610
+ If more than one key provided, return a ``tuple`` of retrieved values.
611
+ If a single key provided, return the retrieved value.
612
+ """
235
613
  ret = []
236
614
 
237
615
  for key in keys:
@@ -249,13 +627,54 @@ class Individual:
249
627
  else:
250
628
  return tuple(ret)
251
629
 
252
- def duplicate(self, key, new_key):
630
+ def duplicate(
631
+ self,
632
+ key: str,
633
+ new_key: str,
634
+ ) -> None:
635
+ """
636
+ Duplicate a key to a new key.
637
+
638
+ Parameters
639
+ ----------
640
+ key : str
641
+ Name of the key to duplicated.
642
+ new_key : str
643
+ Name of the key to which to duplicate the original key.
644
+ """
253
645
  self.set(new_key, self.get(key))
254
646
 
255
- def new(self):
647
+ def new(self) -> 'Individual':
648
+ """
649
+ Create a new instance of this class.
650
+
651
+ Returns
652
+ -------
653
+ out : Individual
654
+ A new instance of an ``Individual``.
655
+ """
256
656
  return self.__class__()
257
657
 
258
- def copy(self, other=None, deep=True):
658
+ def copy(
659
+ self,
660
+ other: Optional['Individual'] = None,
661
+ deep: bool = True,
662
+ ) -> 'Individual':
663
+ """
664
+ Copy an individual.
665
+
666
+ Parameters
667
+ ----------
668
+ other : Individual, None
669
+ The individual to copy. If ``None``, assumed to be self.
670
+ deep : bool
671
+ Whether to deep copy the individual.
672
+
673
+ Returns
674
+ -------
675
+ out : Individual
676
+ A copy of the individual.
677
+ """
259
678
  obj = self.new()
260
679
 
261
680
  # if not provided just copy yourself
@@ -275,7 +694,29 @@ class Individual:
275
694
  return obj
276
695
 
277
696
 
278
- def calc_cv(G=None, H=None, config=None):
697
+ def calc_cv(
698
+ G: Optional[np.ndarray] = None,
699
+ H: Optional[np.ndarray] = None,
700
+ config: Optional[dict] = None,
701
+ ) -> np.ndarray:
702
+ """
703
+ Calculate the constraint violation(s) for a set of inequality constraint(s),
704
+ equality constraint(s), and a scoring configuration.
705
+
706
+ Parameters
707
+ ----------
708
+ G : np.ndarray, None
709
+ A vector of inequality constraint(s).
710
+ H : np.ndarray, None
711
+ A vector of equality constraint(s).
712
+ config : dict, None
713
+ A dictionary of constraint violation scoring configuration settings.
714
+
715
+ Returns
716
+ -------
717
+ out : np.ndarray
718
+ An array of constraint violations for each objective.
719
+ """
279
720
  if G is None:
280
721
  G = np.array([])
281
722
 
@@ -302,7 +743,29 @@ def calc_cv(G=None, H=None, config=None):
302
743
  return np.array(ieq_cv) + np.array(eq_cv)
303
744
 
304
745
 
305
- def constr_to_cv(c, eps=0.0, scale=None, pow=None, func=np.mean):
746
+ def constr_to_cv(
747
+ c: Union[np.ndarray,None],
748
+ eps: float = 0.0,
749
+ scale: Optional[float] = None,
750
+ pow: Optional[float] = None,
751
+ func: object = np.mean,
752
+ ) -> float:
753
+ """
754
+ Convert a constraint to a constraint violation.
755
+
756
+ c : np.ndarray
757
+ An array of constraint violations.
758
+ eps : float
759
+ Error tolerance bounds.
760
+ scale : float, None
761
+ The scale to apply to a constraint violation.
762
+ If ``None``, no scale alteration is applied.
763
+ pow : float, None
764
+ A power to apply to a constraint violation.
765
+ If ``None``, no power alteration is applied.
766
+ func : function
767
+ A function to convert multiple constraint violations into a single score.
768
+ """
306
769
  if c is None or len(c) == 0:
307
770
  return 0.0
308
771