code: def scalarize_posterior_gpytorch(
      posterior: GPyTorchPosterior,
      weights: Tensor,
      offset: float = 0.0,
  ) -> Tuple[Tensor, Union[Tensor, LinearOperator]]:
      r"""Helper function for `scalarize_posterior`, producing a mean and
      variance.
  
      This mean and variance are consumed by `scalarize_posterior` to produce
      a `GPyTorchPosterior`.
  
      Args:
          posterior: The posterior over `m` outcomes to be scalarized.
              Supports `t`-batching.
          weights: A tensor of weights of size `m`.
          offset: The offset of the affine transformation.
  
      Returns:
          The transformed (single-output) posterior. If the input posterior has
              mean `mu` and covariance matrix `Sigma`, this posterior has mean
              `weights^T * mu` and variance `weights^T Sigma w`.
  
      Example:
          Example for a model with two outcomes:
  
          >>> X = torch.rand(1, 2)
          >>> posterior = model.posterior(X)
          >>> weights = torch.tensor([0.5, 0.25])
          >>> mean, cov = scalarize_posterior_gpytorch(posterior, weights=weights)
          >>> mvn = MultivariateNormal(mean, cov)
          >>> new_posterior = GPyTorchPosterior
      """
      mean = posterior.mean
      q, m = mean.shape[-2:]
      _validate_scalarize_inputs(weights, m)
      batch_shape = mean.shape[:-2]
      mvn = posterior.distribution
      cov = (
          mvn.lazy_covariance_matrix
          if mvn.islazy
          else mvn.covariance_matrix
      )
  
      if m == 1:  # just scaling, no scalarization necessary
          new_mean = offset + (weights[0] * mean).view(*batch_shape, q)
          new_cov = weights[0] ** 2 * cov
          return new_mean, new_cov
  
      new_mean = offset + (mean @ weights).view(*batch_shape, q)
  
      if q == 1:
          new_cov = weights.unsqueeze(-2) @ (
              cov @ weights.unsqueeze(-1)
          )
      else:
          # we need to handle potentially different representations of the multi-task mvn
          if mvn._interleaved:
              w_cov = weights.repeat(q).unsqueeze(0)
              sum_shape = batch_shape + torch.Size([q, m, q, m])
              sum_dims = (-1, -2)
          else:
              # special-case the independent setting
              if isinstance(cov, BlockDiagLinearOperator):
                  new_cov = SumLinearOperator(
                      *[
                          cov.base_linear_op[..., i, :, :]
                          * weights[i].pow(2)
                          for i in range(cov.base_linear_op.size(-3))
                      ]
                  )
                  return new_mean, new_cov
  
              w_cov = torch.repeat_interleave(weights, q).unsqueeze(0)
              sum_shape = batch_shape + torch.Size([m, q, m, q])
              sum_dims = (-2, -3)
  
          cov_scaled = w_cov * cov * w_cov.transpose(-1, -2)
          # TODO: Do not instantiate full covariance for LinearOperators
          # (ideally we simplify this in GPyTorch:
          # https://github.com/cornellius-gp/gpytorch/issues/1055)
          if isinstance(cov_scaled, LinearOperator):
              cov_scaled = cov_scaled.to_dense()
          new_cov = (
              cov_scaled.view(sum_shape)
              .sum(dim=sum_dims[0])
              .sum(dim=sum_dims[1])
          )
          new_cov = DenseLinearOperator(new_cov)
  
      return new_mean, new_cov
  
imports: from __future__ import annotations
  import warnings
  from contextlib import ExitStack
  from typing import Optional, Tuple, TYPE_CHECKING, Union
  import torch
  from botorch.exceptions.errors import BotorchTensorDimensionError
  from botorch.posteriors.base_samples import _reshape_base_samples_non_interleaved
  from botorch.posteriors.torch import TorchPosterior
  from gpytorch.distributions import MultitaskMultivariateNormal, MultivariateNormal
  from linear_operator import settings
  from linear_operator.operators import BlockDiagLinearOperator, DenseLinearOperator, LinearOperator, SumLinearOperator
  from torch import Tensor
  from torch.distributions import Normal
label_desc: Use image node_id 2 for calling a global function with example usage: scalarize_posterior_gpytorch(posterior, weights, offset) and returns: new_mean,  new_cov, new_mean,  new_cov, new_mean,  new_cov