
    (^i7                        d dl mZ d dlZd dlmZ d dlZd dlZd dlmZ d dlm	Z	 d dl
mZ d dlmZ  ej                  e      Z G d d	e	      Zy)
    )annotationsN)	Container)logging)
BasePruner)SuccessiveHalvingPruner)
TrialStatec                  t    e Zd ZdZ	 	 	 	 d		 	 	 	 	 	 	 	 	 d
dZddZddZddZ	 	 	 	 	 	 ddZ	 	 	 	 	 	 ddZ	y)HyperbandPruneru  Pruner using Hyperband.

    As SuccessiveHalving (SHA) requires the number of configurations
    :math:`n` as its hyperparameter.  For a given finite budget :math:`B`,
    all the configurations have the resources of :math:`B \over n` on average.
    As you can see, there will be a trade-off of :math:`B` and :math:`B \over n`.
    `Hyperband <http://www.jmlr.org/papers/volume18/16-558/16-558.pdf>`__ attacks this trade-off
    by trying different :math:`n` values for a fixed budget.

    .. note::
        * In the Hyperband paper, the counterpart of :class:`~optuna.samplers.RandomSampler`
          is used.
        * Optuna uses :class:`~optuna.samplers.TPESampler` by default.
        * `The benchmark result
          <https://github.com/optuna/optuna/pull/828#issuecomment-575457360>`__
          shows that :class:`optuna.pruners.HyperbandPruner` supports both samplers.

    .. note::
        If you use ``HyperbandPruner`` with :class:`~optuna.samplers.TPESampler`,
        it's recommended to consider setting larger ``n_trials`` or ``timeout`` to make full use of
        the characteristics of :class:`~optuna.samplers.TPESampler`
        because :class:`~optuna.samplers.TPESampler` uses some (by default, :math:`10`)
        :class:`~optuna.trial.Trial`\ s for its startup.

        As Hyperband runs multiple :class:`~optuna.pruners.SuccessiveHalvingPruner` and collects
        trials based on the current :class:`~optuna.trial.Trial`\ 's bracket ID, each bracket
        needs to observe more than :math:`10` :class:`~optuna.trial.Trial`\ s
        for :class:`~optuna.samplers.TPESampler` to adapt its search space.

        Thus, for example, if ``HyperbandPruner`` has :math:`4` pruners in it,
        at least :math:`4 \times 10` trials are consumed for startup.

    .. note::
        Hyperband has several :class:`~optuna.pruners.SuccessiveHalvingPruner`\ s. Each
        :class:`~optuna.pruners.SuccessiveHalvingPruner` is referred to as "bracket" in the
        original paper. The number of brackets is an important factor to control the early
        stopping behavior of Hyperband and is automatically determined by ``min_resource``,
        ``max_resource`` and ``reduction_factor`` as
        :math:`\mathrm{The\ number\ of\ brackets} =
        \mathrm{floor}(\log_{\texttt{reduction}\_\texttt{factor}}
        (\frac{\texttt{max}\_\texttt{resource}}{\texttt{min}\_\texttt{resource}})) + 1`.
        Please set ``reduction_factor`` so that the number of brackets is not too large (about 4 –
        6 in most use cases). Please see Section 3.6 of the `original paper
        <http://www.jmlr.org/papers/volume18/16-558/16-558.pdf>`__ for the detail.

    .. note::
        ``HyperbandPruner`` computes bracket ID for each trial with a
        function taking ``study_name`` of :class:`~optuna.study.Study` and
        :attr:`~optuna.trial.Trial.number`. Please specify ``study_name``
        to make the pruning algorithm reproducible.

    Example:

        We minimize an objective function with Hyperband pruning algorithm.

        .. testcode::

            import numpy as np
            from sklearn.datasets import load_iris
            from sklearn.linear_model import SGDClassifier
            from sklearn.model_selection import train_test_split

            import optuna

            X, y = load_iris(return_X_y=True)
            X_train, X_valid, y_train, y_valid = train_test_split(X, y)
            classes = np.unique(y)
            n_train_iter = 100


            def objective(trial):
                alpha = trial.suggest_float("alpha", 0.0, 1.0)
                clf = SGDClassifier(alpha=alpha)

                for step in range(n_train_iter):
                    clf.partial_fit(X_train, y_train, classes=classes)

                    intermediate_value = clf.score(X_valid, y_valid)
                    trial.report(intermediate_value, step)

                    if trial.should_prune():
                        raise optuna.TrialPruned()

                return clf.score(X_valid, y_valid)


            study = optuna.create_study(
                direction="maximize",
                pruner=optuna.pruners.HyperbandPruner(
                    min_resource=1, max_resource=n_train_iter, reduction_factor=3
                ),
            )
            study.optimize(objective, n_trials=20)

    Args:
        min_resource:
            A parameter for specifying the minimum resource allocated to a trial noted as :math:`r`
            in the paper. A smaller :math:`r` will give a result faster, but a larger
            :math:`r` will give a better guarantee of successful judging between configurations.
            See the details for :class:`~optuna.pruners.SuccessiveHalvingPruner`.
        max_resource:
            A parameter for specifying the maximum resource allocated to a trial. :math:`R` in the
            paper corresponds to ``max_resource / min_resource``. This value represents and should
            match the maximum iteration steps (e.g., the number of epochs for neural networks).
            When this argument is "auto", the maximum resource is estimated according to the
            completed trials. The default value of this argument is "auto".

            .. note::
                With "auto", the maximum resource will be the largest step reported by
                :meth:`~optuna.trial.Trial.report` in the first, or one of the first if trained in
                parallel, completed trial. No trials will be pruned until the maximum resource is
                determined.

            .. note::
                If the step of the last intermediate value may change with each trial, please
                manually specify the maximum possible step to ``max_resource``.
        reduction_factor:
            A parameter for specifying reduction factor of promotable trials noted as
            :math:`\eta` in the paper.
            See the details for :class:`~optuna.pruners.SuccessiveHalvingPruner`.
        bootstrap_count:
            Parameter specifying the number of trials required in a rung before any trial can be
            promoted. Incompatible with ``max_resource`` is ``"auto"``.
            See the details for :class:`~optuna.pruners.SuccessiveHalvingPruner`.
    c                   || _         || _        || _        g | _        || _        d| _        g | _        d | _        t        | j                  t              s3| j                  dk7  r$t        dj                  | j                              | j                  dkD  r4| j                  dk(  r$t        dj                  | j                              y y )Nr   autozEThe 'max_resource' should be integer or 'auto'. But max_resource = {}z_bootstrap_count > 0 and max_resource == 'auto' are mutually incompatible, bootstrap_count is {})_min_resource_max_resource_reduction_factor_pruners_bootstrap_count_total_trial_allocation_budget_trial_allocation_budgets_n_brackets
isinstanceint
ValueErrorformat)selfmin_resourcemax_resourcereduction_factorbootstrap_counts        Z/var/www/html/hubwallet-dev/venv/lib/python3.12/site-packages/optuna/pruners/_hyperband.py__init__zHyperbandPruner.__init__   s     *)!179 /./+46&'+$,,c2t7I7IV7S((.t/A/A(B 
   1$););v)ECCI6$J_J_C`  *F$    c                T   t        | j                        dk(  r*| j                  |       t        | j                        dk(  ry| j                  ||      }t        j                  dj                  |             | j                  ||      }| j                  |   j                  ||      S )Nr   Fz{}th bracket is selected)	lenr   _try_initialization_get_bracket_id_loggerdebugr   _create_bracket_studyprune)r   studytrial
bracket_idbracket_studys        r   r(   zHyperbandPruner.prune   s    t}}"$$U+4==!Q&))%7
077
CD225*E}}Z(..}eDDr    c                ~   | j                   dk(  r^|j                  dt        j                  f      }|D cg c]  }|j                  |j                   }}|sy t        |      dz   | _         t        | j                   t              sJ | j                  Rt        j                  t        j                  | j                   | j                  z  | j                              dz   | _        t        j                  dj!                  | j                               t#        | j                        D ]  }| j%                  |      }| xj&                  |z  c_        | j(                  j+                  |       t-        | j                  | j                  || j.                        }| j0                  j+                  |        y c c}w )Nr   Fdeepcopystates   zHyperband has {} brackets)r   r   min_early_stopping_rater   )r   
get_trialsr   COMPLETE	last_stepmaxr   r   r   mathfloorlogr   r   r%   r&   r   range"_calculate_trial_allocation_budgetr   r   appendr   r   r   )r   r)   trialstn_stepsr+   trial_allocation_budgetpruners           r   r#   z#HyperbandPruner._try_initialization   s   '%%uj>Q>Q=S%TF,2Nqakk6Mq{{NGN!$W!1D$,,c222# 

HHT//$2D2DDdF\F\]   	1889I9IJK 0 01 	)J&*&M&Mj&Y#//3JJ/**112IJ,!//!%!7!7(2 $ 5 5	F MM  (	)5 Os   F:F:c                    | j                   J | j                   dz
  |z
  }t        j                  | j                   | j                  |z  z  |dz   z        S )a  Compute the trial allocated budget for a bracket of ``bracket_id``.

        In the `original paper <http://www.jmlr.org/papers/volume18/16-558/16-558.pdf>`, the
        number of trials per one bracket is referred as ``n`` in Algorithm 1. Since we do not know
        the total number of trials in the leaning scheme of Optuna, we calculate the ratio of the
        number of trials here instead.
        r1   )r   r7   ceilr   )r   r+   ss      r   r;   z2HyperbandPruner._calculate_trial_allocation_budget   sY     +++q :-yy))T-C-CQ-FG1q5QRRr    c                p   t        | j                        dk(  ry| j                  J t        j                  dj                  |j                  |j                        j                               | j                  z  }t        | j                        D ]  }|| j                  |   z  }|dk  s|c S  J d       )zCompute the index of bracket for a trial of ``trial_number``.

        The index of a bracket is noted as :math:`s` in
        `Hyperband paper <http://www.jmlr.org/papers/volume18/16-558/16-558.pdf>`__.
        r   z{}_{}z This line should be unreachable.)r"   r   r   binasciicrc32r   
study_namenumberencoder   r:   r   )r   r)   r*   nr+   s        r   r$   zHyperbandPruner._get_bracket_id   s     t}}"+++NN7>>%*:*:ELLIPPRS112 	
   0 01 	"J//
;;A1u!!	"
 	988ur    c                b     G fddt         j                  j                         || |      S )Nc                  d     e Zd ZdZ	 	 	 	 	 	 	 	 d fdZ	 	 d	 	 	 	 	 d fdZd	dZfdZ xZS )
<HyperbandPruner._create_bracket_study.<locals>._BracketStudy)r3   _get_trials
directions	direction_directions_storage	_study_idrA   rH   _bracket_idsamplerr=   _is_multi_objectivestop_study_thread_localc                    t         |   |j                  |j                  |j                  |       || _        || _        y )N)rH   storagerV   rA   )superr   rH   rS   rV   rY   rU   )r   r)   rA   r+   	__class__s       r   r   zEHyperbandPruner._create_bracket_study.<locals>._BracketStudy.__init__!  sB      $//!NN!MM!	 !  $#- r    c                    t         |   ||      }| j                  }t        |t              sJ |D cg c]$  }|j                  | |      | j                  k(  s#|& c}S c c}w )Nr.   )r]   rO   rA   r   r
   r$   rU   )r   r/   r0   r=   rA   r>   r^   s         r   r3   zGHyperbandPruner._create_bracket_study.<locals>._BracketStudy.get_trials-  sa    
 ,hv,N!&/:::#)aaV-C-CD!-LPTP`P`-`aaas   $A!A!c                8    | j                   j                          y )N)rY   rX   )r   s    r   rX   zAHyperbandPruner._create_bracket_study.<locals>._BracketStudy.stop7  s       "r    c                    |j                   vrt        dj                  |            t        j	                  | |      S )Nz-_BracketStudy does not have attribute of '{}')_VALID_ATTRSAttributeErrorr   object__getattribute__)r   	attr_name_BracketStudys     r   re   zMHyperbandPruner._create_bracket_study.<locals>._BracketStudy.__getattribute__<  sA    M$>$>>(GNNyY  "224CCr    )r)   'optuna.study.Study'rA   r
   r+   r   returnNone)TN)r/   boolr0   zContainer[TrialState] | Noneri   z list['optuna.trial.FrozenTrial'])ri   rj   )	__name__
__module____qualname__rb   r   r3   rX   re   __classcell__)r^   rg   s   @r   rg   rN     sm    L&
.1
.;J
.X[
.
. "&7;bb 5b 2	b#
D Dr    rg   )optunar)   Study)r   r)   r+   rg   s      @r   r'   z%HyperbandPruner._create_bracket_study  s-    5	DFLL.. 5	Dn UD*55r    N)r1   r      r   )
r   r   r   z	str | intr   r   r   r   ri   rj   )r)   rh   r*   'optuna.trial.FrozenTrial'ri   rk   )r)   rh   ri   rj   )r+   r   ri   r   )r)   rh   r*   rs   ri   r   )r)   rh   r+   r   ri   rh   )
rl   rm   rn   __doc__r   r(   r#   r;   r$   r'    r    r   r
   r
      s    |@ "( !    	
  
8	E()TS9)92L9	90>6)>67:>6	>6r    r
   )
__future__r   rF   collections.abcr   r7   rp   r   optuna.pruners._baser   "optuna.pruners._successive_halvingr   optuna.trial._stater   
get_loggerrl   r%   r
   ru   r    r   <module>r|      sB    "  %    + F * '

X
&s6j s6r    