code: def test_expectation_posterior_transform(self):
      tkwargs = {"dtype": torch.float, "device": self.device}
      # Without weights, simple expectation, single output, no batch.
      # q = 2, n_w = 3.
      org_loc = torch.tensor([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], **tkwargs)
      org_covar = torch.tensor(
          [
              [1.0, 0.8, 0.7, 0.3, 0.2, 0.1],
              [0.8, 1.0, 0.9, 0.25, 0.15, 0.1],
              [0.7, 0.9, 1.0, 0.2, 0.2, 0.05],
              [0.3, 0.25, 0.2, 1.0, 0.7, 0.6],
              [0.2, 0.15, 0.2, 0.7, 1.0, 0.7],
              [0.1, 0.1, 0.05, 0.6, 0.7, 1.0],
          ],
          **tkwargs,
      )
      org_mvn = MultivariateNormal(
          org_loc, to_linear_operator(org_covar)
      )
      org_post = GPyTorchPosterior(distribution=org_mvn)
      tf = ExpectationPosteriorTransform(n_w=3)
      tf_post = tf(org_post)
      self.assertIsInstance(tf_post, GPyTorchPosterior)
      self.assertEqual(tf_post.sample().shape, torch.Size([1, 2, 1]))
      tf_mvn = tf_post.distribution
      self.assertIsInstance(tf_mvn, MultivariateNormal)
      expected_loc = torch.tensor([2.0, 5.0], **tkwargs)
      # This is the average of each 3 x 3 block.
      expected_covar = torch.tensor(
          [[0.8667, 0.1722], [0.1722, 0.7778]], **tkwargs
      )
      self.assertAllClose(tf_mvn.loc, expected_loc)
      self.assertAllClose(
          tf_mvn.covariance_matrix, expected_covar, atol=1e-3
      )
  
      # With weights, 2 outputs, batched.
      tkwargs = {"dtype": torch.double, "device": self.device}
      # q = 2, n_w = 2, m = 2, leading to 8 values for loc and 8x8 cov.
      org_loc = torch.tensor(
          [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0], **tkwargs
      )
      # We have 2 4x4 matrices with 0s as filler. Each block is for one outcome.
      # Each 2x2 sub block corresponds to `n_w`.
      org_covar = torch.tensor(
          [
              [1.0, 0.8, 0.3, 0.2, 0.0, 0.0, 0.0, 0.0],
              [0.8, 1.4, 0.2, 0.1, 0.0, 0.0, 0.0, 0.0],
              [0.3, 0.2, 1.2, 0.5, 0.0, 0.0, 0.0, 0.0],
              [0.2, 0.1, 0.5, 1.0, 0.0, 0.0, 0.0, 0.0],
              [0.0, 0.0, 0.0, 0.0, 1.0, 0.7, 0.4, 0.3],
              [0.0, 0.0, 0.0, 0.0, 0.7, 0.8, 0.3, 0.2],
              [0.0, 0.0, 0.0, 0.0, 0.4, 0.3, 1.4, 0.5],
              [0.0, 0.0, 0.0, 0.0, 0.3, 0.2, 0.5, 1.2],
          ],
          **tkwargs,
      )
      # Making it batched by adding two more batches, mostly the same.
      org_loc = org_loc.repeat(3, 1)
      org_loc[1] += 100
      org_loc[2] += 1000
      org_covar = org_covar.repeat(3, 1, 1)
      # Construct the transform with weights.
      weights = torch.tensor([[1.0, 3.0], [2.0, 1.0]])
      tf = ExpectationPosteriorTransform(n_w=2, weights=weights)
      # Construct the posterior.
      org_mvn = MultitaskMultivariateNormal(
          # The return of mvn.loc and the required input are different.
          # We constructed it according to the output of mvn.loc,
          # reshaping here to have the required `b x n x t` shape.
          org_loc.view(3, 2, 4).transpose(-2, -1),
          to_linear_operator(org_covar),
          interleaved=True,  # To test the error.
      )
      org_post = GPyTorchPosterior(distribution=org_mvn)
      # Error if interleaved.
      with self.assertRaisesRegex(UnsupportedError, "interleaved"):
          tf(org_post)
      # Construct the non-interleaved posterior.
      org_mvn = MultitaskMultivariateNormal(
          org_loc.view(3, 2, 4).transpose(-2, -1),
          to_linear_operator(org_covar),
          interleaved=False,
      )
      org_post = GPyTorchPosterior(distribution=org_mvn)
      self.assertTrue(torch.equal(org_mvn.loc, org_loc))
      tf_post = tf(org_post)
      self.assertIsInstance(tf_post, GPyTorchPosterior)
      self.assertEqual(tf_post.sample().shape, torch.Size([1, 3, 2, 2]))
      tf_mvn = tf_post.distribution
      self.assertIsInstance(tf_mvn, MultitaskMultivariateNormal)
      expected_loc = torch.tensor(
          [[1.6667, 3.6667, 5.25, 7.25]], **tkwargs
      ).repeat(3, 1)
      expected_loc[1] += 100
      expected_loc[2] += 1000
      # This is the weighted average of each 2 x 2 block.
      expected_covar = torch.tensor(
          [
              [1.0889, 0.1667, 0.0, 0.0],
              [0.1667, 0.8, 0.0, 0.0],
              [0.0, 0.0, 0.875, 0.35],
              [0.0, 0.0, 0.35, 1.05],
          ],
          **tkwargs,
      ).repeat(3, 1, 1)
      self.assertAllClose(tf_mvn.loc, expected_loc, atol=1e-3)
      self.assertAllClose(
          tf_mvn.covariance_matrix, expected_covar, atol=1e-3
      )
  
imports: import itertools
  import warnings
  from typing import Optional
  import torch
  from botorch import settings
  from botorch.acquisition import LearnedObjective
  from botorch.acquisition.objective import ConstrainedMCObjective, DEFAULT_NUM_PREF_SAMPLES, ExpectationPosteriorTransform, GenericMCObjective, IdentityMCObjective, LEARNED_OBJECTIVE_PREF_MODEL_MIXED_DTYPE_WARN, LinearMCObjective, MCAcquisitionObjective, PosteriorTransform, ScalarizedPosteriorTransform
  from botorch.exceptions.errors import UnsupportedError
  from botorch.exceptions.warnings import _get_single_precision_warning, InputDataWarning
  from botorch.models.deterministic import PosteriorMeanModel
  from botorch.models.pairwise_gp import PairwiseGP
  from botorch.models.transforms.input import Normalize
  from botorch.posteriors import GPyTorchPosterior
  from botorch.utils import apply_constraints
  from botorch.utils.testing import _get_test_posterior, BotorchTestCase
  from gpytorch.distributions import MultitaskMultivariateNormal, MultivariateNormal
  from linear_operator.operators.dense_linear_operator import to_linear_operator
  from torch import Tensor
label_desc: Use image node_id 3 for calling the TestExpectationPosteriorTransform obj's underlying member method code with example usage: obj.test_expectation_posterior_transform() without return types