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