class_docstr: Implements the HyperBand early stopping algorithm.
  
  HyperBandScheduler early stops trials using the HyperBand optimization
  algorithm. It divides trials into brackets of varying sizes, and
  periodically early stops low-performing trials within each bracket.
  
  To use this implementation of HyperBand with Tune, all you need
  to do is specify the max length of time a trial can run `max_t`, the time
  units `time_attr`, the name of the reported objective value `metric`,
  and if `metric` is to be maximized or minimized (`mode`).
  We automatically determine reasonable values for the other
  HyperBand parameters based on the given values.
  
  For example, to limit trials to 10 minutes and early stop based on the
  `episode_mean_reward` attr, construct:
  
  ``HyperBand('time_total_s', 'episode_reward_mean', max_t=600)``
  
  Note that Tune's stopping criteria will be applied in conjunction with
  HyperBand's early stopping mechanisms.
  
  See also: https://blog.ml.cmu.edu/2018/12/12/massively-parallel-hyperparameter-optimization/
  
  Args:
      time_attr: The training result attr to use for comparing time.
          Note that you can pass in something non-temporal such as
          `training_iteration` as a measure of progress, the only requirement
          is that the attribute should increase monotonically.
      metric: The training result objective value attribute. Stopping
          procedures will use this attribute. If None but a mode was passed,
          the `ray.tune.result.DEFAULT_METRIC` will be used per default.
      mode: One of {min, max}. Determines whether objective is
          minimizing or maximizing the metric attribute.
      max_t: max time units per trial. Trials will be stopped after
          max_t time units (determined by time_attr) have passed.
          The scheduler will terminate trials after this time has passed.
          Note that this is different from the semantics of `max_t` as
          mentioned in the original HyperBand paper.
      reduction_factor: Same as `eta`. Determines how sharp
          the difference is between bracket space-time allocation ratios.
      stop_last_trials: Whether to terminate the trials after
          reaching max_t. Defaults to True.
class_docstr_tok: ["Implements","the","HyperBand","early","stopping","algorithm",".","HyperBandScheduler","early","stops","trials","using","the","HyperBand","optimization","algorithm",".","It","divides","trials","into","brackets","of","varying","sizes",",","and","periodically","early","stops","low-performing","trials","within","each","bracket",".","To","use","this","implementation","of","HyperBand","with","Tune",",","all","you","need","to","do","is","specify","the","max","length","of","time","a","trial","can","run","`","max_t","`",",","the","time","units","`","time_attr","`",",","the","name","of","the","reported","objective","value","`","metric","`",",","and","if","`","metric","`","is","to","be","maximized","or","minimized","(","`","mode","`",")",".","We","automatically","determine","reasonable","values","for","the","other","HyperBand","parameters","based","on","the","given","values",".","For","example",",","to","limit","trials","to","10","minutes","and","early","stop","based","on","the","`","episode_mean_reward","`","attr",",","construct",":","``","HyperBand","(","'time_total_s","'",",","'episode_reward_mean","'",",","max_t=600",")","``","Note","that","Tune","'s","stopping","criteria","will","be","applied","in","conjunction","with","HyperBand","'s","early","stopping","mechanisms",".","See","also",":","https",":","\/\/blog.ml.cmu.edu\/2018\/12\/12\/massively-parallel-hyperparameter-optimization\/","Args",":","time_attr",":","The","training","result","attr","to","use","for","comparing","time",".","Note","that","you","can","pass","in","something","non-temporal","such","as","`","training_iteration","`","as","a","measure","of","progress",",","the","only","requirement","is","that","the","attribute","should","increase","monotonically",".","metric",":","The","training","result","objective","value","attribute",".","Stopping","procedures","will","use","this","attribute",".","If","None","but","a","mode","was","passed",",","the","`","ray.tune.result.DEFAULT_METRIC","`","will","be","used","per","default",".","mode",":","One","of","{","min",",","max","}",".","Determines","whether","objective","is","minimizing","or","maximizing","the","metric","attribute",".","max_t",":","max","time","units","per","trial",".","Trials","will","be","stopped","after","max_t","time","units","(","determined","by","time_attr",")","have","passed",".","The","scheduler","will","terminate","trials","after","this","time","has","passed",".","Note","that","this","is","different","from","the","semantics","of","`","max_t","`","as","mentioned","in","the","original","HyperBand","paper",".","reduction_factor",":","Same","as","`","eta","`",".","Determines","how","sharp","the","difference","is","between","bracket","space-time","allocation","ratios",".","stop_last_trials",":","Whether","to","terminate","the","trials","after","reaching","max_t",".","Defaults","to","True","."]
docstr: This is called whenever a trial makes progress.
  
  When all live trials in the bracket have no more iterations left,
  Trials will be successively halved. If bracket is done, all
  non-running trials will be stopped and cleaned up,
  and during each halving phase, bad trials will be stopped while good
  trials will return to "PENDING".
  
  Note some implicit conditions here: In ``on_trial_result`` a trial is
  either continued (e.g. if it didn't reach the time threshold for the bracket)
  or this method (``_process_bracket``) is called. If there are other trials left
  that still haven't reached the threshold, the trial is PAUSED. This means
  that when the bracket is actually processed (``bracket.cur_iter_done``), there
  is at most one RUNNING trial (which is the trial that is currently processed)
  and the rest are either PAUSED (as explained above) or TERMINATED/ERRORED
  (if they finish separately).
docstr_tok: ["This","is","called","whenever","a","trial","makes","progress",".","When","all","live","trials","in","the","bracket","have","no","more","iterations","left",",","Trials","will","be","successively","halved",".","If","bracket","is","done",",","all","non-running","trials","will","be","stopped","and","cleaned","up",",","and","during","each","halving","phase",",","bad","trials","will","be","stopped","while","good","trials","will","return","to","``","PENDING","''",".","Note","some","implicit","conditions","here",":","In","``","on_trial_result","``","a","trial","is","either","continued","(","e.g",".","if","it","did","n't","reach","the","time","threshold","for","the","bracket",")","or","this","method","(","``","_process_bracket","``",")","is","called",".","If","there","are","other","trials","left","that","still","have","n't","reached","the","threshold",",","the","trial","is","PAUSED",".","This","means","that","when","the","bracket","is","actually","processed","(","``","bracket.cur_iter_done","``",")",",","there","is","at","most","one","RUNNING","trial","(","which","is","the","trial","that","is","currently","processed",")","and","the","rest","are","either","PAUSED","(","as","explained","above",")","or","TERMINATED\/ERRORED","(","if","they","finish","separately",")","."]
code: def _process_bracket(
      self, tune_controller: "TuneController", bracket: "_Bracket"
  ) -> str:
      """This is called whenever a trial makes progress.
  
      When all live trials in the bracket have no more iterations left,
      Trials will be successively halved. If bracket is done, all
      non-running trials will be stopped and cleaned up,
      and during each halving phase, bad trials will be stopped while good
      trials will return to "PENDING".
  
      Note some implicit conditions here: In ``on_trial_result`` a trial is
      either continued (e.g. if it didn't reach the time threshold for the bracket)
      or this method (``_process_bracket``) is called. If there are other trials left
      that still haven't reached the threshold, the trial is PAUSED. This means
      that when the bracket is actually processed (``bracket.cur_iter_done``), there
      is at most one RUNNING trial (which is the trial that is currently processed)
      and the rest are either PAUSED (as explained above) or TERMINATED/ERRORED
      (if they finish separately).
      """
  
      action = TrialScheduler.PAUSE
      if bracket.cur_iter_done():
          if bracket.finished():
              bracket.cleanup_full(tune_controller)
              return TrialScheduler.STOP
  
          bracket.is_being_processed = True
  
          good, bad = bracket.successive_halving(
              self._metric, self._metric_op
          )
  
          logger.debug(
              f"Processing {len(good)} good and {len(bad)} bad trials in "
              f"bracket {bracket}.\n"
              f"Good: {good}\nBad: {bad}"
          )
  
          # kill bad trials
          self._num_stopped += len(bad)
          for t in bad:
              if t.status == Trial.PAUSED or t.is_saving:
                  logger.debug(f"Stopping other trial {str(t)}")
                  tune_controller.stop_trial(t)
              elif t.status == Trial.RUNNING:
                  # See the docstring: There can only be at most one RUNNING
                  # trial, which is the current trial.
                  logger.debug(f"Stopping current trial {str(t)}")
                  bracket.cleanup_trial(t)
                  action = TrialScheduler.STOP
              else:
                  # Trials cannot be ERROR/TERMINATED, as then they would have
                  # been removed from the bracket (in `bracket.cleanup_trial`).
                  # Trials cannot be PENDING, as then they wouldn't have reported
                  # enough results to finish the bracket, and it wouldn't be
                  # processed.
                  raise TuneError(
                      f"Trial with unexpected bad status encountered: "
                      f"{str(t)} is {t.status}"
                  )
  
          # ready the good trials - if trial is too far ahead, don't continue
          for t in good:
              if bracket.continue_trial(t):
                  # The scheduler should have cleaned up this trial already.
                  assert t.status not in (
                      Trial.ERROR,
                      Trial.TERMINATED,
                  ), (
                      f"Good trial {t.trial_id} is in an invalid state: {t.status}\n"
                      "Expected trial to be either PAUSED, PENDING, or RUNNING.\n"
                      "If you encounter this, please file an issue on the Ray Github."
                  )
                  if t.status == Trial.PAUSED or t.is_saving:
                      logger.debug(f"Unpausing trial {str(t)}")
                      self._unpause_trial(tune_controller, t)
                      bracket.trials_to_unpause.add(t)
                  elif t.status == Trial.RUNNING:
                      # See the docstring: There can only be at most one RUNNING
                      # trial, which is the current trial.
                      logger.debug(f"Continuing current trial {str(t)}")
                      action = TrialScheduler.CONTINUE
                  # else: PENDING trial (from a previous unpause) should stay as is.
              elif bracket.finished() and bracket.stop_last_trials:
                  # Scheduler decides to not continue trial because the bracket
                  # reached max_t. In this case, stop the trials
                  if t.status == Trial.PAUSED or t.is_saving:
                      logger.debug(
                          f"Bracket finished. Stopping other trial {str(t)}"
                      )
                      tune_controller.stop_trial(t)
                  elif t.status == Trial.RUNNING:
                      # See the docstring: There can only be at most one RUNNING
                      # trial, which is the current trial.
                      logger.debug(
                          f"Bracket finished. Stopping current trial {str(t)}"
                      )
                      bracket.cleanup_trial(t)
                      action = TrialScheduler.STOP
      return action
  
imports: import collections
  from typing import Dict, List, Optional, Tuple, TYPE_CHECKING
  import numpy
  import logging
  from ray.util.annotations import PublicAPI
  from ray.tune.result import DEFAULT_METRIC
  from ray.tune.schedulers.trial_scheduler import FIFOScheduler, TrialScheduler
  from ray.tune.experiment import Trial
  from ray.tune.error import TuneError
label_desc: Use image node_id 7 for calling the HyperBandScheduler obj's underlying member method code with example usage: obj._process_bracket(tune_controller, bracket) and returns: action, TrialScheduler