class_docstr: The structural additive contextual(SAC) kernel.
  
  The kernel is used for contextual BO without oberseving context breakdowns.
  There are d parameters and M contexts. In total, the dimension of parameter space
  is d*M and input x can be written as
  x=[x_11, ..., x_1d, x_21, ..., x_2d, ...,  x_M1, ..., x_Md].
  
  The kernel uses the parameter decomposition and assumes an additive structure
  across contexts. Each context compponent is assumed to be independent.
  
  .. math::
     \begin{equation*}
        k(\mathbf{x}, \mathbf{x'}) = k_1(\mathbf{x_(1)}, \mathbf{x'_(1)}) + \cdots
        + k_M(\mathbf{x_(M)}, \mathbf{x'_(M)})
     \end{equation*}
  
  where
  * :math: M is the number of partitions of parameter space. Each partition contains
  same number of parameters d. Each kernel `k_i` acts only on d parameters of ith
  partition i.e. `\mathbf{x}_(i)`. Each kernel `k_i` is a scaled Matern kernel
  with same lengthscales but different outputscales.
docstr: iterate across each partition of parameter space and sum the
  covariance matrices together
docstr_tok: ["iterate","across","each","partition","of","parameter","space","and","sum","the","covariance","matrices","together"]
code: def forward(
      self,
      x1: Tensor,
      x2: Tensor,
      diag: bool = False,
      last_dim_is_batch: bool = False,
      **params: Any,
  ) -> Tensor:
      """
      iterate across each partition of parameter space and sum the
      covariance matrices together
      """
      # same lengthscale for all the components
      covars = [
          self.kernel_dict[context](
              x1=x1.index_select(
                  dim=-1, index=active_params
              ),  # pyre-ignore
              x2=x2.index_select(dim=-1, index=active_params),
              diag=diag,
          )
          for context, active_params in self._indexers.items()
      ]
  
      if diag:
          res = sum(covars)
      else:
          res = SumLinearOperator(*covars)
      return res
  
file_path: botorch/botorch/models/kernels/contextual_sac.py
imports: from typing import Any, Dict, List, Optional
  import torch
  from gpytorch.kernels.kernel import Kernel
  from gpytorch.kernels.matern_kernel import MaternKernel
  from gpytorch.kernels.scale_kernel import ScaleKernel
  from gpytorch.priors.torch_priors import GammaPrior
  from linear_operator.operators.sum_linear_operator import SumLinearOperator
  from torch import Tensor
  from torch.nn import ModuleDict
label_desc: Use image node_id 3 for calling the SACKernel obj's underlying member method code with example usage: obj.forward(x1, x2, diag, last_dim_is_batch) and returns: res