class_docstr: A multi-output Model represented by a list of independent models.
  
  All BoTorch models are acceptable as inputs. The cost of this flexibility is
  that `ModelList` does not support all methods that may be implemented by its
  component models. One use case for `ModelList` is combining a regression
  model and a deterministic model in one multi-output container model, e.g.
  for cost-aware or multi-objective optimization where one of the outcomes is
  a deterministic function of the inputs.
class_docstr_tok: ["A","multi-output","Model","represented","by","a","list","of","independent","models",".","All","BoTorch","models","are","acceptable","as","inputs",".","The","cost","of","this","flexibility","is","that","`","ModelList","`","does","not","support","all","methods","that","may","be","implemented","by","its","component","models",".","One","use","case","for","`","ModelList","`","is","combining","a","regression","model","and","a","deterministic","model","in","one","multi-output","container","model",",","e.g",".","for","cost-aware","or","multi-objective","optimization","where","one","of","the","outcomes","is","a","deterministic","function","of","the","inputs","."]
docstr: Computes the posterior over model outputs at the provided points.
  
  Note: The input transforms should be applied here using
      `self.transform_inputs(X)` after the `self.eval()` call and before
      any `model.forward` or `model.likelihood` calls.
  
  Args:
      X: A `b x q x d`-dim Tensor, where `d` is the dimension of the
          feature space, `q` is the number of points considered jointly,
          and `b` is the batch dimension.
      output_indices: A list of indices, corresponding to the outputs over
          which to compute the posterior (if the model is multi-output).
          Can be used to speed up computation if only a subset of the
          model's outputs are required for optimization. If omitted,
          computes the posterior over all model outputs.
      observation_noise: If True, add the observation noise from the
          respective likelihoods to the posterior. If a Tensor of shape
          `(batch_shape) x q x m`, use it directly as the observation
          noise (with `observation_noise[...,i]` added to the posterior
          of the `i`-th model). `observation_noise` is assumed
          to be in the outcome-transformed space, if an outcome transform
          is used by the model.
      posterior_transform: An optional PosteriorTransform.
  
  Returns:
      A `Posterior` object, representing a batch of `b` joint distributions
      over `q` points and `m` outputs each.
code: def posterior(
      self,
      X: Tensor,
      output_indices: Optional[List[int]] = None,
      observation_noise: Union[bool, Tensor] = False,
      posterior_transform: Optional[
          Callable[[PosteriorList], Posterior]
      ] = None,
      **kwargs: Any,
  ) -> Posterior:
      r"""Computes the posterior over model outputs at the provided points.
  
      Note: The input transforms should be applied here using
          `self.transform_inputs(X)` after the `self.eval()` call and before
          any `model.forward` or `model.likelihood` calls.
  
      Args:
          X: A `b x q x d`-dim Tensor, where `d` is the dimension of the
              feature space, `q` is the number of points considered jointly,
              and `b` is the batch dimension.
          output_indices: A list of indices, corresponding to the outputs over
              which to compute the posterior (if the model is multi-output).
              Can be used to speed up computation if only a subset of the
              model's outputs are required for optimization. If omitted,
              computes the posterior over all model outputs.
          observation_noise: If True, add the observation noise from the
              respective likelihoods to the posterior. If a Tensor of shape
              `(batch_shape) x q x m`, use it directly as the observation
              noise (with `observation_noise[...,i]` added to the posterior
              of the `i`-th model). `observation_noise` is assumed
              to be in the outcome-transformed space, if an outcome transform
              is used by the model.
          posterior_transform: An optional PosteriorTransform.
  
      Returns:
          A `Posterior` object, representing a batch of `b` joint distributions
          over `q` points and `m` outputs each.
      """
      group_indices = self._get_group_subset_indices(
          idcs=output_indices
      )
      posteriors = []
      for i, idcs in group_indices.items():
          if isinstance(observation_noise, Tensor):
              if idcs is None:
                  start_idx = sum(
                      m.num_outputs for m in self.models[:i]
                  )
                  end_idx = start_idx + self.models[i].num_outputs
                  idcs = list(range(start_idx, end_idx))
              obs_noise = observation_noise[..., idcs]
          else:
              obs_noise = observation_noise
          posteriors.append(
              self.models[i].posterior(
                  X=X, output_indices=idcs, observation_noise=obs_noise
              )
          )
      posterior = PosteriorList(*posteriors)
      if posterior_transform is not None:
          posterior = posterior_transform(posterior)
      return posterior
  
imports: from __future__ import annotations
  import warnings
  from abc import ABC, abstractmethod
  from collections import defaultdict
  from copy import deepcopy
  from typing import Any, Callable, Dict, List, Mapping, Optional, Set, TYPE_CHECKING, TypeVar, Union
  import numpy
  import torch
  from botorch import settings
  from botorch.exceptions.errors import BotorchTensorDimensionError, DeprecationError, InputDataError
  from botorch.logging import shape_to_str
  from botorch.models.utils.assorted import fantasize
  from botorch.posteriors import Posterior, PosteriorList
  from botorch.sampling.base import MCSampler
  from botorch.sampling.list_sampler import ListSampler
  from botorch.utils.datasets import SupervisedDataset
  from botorch.utils.transforms import is_fully_bayesian
  from gpytorch.likelihoods.gaussian_likelihood import FixedNoiseGaussianLikelihood
  from torch import Tensor
  from torch.nn import Module, ModuleDict, ModuleList
label_desc: Use image node_id 3 for calling the ModelList obj's underlying member method code with example usage: obj.posterior(X, output_indices, observation_noise, posterior_transform) and returns: posterior