code: def compute_sample_box_decomposition(
      pareto_fronts: Tensor,
      partitioning: BoxDecomposition = DominatedPartitioning,
      maximize: bool = True,
      num_constraints: Optional[int] = 0,
  ) -> Tensor:
      r"""Computes the box decomposition associated with some sampled optimal
      objectives. This also supports the single-objective and constrained optimization
      setting. An objective `y` is feasible if `y <= 0`.
  
      To take advantage of batch computations, we pad the hypercell bounds with a
      `2 x (M + K)`-dim Tensor of zeros `[0, 0]`.
  
      Args:
          pareto_fronts: A `num_pareto_samples x num_pareto_points x M` dim Tensor
              containing the sampled optimal set of objectives.
          partitioning: A `BoxDecomposition` module that is used to obtain the
              hyper-rectangle bounds for integration. In the unconstrained case, this
              gives the partition of the dominated space. In the constrained case, this
              gives the partition of the feasible dominated space union the infeasible
              space.
          maximize: If true, the box-decomposition is computed assuming maximization.
          num_constraints: The number of constraints `K`.
  
      Returns:
          A `num_pareto_samples x 2 x J x (M + K)`-dim Tensor containing the bounds for
          the hyper-rectangles. The number `J` is the smallest number of boxes needed
          to partition all the Pareto samples.
      """
      tkwargs = {
          "dtype": pareto_fronts.dtype,
          "device": pareto_fronts.device,
      }
      # We will later compute `norm.log_prob(NEG_INF)`, this is `-inf` if `NEG_INF` is
      # too small.
      NEG_INF = -1e10
  
      if pareto_fronts.ndim != 3:
          raise UnsupportedError(
              "Currently this only supports Pareto fronts of the shape "
              "`num_pareto_samples x num_pareto_points x num_objectives`."
          )
  
      num_pareto_samples = pareto_fronts.shape[0]
      M = pareto_fronts.shape[-1]
      K = num_constraints
      ref_point = torch.ones(M, **tkwargs) * NEG_INF
      weight = 1.0 if maximize else -1.0
  
      if M == 1:
          # Only consider a Pareto front with one element.
          extreme_values = (
              weight * torch.max(weight * pareto_fronts, dim=-2).values
          )
          ref_point = weight * ref_point.expand(extreme_values.shape)
  
          if maximize:
              hypercell_bounds = torch.stack(
                  [ref_point, extreme_values], axis=-2
              ).unsqueeze(-1)
          else:
              hypercell_bounds = torch.stack(
                  [extreme_values, ref_point], axis=-2
              ).unsqueeze(-1)
      else:
          bd_list = []
          for i in range(num_pareto_samples):
              bd_list = bd_list + [
                  partitioning(
                      ref_point=ref_point,
                      Y=weight * pareto_fronts[i, :, :],
                  )
              ]
  
          # `num_pareto_samples x 2 x J x (M + K)`
          hypercell_bounds = (
              BoxDecompositionList(*bd_list)
              .get_hypercell_bounds()
              .movedim(0, 1)
          )
  
          # If minimizing, then the bounds should be negated and flipped
          if not maximize:
              hypercell_bounds = weight * torch.flip(
                  hypercell_bounds, dims=[1]
              )
  
      # Add an extra box for the inequality constraint.
      if K > 0:
          # `num_pareto_samples x 2 x (J - 1) x K`
          feasible_boxes = torch.zeros(
              hypercell_bounds.shape[:-1] + torch.Size([K]), **tkwargs
          )
  
          feasible_boxes[..., 0, :, :] = NEG_INF
          # `num_pareto_samples x 2 x (J - 1) x (M + K)`
          hypercell_bounds = torch.cat(
              [hypercell_bounds, feasible_boxes], dim=-1
          )
  
          # `num_pareto_samples x 2 x 1 x (M + K)`
          infeasible_box = torch.zeros(
              hypercell_bounds.shape[:-2] + torch.Size([1, M + K]),
              **tkwargs,
          )
          infeasible_box[..., 1, :, M:] = -NEG_INF
          infeasible_box[..., 0, :, 0:M] = NEG_INF
          infeasible_box[..., 1, :, 0:M] = -NEG_INF
  
          # `num_pareto_samples x 2 x J x (M + K)`
          hypercell_bounds = torch.cat(
              [hypercell_bounds, infeasible_box], dim=-2
          )
  
      # `num_pareto_samples x 2 x J x (M + K)`
      return hypercell_bounds
  
imports: from __future__ import annotations
  import math
  import warnings
  from math import ceil
  from typing import Any, Callable, Dict, List, Optional, Tuple
  import torch
  from botorch.acquisition import monte_carlo
  from botorch.acquisition.multi_objective.objective import IdentityMCMultiOutputObjective, MCMultiOutputObjective
  from botorch.exceptions.errors import UnsupportedError
  from botorch.exceptions.warnings import BotorchWarning
  from botorch.models.deterministic import GenericDeterministicModel
  from botorch.models.fully_bayesian import MCMC_DIM
  from botorch.models.model import Model
  from botorch.sampling.get_sampler import get_sampler
  from botorch.utils.gp_sampling import get_gp_samples
  from botorch.utils.multi_objective.box_decompositions.box_decomposition import BoxDecomposition
  from botorch.utils.multi_objective.box_decompositions.box_decomposition_list import BoxDecompositionList
  from botorch.utils.multi_objective.box_decompositions.dominated import DominatedPartitioning
  from botorch.utils.multi_objective.pareto import is_non_dominated
  from botorch.utils.objective import compute_feasibility_indicator
  from botorch.utils.sampling import draw_sobol_samples
  from botorch.utils.transforms import is_ensemble
  from torch import Tensor
label_desc: Use image node_id 3 for calling a global function with example usage: compute_sample_box_decomposition(pareto_fronts, partitioning, maximize, num_constraints) and returns: hypercell_bounds