class_docstr: Implementation of Succesive Halving supporting multi-fidelity, multi-objective, and multi-processing.
  Internally, a tracker keeps track of configurations and their bracket and stage.
  
  The behaviour of this intensifier is as follows:
  
  - First, adds configurations from the runhistory to the tracker. The first stage is always filled-up. For example,
    the user provided 4 configs with the tell-method but the first stage requires 8 configs: 4 new configs are
    sampled and added together with the provided configs as a group to the tracker.
  - While loop:
  
    - If a trial in the tracker has not been yielded yet, yield it.
    - If we are running out of trials, we simply add a new batch of configurations to the first stage.
  
  Note
  ----
  The implementation natively supports brackets from Hyperband. However, in the case of Successive Halving,
  only one bracket is used.
  
  Parameters
  ----------
  eta : int, defaults to 3
      Input that controls the proportion of configurations discarded in each round of Successive Halving.
  n_seeds : int, defaults to 1
      How many seeds to use for each instance.
  instance_seed_order : str, defaults to "shuffle_once"
      How to order the instance-seed pairs. Can be set to:
  
      - `None`: No shuffling at all and use the instance-seed order provided by the user.
      - `shuffle_once`: Shuffle the instance-seed keys once and use the same order across all runs.
      - `shuffle`: Shuffles the instance-seed keys for each bracket individually.
  incumbent_selection : str, defaults to "highest_observed_budget"
      How to select the incumbent when using budgets. Can be set to:
  
      - `any_budget`: Incumbent is the best on any budget i.e., best performance regardless of budget.
      - `highest_observed_budget`: Incumbent is the best in the highest budget run so far.
      - `highest_budget`: Incumbent is selected only based on the highest budget.
  max_incumbents : int, defaults to 10
      How many incumbents to keep track of in the case of multi-objective.
  seed : int, defaults to None
      Internal seed used for random events like shuffle seeds.
docstr: Post initialization steps after the runhistory has been set.
code: def __post_init__(self) -> None:
      """Post initialization steps after the runhistory has been set."""
      super().__post_init__()
  
      # We generate our instance seed pairs once
      is_keys = self.get_instance_seed_keys_of_interest()
  
      # Budgets, followed by lots of sanity-checking
      eta = self._eta
      min_budget = self._min_budget
      max_budget = self._max_budget
  
      if (
          max_budget is not None
          and min_budget is not None
          and max_budget < min_budget
      ):
          raise ValueError(
              "Max budget has to be larger than min budget."
          )
  
      if self.uses_instances:
          if isinstance(min_budget, float) or isinstance(
              max_budget, float
          ):
              raise ValueError(
                  "Successive Halving requires integer budgets when using instances."
              )
  
          min_budget = min_budget if min_budget is not None else 1
          max_budget = (
              max_budget if max_budget is not None else len(is_keys)
          )
  
          if max_budget > len(is_keys):
              raise ValueError(
                  f"Max budget of {max_budget} can not be greater than the number of instance-seed "
                  f"keys ({len(is_keys)})."
              )
  
          if max_budget < len(is_keys):
              logger.warning(
                  f"Max budget {max_budget} does not include all instance seed  "
                  f"pairs ({len(is_keys)})."
              )
      else:
          if min_budget is None or max_budget is None:
              raise ValueError(
                  "Successive Halving requires the parameters min_budget and max_budget defined in the scenario."
              )
  
          if len(is_keys) != 1:
              raise ValueError(
                  "Successive Halving supports only one seed when using budgets."
              )
  
      if min_budget is None or min_budget <= 0:
          raise ValueError("Min budget has to be larger than 0.")
  
      budget_type = "INSTANCES" if self.uses_instances else "BUDGETS"
      logger.info(
          f"Successive Halving uses budget type {budget_type} with eta {eta}, "
          f"min budget {min_budget}, and max budget {max_budget}."
      )
  
      # Pre-computing Successive Halving variables
      max_iter = self._get_max_iterations(eta, max_budget, min_budget)
      budgets, n_configs = self._compute_configs_and_budgets_for_stages(
          eta, max_budget, max_iter
      )
  
      # Global variables
      self._min_budget = min_budget
      self._max_budget = max_budget
  
      # Stage variables, depending on the bracket (0 is the bracket here since SH only has one bracket)
      self._max_iterations: dict[int, int] = {0: max_iter + 1}
      self._n_configs_in_stage: dict[int, list] = {0: n_configs}
      self._budgets_in_stage: dict[int, list] = {0: budgets}
  
imports: from __future__ import annotations
  from typing import Any, Iterator
  import math
  from collections import defaultdict
  import numpy
  from ConfigSpace import Configuration
  from smac.constants import MAXINT
  from smac.intensifier.abstract_intensifier import AbstractIntensifier
  from smac.runhistory import TrialInfo
  from smac.runhistory.dataclasses import InstanceSeedBudgetKey
  from smac.runhistory.errors import NotEvaluatedError
  from smac.scenario import Scenario
  from smac.utils.configspace import get_config_hash
  from smac.utils.data_structures import batch
  from smac.utils.logging import get_logger
  from smac.utils.pareto_front import calculate_pareto_front, sort_by_crowding_distance
label_desc: Use image node_id 4 for calling the SuccessiveHalving obj's underlying member method code with example usage: obj.__post_init__() without return types