class_docstr: Abstract base class for models based on GPyTorch models.
  
  The easiest way to use this is to subclass a model from a GPyTorch model
  class (e.g. an `ExactGP`) and this `GPyTorchModel`. See e.g. `SingleTaskGP`.
  
  :meta private:
class_docstr_tok: ["Abstract","base","class","for","models","based","on","GPyTorch","models",".","The","easiest","way","to","use","this","is","to","subclass","a","model","from","a","GPyTorch","model","class","(","e.g",".","an","`","ExactGP","`",")","and","this","`","GPyTorchModel","`",".","See","e.g",".","`","SingleTaskGP","`",".",":","meta","private",":"]
docstr: Checks that `Y` and `Yvar` have an explicit output dimension if strict.
  Checks that the dtypes of the inputs match, and warns if using float.
  
  This also checks that `Yvar` has the same trailing dimensions as `Y`. Note
  we only infer that an explicit output dimension exists when `X` and `Y` have
  the same `batch_shape`.
  
  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 (potentially empty).
      Y: A `batch_shape' x n x m`-dim Tensor, where `m` is the number of
          model outputs, `n'` is the number of points per batch, and
          `batch_shape'` is the batch shape of the observations.
      Yvar: A `batch_shape' x n x m` tensor of observed measurement noise.
          Note: this will be None when using a model that infers the noise
          level (e.g. a `SingleTaskGP`).
      strict: A boolean indicating whether to check that `Y` and `Yvar`
          have an explicit output dimension.
docstr_tok: ["Checks","that","`","Y","`","and","`","Yvar","`","have","an","explicit","output","dimension","if","strict",".","Checks","that","the","dtypes","of","the","inputs","match",",","and","warns","if","using","float",".","This","also","checks","that","`","Yvar","`","has","the","same","trailing","dimensions","as","`","Y","`",".","Note","we","only","infer","that","an","explicit","output","dimension","exists","when","`","X","`","and","`","Y","`","have","the","same","`","batch_shape","`",".","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","(","potentially","empty",")",".","Y",":","A","`","batch_shape","'","x","n","x","m","`","-dim","Tensor",",","where","`","m","`","is","the","number","of","model","outputs",",","`","n","'","`","is","the","number","of","points","per","batch",",","and","`","batch_shape","'","`","is","the","batch","shape","of","the","observations",".","Yvar",":","A","`","batch_shape","'","x","n","x","m","`","tensor","of","observed","measurement","noise",".","Note",":","this","will","be","None","when","using","a","model","that","infers","the","noise","level","(","e.g",".","a","`","SingleTaskGP","`",")",".","strict",":","A","boolean","indicating","whether","to","check","that","`","Y","`","and","`","Yvar","`","have","an","explicit","output","dimension","."]
code: def _validate_tensor_args(
      X: Tensor,
      Y: Tensor,
      Yvar: Optional[Tensor] = None,
      strict: bool = True,
  ) -> None:
      r"""Checks that `Y` and `Yvar` have an explicit output dimension if strict.
      Checks that the dtypes of the inputs match, and warns if using float.
  
      This also checks that `Yvar` has the same trailing dimensions as `Y`. Note
      we only infer that an explicit output dimension exists when `X` and `Y` have
      the same `batch_shape`.
  
      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 (potentially empty).
          Y: A `batch_shape' x n x m`-dim Tensor, where `m` is the number of
              model outputs, `n'` is the number of points per batch, and
              `batch_shape'` is the batch shape of the observations.
          Yvar: A `batch_shape' x n x m` tensor of observed measurement noise.
              Note: this will be None when using a model that infers the noise
              level (e.g. a `SingleTaskGP`).
          strict: A boolean indicating whether to check that `Y` and `Yvar`
              have an explicit output dimension.
      """
      if X.dim() != Y.dim():
          if (X.dim() - Y.dim() == 1) and (X.shape[:-1] == Y.shape):
              message = (
                  "An explicit output dimension is required for targets."
                  f" Expected Y with dimension {X.dim()} (got {Y.dim()=})."
              )
          else:
              message = (
                  "Expected X and Y to have the same number of dimensions"
                  f" (got X with dimension {X.dim()} and Y with dimension"
                  f" {Y.dim()})."
              )
          if strict:
              raise BotorchTensorDimensionError(message)
          else:
              warnings.warn(
                  "Non-strict enforcement of botorch tensor conventions. The "
                  "following error would have been raised with strict enforcement: "
                  f"{message}",
                  BotorchTensorDimensionWarning,
                  stacklevel=2,
              )
      # Yvar may not have the same batch dimensions, but the trailing dimensions
      # of Yvar should be the same as the trailing dimensions of Y.
      if Yvar is not None and Y.shape[-(Yvar.dim()) :] != Yvar.shape:
          raise BotorchTensorDimensionError(
              "An explicit output dimension is required for observation noise."
              f" Expected Yvar with shape: {Y.shape[-Yvar.dim() :]} (got"
              f" {Yvar.shape})."
          )
      # Check the dtypes.
      if X.dtype != Y.dtype or (
          Yvar is not None and Y.dtype != Yvar.dtype
      ):
          raise InputDataError(
              "Expected all inputs to share the same dtype. Got "
              f"{X.dtype} for X, {Y.dtype} for Y, and "
              f"{Yvar.dtype if Yvar is not None else None} for Yvar."
          )
      if X.dtype != torch.float64:
          # NOTE: Not using a BotorchWarning since those get ignored.
          warnings.warn(
              _get_single_precision_warning(str(X.dtype)),
              UserWarning,
              stacklevel=2,
          )
  
imports: from __future__ import annotations
  import itertools
  import warnings
  from abc import ABC
  from copy import deepcopy
  from typing import Any, List, Optional, Tuple, TYPE_CHECKING, Union
  import torch
  from botorch.acquisition.objective import PosteriorTransform
  from botorch.exceptions.errors import BotorchTensorDimensionError, InputDataError
  from botorch.exceptions.warnings import _get_single_precision_warning, BotorchTensorDimensionWarning
  from botorch.models.model import Model, ModelList
  from botorch.models.utils import _make_X_full, add_output_dim, gpt_posterior_settings, mod_batch_shape, multioutput_to_batch_mode_transform
  from botorch.posteriors.fully_bayesian import GaussianMixturePosterior
  from botorch.posteriors.gpytorch import GPyTorchPosterior
  from botorch.utils.multitask import separate_mtmvn
  from botorch.utils.transforms import is_ensemble
  from gpytorch.distributions import MultitaskMultivariateNormal, MultivariateNormal
  from gpytorch.likelihoods.gaussian_likelihood import FixedNoiseGaussianLikelihood
  from linear_operator.operators import BlockDiagLinearOperator, CatLinearOperator
  from torch import Tensor
label_desc: Use image node_id 1 for calling the GPyTorchModel obj's underlying member method code with example usage: obj._validate_tensor_args(X, Y, Yvar, strict) without return types