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: Actual function to add new entry to data structures.
  
  Note
  ----
  This method always calls `update_cost` in the multi-objective setting.
docstr_tok: ["Actual","function","to","add","new","entry","to","data","structures",".","Note","--","--","This","method","always","calls","`","update_cost","`","in","the","multi-objective","setting","."]
code: def _add(
      self, k: TrialKey, v: TrialValue, status: StatusType
  ) -> None:
      """
      Actual function to add new entry to data structures.
  
      Note
      ----
      This method always calls `update_cost` in the multi-objective setting.
      """
      self._data[k] = v
  
      # Update objective bounds based on raw data
      self._update_objective_bounds()
  
      # Do not register the cost until the run has completed
      if status != StatusType.RUNNING:
          # Also add to fast data structure
          isk = InstanceSeedKey(k.instance, k.seed)
          self._config_id_to_isk_to_budget[
              k.config_id
          ] = self._config_id_to_isk_to_budget.get(k.config_id, {})
  
          # We sanity-check whether we don't mix none and str in the instances
          for isk_ in self._config_id_to_isk_to_budget[
              k.config_id
          ].keys():
              if isinstance(isk_, str) != isinstance(isk, str):
                  raise ValueError(
                      "Can not mix instances of different types. "
                      f"Wants to add {isk_.instance} but found already {isk.instance}."
                  )
  
          if isk not in self._config_id_to_isk_to_budget[k.config_id]:
              # Add new inst-seed-key with budget to main dict
              self._config_id_to_isk_to_budget[k.config_id][isk] = [
                  k.budget
              ]
          # Before it was k.budget not in isk
          elif k.budget != isk.instance and k.budget != isk.seed:
              # We have to make sure that we don't mix none and float budgets
              if isinstance(
                  self._config_id_to_isk_to_budget[k.config_id][isk][0],
                  float,
              ) != isinstance(k.budget, float):
                  raise ValueError(
                      "Can not mix budgets of different types for the same instance-seed pair. "
                      f"Wants to add {k.budget} but found already "
                      f"{self._config_id_to_isk_to_budget[k.config_id][isk][0]}."
                  )
  
              # Append new budget to existing inst-seed-key dict
              self._config_id_to_isk_to_budget[k.config_id][isk].append(
                  k.budget
              )
  
          config = self._ids_config[k.config_id]
          config_hash = get_config_hash(config)
  
          # If budget is used, then update cost instead of incremental updates
          if not self._overwrite_existing_trials and k.budget == 0:
              logger.debug(
                  f"Incremental update cost for config {config_hash}"
              )
              # Assumes an average across trials as cost function aggregation, this is used for
              # algorithm configuration (incremental updates are used to save time as getting the
              # cost for > 100 instances is high)
              self.incremental_update_cost(config, v.cost)
          else:
              # This happens when budget > 0 (only successive halving and hyperband so far)
              logger.debug(f"Update cost for config {config_hash}.")
              self.update_cost(config)
  
      # Make TrialInfo object
      trial_info = TrialInfo(
          self.get_config(k.config_id),
          instance=k.instance,
          seed=k.seed,
          budget=k.budget,
      )
  
      # Fast data structure for pending trials
      if status == StatusType.RUNNING:
          # Add to running cache
          self._running_trials.append(trial_info)
      else:
          # Remove from cache
          if trial_info in self._running_trials:
              self._running_trials.remove(trial_info)
  
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 43 for calling the RunHistory obj's underlying member method code with example usage: obj._add(k, v, status) without return types