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: Construct a fantasy model.
  
  Constructs a fantasy model in the following fashion:
  (1) compute the model posterior at `X` (including observation noise if
  `observation_noise=True`).
  (2) sample from this posterior (using `sampler`) to generate "fake"
  observations.
  (3) condition the model on the new fake observations.
  
  Args:
      X: A `batch_shape x n' x d`-dim Tensor, where `d` is the dimension of
          the feature space, `n'` is the number of points per batch, and
          `batch_shape` is the batch shape (must be compatible with the
          batch shape of the model).
      sampler: The sampler used for sampling from the posterior at `X`. If
          evaluation_mask is not None, this must be a `ListSampler`.
      observation_noise: A `model_batch_shape x 1 x m`-dim tensor or
          a `model_batch_shape x n' x m`-dim tensor containing the average
          noise for each batch and output, where `m` is the number of outputs.
          `noise` must be in the outcome-transformed space if an outcome
          transform is used. If None, then the noise will be the inferred
          noise level.
      evaluation_mask: A `n' x m`-dim tensor of booleans indicating which
          outputs should be fantasized for a given design. This uses the same
          evaluation mask for all batches.
  
  Returns:
      The constructed fantasy model.
code: def fantasize(
      self,
      X: Tensor,
      sampler: MCSampler,
      observation_noise: Optional[Tensor] = None,
      evaluation_mask: Optional[Tensor] = None,
      **kwargs: Any,
  ) -> Model:
      r"""Construct a fantasy model.
  
      Constructs a fantasy model in the following fashion:
      (1) compute the model posterior at `X` (including observation noise if
      `observation_noise=True`).
      (2) sample from this posterior (using `sampler`) to generate "fake"
      observations.
      (3) condition the model on the new fake observations.
  
      Args:
          X: A `batch_shape x n' x d`-dim Tensor, where `d` is the dimension of
              the feature space, `n'` is the number of points per batch, and
              `batch_shape` is the batch shape (must be compatible with the
              batch shape of the model).
          sampler: The sampler used for sampling from the posterior at `X`. If
              evaluation_mask is not None, this must be a `ListSampler`.
          observation_noise: A `model_batch_shape x 1 x m`-dim tensor or
              a `model_batch_shape x n' x m`-dim tensor containing the average
              noise for each batch and output, where `m` is the number of outputs.
              `noise` must be in the outcome-transformed space if an outcome
              transform is used. If None, then the noise will be the inferred
              noise level.
          evaluation_mask: A `n' x m`-dim tensor of booleans indicating which
              outputs should be fantasized for a given design. This uses the same
              evaluation mask for all batches.
  
      Returns:
          The constructed fantasy model.
      """
      if evaluation_mask is not None:
          if (
              evaluation_mask.ndim != 2
              or evaluation_mask.shape
              != torch.Size([X.shape[-2], self.num_outputs])
          ):
              raise BotorchTensorDimensionError(
                  f"Expected evaluation_mask of shape `{X.shape[0]} "
                  f"x {self.num_outputs}`, but got "
                  f"{shape_to_str(evaluation_mask.shape)}."
              )
          if not isinstance(sampler, ListSampler):
              raise ValueError(
                  "Decoupled fantasization requires a list of samplers."
              )
  
      fant_models = []
      X_i = X
      if observation_noise is None:
          observation_noise_i = observation_noise
      for i in range(self.num_outputs):
          # get the inputs to fantasize at for output i
          if evaluation_mask is not None:
              mask_i = evaluation_mask[:, i]
              X_i = X[..., mask_i, :]
              # TODO (T158701749): implement a QMC DecoupledSampler that draws all
              # samples from a single Sobol sequence or consider requiring that the
              # sampling is IID to ensure good coverage.
              sampler_i = sampler.samplers[i]
              if observation_noise is not None:
                  observation_noise_i = observation_noise[
                      ..., mask_i, i : i + 1
                  ]
          else:
              sampler_i = (
                  sampler.samplers[i]
                  if isinstance(sampler, ListSampler)
                  else sampler
              )
  
          fant_model = self.models[i].fantasize(
              X=X_i,
              sampler=sampler_i,
              observation_noise=observation_noise_i,
              **kwargs,
          )
          fant_models.append(fant_model)
      return self.__class__(*fant_models)
  
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 9 for calling the ModelList obj's underlying member method code with example usage: obj.fantasize(X, sampler, observation_noise, evaluation_mask) and returns: self