o
    }oi$                     @  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   K/home/ubuntu/.local/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  | j d dkrd}t| d D ]
\}}||| 9 }qt|S | j d dkrVd\}}}t| d | d D ]\}}}	||| 9 }|||	 9 }||t||	 9 }q5|| | S |  jdd t| d d tjf |  d t fdd	t	 j
d D  S )
Nr   r	         ?r
   )r(   r(   r(   r   r   c                 3  s0    | ]}t ||d  df  | V  qdS )r	   N)_compute_exclusive_hv).0iinclusive_hvslimited_sols_arrayr   r   r   	<genexpr>=   s
    
z_compute_hv.<locals>.<genexpr>)r   zipr   maxprodr   r   newaxissumrangesize)
r'   r   inclusive_hvrvhv1hv2intersecv1v2r   r,   r   _compute_hv)   s"   

r?   limited_solsr7   c                 C  sL   | j d dks	J | j d dkr|t| | S t| dd}|t| | | S )Nr   r	   r   Tassume_unique_lexsorted)r   r?   r   )r@   r7   r   on_frontr   r   r   r)   C   s
   !r)   F	loss_valsassume_paretoboolc                 C  s   t | |kstdt t |stdS | jdkrdS |s2t j| dd}t|dd}|| }n| | dddf   }|j	d d	krKt
||}n|j	d d
krXt||}nt||}t |rd|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   g        r   TrA   Nr
   r   )r   all
ValueErrorisfiniter   r6   uniquer   r   r   r   r&   r?   )rD   r   rE   unique_lexsorted_loss_valsrC   r   hvr   r   r   compute_hypervolumen   s&   "


rN   )r   r   r   r   r   r   )r'   r   r   r   r   r   )r@   r   r7   r   r   r   r   r   )F)rD   r   r   r   rE   rF   r   r   )
__future__r   numpyr   optuna.study._multi_objectiver   r   r&   r?   r)   rN   r   r   r   r   <module>   s    



,