code: def _generate_neighbors(
      x: Tensor,
      discrete_choices: List[Tensor],
      X_avoid: Tensor,
      inequality_constraints: List[Tuple[Tensor, Tensor, float]],
  ):
      # generate all 1D perturbations
      npts = sum([len(c) for c in discrete_choices])
      X_loc = x.repeat(npts, 1)
      j = 0
      for i, c in enumerate(discrete_choices):
          X_loc[j : j + len(c), i] = c
          j += len(c)
      # remove invalid and infeasible points (also remove x)
      X_loc = _filter_invalid(X=X_loc, X_avoid=torch.cat((X_avoid, x)))
      X_loc = _filter_infeasible(
          X=X_loc, inequality_constraints=inequality_constraints
      )
      return X_loc
  
imports: from __future__ import annotations
  import dataclasses
  import warnings
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union
  import torch
  from botorch.acquisition.acquisition import AcquisitionFunction, OneShotAcquisitionFunction
  from botorch.acquisition.knowledge_gradient import qKnowledgeGradient
  from botorch.acquisition.multi_objective.hypervolume_knowledge_gradient import qHypervolumeKnowledgeGradient
  from botorch.exceptions import InputDataError, UnsupportedError
  from botorch.exceptions.warnings import OptimizationWarning
  from botorch.generation.gen import gen_candidates_scipy, TGenCandidates
  from botorch.logging import logger
  from botorch.optim.initializers import gen_batch_initial_conditions, gen_one_shot_hvkg_initial_conditions, gen_one_shot_kg_initial_conditions, TGenInitialConditions
  from botorch.optim.stopping import ExpMAStoppingCriterion
  from botorch.optim.utils import _filter_kwargs
  from torch import Tensor
label_desc: Use image node_id 13 for calling a global function with example usage: _generate_neighbors(x, discrete_choices, X_avoid, inequality_constraints) and returns: X_loc