o
    /wi>!                     @  sZ   d dl mZ d dlZd dlmZ dd	d
ZdddZdddZdddZ		ddddZ
dS )    )annotationsN)_is_pareto_frontsorted_pareto_sols
np.ndarrayreference_pointreturnfloatc                 C  s~   | j d |j d   krdksJ  J t|dd  | d ddf g}|d | d d df  }|| d d df  }|| S )N   r      )shapenpconcatenate)r   r   rect_diag_yedge_length_xedge_length_y r   T/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/optuna/_hypervolume/wfg.py_compute_2d   s
   ("r   c           	      C  s  | j d |j d   krdksJ  J | j d }t| dddf }tj||ftd}|d | |df  ||t|f< tjjtjj|dddd}| dddf }| |df }t|dd |dd g| }t|dd |dd g| }t	t	|||S )aw  
    Compute hypervolume in 3D. Time complexity is O(N^2) where N is sorted_pareto_sols.shape[0].
    If X, Y, Z coordinates are permutations of 0, 1, ..., N-1 and reference_point is (N, N, N), the
    hypervolume is calculated as the number of voxels (x, y, z) dominated by at least one point.
    If we fix x and y, this number is equal to the minimum of z' over all points (x', y', z')
    satisfying x' <= x and y' <= y. This can be efficiently computed using cumulative minimum
    (`np.minimum.accumulate`). Non-permutation coordinates can be transformed into permutation
    coordinates by using coordinate compression.
    r	   r      N)dtyper
   axis)
r   r   argsortzerosr   arangemaximum
accumulater   dot)	r   r   ny_orderz_deltax_valsy_valsx_deltay_deltar   r   r   _compute_3d   s   (

"""r&   sorted_loss_valsc                   s   t j|  dd}|jd dkrt|d S |jd dkr3t t | d | d  }t || S t | d d t jf |  t fddt|D S )Nr   r   r   r	   r
   c                 3  s0    | ]\}}t  ||d  df |V  qdS )r	   N)_compute_exclusive_hv).0iinclusive_hvlimited_sols_arrayr   r   r   	<genexpr>4   s
    
z_compute_hv.<locals>.<genexpr>)r   prodr   r   r   sumnewaxis	enumerate)r'   r   inclusive_hvsintersecr   r,   r   _compute_hv)   s   r5   limited_solsr+   c                 C  s0   | j d dkr	|S t| dd}|t| | | S )Nr   Tassume_unique_lexsorted)r   r   r5   )r6   r+   r   on_frontr   r   r   r(   :   s   r(   F	loss_valsassume_paretoboolc                 C  s   t | |kstdt t |stdS |s+t j| dd}t|dd}|| }n| | dddf   }|jd dkrDt	||}n|jd d	krQt
||}nt||}t |r]|S tdS )
aO  Hypervolume calculator for any dimension.

    This class exactly calculates the hypervolume for any dimension.
    For 3 dimensions or higher, the WFG algorithm will be used.
    Please refer to ``A Fast Way of Calculating Exact Hypervolumes`` for the WFG algorithm.

    .. note::
        This class is used for computing the hypervolumes of points in multi-objective space.
        Each coordinate of each point represents a ``values`` of the multi-objective function.

    .. note::
        We check that each objective is to be minimized. Transform objective values that are
        to be maximized before calling this class's ``compute`` method.

    Args:
        loss_vals:
            An array of loss value vectors to calculate the hypervolume.
        reference_point:
            The reference point used to calculate the hypervolume.
        assume_pareto:
            Whether to assume the Pareto optimality to ``loss_vals``.
            In other words, if ``True``, none of loss vectors are dominated by another.
            ``assume_pareto`` is used only for speedup and it does not change the result even if
            this argument is wrongly given. If there are many non-Pareto solutions in
            ``loss_vals``, ``assume_pareto=True`` will speed up the calculation.

    Returns:
        The hypervolume of the given arguments.

    zAll points must dominate or equal the reference point. That is, for all points in the loss_vals and the coordinate `i`, `loss_vals[i] <= reference_point[i]`.infr   r   Tr7   Nr
   r   )r   all
ValueErrorisfiniter   uniquer   r   r   r   r&   r5   )r:   r   r;   unique_lexsorted_loss_valsr9   r   hvr   r   r   compute_hypervolume`   s"   "

rD   )r   r   r   r   r   r   )r'   r   r   r   r   r   )r6   r   r+   r   r   r   r   r   )F)r:   r   r   r   r;   r<   r   r   )
__future__r   numpyr   optuna.study._multi_objectiver   r   r&   r5   r(   rD   r   r   r   r   <module>   s    



'