code: def initialize_q_batch(
      X: Tensor, Y: Tensor, n: int, eta: float = 1.0
  ) -> Tensor:
      r"""Heuristic for selecting initial conditions for candidate generation.
  
      This heuristic selects points from `X` (without replacement) with probability
      proportional to `exp(eta * Z)`, where `Z = (Y - mean(Y)) / std(Y)` and `eta`
      is a temperature parameter.
  
      When using an acquisiton function that is non-negative and possibly zero
      over large areas of the feature space (e.g. qEI), you should use
      `initialize_q_batch_nonneg` instead.
  
      Args:
          X: A `b x batch_shape x q x d` tensor of `b` - `batch_shape` samples of
              `q`-batches from a d`-dim feature space. Typically, these are generated
              using qMC sampling.
          Y: A tensor of `b x batch_shape` outcomes associated with the samples.
              Typically, this is the value of the batch acquisition function to be
              maximized.
          n: The number of initial condition to be generated. Must be less than `b`.
          eta: Temperature parameter for weighting samples.
  
      Returns:
          A `n x batch_shape x q x d` tensor of `n` - `batch_shape` `q`-batch initial
          conditions, where each batch of `n x q x d` samples is selected independently.
  
      Example:
          >>> # To get `n=10` starting points of q-batch size `q=3`
          >>> # for model with `d=6`:
          >>> qUCB = qUpperConfidenceBound(model, beta=0.1)
          >>> Xrnd = torch.rand(500, 3, 6)
          >>> Xinit = initialize_q_batch(Xrnd, qUCB(Xrnd), 10)
      """
      n_samples = X.shape[0]
      batch_shape = X.shape[1:-2] or torch.Size()
      if n > n_samples:
          raise RuntimeError(
              f"n ({n}) cannot be larger than the number of "
              f"provided samples ({n_samples})"
          )
      elif n == n_samples:
          return X
  
      Ystd = Y.std(dim=0)
      if torch.any(Ystd == 0):
          warnings.warn(
              "All acquisition values for raw samples points are the same for "
              "at least one batch. Choosing initial conditions at random.",
              BadInitialCandidatesWarning,
          )
          return X[torch.randperm(n=n_samples, device=X.device)][:n]
  
      max_val, max_idx = torch.max(Y, dim=0)
      Z = (Y - Y.mean(dim=0)) / Ystd
      etaZ = eta * Z
      weights = torch.exp(etaZ)
      while torch.isinf(weights).any():
          etaZ *= 0.5
          weights = torch.exp(etaZ)
      if batch_shape == torch.Size():
          idcs = torch.multinomial(weights, n)
      else:
          idcs = batched_multinomial(
              weights=weights.permute(
                  *range(1, len(batch_shape) + 1), 0
              ),
              num_samples=n,
          ).permute(-1, *range(len(batch_shape)))
      # make sure we get the maximum
      if max_idx not in idcs:
          idcs[-1] = max_idx
      if batch_shape == torch.Size():
          return X[idcs]
      else:
          return X.gather(
              dim=0,
              index=idcs.view(*idcs.shape, 1, 1).expand(
                  n, *X.shape[1:]
              ),
          )
  
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 9 for calling a global function with example usage: initialize_q_batch(X, Y, n, eta) and returns: X, X, X, X