code: def batched_bisect(
      f: Callable,
      target: float,
      bounds: Tensor,
      tol: float = TOL,
      max_steps: int = 32,
  ):
      r"""Batched bisection with a fixed number of steps.
  
      Args:
          f: Target function that takes a `(b1 x ... x bk)`-dim tensor and returns a
              `(b1 x ... x bk)`-dim tensor.
          target: Scalar target value of type float.
          bounds: Lower and upper bounds, of size `2 x b1 x ... x bk`.
          tol: We termniate if all elements satisfy are within `tol` of the `target`.
          max_steps: Maximum number of bisection steps.
  
      Returns:
          Tensor X of size `b1 x ... x bk` such that `f(X) = target`.
      """
      # Make sure target is actually contained in the interval
      f1, f2 = f(bounds[0]), f(bounds[1])
      if not ((f1 <= target) & (target <= f2)).all():
          raise ValueError(
              "The target is not contained in the interval specified by the bounds"
          )
      bounds = bounds.clone()  # Will be modified in-place
      center = bounds.mean(dim=0)
      f_center = f(center)
      for _ in range(max_steps):
          go_left = f_center > target
          bounds[1, go_left] = center[go_left]
          bounds[0, ~go_left] = center[~go_left]
          center = bounds.mean(dim=0)
          f_center = f(center)
          # Check convergence
          if (f_center - target).abs().max() <= tol:
              return center
      return center
  
file_path: botorch/botorch/posteriors/fully_bayesian.py
imports: from __future__ import annotations
  from typing import Callable, Optional, Tuple
  from warnings import warn
  import torch
  from botorch.posteriors.gpytorch import GPyTorchPosterior
  from gpytorch.distributions import MultivariateNormal
  from torch import Tensor
label_desc: Use image node_id 1 for calling a global function with example usage: batched_bisect(f, target, bounds, tol, max_steps) and returns: center, center