class_docstr: GPyTorch Linear Truncated Fidelity Kernel.
  
  Computes a covariance matrix based on the Linear truncated kernel between
  inputs `x_1` and `x_2` for up to two fidelity parmeters:
  
      K(x_1, x_2) = k_0 + c_1(x_1, x_2)k_1 + c_2(x_1,x_2)k_2 + c_3(x_1,x_2)k_3
  
  where
  
  - `k_i(i=0,1,2,3)` are Matern kernels calculated between non-fidelity
      parameters of `x_1` and `x_2` with different priors.
  - `c_1=(1 - x_1[f_1])(1 - x_2[f_1]))(1 + x_1[f_1] x_2[f_1])^p` is the kernel
      of the the bias term, which can be decomposed into a determistic part
      and a polynomial kernel. Here `f_1` is the first fidelity dimension and
      `p` is the order of the polynomial kernel.
  - `c_3` is the same as `c_1` but is calculated for the second fidelity
      dimension `f_2`.
  - `c_2` is the interaction term with four deterministic terms and the
      polynomial kernel between `x_1[..., [f_1, f_2]]` and
      `x_2[..., [f_1, f_2]]`.
  
  Example:
      >>> x = torch.randn(10, 5)
      >>> # Non-batch: Simple option
      >>> covar_module = LinearTruncatedFidelityKernel()
      >>> covar = covar_module(x)  # Output: LinearOperator of size (10 x 10)
      >>>
      >>> batch_x = torch.randn(2, 10, 5)
      >>> # Batch: Simple option
      >>> covar_module = LinearTruncatedFidelityKernel(batch_shape = torch.Size([2]))
      >>> covar = covar_module(x)  # Output: LinearOperator of size (2 x 10 x 10)
class_docstr_tok: ["GPyTorch","Linear","Truncated","Fidelity","Kernel",".","Computes","a","covariance","matrix","based","on","the","Linear","truncated","kernel","between","inputs","`","x_1","`","and","`","x_2","`","for","up","to","two","fidelity","parmeters",":","K","(","x_1",",","x_2",")","=","k_0","+","c_1","(","x_1",",","x_2",")","k_1","+","c_2","(","x_1",",","x_2",")","k_2","+","c_3","(","x_1",",","x_2",")","k_3","where","-","`","k_i","(","i=0,1,2,3",")","`","are","Matern","kernels","calculated","between","non-fidelity","parameters","of","`","x_1","`","and","`","x_2","`","with","different","priors",".","-","`","c_1=","(","1","-","x_1","[","f_1","]",")","(","1","-","x_2","[","f_1","]",")",")","(","1","+","x_1","[","f_1","]","x_2","[","f_1","]",")","^p","`","is","the","kernel","of","the","the","bias","term",",","which","can","be","decomposed","into","a","determistic","part","and","a","polynomial","kernel",".","Here","`","f_1","`","is","the","first","fidelity","dimension","and","`","p","`","is","the","order","of","the","polynomial","kernel",".","-","`","c_3","`","is","the","same","as","`","c_1","`","but","is","calculated","for","the","second","fidelity","dimension","`","f_2","`",".","-","`","c_2","`","is","the","interaction","term","with","four","deterministic","terms","and","the","polynomial","kernel","between","`","x_1","[","...",",","[","f_1",",","f_2","]","]","`","and","`","x_2","[","...",",","[","f_1",",","f_2","]","]","`",".","Example",":",">",">",">","x","=","torch.randn","(","10",",","5",")",">",">",">","#","Non-batch",":","Simple","option",">",">",">","covar_module","=","LinearTruncatedFidelityKernel","(",")",">",">",">","covar","=","covar_module","(","x",")","#","Output",":","LinearOperator","of","size","(","10","x","10",")",">",">",">",">",">",">","batch_x","=","torch.randn","(","2",",","10",",","5",")",">",">",">","#","Batch",":","Simple","option",">",">",">","covar_module","=","LinearTruncatedFidelityKernel","(","batch_shape","=","torch.Size","(","[","2","]",")",")",">",">",">","covar","=","covar_module","(","x",")","#","Output",":","LinearOperator","of","size","(","2","x","10","x","10",")"]
code: def forward(
      self, x1: Tensor, x2: Tensor, diag: bool = False, **params
  ) -> Tensor:
      if params.get("last_dim_is_batch", False):
          raise NotImplementedError(
              "last_dim_is_batch not yet supported by LinearTruncatedFidelityKernel"
          )
  
      power = self.power.view(*self.batch_shape, 1, 1)
      active_dimsM = torch.tensor(
          [
              i
              for i in range(x1.size(-1))
              if i not in self.fidelity_dims
          ],
          device=x1.device,
      )
      if len(active_dimsM) == 0:
          raise RuntimeError(
              "Input to LinearTruncatedFidelityKernel must have at least one "
              "non-fidelity dimension."
          )
      x1_ = x1.index_select(dim=-1, index=active_dimsM)
      x2_ = x2.index_select(dim=-1, index=active_dimsM)
      covar_unbiased = self.covar_module_unbiased(x1_, x2_, diag=diag)
      covar_biased = self.covar_module_biased(x1_, x2_, diag=diag)
  
      # clamp to avoid numerical issues
      fd_idxr0 = torch.full(
          (1,),
          self.fidelity_dims[0],
          dtype=torch.long,
          device=x1.device,
      )
      x11_ = x1.index_select(dim=-1, index=fd_idxr0).clamp(0, 1)
      x21t_ = x2.index_select(dim=-1, index=fd_idxr0).clamp(0, 1)
      if not diag:
          x21t_ = x21t_.transpose(-1, -2)
      cross_term_1 = (1 - x11_) * (1 - x21t_)
      bias_factor = cross_term_1 * (1 + x11_ * x21t_).pow(power)
  
      if len(self.fidelity_dims) > 1:
          # clamp to avoid numerical issues
          fd_idxr1 = torch.full(
              (1,),
              self.fidelity_dims[1],
              dtype=torch.long,
              device=x1.device,
          )
          x12_ = x1.index_select(dim=-1, index=fd_idxr1).clamp(0, 1)
          x22t_ = x2.index_select(dim=-1, index=fd_idxr1).clamp(0, 1)
          x1b_ = torch.cat([x11_, x12_], dim=-1)
          if diag:
              x2bt_ = torch.cat([x21t_, x22t_], dim=-1)
              k = (1 + (x1b_ * x2bt_).sum(dim=-1, keepdim=True)).pow(
                  power
              )
          else:
              x22t_ = x22t_.transpose(-1, -2)
              x2bt_ = torch.cat([x21t_, x22t_], dim=-2)
              k = (1 + x1b_ @ x2bt_).pow(power)
  
          cross_term_2 = (1 - x12_) * (1 - x22t_)
          bias_factor += cross_term_2 * (1 + x12_ * x22t_).pow(power)
          bias_factor += cross_term_2 * cross_term_1 * k
  
      if diag:
          bias_factor = bias_factor.view(covar_biased.shape)
  
      return covar_unbiased + bias_factor * covar_biased
  
file_path: botorch/botorch/models/kernels/linear_truncated_fidelity.py
imports: from __future__ import annotations
  from typing import Any, List, Optional
  import torch
  from botorch.exceptions import UnsupportedError
  from gpytorch.constraints import Interval, Positive
  from gpytorch.kernels import Kernel
  from gpytorch.kernels.matern_kernel import MaternKernel
  from gpytorch.priors import Prior
  from gpytorch.priors.torch_priors import GammaPrior
  from torch import Tensor
label_desc: Use image node_id 5 for calling the LinearTruncatedFidelityKernel obj's underlying member method code with example usage: obj.forward(x1, x2, diag) and returns: unknown