code: def _remove_fixed_features_from_optimization(
      fixed_features: Dict[int, Optional[float]],
      acquisition_function: AcquisitionFunction,
      initial_conditions: Tensor,
      lower_bounds: Optional[Union[float, Tensor]],
      upper_bounds: Optional[Union[float, Tensor]],
      inequality_constraints: Optional[
          List[Tuple[Tensor, Tensor, float]]
      ],
      equality_constraints: Optional[
          List[Tuple[Tensor, Tensor, float]]
      ],
      nonlinear_inequality_constraints: Optional[
          List[Callable[[Tensor], Tensor]]
      ],
  ) -> _NoFixedFeatures:
      """
      Given a set of non-empty fixed features, this function effectively reduces the
      dimensionality of the domain that the acquisition function is being optimized
      over by removing the set of fixed features. Consequently, this function returns a
      new `FixedFeatureAcquisitionFunction`, new constraints, and bounds defined over
      unfixed features.
  
      Args:
          fixed_features: This is a dictionary of feature indices to values, where
              all generated candidates will have features fixed to these values.
              If the dictionary value is None, then that feature will just be
              fixed to the clamped value and not optimized. Assumes values to be
              compatible with lower_bounds and upper_bounds!
          acquisition_function: Acquisition function over the original domain being
              maximized.
          initial_conditions: Starting points for optimization w.r.t. the complete domain.
          lower_bounds: Minimum values for each column of initial_conditions.
          upper_bounds: Minimum values for each column of initial_conditions.
          inequality constraints: A list of tuples (indices, coefficients, rhs),
              with each tuple encoding an inequality constraint of the form
              `sum_i (X[indices[i]] * coefficients[i]) >= rhs`.
          equality constraints: A list of tuples (indices, coefficients, rhs),
              with each tuple encoding an inequality constraint of the form
              `sum_i (X[indices[i]] * coefficients[i]) = rhs`.
          nonlinear_inequality_constraints: A list of callables with that represent
              non-linear inequality constraints of the form `callable(x) >= 0`. Each
              callable is expected to take a `(num_restarts) x q x d`-dim tensor as
              an input and return a `(num_restarts) x q`-dim tensor with the
              constraint values.
  
      Returns:
          _NoFixedFeatures dataclass object.
      """
      # sort the keys for consistency
      sorted_keys = sorted(fixed_features)
      sorted_values = []
      for key in sorted_keys:
          if fixed_features[key] is None:
              val = initial_conditions[..., [key]]
          else:
              val = fixed_features[key]
          sorted_values.append(val)
  
      d = initial_conditions.shape[-1]
      acquisition_function = FixedFeatureAcquisitionFunction(
          acq_function=acquisition_function,
          d=d,
          columns=sorted_keys,
          values=sorted_values,
      )
  
      # extract initial_conditions, bounds at unfixed indices
      unfixed_indices = sorted(set(range(d)) - set(sorted_keys))
      initial_conditions = initial_conditions[..., unfixed_indices]
      if isinstance(lower_bounds, Tensor):
          lower_bounds = lower_bounds[..., unfixed_indices]
      if isinstance(upper_bounds, Tensor):
          upper_bounds = upper_bounds[..., unfixed_indices]
  
      inequality_constraints = _generate_unfixed_lin_constraints(
          constraints=inequality_constraints,
          fixed_features=fixed_features,
          dimension=d,
          eq=False,
      )
      equality_constraints = _generate_unfixed_lin_constraints(
          constraints=equality_constraints,
          fixed_features=fixed_features,
          dimension=d,
          eq=True,
      )
      nonlinear_inequality_constraints = (
          _generate_unfixed_nonlin_constraints(
              constraints=nonlinear_inequality_constraints,
              fixed_features=fixed_features,
              dimension=d,
          )
      )
      return _NoFixedFeatures(
          acquisition_function=acquisition_function,
          initial_conditions=initial_conditions,
          lower_bounds=lower_bounds,
          upper_bounds=upper_bounds,
          inequality_constraints=inequality_constraints,
          equality_constraints=equality_constraints,
          nonlinear_inequality_constraints=nonlinear_inequality_constraints,
      )
  
file_path: botorch/botorch/generation/utils.py
imports: from __future__ import annotations
  import warnings
  from dataclasses import dataclass
  from typing import Callable, Dict, List, Optional, Tuple, Union
  import torch
  from botorch.acquisition import AcquisitionFunction, FixedFeatureAcquisitionFunction
  from botorch.optim.parameter_constraints import _generate_unfixed_lin_constraints, _generate_unfixed_nonlin_constraints
  from torch import Tensor
label_desc: Use image node_id 3 for calling a global function with example usage: _remove_fixed_features_from_optimization(fixed_features, acquisition_function, initial_conditions, lower_bounds, upper_bounds, inequality_constraints, equality_constraints, nonlinear_inequality_constraints) and returns: _NoFixedFeatures