class_docstr: This is a multi-task dataset that is constructed from the datasets of
  individual tasks. It offers functionality to combine parts of individual
  datasets to construct the inputs necessary for the `MultiTaskGP` models.
  
  The datasets of individual tasks are allowed to represent different sets
  of features. When there are heterogeneous feature sets, calling
  `MultiTaskDataset.X` will result in an error.
docstr: Validates that:
  * Each dataset models only one outcome;
  * Each outcome is modeled by only one dataset;
  * The target outcome is included in the datasets;
  * The datasets do not model batched inputs;
  * The task feature names of the datasets all match;
  * Either all or none of the datasets specify Yvar.
code: def _validate_datasets(
      self, datasets: List[SupervisedDataset]
  ) -> None:
      """Validates that:
      * Each dataset models only one outcome;
      * Each outcome is modeled by only one dataset;
      * The target outcome is included in the datasets;
      * The datasets do not model batched inputs;
      * The task feature names of the datasets all match;
      * Either all or none of the datasets specify Yvar.
      """
      if any(len(ds.outcome_names) > 1 for ds in datasets):
          raise UnsupportedError(
              "Datasets containing more than one outcome are not supported."
          )
      if len(self.datasets) != len(datasets):
          raise UnsupportedError(
              "Received multiple datasets for the same outcome. Each dataset "
              "must contain data for a unique outcome. Got datasets with "
              f"outcome names: {(ds.outcome_names for ds in datasets)}."
          )
      if self.target_outcome_name not in self.datasets:
          raise InputDataError(
              "Target outcome is not present in the datasets. "
              f"Got {self.target_outcome_name=} and datasets for "
              f"outcomes {list(self.datasets.keys())}."
          )
      if any(len(ds.X.shape) > 2 for ds in datasets):
          raise UnsupportedError(
              "Datasets modeling batched inputs are not supported."
          )
      if self.task_feature_index is not None:
          tf_names = [
              ds.feature_names[self.task_feature_index]
              for ds in datasets
          ]
          if any(name != tf_names[0] for name in tf_names[1:]):
              raise InputDataError(
                  "Expected the names of the task features to match across all "
                  f"datasets. Got {tf_names}."
              )
      all_Yvars = [ds.Yvar for ds in datasets]
      is_none = [yvar is None for yvar in all_Yvars]
      # Check that either all or None of the Yvars exist.
      if not all(is_none) and any(is_none):
          raise UnsupportedError(
              "Expected either all or none of the datasets to have a Yvar. "
              "Only subset of datasets define Yvar, which is unsupported."
          )
  
imports: from __future__ import annotations
  import collections
  import warnings
  from typing import Any, Dict, List, Optional, Union
  import torch
  from botorch.exceptions.errors import InputDataError, UnsupportedError
  from botorch.utils.containers import BotorchContainer, SliceContainer
  from torch import long, ones, Tensor
label_desc: Use image node_id 3 for calling the MultiTaskDataset obj's underlying member method code with example usage: obj._validate_datasets(datasets) without return types