class_docstr: Container for the target function run information.
  
  Most importantly, the runhistory contains an efficient mapping from each evaluated configuration to the
  empirical cost observed on either the full instance set or a subset. The cost is the average over all
  observed costs for one configuration:
  
  * If using budgets for a single instance, only the cost on the highest observed budget is returned.
  * If using instances as the budget, the average cost over all evaluated instances is returned.
  * Theoretically, the runhistory object can handle instances and budgets at the same time. This is
    neither used nor tested.
  
  Note
  ----
  Guaranteed to be picklable.
  
  Parameters
  ----------
  multi_objective_algorithm : AbstractMultiObjectiveAlgorithm | None, defaults to None
      The multi-objective algorithm is required to scalarize the costs in case of multi-objective.
  overwrite_existing_trials : bool, defaults to false
      Overwrites a trial (combination of configuration, instance, budget and seed) if it already exists.
docstr: Adds a new trial to the RunHistory.
  
  Parameters
  ----------
  config : Configuration
  cost : int | float | list[int | float]
      Cost of the evaluated trial. Might be a list in case of multi-objective.
  time : float
      How much time was needed to evaluate the trial.
  status : StatusType, defaults to StatusType.SUCCESS
      The status of the trial.
  instance : str | None, defaults to none
  seed : int | None, defaults to none
  budget : float | None, defaults to none
  starttime : float, defaults to 0.0
  endtime : float, defaults to 0.0
  additional_info : dict[str, Any], defaults to {}
  force_update : bool, defaults to false
      Overwrites a previous trial if the trial already exists.
docstr_tok: ["Adds","a","new","trial","to","the","RunHistory",".","Parameters","--","--","--","--","--","config",":","Configuration","cost",":","int","|","float","|","list","[","int","|","float","]","Cost","of","the","evaluated","trial",".","Might","be","a","list","in","case","of","multi-objective",".","time",":","float","How","much","time","was","needed","to","evaluate","the","trial",".","status",":","StatusType",",","defaults","to","StatusType.SUCCESS","The","status","of","the","trial",".","instance",":","str","|","None",",","defaults","to","none","seed",":","int","|","None",",","defaults","to","none","budget",":","float","|","None",",","defaults","to","none","starttime",":","float",",","defaults","to","0.0","endtime",":","float",",","defaults","to","0.0","additional_info",":","dict","[","str",",","Any","]",",","defaults","to","{","}","force_update",":","bool",",","defaults","to","false","Overwrites","a","previous","trial","if","the","trial","already","exists","."]
code: def add(
      self,
      config: Configuration,
      cost: int | float | list[int | float],
      time: float = 0.0,
      status: StatusType = StatusType.SUCCESS,
      instance: str | None = None,
      seed: int | None = None,
      budget: float | None = None,
      starttime: float = 0.0,
      endtime: float = 0.0,
      additional_info: dict[str, Any] = {},
      force_update: bool = False,
  ) -> None:
      """Adds a new trial to the RunHistory.
  
      Parameters
      ----------
      config : Configuration
      cost : int | float | list[int | float]
          Cost of the evaluated trial. Might be a list in case of multi-objective.
      time : float
          How much time was needed to evaluate the trial.
      status : StatusType, defaults to StatusType.SUCCESS
          The status of the trial.
      instance : str | None, defaults to none
      seed : int | None, defaults to none
      budget : float | None, defaults to none
      starttime : float, defaults to 0.0
      endtime : float, defaults to 0.0
      additional_info : dict[str, Any], defaults to {}
      force_update : bool, defaults to false
          Overwrites a previous trial if the trial already exists.
      """
      if config is None:
          raise TypeError("Configuration must not be None.")
      elif not isinstance(config, Configuration):
          raise TypeError(
              "Configuration is not of type Configuration, but %s."
              % type(config)
          )
  
      # Squeeze is important to reduce arrays with one element
      # to scalars.
      cost_array = np.asarray(cost).squeeze()
      n_objectives = np.size(cost_array)
  
      # Get the config id
      config_id = self._config_ids.get(config)
  
      if config_id is None:
          self._n_id += 1
          self._config_ids[config] = self._n_id
          self._ids_config[self._n_id] = config
  
          config_id = self._n_id
  
      # Set the id attribute of the config object, so that users can access it
      config.config_id = config_id
  
      if status != StatusType.RUNNING:
          if self._n_objectives == -1:
              self._n_objectives = n_objectives
          elif self._n_objectives != n_objectives:
              raise ValueError(
                  f"Cost is not of the same length ({n_objectives}) as the number of "
                  f"objectives ({self._n_objectives})."
              )
  
          # Let's always work with floats; Makes it easier to deal with later on
          # array.tolist(), it returns a scalar if the array has one element.
          c = cost_array.tolist()
          if self._n_objectives == 1:
              c = float(c)
          else:
              c = [float(i) for i in c]
      else:
          c = cost_array.tolist()
  
      if budget is not None:
          # Just to make sure we really add a float
          budget = float(budget)
  
      k = TrialKey(
          config_id=config_id,
          instance=instance,
          seed=seed,
          budget=budget,
      )
      v = TrialValue(
          cost=c,
          time=time,
          status=status,
          starttime=starttime,
          endtime=endtime,
          additional_info=additional_info,
      )
  
      # Construct keys and values for the data dictionary
      for key, value in (
          ("config", config.get_dictionary()),
          ("config_id", config_id),
          ("instance", instance),
          ("seed", seed),
          ("budget", budget),
          ("cost", c),
          ("time", time),
          ("status", status),
          ("starttime", starttime),
          ("endtime", endtime),
          ("additional_info", additional_info),
          ("origin", config.origin),
      ):
          self._check_json_serializable(key, value, k, v)
  
      # Each trial_key is supposed to be used only once. Repeated tries to add
      # the same trial_key will be ignored silently if not capped.
      previous_k = self._data.get(k)
      if (
          self._overwrite_existing_trials
          or force_update
          or previous_k is None
      ):
          # Update stati
          if previous_k is None:
              if status == StatusType.RUNNING:
                  self._running += 1
              else:
                  self._finished += 1
  
              self._submitted += 1
          else:
              if (
                  previous_k.status == StatusType.RUNNING
                  and status != StatusType.RUNNING
              ):
                  self._running -= 1
                  self._finished += 1
  
          self._add(k, v, status)
      else:
          logger.info(
              "Entry was not added to the runhistory because existing trials will not be overwritten."
          )
  
imports: from __future__ import annotations
  from typing import Any, Iterable, Iterator, Mapping, cast
  import json
  from collections import OrderedDict
  from pathlib import Path
  import numpy
  from ConfigSpace import Configuration, ConfigurationSpace
  from smac.constants import MAXINT
  from smac.multi_objective.abstract_multi_objective_algorithm import AbstractMultiObjectiveAlgorithm
  from smac.runhistory.dataclasses import InstanceSeedBudgetKey, InstanceSeedKey, TrialInfo, TrialKey, TrialValue
  from smac.runhistory.enumerations import StatusType
  from smac.utils.configspace import get_config_hash
  from smac.utils.logging import get_logger
  from smac.utils.multi_objective import normalize_costs
label_desc: Use image node_id 17 for calling the RunHistory obj's underlying member method code with example usage: obj.add(config, cost, time, status, instance, seed, budget, starttime, endtime, additional_info, force_update) without return types