code: def get_outcome_feasibility_probability(
      model: model.Model,
      X: Tensor,
      outcome_constraints: List[Callable[[Tensor], Tensor]],
      threshold: float = 0.1,
      nsample_outcome: int = 1000,
      seed: Optional[int] = None,
  ) -> float:
      r"""
      Monte Carlo estimate of the feasible volume with respect to the outcome constraints.
  
      Args:
          model: The model used for sampling the posterior.
          X: A tensor of dimension `batch-shape x 1 x d`, where d is feature dimension.
          outcome_constraints: A list of callables, each mapping a Tensor of dimension
              `sample_shape x batch-shape x q x m` to a Tensor of dimension
              `sample_shape x batch-shape x q`, where negative values imply feasibility.
          threshold: A lower limit for the probability of posterior samples feasibility.
          nsample_outcome: The number of samples from the model posterior.
          seed: The seed for the posterior sampler. If omitted, use a random seed.
  
      Returns:
          Estimated proportion of features for which posterior samples satisfy
          given outcome constraints with probability above or equal to
          the given threshold.
      """
      if outcome_constraints is None:
          return 1.0
  
      from botorch.sampling.get_sampler import get_sampler
  
      seed = (
          seed
          if seed is not None
          else torch.randint(0, 1000000, (1,)).item()
      )
  
      posterior = model.posterior(
          X
      )  # posterior consists of batch_shape marginals
      sampler = get_sampler(
          posterior=posterior,
          sample_shape=torch.Size([nsample_outcome]),
          seed=seed,
      )
      # size of samples: (num outcome samples, batch_shape, 1, outcome dim)
      samples = sampler(posterior)
  
      feasible = torch.ones(
          samples.shape[:-1], dtype=torch.bool, device=samples.device
      )
  
      # a sample passes if each constraint applied to the sample
      # produces a non-negative tensor
      for oc in outcome_constraints:
          # broadcasted evaluation of the outcome constraints
          feasible &= oc(samples) <= 0
  
      # proportion of feasibile samples for each of the elements of X
      # summation is done across feasible outcome samples
      p_feas = feasible.sum(0).float() / feasible.size(0)
  
      # proportion of features leading to the posterior outcome
      # satisfying the given outcome constraints
      # with at probability above a given threshold
      p_outcome = (p_feas >= threshold).sum().item() / X.size(0)
  
      return p_outcome
  
file_path: botorch/botorch/utils/feasible_volume.py
imports: from __future__ import annotations
  from typing import Callable, List, Optional, Tuple
  import botorch.models.model
  import torch
  from botorch.logging import _get_logger
  from botorch.utils.sampling import manual_seed
  from torch import Tensor
label_desc: Use image node_id 2 for calling a global function with example usage: get_outcome_feasibility_probability(model, X, outcome_constraints, threshold, nsample_outcome, seed) and returns: p_outcome, int