code: def _optimize_and_get_candidates(
      acq_function: qKnowledgeGradient,
      bounds_: Tensor,
      n: int,
      num_restarts: int,
      raw_samples: int,
      # pyre-fixme[24]: Generic type `dict` expects 2 type parameters, use
      #  `typing.Dict` to avoid runtime subscripting errors.
      optimizer_options: Dict,
      rounding_func: Optional[Callable[[Tensor], Tensor]],
      inequality_constraints: Optional[
          List[Tuple[Tensor, Tensor, float]]
      ],
      fixed_features: Optional[Dict[int, float]],
  ) -> Tensor:
      r"""Generates initial conditions for optimization, optimize the acquisition
      function, and return the candidates.
      """
      batch_initial_conditions = gen_one_shot_kg_initial_conditions(
          acq_function=acq_function,
          bounds=bounds_,
          q=n,
          num_restarts=num_restarts,
          raw_samples=raw_samples,
          options={
              "frac_random": optimizer_options.get("frac_random", 0.1),
              "num_inner_restarts": num_restarts,
              "raw_inner_samples": raw_samples,
          },
      )
  
      botorch_rounding_func = get_rounding_func(rounding_func)
  
      opt_options: Dict[str, Union[bool, float, int, str]] = {
          "batch_limit": 8,
          "maxiter": 200,
          "method": "L-BFGS-B",
          "nonnegative": False,
      }
      opt_options.update(optimizer_options.get("options", {}))
      candidates, _ = optimize_acqf(
          acq_function=acq_function,
          bounds=bounds_,
          q=n,
          inequality_constraints=inequality_constraints,
          fixed_features=fixed_features,
          post_processing_func=botorch_rounding_func,
          num_restarts=num_restarts,
          raw_samples=raw_samples,
          options=opt_options,
          batch_initial_conditions=batch_initial_conditions,
      )
      new_x = candidates.detach().cpu()
      return new_x
  
imports: import dataclasses
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union
  import torch
  from ax.core.search_space import SearchSpaceDigest
  from ax.models.torch.botorch import BotorchModel, get_rounding_func
  from ax.models.torch.botorch_defaults import recommend_best_out_of_sample_point
  from ax.models.torch.utils import _get_X_pending_and_observed, _to_inequality_constraints, get_botorch_objective_and_transform, get_out_of_sample_best_point_acqf, subset_model
  from ax.models.torch_base import TorchGenResults, TorchOptConfig
  from ax.utils.common.typeutils import not_none
  from botorch.acquisition.acquisition import AcquisitionFunction
  from botorch.acquisition.cost_aware import InverseCostWeightedUtility
  from botorch.acquisition.knowledge_gradient import qKnowledgeGradient, qMultiFidelityKnowledgeGradient
  from botorch.acquisition.objective import MCAcquisitionObjective, PosteriorTransform
  from botorch.acquisition.utils import expand_trace_observations, project_to_target_fidelity
  from botorch.exceptions.errors import UnsupportedError
  from botorch.models.cost import AffineFidelityCostModel
  from botorch.models.model import Model
  from botorch.optim.initializers import gen_one_shot_kg_initial_conditions
  from botorch.optim.optimize import optimize_acqf
  from botorch.sampling.normal import IIDNormalSampler, SobolQMCNormalSampler
  from torch import Tensor
label_desc: Use image node_id 2 for calling a global function with example usage: _optimize_and_get_candidates(acq_function, bounds_, n, num_restarts, raw_samples, optimizer_options, rounding_func, inequality_constraints, fixed_features) and returns: new_x