code: def _update_damping(
      nat_cov: Tensor,
      nat_cov_new: Tensor,
      damping_factor: Tensor,
      jitter: Tensor,
  ) -> Tuple[Tensor, Tensor]:
      r"""Updates the damping factor whilst ensuring the covariance matrix is positive
      definite by trying a Cholesky decomposition.
  
      Args:
          nat_cov: A `batch_shape x R x R`-dim Tensor containing the old natural
              covariance matrix.
          nat_cov_new: A `batch_shape x R x R`-dim Tensor containing the new natural
              covariance matrix.
          damping_factor: A`batch_shape`-dim Tensor containing the damping factor.
          jitter: The amount of jitter added before matrix inversion.
  
      Returns:
          A two-element tuple containing
  
          - A `batch_shape x param_shape`-dim Tensor containing the updated damping
              factor.
          - A `batch_shape x R x R`-dim Tensor containing the Cholesky factor.
      """
      tkwargs = {"dtype": nat_cov.dtype, "device": nat_cov.device}
      df = damping_factor
      jitter = jitter * torch.diag_embed(
          torch.ones(nat_cov.shape[:-1], **tkwargs)
      )
      _, info = torch.linalg.cholesky_ex(nat_cov + jitter)
  
      if torch.sum(info) > 1:
          raise ValueError(
              "The previous covariance is not positive semi-definite. "
              "This usually happens if the predictive covariance is "
              "ill-conditioned and the added jitter is insufficient."
          )
  
      damped_nat_cov = _damped_update(
          old_factor=nat_cov, new_factor=nat_cov_new, damping_factor=df
      )
      cholesky_factor, info = torch.linalg.cholesky_ex(damped_nat_cov)
      contains_nans = torch.any(torch.isnan(cholesky_factor)).item()
  
      run = 0
      while torch.sum(info) > 1 or contains_nans:
          # propose an alternate damping factor which is half the original
          df_alt = 0.5 * df
          # hard threshold at 1e-3
          df_alt = torch.where(
              df_alt > 1e-3,
              df_alt,
              torch.zeros(df_alt.shape, **tkwargs),
          )
          # only change the damping factor where psd failure occurs
          df_new = torch.where(info == 0, df, df_alt)
  
          # new damped covariance
          damped_nat_cov = _damped_update(nat_cov, nat_cov_new, df_new)
  
          # try cholesky decomposition
          cholesky_factor, info = torch.linalg.cholesky_ex(
              damped_nat_cov + jitter
          )
          contains_nans = torch.any(torch.isnan(cholesky_factor)).item()
          df = df_new
          run = run + 1
  
      return df, cholesky_factor
  
imports: from __future__ import annotations
  from typing import Any, Optional, Tuple
  import torch
  from botorch.acquisition.acquisition import AcquisitionFunction
  from botorch.exceptions import InputDataError
  from botorch.exceptions.errors import UnsupportedError
  from botorch.models.model import Model
  from botorch.models.model_list_gp_regression import ModelListGP
  from botorch.models.utils import check_no_nans
  from botorch.utils.transforms import concatenate_pending_points, t_batch_mode_transform
  from torch import Tensor
  from torch.distributions import Normal
label_desc: Use image node_id 9 for calling a global function with example usage: _update_damping(nat_cov, nat_cov_new, damping_factor, jitter) and returns: df,  cholesky_factor