moocore API Reference
Core utilities and performance metrics for multi-objective optimization algorithms.
moocore.Hypervolume
Python Library Documentation: class Hypervolume in module moocore._moocore class Hypervolume(builtins.object) | Hypervolume(ref: 'ArrayLike', maximise: 'bool | Sequence[bool]' = False) -> 'None' | | Object-oriented interface for the hypervolume indicator. | | .. seealso:: For examples, see :func:`hypervolume`. | | Parameters | ---------- | ref : | Reference point as a 1D vector. Must be either a single value, which will be used for all coordinates, | or the same length as a single point in ``points``. | maximise : | Whether the objectives must be maximised instead of minimised. | Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective. | Also accepts a 1D numpy array with value 0/1 for each objective. | | | Examples | -------- | This function assumes that objectives must be minimized by default. We can | easily specify maximization: | | >>> hv_ind = moocore.Hypervolume(ref=0, maximise=True) | >>> hv_ind([[5, 5], [4, 6], [2, 7], [7, 4]]) | 39.0 | >>> hv_ind([[5, 5], [4, 6], [7, 4]]) | 37.0 | | See Also | -------- | RelativeHypervolume : Compute hypervolume relative to a reference set. | | Methods defined here: | | __call__(self, points: 'ArrayLike') -> 'float' | Compute hypervolume indicator. | | Parameters | ---------- | points : | Array of numerical values, where each row gives the coordinates of a point in objective space. | If the array is created by the :func:`read_datasets()` function, remove the last column. | | Returns | ------- | A single numerical value, the hypervolume indicator. | | __init__(self, ref: 'ArrayLike', maximise: 'bool | Sequence[bool]' = False) -> 'None' | Initialize self. See help(type(self)) for accurate signature. | | ---------------------------------------------------------------------- | Data descriptors defined here: | | __dict__ | dictionary for instance variables | | __weakref__ | list of weak references to the object
moocore.ReadDatasetsError
Python Library Documentation: class ReadDatasetsError in module moocore._moocore class ReadDatasetsError(builtins.Exception) | ReadDatasetsError(error_code: 'int') | | Custom exception class for an error returned by the :func:`read_datasets()` function. | | Parameters | ---------- | error_code: | Error code returned by ``read_datasets()`` C function. | | Method resolution order: | ReadDatasetsError | builtins.Exception | builtins.BaseException | builtins.object | | Methods defined here: | | __init__(self, error_code: 'int') | Initialize self. See help(type(self)) for accurate signature. | | ---------------------------------------------------------------------- | Data descriptors defined here: | | __weakref__ | list of weak references to the object | | ---------------------------------------------------------------------- | Static methods inherited from builtins.Exception: | | __new__(*args, **kwargs) class method of builtins.Exception | Create and return a new object. See help(type) for accurate signature. | | ---------------------------------------------------------------------- | Methods inherited from builtins.BaseException: | | __getattribute__(self, name, /) | Return getattr(self, name). | | __reduce__(...) | Helper for pickle. | | __repr__(self, /) | Return repr(self). | | __setstate__(...) | | __str__(self, /) | Return str(self). | | add_note(...) | Exception.add_note(note) -- | add a note to the exception | | with_traceback(...) | Exception.with_traceback(tb) -- | set self.__traceback__ to tb and return self. | | ---------------------------------------------------------------------- | Data descriptors inherited from builtins.BaseException: | | __cause__ | exception cause | | __context__ | exception context | | __dict__ | | __suppress_context__ | | __traceback__ | | args
moocore.RelativeHypervolume
Python Library Documentation: class RelativeHypervolume in module moocore._moocore
class RelativeHypervolume(Hypervolume)
| RelativeHypervolume(ref: 'ArrayLike', ref_set: 'ArrayLike', maximise: 'bool | Sequence[bool]' = False) -> 'None'
|
| Computes the hypervolume value of fronts relative to the hypervolume of a reference front.
|
| The value is computed as :math:`1 - \frac{\text{hyp}(X)}{\text{hyp}(R)}`,
| where :math:`X` is an input set (front), :math:`R` is the reference front
| and :math:`\text{hyp}()` is calculated by :func:`hypervolume`. Thus, lower
| values are better, in contrast to the usual hypervolume. The metric has
| also been called *hypervolume relative deviation*
| :footcite:p:`BezLopStu2017assessment`.
|
| Parameters
| ----------
| ref :
| Reference point as a 1D vector. Must be either a single value, which will be used for all coordinates,
| or the same length as a single point in ``points``.
| ref_set :
| Reference set (front) as 2D array. The reference front does not need to
| weakly dominate the input sets. If this is required, the user must ensure it.
| maximise :
| Whether the objectives must be maximised instead of minimised.
| Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
| Also accepts a 1D numpy array with value 0/1 for each objective.
|
|
| References
| ----------
| .. footbibliography::
|
|
| Examples
| --------
| This function assumes that objectives must be minimized by default. We can
| easily specify maximization:
|
| >>> ref_set = [[6, 6], [2, 7], [7, 2]]
| >>> hv_ind = moocore.RelativeHypervolume(ref=0, ref_set=ref_set, maximise=True)
| >>> hv_ind([[5, 5], [4, 6], [2, 7], [7, 4]])
| 0.0250000
| >>> hv_ind([[5, 5], [4, 6], [7, 4]])
| 0.0749999
| >>> hv_ind([[0, 0]])
| 1.0
| >>> hv_ind(ref_set)
| 0.0
|
| Method resolution order:
| RelativeHypervolume
| Hypervolume
| builtins.object
|
| Methods defined here:
|
| __call__(self, points: 'ArrayLike') -> 'float'
| Compute relative hypervolume indicator as ``1 - (hypervolume(points, ref=ref) / hypervolume(ref_set, ref=ref))``.
|
| Parameters
| ----------
| points :
| Array of numerical values, where each row gives the coordinates of a point in objective space.
| If the array is created by the :func:`read_datasets()` function, remove the last column.
|
| Returns
| -------
| A single numerical value, the relative hypervolume indicator, which must be minimized.
|
| __init__(self, ref: 'ArrayLike', ref_set: 'ArrayLike', maximise: 'bool | Sequence[bool]' = False) -> 'None'
| Initialize self. See help(type(self)) for accurate signature.
|
| ----------------------------------------------------------------------
| Data descriptors inherited from Hypervolume:
|
| __dict__
| dictionary for instance variables
|
| __weakref__
| list of weak references to the object
moocore.any_dominated
Python Library Documentation: function any_dominated in module moocore._moocore
any_dominated(points: 'ArrayLike', /, *, maximise: 'bool | Sequence[bool]' = False, keep_weakly: 'bool' = False) -> 'bool'
Test whether the input points contains any (weakly-)dominated point.
This function is equivalent to ``np.logical_not(moocore.is_nondominated(x)).any()``, but significantly faster.
.. seealso:: For details about the calculation, see :func:`is_nondominated`.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
keep_weakly:
If ``False``, return ``True`` if any point is duplicated.
Returns
-------
Returns ``True`` if the input array contains at least one point that is weakly-dominated by another point in the array. With ``keep_weakly=True``, the point must be dominated not just a duplicate.
Examples
--------
>>> S = np.array([[1, 1], [1, 0], [0, 1], [1, 0]])
>>> moocore.is_nondominated(S)
array([False, True, True, False])
>>> moocore.any_dominated(S)
True
>>> moocore.any_dominated(moocore.filter_dominated(S))
False
>>> S = np.array([[0, 1], [1, 0], [1, 0]])
>>> moocore.is_nondominated(S, keep_weakly=True)
array([ True, True, True])
>>> moocore.any_dominated(S, keep_weakly=True)
False
moocore.apply_within_sets
Python Library Documentation: function apply_within_sets in module moocore._moocore
apply_within_sets(x: 'ArrayLike', sets: 'ArrayLike', func: 'Callable[..., Any]', **kwargs) -> 'np.ndarray'
Split ``x`` by row according to ``sets`` and apply ``func`` to each sub-array.
Parameters
----------
x :
2D array to be divided into sub-arrays.
sets :
A list or 1D array of length equal to the number of rows of ``x``. The values are used as-is to determine the groups and do not need to be sorted.
func :
A function that can take a 2D array as input. This function may return (1) a 2D array with the same number of rows as the input,
(2) a 1D array as long as the number of input rows,
(3) a scalar value, or
(4) a 2D array with a single row.
kwargs :
Additional keyword arguments to ``func``.
Returns
-------
An array whose shape depends on the output of ``func``. See Examples below.
See Also
--------
is_nondominated_within_sets, filter_dominated_within_sets
Examples
--------
>>> sets = np.array([3, 1, 2, 4, 2, 3, 1])
>>> x = np.arange(len(sets) * 2).reshape(-1, 2)
>>> x = np.hstack((x, sets.reshape(-1, 1)))
If ``func`` returns an array with the same number of rows as the input (case 1),
then the output is ordered in exactly the same way as the input.
>>> moocore.apply_within_sets(x, sets, lambda x: x)
array([[ 0, 1, 3],
[ 2, 3, 1],
[ 4, 5, 2],
[ 6, 7, 4],
[ 8, 9, 2],
[10, 11, 3],
[12, 13, 1]])
This is also the behavior if ``func`` returns a 1D array with one value per input row (case 2).
>>> moocore.apply_within_sets(x, sets, lambda x: x.sum(axis=1))
array([ 4, 6, 11, 17, 19, 24, 26])
If ``func`` returns a single scalar (case 3) or a 2D array with a single row (case 4),
then the order of the output is the order of the unique values as found in
``sets``, without sorting the unique values, which is what
:meth:`pandas.Series.unique` returns and NOT what :func:`numpy.unique`
returns.
>>> moocore.apply_within_sets(x, sets, lambda x: x.max())
array([11, 13, 9, 7])
>>> moocore.apply_within_sets(x, sets, lambda x: [x.max(axis=0)])
array([[10, 11, 3],
[12, 13, 1],
[ 8, 9, 2],
[ 6, 7, 4]])
In the previous example, ``func`` returns a 2D array with a single row. The
following will produce an error because it returns a 1D array, which is
interpreted as case 2, but the number of values does not match the number
of input rows.
>>> moocore.apply_within_sets(
... x, sets, lambda x: x.max(axis=0)
... ) # doctest: +ELLIPSIS
Traceback (most recent call last):
...
ValueError: `func` returned an array of length 3 but the input has length 2 for rows [0 5]
moocore.avg_hausdorff_dist
Python Library Documentation: function avg_hausdorff_dist in module moocore._moocore
avg_hausdorff_dist(points: 'ArrayLike', /, ref: 'ArrayLike', *, maximise: 'bool | Sequence[bool]' = False, p: 'int' = 1) -> 'float'
Average Hausdorff distance.
.. seealso:: For examples, see :func:`igd_plus`. For details of the calculation, see :ref:`igd_hausdorf`.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
ref :
Reference set as a matrix of numerical values. Must have the same number of columns as ``points``.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
p :
Hausdorff distance parameter. Must be larger than 0.
Returns
-------
A single numerical value.
moocore.eaf
Python Library Documentation: function eaf in module moocore._moocore
eaf(points: 'ArrayLike', /, sets: 'ArrayLike', *, percentiles: 'Sequence[float]' = ()) -> 'np.ndarray'
Exact computation of the Empirical Attainment Function (EAF).
.. seealso:: For the definition of EAF, see :ref:`eaf_computation`.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
sets :
1D vector or list of values that gives the set of each row of ``points``.
percentiles :
List indicating which percentiles are computed. By default, all possible percentiles are calculated.
Returns
-------
EAF data points, with the same number of columns as the input argument, but a different number of rows. The last column represents the EAF percentile for that data point.
See Also
--------
mooplot.plot_eaf: Plotting the EAF.
Notes
-----
In the current implementation, the EAF is computed using the algorithms
proposed by :footcite:t:`FonGueLopPaq2011emo`, which have complexity
:math:`\Theta(m\log m + nm)` in 2D and :math:`O(n^2 m \log m)` in 3D, where
:math:`n` is the number of input sets and :math:`m` is the total number of
input points.
References
----------
.. footbibliography::
Examples
--------
>>> x = moocore.get_dataset("input1.dat")
>>> moocore.eaf(x[:, :-1], x[:, -1]) # doctest: +ELLIPSIS
array([[ 0.17470556, 8.89066343, 10. ],
[ 0.20816431, 4.62275469, 10. ],
[ 0.22997367, 1.11772205, 10. ],
[ 0.58799475, 0.73891181, 10. ],
[ 1.54506255, 0.38303122, 10. ],
[ 8.57911868, 0.35169752, 10. ],
[ 0.20816431, 8.89066343, 20. ],
[ 0.2901393 , 8.32259412, 20. ],
...
[ 9.78758589, 2.8124162 , 90. ],
[ 1.13096306, 9.72645436, 100. ],
[ 2.71891214, 8.84691923, 100. ],
[ 3.34035397, 7.49376946, 100. ],
[ 4.43498452, 6.94327481, 100. ],
[ 4.96525837, 6.20957074, 100. ],
[ 7.92511295, 3.92669598, 100. ]])
>>> moocore.eaf(x[:, :-1], x[:, -1], percentiles=[0, 50, 100]) # doctest: +ELLIPSIS
array([[ 0.17470556, 8.89066343, 0. ],
[ 0.20816431, 4.62275469, 0. ],
[ 0.22997367, 1.11772205, 0. ],
[ 0.58799475, 0.73891181, 0. ],
[ 1.54506255, 0.38303122, 0. ],
[ 8.57911868, 0.35169752, 0. ],
[ 0.53173087, 9.73244829, 50. ],
[ 0.62230271, 9.02211752, 50. ],
[ 0.79293574, 8.89066343, 50. ],
[ 0.9017068 , 8.32259412, 50. ],
[ 0.97468676, 7.65893644, 50. ],
[ 1.06855707, 7.49376946, 50. ],
[ 1.54506255, 6.7102429 , 50. ],
[ 1.5964888 , 5.98825094, 50. ],
[ 2.16315952, 4.7394435 , 50. ],
[ 2.85891341, 4.49240941, 50. ],
[ 3.34035397, 2.89377444, 50. ],
[ 4.61023932, 2.87955367, 50. ],
[ 4.96525837, 2.29231998, 50. ],
[ 7.04694467, 1.83484358, 50. ],
[ 9.7398055 , 1.00153569, 50. ],
[ 1.13096306, 9.72645436, 100. ],
[ 2.71891214, 8.84691923, 100. ],
[ 3.34035397, 7.49376946, 100. ],
[ 4.43498452, 6.94327481, 100. ],
[ 4.96525837, 6.20957074, 100. ],
[ 7.92511295, 3.92669598, 100. ]])
moocore.eafdiff
Python Library Documentation: function eafdiff in module moocore._moocore
eafdiff(x: 'ArrayLike', y: 'ArrayLike', /, *, intervals: 'int | None' = None, maximise: 'bool | Sequence[bool]' = False, rectangles: 'bool' = False) -> 'np.ndarray'
Compute empirical attainment function (EAF) differences.
Calculate the differences between the empirical attainment functions of two
data sets.
.. warning::
The current implementation only supports 2 objectives.
Parameters
----------
x, y : ArrayLike
Numpy matrices corresponding to the input data of left and right sides,
respectively. Each data frame has at least three columns, the third one
being the set of each point. See also :func:`read_datasets`.
intervals :
The absolute range of the differences :math:`[0, 1]` is partitioned into the number of intervals provided.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
rectangles :
If ``True``, the output is in the form of rectangles of the same color.
Returns
-------
With ``rectangles=False``, a matrix with three columns, The first two
columns describe the points where there is a transition in the value of
the EAF differences.
With ``rectangles=True``, a matrix with five columns, where the first 4
columns give the coordinates of two corners of each rectangle. In both
cases, the last column gives the difference in terms of sets in ``x``
minus sets in ``y`` that attain each point (i.e., negative values are
differences in favour ``y``).
See Also
--------
mooplot.eafdiffplot: Plotting EAF differences.
Examples
--------
>>> from io import StringIO
>>> A1 = moocore.read_datasets(
... StringIO('''
... 3 2
... 2 3
...
... 2.5 1
... 1 2
...
... 1 2''')
... )
>>> A2 = moocore.read_datasets(
... StringIO('''
... 4 2.5
... 3 3
... 2.5 3.5
...
... 3 3
... 2.5 3.5
...
... 2 1''')
... )
>>> moocore.eafdiff(A1, A2)
array([[ 1. , 2. , 2. ],
[ 2. , 1. , -1. ],
[ 2.5, 1. , 0. ],
[ 2. , 2. , 1. ],
[ 2. , 3. , 2. ],
[ 3. , 2. , 2. ],
[ 2.5, 3.5, 0. ],
[ 3. , 3. , 0. ],
[ 4. , 2.5, 1. ]])
>>> moocore.eafdiff(A1, A2, rectangles=True)
array([[ 2. , 1. , 2.5, 2. , -1. ],
[ 1. , 2. , 2. , inf, 2. ],
[ 2.5, 1. , inf, 2. , 0. ],
[ 2. , 2. , 3. , 3. , 1. ],
[ 2. , 3.5, 2.5, inf, 2. ],
[ 2. , 3. , 3. , 3.5, 2. ],
[ 3. , 2.5, 4. , 3. , 2. ],
[ 3. , 2. , inf, 2.5, 2. ],
[ 4. , 2.5, inf, 3. , 1. ]])
moocore.epsilon_additive
Python Library Documentation: function epsilon_additive in module moocore._moocore
epsilon_additive(points: 'ArrayLike', /, ref: 'ArrayLike', *, maximise: 'bool | Sequence[bool]' = False) -> 'float'
Additive epsilon metric.
The current implementation uses the naive algorithm that requires
:math:`O(m \cdot |A| \cdot |R|)`, where :math:`m` is the number of
objectives (dimension of vectors), :math:`A` is the input set and :math:`R`
is the reference set.
.. seealso:: For details of the calculation, see :ref:`epsilon_metric`.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
ref :
Reference set as a matrix of numerical values. Must have the same number of columns as ``points``.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
Returns
-------
A single numerical value.
Examples
--------
>>> import numpy as np
>>> dat = np.array([[3.5, 5.5], [3.6, 4.1], [4.1, 3.2], [5.5, 1.5]])
>>> ref = np.array([[1, 6], [2, 5], [3, 4], [4, 3], [5, 2], [6, 1]])
>>> moocore.epsilon_additive(dat, ref=ref)
2.5
>>> moocore.epsilon_mult(dat, ref=ref)
3.5
>>> float(np.exp(moocore.epsilon_additive(np.log(dat), ref=np.log(ref))))
3.5
moocore.epsilon_mult
Python Library Documentation: function epsilon_mult in module moocore._moocore
epsilon_mult(points: 'ArrayLike', /, ref: 'ArrayLike', *, maximise: 'bool | Sequence[bool]' = False) -> 'float'
Multiplicative epsilon metric.
.. warning::
All values in ``points`` and ``ref`` must be larger than 0.
.. seealso:: For examples, see :func:`epsilon_additive`. For details of the calculation, see :ref:`epsilon_metric`.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
ref :
Reference set as a matrix of numerical values. Must have the same number of columns as ``points``.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
Returns
-------
A single numerical value.
moocore.filter_dominated
Python Library Documentation: function filter_dominated in module moocore._moocore
filter_dominated(points: 'ArrayLike', /, *, maximise: 'bool | Sequence[bool]' = False, keep_weakly: 'bool' = False) -> 'np.ndarray'
Remove dominated points according to Pareto optimality.
.. seealso:: For examples, see :func:`is_nondominated`.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
keep_weakly :
If ``False``, delete duplicates of nondominated points.
Returns
-------
Returns the rows of ``points`` where :func:`is_nondominated` is ``True``.
moocore.filter_dominated_within_sets
Python Library Documentation: function filter_dominated_within_sets in module moocore._moocore
filter_dominated_within_sets(data: 'ArrayLike', /, *, maximise: 'bool | Sequence[bool]' = False, keep_weakly: 'bool' = False) -> 'np.ndarray'
Given a matrix that represents multiple sets of points (last column gives the set index), filter dominated points within each set.
Executes the :func:`filter_dominated` function within each set in a dataset
and returns back a dataset. This is roughly equivalent to partitioning ``dataset`` according to the last column,
filtering dominated solutions within each partition, and joining back the result.
Parameters
----------
data :
Numpy array of numerical values and set numbers, containing multiple datasets. For example the output of the :func:`read_datasets` function.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
keep_weakly :
If ``False``, delete duplicates of nondominated points.
Returns
-------
A numpy array where each set only contains nondominated points with respect to the set (last column is the set index).
Points from one set can still dominate points from another set.
Examples
--------
>>> x = moocore.get_dataset("input1.dat")
>>> pf_per_set = moocore.filter_dominated_within_sets(x)
>>> len(pf_per_set)
42
>>> pf_per_set # doctest: +ELLIPSIS
array([[ 0.20816431, 4.62275469, 1. ],
[ 0.22997367, 1.11772205, 1. ],
[ 0.58799475, 0.73891181, 1. ],
[ 1.5964888 , 5.98825094, 2. ],
[ 5.2812367 , 3.47800969, 2. ],
[ 2.16315952, 4.7394435 , 2. ],
...
[ 0.6510164 , 9.42381213, 9. ],
[ 1.30291449, 4.50417698, 9. ],
[ 0.62230271, 3.56945324, 10. ],
[ 0.86723965, 1.58599089, 10. ],
[ 6.43135537, 1.00153569, 10. ]])
>>> pf = moocore.filter_dominated(x[:, :-1])
>>> len(pf)
6
>>> pf
array([[0.20816431, 4.62275469],
[0.22997367, 1.11772205],
[0.58799475, 0.73891181],
[1.54506255, 0.38303122],
[0.17470556, 8.89066343],
[8.57911868, 0.35169752]])
>>> moocore.filter_dominated_within_sets(x[(x[:, 2] >= 3) & (x[:, 2] <= 5), :])
array([[2.60764118, 6.31309852, 3. ],
[3.22509709, 6.1522834 , 3. ],
[0.37731545, 9.02211752, 3. ],
[4.61023932, 2.29231998, 3. ],
[0.2901393 , 8.32259412, 4. ],
[1.54506255, 0.38303122, 4. ],
[4.43498452, 4.13150648, 5. ],
[9.78758589, 1.41238277, 5. ],
[7.85344142, 3.02219054, 5. ],
[0.9017068 , 7.49376946, 5. ],
[0.17470556, 8.89066343, 5. ]])
The above returns sets 3,4,5 with dominated points within each set removed.
See Also
--------
read_datasets : read datasets from a file.
filter_dominated : to be used with a single dataset.
moocore.generate_ndset
Python Library Documentation: function generate_ndset in module moocore._moocore
generate_ndset(n: 'int', d: 'int', /, method: 'str', *, seed: 'int | np.random.Generator | None' = None, integer: 'bool' = False) -> 'np.ndarray'
Generate a random set of ``n`` mutually nondominated points of dimension ``d`` with the shape defined by ``method``.
When ``integer=False`` (the default), the points are generated within the
hypercube :math:`(0,1)^d` and can be scaled to another range using
:func:`normalise`. Otherwise, points are scaled to a non-negative integer
range that keeps the points mutually nondominated.
Parameters
----------
n :
Number of rows in the output.
d :
Number of columns in the output.
method :
Method used to generate the random nondominated set. See the Notes below for more details.
seed :
Either an integer to seed :func:`numpy.random.default_rng`, Numpy
default random number generator (RNG) or an instance of a
Numpy-compatible RNG. ``None`` uses the equivalent of a random seed, as in :func:`numpy.random.default_rng`.
integer:
If ``True``, return integer-valued points.
Returns
-------
A numeric matrix of size :math:`n \times d` containing nondominated points.
Notes
-----
The available methods are:
``'simplex' | 'linear' | 'L'``
Uniformly samples points on the standard simplex.
This shape of nondominated set is also called ``'linear'`` in the literature :footcite:p:`LacKlaFon2017box`.
The standard :math:`(d-1)`-simplex is defined by :math:`\{\vec{x}\in
\mathbb{R}_+^d : \sum_{i=1}^d x_i = 1\}`. Each point :math:`\vec{z} \in
(0,1)^d \subset \mathbb{R}^d` is generated by sampling :math:`d`
independent and identically distributed values :math:`(x_1,x_2, \dots,
x_d)` from the exponential distribution, then dividing each value by the
l1-norm of the vector, :math:`z_i = x_i / \sum_{i=1}^d x_i`
:footcite:p:`RubMel1998simulation`. Values sampled from the exponential
distribution are guaranteed to be positive. Sampling from either the
standard normal distribution :footcite:p:`GueFonPaq2021hv` or the uniform
distribution :footcite:p:`LacKlaFon2017box` does not produce a uniform
distribution when projected onto the simplex.
``'concave-sphere' | 'sphere' | 'C'``
Uniformly samples points on the positive orthant of the hyper-sphere, which is concave when all objectives are minimised.
Each point :math:`\vec{z} \in (0,1)^d \subset \mathbb{R}^d` is
generated by sampling :math:`d` independent and identically distributed
values :math:`\vec{x}=(x_1,x_2, \dots, x_d)` from the standard normal
distribution, then dividing each value by the l2-norm of the vector,
:math:`z_i = \frac{|x_i|}{\|\vec{x}\|_2}`
:footcite:p:`Muller1959sphere`. The absolute value in the numerator ensures
that points are sampled on the positive orthant of the hyper-sphere.
Sampling from the uniform distribution :footcite:p:`LacKlaFon2017box` would
not result in a uniform sampling when projected onto the surface of the
hyper-sphere.
``'convex-sphere' | 'X'``
Equivalent to ``1 - generate_ndset(..., method='concave-sphere')``, which is convex for minimisation problems. This shape has also been called *inverted convex* :footcite:p:`IshHeSha2019regular`. This sampling is uniform.
It corresponds to translating points from the negative orthant of the hyper-sphere to the positive orthant. Thus, the sampling remains uniform.
``'convex-simplex'``
Equivalent to :code:`generate_ndset(..., method='simplex') ** 2`, which is convex for minimisation problems.
Such a set cannot be obtained by any affine transformation of a subset of the hyper-sphere. This sampling is *not* uniform.
The corresponding surface is equivalent to a simplex curved towards the
origin. The generated points :math:`\vec{z} \in (0,1)^d \subset
\mathbb{R}^d` satisfy :math:`\sum_{i=1}^d \sqrt{z_i} = 1`. Although
the sampling on the simplex is uniform, the transformed points are not.
``'concave-simplex'``
Equivalent to ``1 - generate_ndset(..., method='convex-simplex')``, which is concave for minimisation problems. This shape has also been called *inverted concave* :footcite:p:`IshHeSha2019regular`. This sampling is *not* uniform because ``method='convex-simplex'`` is not uniform.
``'inverted-simplex' | 'inverted-linear'``
Equivalent to ``1 - generate_ndset(..., method='simplex')``. This sampling is uniform.
Methods ``'inverted-simplex'``, ``'concave-simplex'`` and
``'convex-sphere'`` are translations of ``'simplex'``, ``'convex-simplex'``
and ``'concave-sphere'``, respectively. These translations have been
called `inverted` shapes in the literature and have different properties
than their `regular` counterparts :footcite:p:`IshHeSha2019regular`.
References
----------
.. footbibliography::
Examples
--------
>>> moocore.generate_ndset(5, 3, "simplex", seed=42)
array([[0.33742524, 0.32787894, 0.33469582],
[0.15382676, 0.047522 , 0.79865124],
[0.30561291, 0.67719985, 0.01718724],
[0.47441115, 0.03192912, 0.49365973],
[0.51684378, 0.11549762, 0.3676586 ]])
>>> moocore.generate_ndset(5, 3, "simplex", seed=42, integer=True)
array([[21, 20, 21],
[ 9, 3, 51],
[19, 43, 1],
[30, 2, 31],
[33, 7, 23]])
>>> rng = np.random.default_rng(42)
>>> moocore.generate_ndset(4, 2, "sphere", seed=rng)
array([[0.28118049, 0.9596549 ],
[0.62368072, 0.78167919],
[0.83175713, 0.5551397 ],
[0.37478326, 0.92711246]])
>>> moocore.generate_ndset(3, 5, "convex-sphere", seed=rng)
array([[0.98843533, 0.41282763, 0.39468745, 0.46462554, 0.95454935],
[0.37787475, 0.74198125, 0.52575586, 0.79648617, 0.47079199],
[0.47186748, 0.96998408, 0.88885902, 0.5906188 , 0.26499673]])
>>> moocore.generate_ndset(4, 4, "convex-simplex", seed=rng)
array([[0.19863075, 0.05673281, 0.02294823, 0.02710852],
[0.00335494, 0.01822224, 0.26522868, 0.08531355],
[0.22390087, 0.07032143, 0.00793081, 0.02978433],
[0.08611603, 0.02473488, 0.02168134, 0.16162454]])
moocore.get_dataset
Python Library Documentation: function get_dataset in module moocore._datasets
get_dataset(filename: 'str', /, **kwargs) -> 'np.ndarray'
Return dataset provided by ``moocore`` as a NumPy array.
Parameters
----------
filename :
Name of the dataset.
kwargs :
Additional arguments are passed to :func:`get_dataset_path`.
Returns
-------
An array containing a representation of the data in the file.
The first :math:`n-1` columns contain the numerical data for each of the objectives.
The last column contains an identifier for which set the data is relevant to.
See Also
--------
read_datasets : Function used to read the dataset.
moocore.get_dataset_path
Python Library Documentation: function get_dataset_path in module moocore._datasets
get_dataset_path(filename: 'str', /, *, force: 'bool' = False, n_retries: 'int' = 3, delay: 'int' = 1) -> 'Path'
Return path to a dataset provided with ``moocore``.
Small datasets are installed together with the ``moocore`` package.
Large datasets are downloaded from a remote repository and stored in the
local cache folder. If the file already exists locally (and the SHA256
checksums match when provided), the path to the local file is returned
without re-downloading.
Parameters
----------
filename :
Name of the dataset.
force :
If ``True``, always download remote datasets, even if present or their
checksum does not match what is expected for this version of ``moocore``.
n_retries :
Number of retries when download errors are encountered.
delay :
Number of seconds between retries when downloading.
Returns
-------
Full path to the dataset.
moocore.hv_approx
Python Library Documentation: function hv_approx in module moocore._moocore
hv_approx(points: 'ArrayLike', /, ref: 'ArrayLike', *, maximise: 'bool | Sequence[bool]' = False, nsamples: 'int' = 262144, seed: 'int | np.random.Generator | None' = None, method: "Literal['DZ2019-HW', 'DZ2019-MC', 'Rphi-FWE+']" = 'Rphi-FWE+') -> 'float'
Approximate the hypervolume indicator.
Approximate the value of the hypervolume metric with respect to a given
reference point assuming minimization of all objectives. Methods
``"Rphi-FWE+"`` and ``"DZ2019-HW"`` are deterministic and ignore the
parameter ``seed``, while ``method="DZ2019-MC"`` relies on Monte-Carlo
sampling :footcite:p:`DenZha2019approxhv`. All methods tend to get more
accurate with higher values of ``nsamples``, but the increase in accuracy
is not monotonic as shown in the example
:ref:`sphx_glr_auto_examples_plot_hv_approx.py`.
.. seealso:: For details of the calculation, see the Notes section below.
See :ref:`Benchmarks: Approximation of the hypervolume <bench-hvapprox>`.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
ref :
Reference point as a 1D vector. Must be either a single value, which will be used for all coordinates,
or the same length as a single point in ``points``.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
nsamples :
Number of samples for Monte-Carlo sampling. Higher values typically produce more
accurate approximations of the true hypervolume, but require more time.
seed :
Either an integer to seed :func:`numpy.random.default_rng`, Numpy
default random number generator (RNG) or an instance of a
Numpy-compatible RNG. ``None`` uses the equivalent of a random seed, as in :func:`numpy.random.default_rng`.
method :
Method to approximate the hypervolume.
Returns
-------
A single numerical value, the approximate hypervolume indicator.
See Also
--------
hypervolume, whv_hype
Notes
-----
All available methods approximate the hypervolume as a :math:`(m-1)`-dimensional
integral over the surface of hypersphere :footcite:p:`DenZha2019approxhv`:
.. math::
\widehat{HV}_r(A) = \frac{2\pi^\frac{m}{2}}{\Gamma(\frac{m}{2})}\frac{1}{m 2^m}\frac{1}{n}\sum_{i=1}^n \max_{y \in A} s(w^{(i)}, y)^m
where :math:`m` is the number of objectives, :math:`w^{(i)}` are weights
uniformly distributed on :math:`S_{+}`, i.e., the positive orthant of the
:math:`(m-1)`-D unit hypersphere, :math:`n` is the number of weights
sampled, :math:`\Gamma()` is the gamma function :func:`math.gamma()`, i.e.,
the analytical continuation of the factorial function, and :math:`s(w, y) =
\min_{k=1}^m (r_k - y_k)/w_k`.
In the default ``method="Rphi-FWE+"`` :footcite:p:`Lop2026hvapprox`, the
weights :math:`w^{(i)}, i=1\ldots n` are defined using the deterministic
low-discrepancy sequence :math:`R_\phi` :footcite:p:`Rob2018unreasonable`
mapped to the positive orthant of the hypersphere using a modified version
of Fang and Wang efficient mapping :footcite:p:`FanWan1994numtheory`.
In ``method="DZ2019-HW"`` :footcite:p:`DenZha2019approxhv`, the weights
:math:`w^{(i)}, i=1\ldots n` are defined using a deterministic
low-discrepancy sequence. The weight values depend on their number
(``nsamples``), thus increasing the number of weights may not necessarily
increase accuracy because the set of weights would be different.
In ``method="DZ2019-MC"`` :footcite:p:`DenZha2019approxhv`, the weights
:math:`w^{(i)}, i=1\ldots n` are sampled from the unit normal vector such
that each weight :math:`w = \frac{|x|}{\|x\|_2}` where each component of
:math:`x` is independently sampled from the standard normal distribution
:footcite:p:`Muller1959sphere`.
The original source code in C++/MATLAB for both ``"DZ2019-HW"`` and
``"DZ2019-MC"`` methods can be found `here
<https://github.com/Ksrma/Hypervolume-Approximation-using-polar-coordinate>`_.
:footcite:t:`Lop2026hvapprox` empirically shows that ``"Rphi-FWE+"``
typically produces an approximation error as low as the other methods, with
a computational cost similar to ``"DZ2019-MC"`` and significantly faster
than ``"DZ2019-HW"``.
References
----------
.. footbibliography::
Examples
--------
>>> x = np.array([[5, 5], [4, 6], [2, 7], [7, 4]])
>>> moocore.hypervolume(x, ref=[10, 10])
38.0
>>> moocore.hv_approx(x, ref=[10, 10], method="Rphi-FWE+")
37.99998
>>> moocore.hv_approx(x, ref=[10, 10], method="DZ2019-HW")
37.99996
>>> moocore.hv_approx(x, ref=[10, 10], seed=42, method="DZ2019-MC")
38.00081
Merge all the sets of a dataset by removing the set number column:
>>> x = moocore.get_dataset("input1.dat")[:, :-1]
Dominated points are ignored, so this:
>>> moocore.hv_approx(x, ref=10)
93.5533
>>> moocore.hv_approx(x, ref=10, method="DZ2019-HW")
93.5533
gives the same hypervolume approximation as this:
>>> x = moocore.filter_dominated(x)
>>> moocore.hv_approx(x, ref=10)
93.5533
>>> moocore.hv_approx(x, ref=10, method="DZ2019-HW")
93.5533
The approximation is far from perfect for large number of dimensions:
>>> x = moocore.get_dataset("ran.10pts.9d.10")[:, :-1]
>>> x = moocore.filter_dominated(-x, maximise=True)
>>> x = moocore.normalise(x, to_range=[1, 2])
>>> reference = 0.9
>>> moocore.hypervolume(x, ref=reference, maximise=True)
0.483633123747
>>> moocore.hv_approx(x, ref=reference, maximise=True)
0.48397532301
>>> moocore.hv_approx(x, ref=reference, maximise=True, method="DZ2019-HW")
0.483083547763
moocore.hv_contributions
Python Library Documentation: function hv_contributions in module moocore._moocore
hv_contributions(points: 'ArrayLike', /, ref: 'ArrayLike', maximise: 'bool | Sequence[bool]' = False, ignore_dominated: 'bool' = True) -> 'np.ndarray'
Hypervolume contributions of a set of points.
Computes the hypervolume contribution of each point of a set of points with
respect to a given reference point. Duplicated and dominated points have
zero contribution. By default, dominated points are ignored, that is, they
do not affect the contribution of other points. See the Notes below for
more details.
.. seealso:: For details about the hypervolume, see :ref:`hypervolume_metric`.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
ref :
Reference point as a 1D vector. Must be either a single value, which will be used for all coordinates,
or the same length as a single point in ``points``.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
ignore_dominated :
Whether dominated points are ignored when computing the contribution of nondominated points.
The value of this parameter has an effect on the return values only if the input contains dominated points.
Setting this to ``False`` slows down the computation significantly.
See the Notes below for a detailed explanation.
Returns
-------
An array of floating-point values as long as the number of rows in ``points``.
Each value is the contribution of the corresponding point in ``points``.
Notes
-----
The hypervolume contribution of point :math:`\vec{p} \in X` is defined as
:math:`\text{hvc}(\vec{p}) = \text{hyp}(X) - \text{hyp}(X \setminus
\{\vec{p}\})`. This definition implies that duplicated points have zero
contribution even if not dominated, because removing one of the duplicates
does not change the hypervolume of the remaining set. Moreover, dominated
points also have zero contribution. However, a point that is dominated by
a single (dominating) nondominated point reduces the contribution of the
latter, because removing the dominating point makes the dominated one
become nondominated.
Handling this special case is non-trivial and makes the computation more
expensive, thus the default (``ignore_dominated=True``) ignores all
dominated points in the input, that is, their contribution is set to zero
and their presence does not affect the contribution of any other point. Setting
``ignore_dominated=False`` will consider dominated points according to the
mathematical definition given above, but the computation will be slower.
When the input only consists of mutually nondominated points, the value of
``ignore_dominated`` does not change the result, but the default value is
significantly faster.
The current implementation uses a :math:`O(n \log n)` dimension-sweep
algorithm for 2D. With ``ignore_dominated=True``, the 3D case uses the
HVC3D algorithm :footcite:p:`GueFon2017hv4d`, which has :math:`O(n \log n)`
complexity. Otherwise, the implementation uses the naive algorithm that
requires calculating the hypervolume :math:`|X|+1` times.
References
----------
.. footbibliography::
Examples
--------
>>> x = np.array([[5, 1], [1, 5], [4, 2], [4, 4], [5, 1]])
>>> moocore.hv_contributions(x, ref=(6, 6), ignore_dominated=True)
... ## Explanation:
... # hvc[(5,1)] = 0 = duplicated
... # hvc[(1,5)] = 3 = (4 - 1) * (6 - 5)
... # hvc[(4,2)] = 3 = (5 - 4) * (5 - 2)
... # hvc[(4,4)] = 0 = dominated
... # hvc[(5,1)] = 0 = duplicated
array([0., 3., 3., 0., 0.])
>>> moocore.hv_contributions(x, ref=(6, 6), ignore_dominated=False)
... ## Explanation:
... # hvc[(5,1)] = 0 = duplicated
... # hvc[(1,5)] = 3 = (4 - 1) * (6 - 5)
... # hvc[(4,2)] = 2 = (5 - 4) * (4 - 2)
... # hvc[(4,4)] = 0 = dominated
... # hvc[(5,1)] = 0 = duplicated
array([0., 3., 2., 0., 0.])
>>> x = np.array([[5, 5], [4, 6], [2, 7], [7, 4]])
>>> moocore.hv_contributions(x, ref=[10, 10])
array([2., 1., 6., 3.])
moocore.hypervolume
Python Library Documentation: function hypervolume in module moocore._moocore
hypervolume(points: 'ArrayLike', /, ref: 'ArrayLike', *, maximise: 'bool | Sequence[bool]' = False) -> 'float'
Hypervolume indicator.
Compute the hypervolume metric with respect to a given reference point
assuming minimization of all objectives.
.. seealso:: For details about the hypervolume, see :ref:`hypervolume_metric`.
See :ref:`Benchmarking the exact computation of hypervolume <bench-hv>`.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
ref :
Reference point as a 1D vector. Must be either a single value, which will be used for all coordinates,
or the same length as a single point in ``points``.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
Returns
-------
A single numerical value, the hypervolume indicator.
See Also
--------
Hypervolume : Object-oriented interface.
RelativeHypervolume : Compute hypervolume relative to a reference set.
hv_contributions: Hypervolume contribution of individual points.
Notes
-----
For 2D and 3D, the algorithms used
:footcite:p:`FonPaqLop06:hypervolume,BeuFonLopPaqVah09:tec` have :math:`O(n
\log n)` complexity, where :math:`n` is the number of input points. The 3D
case uses the HV3D\ :sup:`+` algorithm :footcite:p:`GueFon2017hv4d`, which
has the same complexity as the HV3D algorithm
:footcite:p:`FonPaqLop06:hypervolume,BeuFonLopPaqVah09:tec`, but it is
faster in practice.
For 4D, the algorithm used is HV4D\ :sup:`+` :footcite:p:`GueFon2017hv4d`,
which has :math:`O(n^2)` complexity. Compared to the `original
implementation <https://github.com/apguerreiro/HVC/>`_, this implementation
correctly handles weakly dominated points and has been further optimized
for speed.
For 5D or higher and up to |HV_INEX_MAX_ROWS| points, the implementation
uses the inclusion-exclusion algorithm :footcite:p:`WuAza2001metrics`,
which has :math:`O(m 2^{n})` time and :math:`O(n\cdot m)` space complexity,
where :math:`m` is the dimension of the points, but it is very fast for
such small sets. For larger number of points, it uses a recursive
algorithm :footcite:p:`FonPaqLop06:hypervolume` that computes 4D
contributions :footcite:p:`GueFon2017hv4d` as the base case, resulting in a
:math:`O(n^{m-2})` time complexity and :math:`O(n)` space complexity in the
worst-case. Experimental results show that the pruning techniques used may
reduce the time complexity even further. The original proposal
:footcite:p:`FonPaqLop06:hypervolume` had the HV3D algorithm as the base
case, giving a time complexity of :math:`O(n^{m-2} \log n)`. Andreia
P. Guerreiro enhanced the numerical stability of the recursive algorithm by
avoiding floating-point comparisons of partial hypervolumes.
The hypervolume of 1D inputs is defined as :code:`max(0, ref - points.min())`.
References
----------
.. footbibliography::
Examples
--------
>>> dat = np.array([[5, 5], [4, 6], [2, 7], [7, 4]])
>>> moocore.hypervolume(dat, ref=[10, 10])
38.0
This function assumes that objectives must be minimized by default. We can
easily specify maximization:
>>> moocore.hypervolume(dat, ref=0, maximise=True)
39.0
Merge all the sets of a dataset by removing the set number column:
>>> dat = moocore.get_dataset("input1.dat")[:, :-1]
>>> len(dat)
100
Dominated points are ignored, so this:
>>> moocore.hypervolume(dat, ref=[10, 10])
93.55331425585321
gives the same hypervolume as this:
>>> dat = moocore.filter_dominated(dat)
>>> len(dat)
6
>>> moocore.hypervolume(dat, ref=[10, 10])
93.55331425585321
moocore.igd
Python Library Documentation: function igd in module moocore._moocore
igd(points: 'ArrayLike', /, ref: 'ArrayLike', *, maximise: 'bool | Sequence[bool]' = False) -> 'float'
Inverted Generational Distance (IGD).
.. seealso:: For examples, see :func:`igd_plus`.
For details of the calculation, see :ref:`igd_hausdorf`.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
ref :
Reference set as a matrix of numerical values. Must have the same number of columns as ``points``.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
Returns
-------
A single numerical value.
moocore.igd_plus
Python Library Documentation: function igd_plus in module moocore._moocore
igd_plus(points: 'ArrayLike', /, ref: 'ArrayLike', *, maximise: 'bool | Sequence[bool]' = False) -> 'float'
Modified IGD (IGD+).
IGD+ is a Pareto-compliant version of :func:`igd` proposed by :cite:t:`IshMasTanNoj2015igd`.
.. seealso:: For details of the calculation, see :ref:`igd_hausdorf`.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
ref :
Reference set as a matrix of numerical values. Must have the same number of columns as ``points``.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
Returns
-------
A single numerical value.
Examples
--------
>>> dat = np.array([[3.5, 5.5], [3.6, 4.1], [4.1, 3.2], [5.5, 1.5]])
>>> ref = np.array([[1, 6], [2, 5], [3, 4], [4, 3], [5, 2], [6, 1]])
>>> moocore.igd(dat, ref=ref)
1.0627908666722465
>>> moocore.igd_plus(dat, ref=ref)
0.9855036468106652
>>> moocore.avg_hausdorff_dist(dat, ref)
1.0627908666722465
Example 4 by :cite:t:`IshMasTanNoj2015igd` shows a case where IGD gives the
wrong answer. In this case A is better than B in terms of Pareto optimality.
>>> ref = np.array([10, 0, 6, 1, 2, 2, 1, 6, 0, 10]).reshape(-1, 2)
>>> A = np.array([4, 2, 3, 3, 2, 4]).reshape(-1, 2)
>>> B = np.array([8, 2, 4, 4, 2, 8]).reshape(-1, 2)
>>> print(
... f"IGD(A)={moocore.igd(A, ref)} > IGD(B)={moocore.igd(B, ref)}\n"
... + f"and AvgHausdorff(A)={moocore.avg_hausdorff_dist(A, ref)} > "
... + f"AvgHausdorff(B)={moocore.avg_hausdorff_dist(B, ref)},\n"
... + f"which both contradict Pareto optimality. By contrast,\n"
... + f"IGD+(A)={moocore.igd_plus(A, ref)} < IGD+(B)={moocore.igd_plus(B, ref)},"
... + " which is correct."
... )
IGD(A)=3.707092031609239 > IGD(B)=2.59148346584763
and AvgHausdorff(A)=3.707092031609239 > AvgHausdorff(B)=2.59148346584763,
which both contradict Pareto optimality. By contrast,
IGD+(A)=1.482842712474619 < IGD+(B)=2.260112615949154, which is correct.
moocore.is_nondominated
Python Library Documentation: function is_nondominated in module moocore._moocore
is_nondominated(points: 'ArrayLike', /, *, maximise: 'bool | Sequence[bool]' = False, keep_weakly: 'bool' = False) -> 'np.ndarray'
Identify dominated points according to Pareto optimality.
.. seealso:: :ref:`Benchmarks of identifying nondominated points <bench-ndom>`.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
keep_weakly:
If ``False``, return ``False`` for any duplicates of nondominated points except the first one.
Returns
-------
Returns a boolean array of the same length as the number of rows of points,
where ``True`` means that the point is not dominated by any other point.
See Also
--------
filter_dominated : to filter out dominated points.
pareto_rank : to rank points according to Pareto dominance (nondominated sorting).
Notes
-----
Given :math:`n` points of dimension :math:`m`, the current implementation
of :func:`is_nondominated`, :func:`filter_dominated` and
:func:`any_dominated` always uses the best-known :math:`O(n \log n)`
dimension-sweep algorithm :footcite:p:`KunLucPre1975jacm` for :math:`m \leq 3`.
For :math:`m \geq 4`, functions :func:`is_nondominated` and
:func:`filter_dominated` use the best-known :math:`O(n \log^{m-2} n)`
algorithm :footcite:p:`KunLucPre1975jacm` when :math:`n > \KUNGSMALLTHRESHOLD`,
and the naive :math:`O(m n^2)` algorithm otherwise.
Function :func:`any_dominated` always uses the naive algorithm for :math:`m
\geq 4`.
References
----------
.. footbibliography::
Examples
--------
>>> S = np.array([[1, 1], [0, 1], [1, 0], [1, 0]])
>>> moocore.is_nondominated(S)
array([False, True, True, False])
>>> moocore.filter_dominated(S)
array([[0, 1],
[1, 0]])
>>> moocore.is_nondominated(S, keep_weakly=True)
array([False, True, True, True])
>>> moocore.filter_dominated(S, keep_weakly=True)
array([[0, 1],
[1, 0],
[1, 0]])
moocore.is_nondominated_within_sets
Python Library Documentation: function is_nondominated_within_sets in module moocore._moocore
is_nondominated_within_sets(points: 'ArrayLike', /, sets: 'ArrayLike', *, maximise: 'bool | Sequence[bool]' = False, keep_weakly: 'bool' = False) -> 'np.ndarray'
Identify dominated points according to Pareto optimality within each set.
Executes the :func:`is_nondominated` function within each set in a dataset
and returns back a 1D array of booleans. This is equivalent to
``apply_within_sets(points, sets, is_nondominated, ...)`` but slightly
faster.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
sets :
1D vector or list of values that gives the set of each row of ``points``.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
keep_weakly :
If ``False``, return ``False`` for any duplicates of nondominated points.
Returns
-------
Returns a boolean array of the same length as the number of rows of points,
where ``True`` means that the point is not dominated by any other point.
See Also
--------
filter_dominated_within_sets : filter out dominated points.
apply_within_sets : a more general way to apply any function to each set.
Examples
--------
>>> x = np.array([[1, 2, 1], [1, 3, 1], [2, 1, 1], [2, 2, 2]])
>>> moocore.is_nondominated_within_sets(x[:, :-1], x[:, -1])
array([ True, False, True, True])
>>> x = moocore.get_dataset("input1.dat")
>>> nondom_per_set = moocore.is_nondominated_within_sets(x[:, :-1], x[:, -1])
>>> len(nondom_per_set)
100
>>> nondom_per_set # doctest: +ELLIPSIS
array([False, False, True, False, True, False, False, False, False,
True, False, True, True, True, False, True, True, True,
False, True, False, False, False, False, True, False, True,
...
True, True, True, False, True, False, True, True, False,
True, False, False, True, True, False, False, False, False,
False])
>>> x[nondom_per_set, :] # doctest: +ELLIPSIS
array([[ 0.20816431, 4.62275469, 1. ],
[ 0.22997367, 1.11772205, 1. ],
[ 0.58799475, 0.73891181, 1. ],
[ 1.5964888 , 5.98825094, 2. ],
[ 5.2812367 , 3.47800969, 2. ],
[ 2.16315952, 4.7394435 , 2. ],
...
[ 0.6510164 , 9.42381213, 9. ],
[ 1.30291449, 4.50417698, 9. ],
[ 0.62230271, 3.56945324, 10. ],
[ 0.86723965, 1.58599089, 10. ],
[ 6.43135537, 1.00153569, 10. ]])
moocore.largest_eafdiff
Python Library Documentation: function largest_eafdiff in module moocore._moocore
largest_eafdiff(x: 'list', /, ref: 'ArrayLike', *, maximise: 'bool | Sequence[bool]' = False, intervals: 'int' = 5, ideal: 'ArrayLike' = None) -> 'tuple[tuple[int, int], float]'
Identify largest EAF differences.
Given a list of datasets, return the indexes of the pair with the largest
EAF differences according to the method proposed by :footcite:t:`DiaLop2020ejor`.
.. warning::
The current implementation only supports 2 objectives.
Parameters
----------
x :
A list of matrices with at least 3 columns (last column indicates the set).
ref :
Reference point as a 1D vector. Must be same length as a single point in the input data.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
intervals :
The absolute range of the differences :math:`[0, 1]` is partitioned into the number of intervals provided.
ideal :
Ideal point as a vector of numerical values. If ``None``, it is calculated as minimum (or maximum if maximising that objective) of each objective in the input data.
Returns
-------
pair : tuple[int,int]
Pair of indexes into the list that give the largest EAF difference.
value : float
Value of the largest difference.
See Also
--------
eafdiff, whv_rect
References
----------
.. footbibliography::
Examples
--------
>>> import pandas as pd
>>> df = pd.read_csv(moocore.get_dataset_path("tpls50x20_1_MWT.csv"))
>>> df
algorithm Makespan WeightedTardiness run
0 1to2 4280.0 10231.0 1.0
1 1to2 4238.0 10999.0 1.0
2 1to2 4137.0 11737.0 1.0
3 1to2 4024.0 14871.0 1.0
4 1to2 4014.0 17825.0 1.0
... ... ... ... ...
1506 double 4048.0 14755.0 15.0
1507 double 3923.0 25507.0 15.0
1508 double 3890.0 29567.0 15.0
1509 double 3862.0 31148.0 15.0
1510 double 4413.0 9894.0 15.0
<BLANKLINE>
[1511 rows x 4 columns]
>>> nadir = df.iloc[:, 1:3].max().to_numpy()
>>> # Split by column 'algorithm'
>>> x = [
... g.drop("algorithm", axis=1) for i, g in df.groupby("algorithm", sort=False)
... ]
>>> moocore.largest_eafdiff(x, ref=nadir)
((2, 5), 777017.0)
moocore.normalise
Python Library Documentation: function normalise in module moocore._moocore
normalise(points: 'ArrayLike', /, to_range: 'ArrayLike' = (0.0, 1.0), *, lower: 'ArrayLike' = nan, upper: 'ArrayLike' = nan, maximise: 'bool | Sequence[bool]' = False) -> 'np.ndarray'
Normalise points per coordinate to a range, e.g., ``to_range = [1,2]``, where the minimum value will correspond to 1 and the maximum to 2.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
to_range :
Range composed of two numerical values. Normalise values to this range. If the objective is maximised, it is normalised to ``(to_range[1], to_range[0])`` instead.
upper, lower:
Bounds on the values. If :data:`numpy.nan`, the maximum and minimum values of each coordinate are used.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
Returns
-------
Returns the points normalised as requested.
Examples
--------
>>> dat = np.array([[3.5, 5.5], [3.6, 4.1], [4.1, 3.2], [5.5, 1.5]])
>>> moocore.normalise(dat)
array([[0. , 1. ],
[0.05 , 0.65 ],
[0.3 , 0.425],
[1. , 0. ]])
>>> moocore.normalise(dat, to_range=[1, 2], lower=[3.5, 3.5], upper=5.5)
array([[1. , 2. ],
[1.05, 1.3 ],
[1.3 , 0.85],
[2. , 0. ]])
moocore.pareto_rank
Python Library Documentation: function pareto_rank in module moocore._moocore
pareto_rank(points: 'ArrayLike', /, *, maximise: 'bool | Sequence[bool]' = False) -> 'np.ndarray'
Rank points according to Pareto-optimality (nondominated sorting).
The function :func:`pareto_rank` is meant to be used like
:func:`numpy.argsort`, but it assigns indexes according to Pareto
dominance, where rank 0 indicates those solutions not dominated by any
other solution in the input set. Duplicated points are assigned the same
rank. The resulting ranking can be used to partition points into different
lists or arrays, each of them being mutually nondominated
:footcite:p:`Deb02nsga2` (see examples below).
.. seealso:: :ref:`Benchmarks of nondominated Sorting (Pareto ranking) <bench-ndsort>`.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
Returns
-------
An integer vector of the same length as the number of rows of ``points`` with values within ``[0, len(points) - 1]``, where each value gives the Pareto rank of each point (lower is better).
Notes
-----
Given a finite set of points :math:`X \subset \mathbb{R}^m`, the
rank of a point :math:`x \in X` is defined as:
.. math::
\operatorname{rank}(x) = r \iff x \in F^c_{r} \land \nexists y \in F^c_{r}, y \prec x
where :math:`y \prec x` means that :math:`y` dominates :math:`x` according to Pareto
optimality, :math:`F^c_r = X \setminus \bigcup_{i=0}^{r-1} F_i`
and :math:`F_r = \{x \in X \land \operatorname{rank}(x) = r\}`. The sets
:math:`F_c`, with :math:`c=0,1,\dots,k-1`, partition :math:`X` into :math:`k`
`fronts`, that is, mutually nondominated subsets of :math:`X`.
With :math:`m=2`, the code uses the best-known :math:`O(n \log n)`
algorithm by :footcite:t:`Jen03`. When :math:`m \geq 3`, it uses the naive
algorithm that identifies one `front` at a time, which requires
:math:`O(n^2\log n)` for :math:`m=3`, and :math:`O(n^2 \log^{m-2} n)` for
:math:`m \geq 4`.
References
----------
.. footbibliography::
Examples
--------
>>> x = moocore.get_dataset("input1.dat")[:, :2]
>>> ranks = moocore.pareto_rank(x)
>>> ranks
array([ 4, 8, 0, 11, 0, 3, 7, 1, 3, 0, 8, 4, 5, 4, 11, 4, 4,
5, 7, 3, 8, 12, 8, 9, 5, 10, 6, 2, 7, 3, 10, 7, 2, 5,
2, 7, 1, 2, 9, 0, 11, 6, 7, 10, 13, 3, 6, 3, 0, 9, 9,
0, 2, 13, 1, 6, 7, 6, 6, 10, 4, 13, 6, 8, 12, 13, 4, 8,
5, 1, 12, 10, 3, 8, 9, 6, 7, 6, 6, 9, 5, 2, 3, 4, 7,
3, 8, 3, 2, 10, 1, 2, 12, 1, 2, 9, 4, 2, 5, 2],
dtype=int32)
We can now split the original set into a list of nondominated sets ordered by Pareto rank:
>>> fronts = [x.compress((g == ranks), axis=0) for g in np.unique(ranks)]
>>> len(fronts)
14
The first element is the set of points not dominated by anything else:
>>> np.array_equal(fronts[0], moocore.filter_dominated(x))
True
moocore.r2_exact
Python Library Documentation: function r2_exact in module moocore._moocore
r2_exact(points: 'ArrayLike', /, ref: 'ArrayLike', *, maximise: 'bool | Sequence[bool]' = False) -> 'float'
Exact R2 indicator.
Computes the exact R2 indicator with respect to a given ideal/utopian reference point
assuming minimization of all objectives.
.. seealso:: For details of the R2 indicator, see :ref:`r2_indicator`.
.. warning::
The current implementation only supports 2 objectives.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
ref :
Reference point as a 1D vector. Must be either a single value, which will be used for all coordinates,
or the same length as a single point in ``points``.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
Returns
-------
A single numerical value, the exact R2 indicator.
Notes
-----
The current implementation exclusively supports bi-objective solution sets and runs in :math:`O(n \log n)`.
For more details on the computation of the exact R2 indicator refer to :footcite:t:`SchKer2025r2v2`.
References
----------
.. footbibliography::
Examples
--------
>>> dat = np.array([[5, 5], [4, 6], [2, 7], [7, 4]])
>>> moocore.r2_exact(dat, ref=[0, 0])
2.594191919191919
This function assumes that objectives must be minimized by default. We can
easily specify maximization:
>>> dat = np.array([[5, 5], [4, 6], [2, 7], [7, 4]])
>>> moocore.r2_exact(dat, ref=[10, 10], maximise=True)
2.519696969696969
Merge all the sets of a dataset by removing the set number column:
>>> dat = moocore.get_dataset("input1.dat")[:, :-1]
>>> len(dat)
100
Dominated points are ignored, so this:
>>> moocore.r2_exact(dat, ref=0)
0.3336076878950565
gives the same exact R2 value as this:
>>> dat = moocore.filter_dominated(dat)
>>> len(dat)
6
>>> moocore.r2_exact(dat, ref=0)
0.3336076878950565
moocore.read_datasets
Python Library Documentation: function read_datasets in module moocore._moocore
read_datasets(filename: 'str | os.PathLike | StringIO') -> 'np.ndarray'
Read an input dataset file, parsing the file and returning a numpy array.
Parameters
----------
filename:
Filename of the dataset file or :class:`io.StringIO` directly containing the file contents.
If it does not contain an absolute path, the filename is relative to the current working directory.
If the filename has extension ``.xz``, it is decompressed to a temporary file before reading it.
Each line of the file corresponds to one point of one dataset. Different datasets are separated by an empty line.
Returns
-------
An array containing a representation of the data in the file.
The first :math:`n-1` columns contain the numerical data for each of the objectives.
The last column contains an identifier for which set the data is relevant to.
Examples
--------
>>> filename = moocore.get_dataset_path("input1.dat")
>>> moocore.read_datasets(filename) # doctest: +ELLIPSIS
array([[ 8.07559653, 2.40702554, 1. ],
[ 8.66094446, 3.64050144, 1. ],
[ 0.20816431, 4.62275469, 1. ],
...
[ 4.92599726, 2.70492519, 10. ],
[ 1.22234394, 5.68950311, 10. ],
[ 7.99466959, 2.81122537, 10. ],
[ 2.12700289, 2.43114174, 10. ]])
The numpy array represents this data:
+-------------+-------------+------------+
| Objective 1 | Objective 2 | Set Number |
+-------------+-------------+------------+
| 8.07559653 | 2.40702554 | 1. |
+-------------+-------------+------------+
| 8.66094446 | 3.64050144 | 1. |
+-------------+-------------+------------+
| ... | ... | ... |
+-------------+-------------+------------+
| 7.99466959 | 2.81122537 | 10. |
+-------------+-------------+------------+
| 2.12700289 | 2.43114174 | 10. |
+-------------+-------------+------------+
It is also possible to read datasets from a string:
>>> from io import StringIO
>>> fh = StringIO("0.5 0.5\n\n1 0\n0 1\n\n0.5 0.5")
>>> moocore.read_datasets(fh)
array([[0.5, 0.5, 1. ],
[1. , 0. , 2. ],
[0. , 1. , 2. ],
[0.5, 0.5, 3. ]])
moocore.total_whv_rect
Python Library Documentation: function total_whv_rect in module moocore._moocore
total_whv_rect(points: 'ArrayLike', /, rectangles: 'ArrayLike', *, ref: 'ArrayLike', maximise: 'bool | Sequence[bool]' = False, ideal: 'ArrayLike' = None, scalefactor: 'float' = 0.1) -> 'float'
Compute total weighted hypervolume given a set of rectangles.
Calculates the hypervolume weighted by a set of rectangles (with zero
weight outside the rectangles). The function :func:`total_whv_rect()`
calculates the total weighted hypervolume as :func:`hypervolume()` ``+
scalefactor * abs(prod(ref - ideal)) *`` :func:`whv_rect()`. The
details of the computation are given by :footcite:t:`DiaLop2020ejor`.
.. warning::
The current implementation only supports 2 objectives.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
rectangles :
Weighted rectangles that will bias the computation of the hypervolume.
Maybe generated by :func:`eafdiff()` with ``rectangles=True`` or by :func:`choose_eafdiff()`.
ref :
Reference point as a 1D vector. Must be either a single value, which will be used for all coordinates,
or the same length as a single point in ``points``.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
ideal :
Ideal point as a vector of numerical values. If ``None``, it is calculated as minimum (or maximum if maximising that objective) of each objective in the input points.
scalefactor :
Real value within :math:`(0,1]` that scales the overall weight of the differences. This is parameter psi (:math:`\psi`) in :footcite:t:`DiaLop2020ejor`.
Returns
-------
A single numerical value, the weighted hypervolume.
See Also
--------
hypervolume, whv_rect, whv_hype
References
----------
.. footbibliography::
Examples
--------
>>> rectangles = np.array(
... [
... [1.0, 3.0, 2.0, np.inf, 1],
... [2.0, 3.5, 2.5, np.inf, 2],
... [2.0, 3.0, 3.0, 3.5, 3],
... ]
... )
>>> whv_rect([[2, 2]], rectangles, ref=6)
4.0
>>> whv_rect([[2, 1]], rectangles, ref=6)
4.0
>>> whv_rect([[1, 2]], rectangles, ref=6)
7.0
>>> total_whv_rect([[2, 2]], rectangles, ref=6, ideal=1)
26.0
>>> total_whv_rect([[2, 1]], rectangles, ref=6, ideal=1)
30.0
>>> total_whv_rect([[1, 2]], rectangles, ref=6, ideal=1)
37.5
moocore.vorob_dev
Python Library Documentation: function vorob_dev in module moocore._moocore
vorob_dev(points: 'ArrayLike', /, sets: 'ArrayLike', *, ref: 'ArrayLike', ve: 'ArrayLike' = None) -> 'float'
Compute Vorob'ev deviation.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
sets :
1D vector or list of values that gives the set of each row of ``points``.
ref :
Reference point as a 1D vector. Must be either a single value, which will be used for all coordinates,
or the same length as a single point in ``points``.
ve :
Vorob'ev expectation, e.g., as returned by :func:`vorob_t`. If not
provided, it is calculated by calling ``vorob_t(data, sets, ref)``.
Returns
-------
Vorob'ev deviation.
See Also
--------
vorob_t : Compute Vorob'ev threshold and expectation.
Notes
-----
For more background, see :footcite:t:`BinGinRou2015gaupar,Molchanov2005theory,CheGinBecMol2013moda`.
References
----------
.. footbibliography::
Examples
--------
>>> CPFs = moocore.get_dataset("CPFs.txt.xz")
>>> vd = moocore.vorob_dev(CPFs[:, :-1], sets=CPFs[:, -1], ref=(2, 200))
>>> vd
3017.12989402326
moocore.vorob_t
Python Library Documentation: function vorob_t in module moocore._moocore
vorob_t(points: 'ArrayLike', /, sets: 'ArrayLike', *, ref: 'ArrayLike') -> 'dict'
Compute Vorob'ev threshold and expectation.
.. seealso:: For the definition of these concepts, see :ref:`vorobev_expectation_and_deviation`.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
sets :
1D vector or list of values that gives the set of each row of ``points``.
ref :
Reference point as a 1D vector. Must be either a single value, which will be used for all coordinates,
or the same length as a single point in ``points``.
Returns
-------
A dictionary with elements ``threshold``, ``ve``, and ``avg_hyp`` (average hypervolume). The threshold is returned as a percentile :math:`\beta^{*} \in [0,100]`. The expectation :math:`\mathcal{Q}_{\beta^{*}}` is returned as a 2D array (:class:`numpy.ndarray`). In addition, the hypervolume of the expectation is returned as ``avg_hyp``.
See Also
--------
vorob_dev : Compute Vorob'ev deviation.
Examples
--------
>>> CPFs = moocore.get_dataset("CPFs.txt.xz")
>>> res = moocore.vorob_t(CPFs[:, :-1], sets=CPFs[:, -1], ref=(2, 200))
>>> res["threshold"]
44.140625
>>> res["avg_hyp"]
8943.333191728081
>>> res["ve"].shape
(213, 2)
moocore.whv_hype
Python Library Documentation: function whv_hype in module moocore._moocore
whv_hype(points: 'ArrayLike', /, *, ref: 'ArrayLike', ideal: 'ArrayLike', maximise: 'bool | Sequence[bool]' = False, nsamples: 'int' = 100000, seed: 'int | np.random.Generator | None' = None, dist: "Literal['uniform', 'point', 'exponential']" = 'uniform', mu: 'float | ArrayLike | None' = None) -> 'float'
Approximation of the (weighted) hypervolume by Monte-Carlo sampling (2D only).
Return an estimation of the hypervolume of the space dominated by the input
points following the procedure described by :footcite:t:`AugBadBroZit2009gecco`.
A weight distribution describing user preferences may be specified.
.. warning::
The current implementation only supports 2 objectives.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
ref :
Reference point as a 1D vector. Must be either a single value, which will be used for all coordinates,
or the same length as a single point in ``points``.
ideal :
Ideal point as a numpy array or list. Must have same length as the number of columns of the dataset.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
nsamples :
Number of samples for Monte-Carlo sampling. Higher values give more
accurate approximation of the true hypervolume but require more time.
seed :
Either an integer to seed :func:`numpy.random.default_rng`, Numpy
default random number generator (RNG) or an instance of a
Numpy-compatible RNG. ``None`` uses the equivalent of a random seed, as in :func:`numpy.random.default_rng`.
dist :
Weight distribution :footcite:p:`AugBadBroZit2009gecco`. The ones currently supported are:
``'uniform'``
corresponds to the default hypervolume (unweighted). ``mu`` should be ``None``.
``'point'``
describes a goal in the objective space, where ``mu`` gives the
coordinates of the goal (1D Numpy array). The resulting weight distribution is a
multivariate normal distribution centred at the goal.
``'exponential'``
describes an exponential distribution with rate parameter ``1/mu``, i.e., :math:`\lambda = \frac{1}{\mu}`.
mu :
Parameter of ``dist``. See above for details.
Returns
-------
A single numerical value, the approximated (weighted) hypervolume.
See Also
--------
hypervolume, hv_approx
References
----------
.. footbibliography::
Examples
--------
>>> moocore.hypervolume([[2, 2]], ref=4)
4.0
>>> moocore.whv_hype([[2, 2]], ref=4, ideal=1, seed=42)
3.99807
>>> moocore.hypervolume([[3, 1]], ref=4)
3.0
>>> moocore.whv_hype([[3, 1]], ref=4, ideal=1, seed=42)
3.00555
>>> moocore.whv_hype([[2, 2]], ref=4, ideal=1, dist="exponential", mu=0.2, seed=42)
1.14624
>>> moocore.whv_hype([[3, 1]], ref=4, ideal=1, dist="exponential", mu=0.2, seed=42)
1.66815
>>> moocore.whv_hype(
... [[2, 2]],
... ref=4,
... ideal=1,
... dist="point",
... mu=[2.9, 0.9],
... seed=42,
... )
0.64485
>>> moocore.whv_hype(
... [[3, 1]],
... ref=4,
... ideal=1,
... dist="point",
... mu=[2.9, 0.9],
... seed=42,
... )
4.03632
moocore.whv_rect
Python Library Documentation: function whv_rect in module moocore._moocore
whv_rect(points: 'ArrayLike', /, rectangles: 'ArrayLike', *, ref: 'ArrayLike', maximise: 'bool | Sequence[bool]' = False) -> 'float'
Compute weighted hypervolume given a set of rectangles.
.. seealso:: For examples, see :func:`total_whv_rect`.
.. warning::
The current implementation only supports 2 objectives.
Parameters
----------
points :
Array of numerical values, where each row gives the coordinates of a point in objective space.
If the array is created by the :func:`read_datasets()` function, remove the last column.
rectangles :
Weighted rectangles that will bias the computation of the hypervolume.
Maybe generated by :func:`eafdiff()` with ``rectangles=True`` or by :func:`choose_eafdiff()`.
ref :
Reference point as a 1D vector. Must be either a single value, which will be used for all coordinates,
or the same length as a single point in ``points``.
maximise :
Whether the objectives must be maximised instead of minimised.
Either a single boolean value that applies to all objectives or a list of boolean values, with one value per objective.
Also accepts a 1D numpy array with value 0/1 for each objective.
Returns
-------
A single numerical value, the weighted hypervolume.
See Also
--------
total_whv_rect, whv_hype