code: def test_degenerate_GPyTorchPosterior(self):
      for dtype, multi_task in (
          (torch.float, False),
          (torch.double, False),
          (torch.double, True),
      ):
          # singular covariance matrix
          degenerate_covar = torch.tensor(
              [[1, 1, 0], [1, 1, 0], [0, 0, 2]],
              dtype=dtype,
              device=self.device,
          )
          mean = torch.rand(3, dtype=dtype, device=self.device)
          mvn = MultivariateNormal(
              mean, to_linear_operator(degenerate_covar)
          )
          mean_exp = mean.unsqueeze(-1)
          variance_exp = degenerate_covar.diag().unsqueeze(-1)
          if multi_task:
              expected_dim = 2
              mvn = MultitaskMultivariateNormal.from_independent_mvns(
                  [mvn, mvn]
              )
              mean_exp = mean_exp.repeat(1, 2)
              variance_exp = variance_exp.repeat(1, 2)
              base_samples = torch.randn(
                  4, 3, 2, device=self.device, dtype=dtype
              )
              base_samples2 = torch.randn(
                  4, 2, 3, 2, device=self.device, dtype=dtype
              )
          else:
              expected_dim = 1
              base_samples = torch.randn(
                  4, 3, device=self.device, dtype=dtype
              )
              base_samples2 = torch.randn(
                  4, 2, 3, device=self.device, dtype=dtype
              )
          posterior = GPyTorchPosterior(distribution=mvn)
          # basics
          self.assertEqual(posterior.device.type, self.device.type)
          self.assertTrue(posterior.dtype == dtype)
          self.assertEqual(
              posterior._extended_shape(), torch.Size([3, expected_dim])
          )
          self.assertTrue(torch.equal(posterior.mean, mean_exp))
          self.assertTrue(torch.equal(posterior.variance, variance_exp))
  
          # rsample
          with warnings.catch_warnings(record=True) as ws:
              # we check that the p.d. warning is emitted - this only
              # happens once per posterior, so we need to check only once
              samples = posterior.rsample(sample_shape=torch.Size([4]))
              self.assertTrue(
                  any(
                      issubclass(w.category, RuntimeWarning) for w in ws
                  )
              )
              self.assertTrue(
                  any("not p.d" in str(w.message) for w in ws)
              )
          self.assertEqual(
              samples.shape, torch.Size([4, 3, expected_dim])
          )
          samples2 = posterior.rsample(sample_shape=torch.Size([4, 2]))
          self.assertEqual(
              samples2.shape, torch.Size([4, 2, 3, expected_dim])
          )
          # rsample w/ base samples
          samples_b1 = posterior.rsample_from_base_samples(
              sample_shape=torch.Size([4]), base_samples=base_samples
          )
          samples_b2 = posterior.rsample_from_base_samples(
              sample_shape=torch.Size([4]), base_samples=base_samples
          )
          self.assertAllClose(samples_b1, samples_b2)
          samples2_b1 = posterior.rsample_from_base_samples(
              sample_shape=torch.Size([4, 2]),
              base_samples=base_samples2,
          )
          samples2_b2 = posterior.rsample_from_base_samples(
              sample_shape=torch.Size([4, 2]),
              base_samples=base_samples2,
          )
          self.assertAllClose(samples2_b1, samples2_b2)
  
file_path: botorch/test/posteriors/test_gpytorch.py
imports: import itertools
  import warnings
  from contextlib import ExitStack
  from unittest import mock
  import torch
  from botorch.exceptions import BotorchTensorDimensionError
  from botorch.posteriors.gpytorch import GPyTorchPosterior, scalarize_posterior
  from botorch.utils.testing import _get_test_posterior, BotorchTestCase, MockPosterior
  from gpytorch import settings
  from gpytorch.distributions import MultitaskMultivariateNormal, MultivariateNormal
  from linear_operator.operators import to_linear_operator
  from torch.distributions.normal import Normal
label_desc: Use image node_id 3 for calling the TestGPyTorchPosterior obj's underlying member method code with example usage: obj.test_degenerate_GPyTorchPosterior() without return types