
    (^i                        d Z ddlmZ ddlZddlZddlmZ 	 	 	 	 	 	 d	dZ	 	 	 	 	 	 	 	 d
dZ		 	 	 	 	 	 d	dZ
	 	 	 	 	 	 ddZy)a  
The functions in this file are mostly based on BoTorch v0.13.0,
but they are refactored significantly from the original version.

For ``_get_upper_bound_set``, look at:
    * https://github.com/pytorch/botorch/blob/v0.13.0/botorch/utils/multi_objective/box_decompositions/utils.py#L101-L160

For ``_get_box_bounds``, look at:
    * https://github.com/pytorch/botorch/blob/v0.13.0/botorch/utils/multi_objective/box_decompositions/utils.py#L163-L193

For ``_get_non_dominated_box_bounds``, look at:
    * https://github.com/pytorch/botorch/blob/v0.13.0/botorch/utils/multi_objective/box_decompositions/non_dominated.py#L395-L430

The preprocessing for four or fewer objectives, we use the algorithm proposed by:
    Title: A Box Decomposition Algorithm to Compute the Hypervolume Indicator
    Authors: Renaud Lacour, Kathrin Klamroth, and Carlos M. Fonseca
    URL: https://arxiv.org/abs/1510.01963
We refer this paper as Lacour17 in this file.

    )annotationsN)_is_pareto_frontc                d  	 | j                   \  }t        j                        t        j                  t              	d	dddf<   d	fd}t        j
                  |g      }t        j                  dft        j                         }||df<   | D ]  } ||||      \  }} ||fS )a!  
    This function follows Algorithm 2 of Lacour17.

    Args:
        sorted_pareto_sols: Pareto solutions sorted with respect to the first objective.
        ref_point: The reference point.

    Returns:
        upper_bound_set: The upper bound set, which is ``U(N)`` in the paper. The shape is
        ``(n_bounds, n_objectives)``.
        def_points: The defining points of each vector in ``U(N)``. The shape is
        ``(n_bounds, n_objectives, n_objectives)``.

    NOTE:
        ``pareto_sols`` corresponds to ``N`` and ``upper_bound_set`` corresponds to ``U(N)`` in the
        paper.
        ``def_points`` (the shape is ``(n_bounds, n_objectives, n_objectives)``) is not well
        explained in the paper, but basically, ``def_points[i, j] = z[j]`` of
        ``upper_bound_set[i]``.
    )dtypeTNr   c                   t        j                  | |k  d      }t        |      s||fS ||   }|j                  d   }| t        j                  t        j
                  t         j                   |      d      k\  }t        j                  t        j                  |      d d t         j                  f         |   }t        j                  |df      |   }|j                  |j                  k(  sJ t        j                  |j                        }	||   }
| |
|	|f<   ||   |   }| |   ||	|f<   t        j                  ||    |g      t        j                  ||    |
g      fS )Naxisr      )npallanyshapemaxwhereinftilearangenewaxissizevstack)solubsdpsis_dominateddominated_dpsn_boundsupdateubs_indices_to_updatedimensions_to_updateindices_for_sweepingnew_dpsnew_ubsn_objectivesobjective_indicesskip_ineq_judges               f/var/www/html/hubwallet-dev/venv/lib/python3.12/site-packages/optuna/_hypervolume/box_decomposition.pyr   z$_get_upper_bound_set.<locals>.update<   sc   vvcCib1< 8O L) &&q) rxx"&&-PWYZZ !#		((;ArzzM(JL YZ` a!ww'88Q-HP$))-A-F-FFFF!yy)=)B)BC 56>A$&::;l#$9:>ABV>W$&::;yy#|m,g67CDVX_C`9aaa    r   )r   
np.ndarrayr   r*   r   r*   returntuple[np.ndarray, np.ndarray])r   r   r   eyeboolasarrayfullr   )
sorted_pareto_sols	ref_point_r   upper_bound_set
def_pointssolutionr%   r&   r'   s
          @@@r(   _get_upper_bound_setr7      s    . +00Q		,/ff\6O OAqDb8 jj)-O!\<8266'BJ:CJq#%667& T&,X
&S#T J&&r)   c                   | j                   d   }|dkD  sJ d       t        j                  dg| j                         }|d d ddf   |dd d df<   |d   |dd d df<   t        j                  |dz
        \  }}t        j                  j                  |d      d d ||dz   f   |dd d dd f<   | d d dd f   |dd d dd f<   t        j                  |d   |d   k  d       }|d d |f   S )Nr   r   8This function is used only for multi-objective problems.   r   r   r	   )r   r   emptydiag_indicesmaximum
accumulater   )r4   r5   r2   r%   boundsrowcol	not_emptys           r(   _get_box_boundsrC   a   s
    #((,L!WWWXXq1?0012F Aq)F1a7OlF1a7O|a/0HCzz,,Zb,A!S#PQ'/RF1a8&q!"u-F1a8q	VAY.R88I!Y,r)   c                    t        | |      d    }t        j                  |d      }t        j                  |t        j                        }t        |t        |d         |      \  }}t        |||       \  }}||fS )Nr   r	   Tassume_unique_lexsorted)r1   r2   )r7   r   unique	full_liker   r   rC   )	r1   r2   neg_upper_bound_setsorted_neg_upper_bound_setpoint_at_infinityneg_lower_bound_setneg_def_pointsbox_upper_boundsbox_lower_boundss	            r(   _get_non_dominated_box_boundsrP   q   s     00BINqQQ!#+>Q!G Y7 +?57QUV
 $	+' +:^->+ *&& ---r)   c                0   t        j                  t        j                  |             sJ d       t        j                  | d      }|t	        |d         }| j
                  d   }|dkD  sJ d       |d	kD  rt        j                  d
       t        ||      S )Nz3loss_vals must be clipped before box decomposition.r   r	   TrE   r   r   r9      zBox decomposition (typically used by `GPSampler`) might be significantly slow for n_objectives > 4. Please consider using another sampler instead.)	r   r   isfiniterG   r   r   warningswarnrP   )	loss_valsr2   unique_lexsorted_loss_valsr1   r%   s        r(   get_non_dominated_box_boundsrX      s     66"++i()`+``)!#91!=33TR ??2&L !WWWaO	

 ));YGGr)   )r1   r*   r2   r*   r+   r,   )r4   r*   r5   r*   r2   r*   r+   r*   )rV   r*   r2   r*   r+   r,   )__doc__
__future__r   rT   numpyr   optuna.study._multi_objectiver   r7   rC   rP   rX    r)   r(   <module>r^      s   * #   :?'"?'/9?'"?'D  -7 DN   ."./9.".4HH&0H"Hr)   