code: def test_SACGP(self):
      for dtype, infer_noise in (
          (torch.float, False),
          (torch.double, True),
      ):
          tkwargs = {"device": self.device, "dtype": dtype}
          datasets, (train_X, train_Y, train_Yvar) = _gen_datasets(
              infer_noise, **tkwargs
          )
          self.decomposition = {"1": [0, 3], "2": [1, 2]}
  
          model = SACGP(
              train_X, train_Y, train_Yvar, self.decomposition
          )
          mll = ExactMarginalLogLikelihood(model.likelihood, model)
          fit_gpytorch_mll(
              mll, optimizer_kwargs={"options": {"maxiter": 1}}
          )
  
          self.assertIsInstance(model, SingleTaskGP)
          self.assertIsInstance(
              model.likelihood,
              GaussianLikelihood
              if infer_noise
              else FixedNoiseGaussianLikelihood,
          )
          self.assertDictEqual(model.decomposition, self.decomposition)
          self.assertIsInstance(model.mean_module, ConstantMean)
          self.assertIsInstance(model.covar_module, SACKernel)
  
          # test number of named parameters
          num_of_mean = 0
          num_of_lengthscales = 0
          num_of_outputscales = 0
          for param_name, param in model.named_parameters():
              if param_name == "mean_module.raw_constant":
                  num_of_mean += param.data.shape.numel()
              elif "raw_lengthscale" in param_name:
                  num_of_lengthscales += param.data.shape.numel()
              elif "raw_outputscale" in param_name:
                  num_of_outputscales += param.data.shape.numel()
          self.assertEqual(num_of_mean, 1)
          self.assertEqual(num_of_lengthscales, 2)
          self.assertEqual(num_of_outputscales, 2)
  
          test_x = torch.rand(5, 4, device=self.device, dtype=dtype)
          posterior = model(test_x)
          self.assertIsInstance(posterior, MultivariateNormal)
  
imports: from typing import Dict, Tuple
  import torch
  from botorch.fit import fit_gpytorch_mll
  from botorch.models.contextual import LCEAGP, SACGP
  from botorch.models.gp_regression import SingleTaskGP
  from botorch.models.kernels.contextual_lcea import LCEAKernel
  from botorch.models.kernels.contextual_sac import SACKernel
  from botorch.utils.datasets import SupervisedDataset
  from botorch.utils.testing import BotorchTestCase
  from gpytorch.distributions.multivariate_normal import MultivariateNormal
  from gpytorch.likelihoods.gaussian_likelihood import FixedNoiseGaussianLikelihood, GaussianLikelihood
  from gpytorch.means import ConstantMean
  from gpytorch.mlls.exact_marginal_log_likelihood import ExactMarginalLogLikelihood
  from torch import Tensor
label_desc: Use image node_id 1 for calling the TestContextualGP obj's underlying member method code with example usage: obj.test_SACGP() without return types