class_docstr: Implementation that contains the main Bayesian optimization loop.
  
  Parameters
  ----------
  scenario : Scenario
      The scenario object, holding all environmental information.
  runner : AbstractRunner
      The runner (containing the target function) is called internally to judge a trial's performance.
  runhistory : Runhistory
      The runhistory stores all trials.
  intensifier : AbstractIntensifier
      The intensifier decides which trial (combination of configuration, seed, budget and instance) should be run
      next.
  overwrite: bool, defaults to False
      When True, overwrites the run results if a previous run is found that is
      inconsistent in the meta data with the current setup. If ``overwrite`` is set to False, the user is asked
      for the exact behaviour (overwrite completely, save old run, or use old results).
  
  Warning
  -------
  This model should be initialized by a facade only.
class_docstr_tok: ["Implementation","that","contains","the","main","Bayesian","optimization","loop",".","Parameters","--","--","--","--","--","scenario",":","Scenario","The","scenario","object",",","holding","all","environmental","information",".","runner",":","AbstractRunner","The","runner","(","containing","the","target","function",")","is","called","internally","to","judge","a","trial","'s","performance",".","runhistory",":","Runhistory","The","runhistory","stores","all","trials",".","intensifier",":","AbstractIntensifier","The","intensifier","decides","which","trial","(","combination","of","configuration",",","seed",",","budget","and","instance",")","should","be","run","next",".","overwrite",":","bool",",","defaults","to","False","When","True",",","overwrites","the","run","results","if","a","previous","run","is","found","that","is","inconsistent","in","the","meta","data","with","the","current","setup",".","If","``","overwrite","``","is","set","to","False",",","the","user","is","asked","for","the","exact","behaviour","(","overwrite","completely",",","save","old","run",",","or","use","old","results",")",".","Warning","--","--","--","-","This","model","should","be","initialized","by","a","facade","only","."]
docstr: Runs the Bayesian optimization loop.
  
  Parameters
  ----------
  data_to_scatter: dict[str, Any] | None
      When a user scatters data from their local process to the distributed network,
      this data is distributed in a round-robin fashion grouping by number of cores.
      Roughly speaking, we can keep this data in memory and then we do not have to (de-)serialize the data
      every time we would like to execute a target function with a big dataset.
      For example, when your target function has a big dataset shared across all the target function,
      this argument is very useful.
  
  Returns
  -------
  incumbent : Configuration
      The best found configuration.
code: def optimize(
      self, *, data_to_scatter: dict[str, Any] | None = None
  ) -> Configuration | list[Configuration]:
      """Runs the Bayesian optimization loop.
  
      Parameters
      ----------
      data_to_scatter: dict[str, Any] | None
          When a user scatters data from their local process to the distributed network,
          this data is distributed in a round-robin fashion grouping by number of cores.
          Roughly speaking, we can keep this data in memory and then we do not have to (de-)serialize the data
          every time we would like to execute a target function with a big dataset.
          For example, when your target function has a big dataset shared across all the target function,
          this argument is very useful.
  
      Returns
      -------
      incumbent : Configuration
          The best found configuration.
      """
      # We return the incumbent if we already finished the a process (we don't want to allow to call
      # optimize more than once).
      if self._finished:
          logger.info(
              "Optimization process was already finished. Returning incumbent..."
          )
          if self._scenario.count_objectives() == 1:
              return self.intensifier.get_incumbent()
          else:
              return self.intensifier.get_incumbents()
  
      # Start the timer before we do anything
      # If we continue the optimization, the starting time is set by the load method
      if self._start_time is None:
          self._start_time = time.time()
  
      for callback in self._callbacks:
          callback.on_start(self)
  
      dask_data_to_scatter = {}
      if (
          isinstance(self._runner, DaskParallelRunner)
          and data_to_scatter is not None
      ):
          dask_data_to_scatter = dict(
              data_to_scatter=self._runner._client.scatter(
                  data_to_scatter, broadcast=True
              )
          )
      elif data_to_scatter is not None:
          raise ValueError(
              "data_to_scatter is valid only for DaskParallelRunner, "
              f"but {dask_data_to_scatter} was provided for {self._runner.__class__.__name__}"
          )
  
      # Main BO loop
      while True:
          for callback in self._callbacks:
              callback.on_iteration_start(self)
  
          try:
              # Sample next trial from the intensification
              trial_info = self.ask()
  
              # We submit the trial to the runner
              # In multi-worker mode, SMAC waits till a new worker is available here
              self._runner.submit_trial(
                  trial_info=trial_info, **dask_data_to_scatter
              )
          except StopIteration:
              self._stop = True
  
          # We add results from the runner if results are available
          self._add_results()
  
          # Some statistics
          logger.debug(
              f"Remaining wallclock time: {self.remaining_walltime}; "
              f"Remaining cpu time: {self.remaining_cputime}; "
              f"Remaining trials: {self.remaining_trials}"
          )
  
          if self.runhistory.finished % 50 == 0:
              logger.info(
                  f"Finished {self.runhistory.finished} trials."
              )
  
          for callback in self._callbacks:
              callback.on_iteration_end(self)
  
          # Now we check whether we have to stop the optimization
          if self.budget_exhausted or self._stop:
              if self.budget_exhausted:
                  logger.info("Configuration budget is exhausted:")
                  logger.info(
                      f"--- Remaining wallclock time: {self.remaining_walltime}"
                  )
                  logger.info(
                      f"--- Remaining cpu time: {self.remaining_cputime}"
                  )
                  logger.info(
                      f"--- Remaining trials: {self.remaining_trials}"
                  )
              else:
                  logger.info(
                      "Shutting down because the stop flag was set."
                  )
  
              # Wait for the trials to finish
              while self._runner.is_running():
                  self._runner.wait()
                  self._add_results()
  
              # Break from the intensification loop, as there are no more resources
              break
  
      for callback in self._callbacks:
          callback.on_end(self)
  
      # We only set the finished flag if the budget really was exhausted
      if self.budget_exhausted:
          self._finished = True
  
      if self._scenario.count_objectives() == 1:
          return self.intensifier.get_incumbent()
      else:
          return self.intensifier.get_incumbents()
  
imports: from __future__ import annotations
  from typing import Any
  import json
  import time
  from pathlib import Path
  import numpy
  from ConfigSpace import Configuration
  from numpy import ndarray
  from smac.acquisition.function.abstract_acquisition_function import AbstractAcquisitionFunction
  from smac.callback.callback import Callback
  from smac.intensifier.abstract_intensifier import AbstractIntensifier
  from smac.model.abstract_model import AbstractModel
  from smac.runhistory import StatusType, TrialInfo, TrialValue
  from smac.runhistory.runhistory import RunHistory
  from smac.runner import FirstRunCrashedException
  from smac.runner.abstract_runner import AbstractRunner
  from smac.runner.dask_runner import DaskParallelRunner
  from smac.scenario import Scenario
  from smac.utils.data_structures import recursively_compare_dicts
  from smac.utils.logging import get_logger
label_desc: Use image node_id 14 for calling the SMBO obj's underlying member method code with example usage: obj.optimize() and returns: self, self, self, self