class_docstr: Implement the acquisition function of Sparsity Exploring Bayesian
  Optimization (SEBO).
  
  The SEBO is a hyperparameter-free method to simultaneously maximize a target
  objective and sparsity. When L0 norm is used, SEBO uses a novel differentiable
  relaxation based on homotopy continuation to efficiently optimize for sparsity.
class_docstr_tok: ["Implement","the","acquisition","function","of","Sparsity","Exploring","Bayesian","Optimization","(","SEBO",")",".","The","SEBO","is","a","hyperparameter-free","method","to","simultaneously","maximize","a","target","objective","and","sparsity",".","When","L0","norm","is","used",",","SEBO","uses","a","novel","differentiable","relaxation","based","on","homotopy","continuation","to","efficiently","optimize","for","sparsity","."]
docstr: Generate a set of candidates via multi-start optimization. Obtains
  candidates and their associated acquisition function values.
  
  Args:
      n: The number of candidates to generate.
      search_space_digest: A ``SearchSpaceDigest`` object containing search space
          properties, e.g. ``bounds`` for optimization.
      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``.
      fixed_features: A map `{feature_index: value}` for features that
          should be fixed to a particular value during generation.
      rounding_func: A function that post-processes an optimization
          result appropriately (i.e., according to `round-trip`
          transformations).
      optimizer_options: Options for the optimizer function, e.g. ``sequential``
          or ``raw_samples``.
docstr_tok: ["Generate","a","set","of","candidates","via","multi-start","optimization",".","Obtains","candidates","and","their","associated","acquisition","function","values",".","Args",":","n",":","The","number","of","candidates","to","generate",".","search_space_digest",":","A","``","SearchSpaceDigest","``","object","containing","search","space","properties",",","e.g",".","``","bounds","``","for","optimization",".","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","``",".","fixed_features",":","A","map","`","{","feature_index",":","value","}","`","for","features","that","should","be","fixed","to","a","particular","value","during","generation",".","rounding_func",":","A","function","that","post-processes","an","optimization","result","appropriately","(","i.e.",",","according","to","`","round-trip","`","transformations",")",".","optimizer_options",":","Options","for","the","optimizer","function",",","e.g",".","``","sequential","``","or","``","raw_samples","``","."]
code: def optimize(
      self,
      n: int,
      search_space_digest: SearchSpaceDigest,
      inequality_constraints: Optional[
          List[Tuple[Tensor, Tensor, float]]
      ] = None,
      fixed_features: Optional[Dict[int, float]] = None,
      rounding_func: Optional[Callable[[Tensor], Tensor]] = None,
      optimizer_options: Optional[Dict[str, Any]] = None,
  ) -> Tuple[Tensor, Tensor]:
      """Generate a set of candidates via multi-start optimization. Obtains
      candidates and their associated acquisition function values.
  
      Args:
          n: The number of candidates to generate.
          search_space_digest: A ``SearchSpaceDigest`` object containing search space
              properties, e.g. ``bounds`` for optimization.
          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``.
          fixed_features: A map `{feature_index: value}` for features that
              should be fixed to a particular value during generation.
          rounding_func: A function that post-processes an optimization
              result appropriately (i.e., according to `round-trip`
              transformations).
          optimizer_options: Options for the optimizer function, e.g. ``sequential``
              or ``raw_samples``.
      """
      if self.penalty_name == "L0_norm":
          if inequality_constraints is not None:
              raise NotImplementedError(
                  "Homotopy does not support optimization with inequality "
                  + "constraints. Use L1 penalty norm instead."
              )
          (
              candidates,
              expected_acquisition_value,
          ) = self._optimize_with_homotopy(
              n=n,
              search_space_digest=search_space_digest,
              fixed_features=fixed_features,
              rounding_func=rounding_func,
              optimizer_options=optimizer_options,
          )
      else:
          # if L1 norm use standard moo-opt
          candidates, expected_acquisition_value = super().optimize(
              n=n,
              search_space_digest=search_space_digest,
              inequality_constraints=inequality_constraints,
              fixed_features=fixed_features,
              rounding_func=rounding_func,
              optimizer_options=optimizer_options,
          )
  
      # similar, make sure if applies to sparse dimensions only
      candidates = clamp_candidates(
          X=candidates,
          target_point=self.target_point,
          clamp_tol=CLAMP_TOL,
          device=self.device,
          dtype=self.dtype,
      )
      return candidates, expected_acquisition_value
  
imports: import functools
  from copy import deepcopy
  from functools import partial
  from typing import Any, Callable, Dict, List, Optional, Tuple, Type
  import torch
  from ax.core.search_space import SearchSpaceDigest
  from ax.models.torch.botorch_modular.acquisition import Acquisition
  from ax.models.torch.botorch_modular.optimizer_argparse import optimizer_argparse
  from ax.models.torch.botorch_modular.surrogate import Surrogate
  from ax.models.torch_base import TorchOptConfig
  from ax.utils.common.constants import Keys
  from ax.utils.common.typeutils import not_none
  from botorch.acquisition.acquisition import AcquisitionFunction
  from botorch.acquisition.multi_objective.monte_carlo import qExpectedHypervolumeImprovement
  from botorch.acquisition.penalized import L0Approximation
  from botorch.models.deterministic import GenericDeterministicModel
  from botorch.models.model import ModelList
  from botorch.optim import Homotopy, HomotopyParameter, LogLinearHomotopySchedule, optimize_acqf_homotopy
  from botorch.utils.datasets import SupervisedDataset
  from botorch.utils.multi_objective.pareto import is_non_dominated
  from torch import Tensor
  from torch.quasirandom import SobolEngine
label_desc: Use image node_id 4 for calling the SEBOAcquisition obj's underlying member method code with example usage: obj.optimize(n, search_space_digest, inequality_constraints, fixed_features, rounding_func, optimizer_options) and returns: candidates,  expected_acquisition_value