code: def infer_objective_thresholds(
      model: Model,
      objective_weights: Tensor,  # objective_directions
      bounds: Optional[List[Tuple[float, float]]] = None,
      outcome_constraints: Optional[Tuple[Tensor, Tensor]] = None,
      linear_constraints: Optional[Tuple[Tensor, Tensor]] = None,
      fixed_features: Optional[Dict[int, float]] = None,
      subset_idcs: Optional[Tensor] = None,
      Xs: Optional[List[Tensor]] = None,
      X_observed: Optional[Tensor] = None,
      objective_thresholds: Optional[Tensor] = None,
  ) -> Tensor:
      """Infer objective thresholds.
  
      This method uses the model-estimated Pareto frontier over the in-sample points
      to infer absolute (not relativized) objective thresholds.
  
      This uses a heuristic that sets the objective threshold to be a scaled nadir
      point, where the nadir point is scaled back based on the range of each
      objective across the current in-sample Pareto frontier.
  
      See `botorch.utils.multi_objective.hypervolume.infer_reference_point` for
      details on the heuristic.
  
      Args:
          model: A fitted botorch Model.
          objective_weights: The objective is to maximize a weighted sum of
              the columns of f(x). These are the weights. These should not
              be subsetted.
          bounds: A list of (lower, upper) tuples for each column of X.
          outcome_constraints: A tuple of (A, b). For k outcome constraints
              and m outputs at f(x), A is (k x m) and b is (k x 1) such that
              A f(x) <= b. These should not be subsetted.
          linear_constraints: A tuple of (A, b). For k linear constraints on
              d-dimensional x, A is (k x d) and b is (k x 1) such that
              A x <= b.
          fixed_features: A map {feature_index: value} for features that
              should be fixed to a particular value during generation.
          subset_idcs: The indices of the outcomes that are modeled by the
              provided model. If subset_idcs not None, this method infers
              whether the model is subsetted.
          Xs: A list of m (k_i x d) feature tensors X. Number of rows k_i can
              vary from i=1,...,m.
          X_observed: A `n x d`-dim tensor of in-sample points to use for
              determining the current in-sample Pareto frontier.
          objective_thresholds: Any known objective thresholds to pass to
              `infer_reference_point` heuristic. This should not be subsetted.
              If only a subset of the objectives have known thresholds, the
              remaining objectives should be NaN. If no objective threshold
              was provided, this can be `None`.
  
      Returns:
          A `m`-dim tensor of objective thresholds, where the objective
              threshold is `nan` if the outcome is not an objective.
      """
      if X_observed is None:
          if bounds is None:
              raise ValueError(
                  "bounds is required if X_observed is None."
              )
          elif Xs is None:
              raise ValueError("Xs is required if X_observed is None.")
          _, X_observed = _get_X_pending_and_observed(
              Xs=Xs,
              objective_weights=objective_weights,
              outcome_constraints=outcome_constraints,
              bounds=bounds,
              linear_constraints=linear_constraints,
              fixed_features=fixed_features,
          )
      num_outcomes = objective_weights.shape[0]
      if subset_idcs is None:
          # check if only a subset of outcomes are modeled
          nonzero = objective_weights != 0
          if outcome_constraints is not None:
              A, _ = outcome_constraints
              nonzero = nonzero | torch.any(A != 0, dim=0)
          expected_subset_idcs = nonzero.nonzero().view(-1)
          if model.num_outputs > expected_subset_idcs.numel():
              # subset the model so that we only compute the posterior
              # over the relevant outcomes
              subset_model_results = subset_model(
                  model=model,
                  objective_weights=objective_weights,
                  outcome_constraints=outcome_constraints,
              )
              model = subset_model_results.model
              objective_weights = subset_model_results.objective_weights
              outcome_constraints = (
                  subset_model_results.outcome_constraints
              )
              subset_idcs = subset_model_results.indices
          else:
              # model is already subsetted.
              subset_idcs = expected_subset_idcs
              # subset objective weights and outcome constraints
              objective_weights = objective_weights[subset_idcs]
              if outcome_constraints is not None:
                  outcome_constraints = (
                      outcome_constraints[0][:, subset_idcs],
                      outcome_constraints[1],
                  )
      else:
          objective_weights = objective_weights[subset_idcs]
          if outcome_constraints is not None:
              outcome_constraints = (
                  outcome_constraints[0][:, subset_idcs],
                  outcome_constraints[1],
              )
      with torch.no_grad():
          pred = _check_posterior_type(
              not_none(model).posterior(not_none(X_observed))
          ).mean
  
      if outcome_constraints is not None:
          cons_tfs = get_outcome_constraint_transforms(
              outcome_constraints
          )
          # pyre-ignore [16]
          feas = torch.stack(
              [c(pred) <= 0 for c in cons_tfs], dim=-1
          ).all(dim=-1)
          pred = pred[feas]
      if pred.shape[0] == 0:
          raise AxError(NO_FEASIBLE_POINTS_MESSAGE)
      obj_mask = objective_weights.nonzero().view(-1)
      obj_weights_subset = objective_weights[obj_mask]
      obj = pred[..., obj_mask] * obj_weights_subset
      pareto_obj = obj[is_non_dominated(obj)]
      # If objective thresholds are provided, set max_ref_point accordingly.
      if objective_thresholds is not None:
          max_ref_point = (
              objective_thresholds[obj_mask] * obj_weights_subset
          )
      else:
          max_ref_point = None
      objective_thresholds = infer_reference_point(
          pareto_Y=pareto_obj,
          max_ref_point=max_ref_point,
          scale=0.1,
      )
      # multiply by objective weights to return objective thresholds in the
      # unweighted space
      objective_thresholds = objective_thresholds * obj_weights_subset
      full_objective_thresholds = torch.full(
          (num_outcomes,),
          float("nan"),
          dtype=objective_weights.dtype,
          device=objective_weights.device,
      )
      obj_idcs = subset_idcs[obj_mask]
      full_objective_thresholds[obj_idcs] = objective_thresholds.clone()
      return full_objective_thresholds
  
imports: from __future__ import annotations
  from typing import Callable, cast, Dict, List, Optional, Tuple, Union
  import torch
  from ax.exceptions.core import AxError
  from ax.models.torch.botorch_defaults import NO_FEASIBLE_POINTS_MESSAGE
  from ax.models.torch.utils import _get_X_pending_and_observed, get_outcome_constraint_transforms, subset_model
  from ax.models.torch_base import TorchModel
  from ax.utils.common.typeutils import checked_cast, not_none
  from botorch.acquisition import get_acquisition_function
  from botorch.acquisition.acquisition import AcquisitionFunction
  from botorch.acquisition.multi_objective.logei import qLogExpectedHypervolumeImprovement, qLogNoisyExpectedHypervolumeImprovement
  from botorch.acquisition.multi_objective.monte_carlo import qExpectedHypervolumeImprovement, qNoisyExpectedHypervolumeImprovement
  from botorch.acquisition.multi_objective.objective import WeightedMCMultiOutputObjective
  from botorch.acquisition.multi_objective.utils import get_default_partitioning_alpha
  from botorch.models.model import Model
  from botorch.optim.optimize import optimize_acqf_list
  from botorch.posteriors.gpytorch import GPyTorchPosterior
  from botorch.posteriors.posterior import Posterior
  from botorch.posteriors.posterior_list import PosteriorList
  from botorch.utils.multi_objective.hypervolume import infer_reference_point
  from botorch.utils.multi_objective.pareto import is_non_dominated
  from torch import Tensor
label_desc: Use image node_id 11 for calling a global function with example usage: infer_objective_thresholds(model, objective_weights, bounds, outcome_constraints, linear_constraints, fixed_features, subset_idcs, Xs, X_observed, objective_thresholds) and returns: full_objective_thresholds