code: def sample_points_around_best(
      acq_function: AcquisitionFunction,
      n_discrete_points: int,
      sigma: float,
      bounds: Tensor,
      best_pct: float = 5.0,
      subset_sigma: float = 1e-1,
      prob_perturb: Optional[float] = None,
  ) -> Optional[Tensor]:
      r"""Find best points and sample nearby points.
  
      Args:
          acq_function: The acquisition function.
          n_discrete_points: The number of points to sample.
          sigma: The standard deviation of the additive gaussian noise for
              perturbing the best points.
          bounds: A `2 x d`-dim tensor containing the bounds.
          best_pct: The percentage of best points to perturb.
          subset_sigma: The standard deviation of the additive gaussian
              noise for perturbing a subset of dimensions of the best points.
          prob_perturb: The probability of perturbing each dimension.
  
      Returns:
          An optional `n_discrete_points x d`-dim tensor containing the
              sampled points. This is None if no baseline points are found.
      """
      X = get_X_baseline(acq_function=acq_function)
      if X is None:
          return
      with torch.no_grad():
          try:
              posterior = acq_function.model.posterior(X)
          except AttributeError:
              warnings.warn(
                  "Failed to sample around previous best points.",
                  BotorchWarning,
              )
              return
          mean = posterior.mean
          while mean.ndim > 2:
              # take average over batch dims
              mean = mean.mean(dim=0)
          try:
              f_pred = acq_function.objective(mean)
          # Some acquisition functions do not have an objective
          # and for some acquisition functions the objective is None
          except (AttributeError, TypeError):
              f_pred = mean
          if hasattr(acq_function, "maximize"):
              # make sure that the optimiztaion direction is set properly
              if not acq_function.maximize:
                  f_pred = -f_pred
          try:
              # handle constraints for EHVI-based acquisition functions
              constraints = acq_function.constraints
              if constraints is not None:
                  neg_violation = -torch.stack(
                      [c(mean).clamp_min(0.0) for c in constraints],
                      dim=-1,
                  ).sum(dim=-1)
                  feas = neg_violation == 0
                  if feas.any():
                      f_pred[~feas] = float("-inf")
                  else:
                      # set objective equal to negative violation
                      f_pred = neg_violation
          except AttributeError:
              pass
          if f_pred.ndim == mean.ndim and f_pred.shape[-1] > 1:
              # multi-objective
              # find pareto set
              is_pareto = is_non_dominated(f_pred)
              best_X = X[is_pareto]
          else:
              if f_pred.shape[-1] == 1:
                  f_pred = f_pred.squeeze(-1)
              n_best = max(1, round(X.shape[0] * best_pct / 100))
              # the view() is to ensure that best_idcs is not a scalar tensor
              best_idcs = torch.topk(f_pred, n_best).indices.view(-1)
              best_X = X[best_idcs]
      use_perturbed_sampling = (
          best_X.shape[-1] >= 20 or prob_perturb is not None
      )
      n_trunc_normal_points = (
          n_discrete_points // 2
          if use_perturbed_sampling
          else n_discrete_points
      )
      perturbed_X = sample_truncated_normal_perturbations(
          X=best_X,
          n_discrete_points=n_trunc_normal_points,
          sigma=sigma,
          bounds=bounds,
      )
      if use_perturbed_sampling:
          perturbed_subset_dims_X = sample_perturbed_subset_dims(
              X=best_X,
              bounds=bounds,
              # ensure that we return n_discrete_points
              n_discrete_points=n_discrete_points
              - n_trunc_normal_points,
              sigma=sigma,
              prob_perturb=prob_perturb,
          )
          perturbed_X = torch.cat(
              [perturbed_X, perturbed_subset_dims_X], dim=0
          )
          # shuffle points
          perm = torch.randperm(perturbed_X.shape[0], device=X.device)
          perturbed_X = perturbed_X[perm]
      return perturbed_X
  
imports: from __future__ import annotations
  import warnings
  from math import ceil
  from typing import Callable, Dict, List, Optional, Tuple, Union
  import torch
  from botorch import settings
  from botorch.acquisition import analytic, monte_carlo, multi_objective
  from botorch.acquisition.acquisition import AcquisitionFunction
  from botorch.acquisition.fixed_feature import FixedFeatureAcquisitionFunction
  from botorch.acquisition.knowledge_gradient import _get_value_function, qKnowledgeGradient
  from botorch.acquisition.multi_objective.hypervolume_knowledge_gradient import _get_hv_value_function, qHypervolumeKnowledgeGradient, qMultiFidelityHypervolumeKnowledgeGradient
  from botorch.exceptions.errors import BotorchTensorDimensionError, UnsupportedError
  from botorch.exceptions.warnings import BadInitialCandidatesWarning, BotorchWarning, SamplingWarning
  from botorch.models.model import Model
  from botorch.optim.utils import fix_features, get_X_baseline
  from botorch.utils.multi_objective.pareto import is_non_dominated
  from botorch.utils.sampling import batched_multinomial, draw_sobol_samples, get_polytope_samples, manual_seed
  from botorch.utils.transforms import normalize, standardize, unnormalize
  from torch import Tensor
  from torch.distributions import Normal
  from torch.quasirandom import SobolEngine
label_desc: Use image node_id 11 for calling a global function with example usage: sample_points_around_best(acq_function, n_discrete_points, sigma, bounds, best_pct, subset_sigma, prob_perturb) and returns: perturbed_X