code: def qnehvi_candidates_func(
      train_x: "torch.Tensor",
      train_obj: "torch.Tensor",
      train_con: Optional["torch.Tensor"],
      bounds: "torch.Tensor",
      pending_x: Optional["torch.Tensor"],
  ) -> "torch.Tensor":
      """Quasi MC-based batch Noisy Expected Hypervolume Improvement (qNEHVI).
  
      According to Botorch/Ax documentation,
      this function may perform better than qEHVI (`qehvi_candidates_func`).
      (cf. https://botorch.org/tutorials/constrained_multi_objective_bo )
  
      .. seealso::
          :func:`~optuna.integration.botorch.qei_candidates_func` for argument and return value
          descriptions.
      """
  
      n_objectives = train_obj.size(-1)
  
      if train_con is not None:
          train_y = torch.cat([train_obj, train_con], dim=-1)
  
          n_constraints = train_con.size(1)
          additional_qnehvi_kwargs = {
              "objective": IdentityMCMultiOutputObjective(
                  outcomes=list(range(n_objectives))
              ),
              "constraints": [
                  (lambda Z, i=i: Z[..., -n_constraints + i])
                  for i in range(n_constraints)
              ],
          }
      else:
          train_y = train_obj
  
          additional_qnehvi_kwargs = {}
  
      train_x = normalize(train_x, bounds=bounds)
      if pending_x is not None:
          pending_x = normalize(pending_x, bounds=bounds)
  
      model = SingleTaskGP(
          train_x,
          train_y,
          outcome_transform=Standardize(m=train_y.shape[-1]),
      )
      mll = ExactMarginalLogLikelihood(model.likelihood, model)
      fit_gpytorch_mll(mll)
  
      # Approximate box decomposition similar to Ax when the number of objectives is large.
      # https://github.com/pytorch/botorch/blob/36d09a4297c2a0ff385077b7fcdd5a9d308e40cc/botorch/acquisition/multi_objective/utils.py#L46-L63
      if n_objectives > 4:
          alpha = 10 ** (-8 + n_objectives)
      else:
          alpha = 0.0
  
      ref_point = train_obj.min(dim=0).values - 1e-8
  
      ref_point_list = ref_point.tolist()
  
      # prune_baseline=True is generally recommended by the documentation of BoTorch.
      # cf. https://botorch.org/api/acquisition.html (accessed on 2022/11/18)
      acqf = monte_carlo.qNoisyExpectedHypervolumeImprovement(
          model=model,
          ref_point=ref_point_list,
          X_baseline=train_x,
          alpha=alpha,
          prune_baseline=True,
          sampler=_get_sobol_qmc_normal_sampler(256),
          X_pending=pending_x,
          **additional_qnehvi_kwargs,
      )
  
      standard_bounds = torch.zeros_like(bounds)
      standard_bounds[1] = 1
  
      candidates, _ = optimize_acqf(
          acq_function=acqf,
          bounds=standard_bounds,
          q=1,
          num_restarts=20,
          raw_samples=1024,
          options={
              "batch_limit": 5,
              "maxiter": 200,
              "nonnegative": True,
          },
          sequential=True,
      )
  
      candidates = unnormalize(candidates.detach(), bounds=bounds)
  
      return candidates
  
imports: from typing import Any
  from typing import Callable
  from typing import Dict
  from typing import Optional
  from typing import Sequence
  from typing import Union
  import warnings
  import numpy
  from packaging import version
  from optuna import logging
  from optuna._experimental import experimental_class
  from optuna._experimental import experimental_func
  from optuna._imports import try_import
  from optuna._transform import _SearchSpaceTransform
  from optuna.distributions import BaseDistribution
  from optuna.samplers import BaseSampler
  from optuna.samplers import RandomSampler
  from optuna.samplers._base import _CONSTRAINTS_KEY
  from optuna.samplers._base import _process_constraints_after_trial
  from optuna.search_space import IntersectionSearchSpace
  from optuna.study import Study
  from optuna.study import StudyDirection
  from optuna.trial import FrozenTrial
  from optuna.trial import TrialState
label_desc: Use image node_id 6 for calling a global function with example usage: qnehvi_candidates_func(train_x, train_obj, train_con, bounds, pending_x) and returns: candidates