class_docstr: Conjugate Gradient Lower Bound.
  
  The key reference is :cite:t:`pmlr-v139-artemev21a`.
  
  :param cg_tolerance: Determines accuracy to which conjugate
      gradient is run when evaluating the elbo. Running more
      iterations of CG would increase the ELBO by at most
      `cg_tolerance`.
  
  :param max_cg_iters: Maximum number of iterations of CG to run
      per evaluation of the ELBO (or mean prediction).
  
  :param restart_cg_iters: How frequently to restart the CG iteration.
      Can be useful to avoid build up of numerical errors when
      many steps of CG are run.
  
  :param v_grad_optimization: If False, in every evaluation of the
      ELBO, CG is run to select a new auxilary vector `v`. If
      False, no CG is run when evaluating the ELBO but
      gradients with respect to `v` are tracked so that it can
      be optimized jointly with other parameters.
class_docstr_tok: ["Conjugate","Gradient","Lower","Bound",".","The","key","reference","is",":","cite",":","t",":","`","pmlr-v139-artemev21a","`",".",":","param","cg_tolerance",":","Determines","accuracy","to","which","conjugate","gradient","is","run","when","evaluating","the","elbo",".","Running","more","iterations","of","CG","would","increase","the","ELBO","by","at","most","`","cg_tolerance","`",".",":","param","max_cg_iters",":","Maximum","number","of","iterations","of","CG","to","run","per","evaluation","of","the","ELBO","(","or","mean","prediction",")",".",":","param","restart_cg_iters",":","How","frequently","to","restart","the","CG","iteration",".","Can","be","useful","to","avoid","build","up","of","numerical","errors","when","many","steps","of","CG","are","run",".",":","param","v_grad_optimization",":","If","False",",","in","every","evaluation","of","the","ELBO",",","CG","is","run","to","select","a","new","auxilary","vector","`","v","`",".","If","False",",","no","CG","is","run","when","evaluating","the","ELBO","but","gradients","with","respect","to","`","v","`","are","tracked","so","that","it","can","be","optimized","jointly","with","other","parameters","."]
docstr: The posterior mean for CGLB model is given by
  
  .. :math::
      m(xs) = K_{sf}v + Q_{ff}Q⁻¹r
  
  where :math:`r = y - K v`  is the residual from CG.
  
  Note that when :math:`v=0`, this agree with the SGPR mean,
  while if :math:`v = K⁻¹ y`, then :math:`r=0`, and the exact
  GP mean is recovered.
  
  :param cg_tolerance: float or None: If None, the cached value of
      :math:`v` is used. If float, conjugate gradient is run until :math:`rᵀQ⁻¹r < ϵ`.
docstr_tok: ["The","posterior","mean","for","CGLB","model","is","given","by","..",":","math",":",":","m","(","xs",")","=","K_","{","sf","}","v","+","Q_","{","ff","}","Q\u207b\u00b9r","where",":","math",":","`","r","=","y","-","K","v","`","is","the","residual","from","CG",".","Note","that","when",":","math",":","`","v=0","`",",","this","agree","with","the","SGPR","mean",",","while","if",":","math",":","`","v","=","K\u207b\u00b9","y","`",",","then",":","math",":","`","r=0","`",",","and","the","exact","GP","mean","is","recovered",".",":","param","cg_tolerance",":","float","or","None",":","If","None",",","the","cached","value","of",":","math",":","`","v","`","is","used",".","If","float",",","conjugate","gradient","is","run","until",":","math",":","`","r\u1d40Q\u207b\u00b9r","<","\u03f5","`","."]
code: def predict_f(
      self,
      Xnew: InputData,
      full_cov: bool = False,
      full_output_cov: bool = False,
      cg_tolerance: Optional[float] = 1e-3,
  ) -> MeanAndVariance:
      """
      The posterior mean for CGLB model is given by
  
      .. :math::
          m(xs) = K_{sf}v + Q_{ff}Q⁻¹r
  
      where :math:`r = y - K v`  is the residual from CG.
  
      Note that when :math:`v=0`, this agree with the SGPR mean,
      while if :math:`v = K⁻¹ y`, then :math:`r=0`, and the exact
      GP mean is recovered.
  
      :param cg_tolerance: float or None: If None, the cached value of
          :math:`v` is used. If float, conjugate gradient is run until :math:`rᵀQ⁻¹r < ϵ`.
      """
      assert_params_false(
          self.predict_f, full_output_cov=full_output_cov
      )
  
      x, y = self.data
      err = y - self.mean_function(x)
      kxx = self.kernel(x, x)
      ksf = self.kernel(Xnew, x)
      sigma_sq = self.likelihood.variance
      sigma = tf.sqrt(sigma_sq)
      iv = self.inducing_variable
      kernel = self.kernel
      matmul = tf.linalg.matmul
      trisolve = tf.linalg.triangular_solve
  
      kmat = add_noise_cov(kxx, sigma_sq)
  
      common = self._common_calculation()
      A, LB, L = common.A, common.LB, common.L
  
      v = self.aux_vec
      if cg_tolerance is not None:
          preconditioner = NystromPreconditioner(A, LB, sigma_sq)
          err_t = tf.transpose(err)
          v = cglb_conjugate_gradient(
              kmat,
              err_t,
              v,
              preconditioner,
              cg_tolerance,
              self._max_cg_iters,
              self._restart_cg_iters,
          )
  
      cg_mean = matmul(ksf, v, transpose_b=True)
      res = err - matmul(kmat, v, transpose_b=True)
  
      Kus = Kuf(iv, kernel, Xnew)
      Ares = matmul(A, res)  # The god of war!
      c = trisolve(LB, Ares, lower=True) / sigma
      tmp1 = trisolve(L, Kus, lower=True)
      tmp2 = trisolve(LB, tmp1, lower=True)
      sgpr_mean = matmul(tmp2, c, transpose_a=True)
  
      if full_cov:
          var = (
              kernel(Xnew)
              + matmul(tmp2, tmp2, transpose_a=True)
              - matmul(tmp1, tmp1, transpose_a=True)
          )
          var = tf.tile(
              var[None, ...], [self.num_latent_gps, 1, 1]
          )  # [P, N, N]
      else:
          var = (
              kernel(Xnew, full_cov=False)
              + tf.reduce_sum(tf.square(tmp2), 0)
              - tf.reduce_sum(tf.square(tmp1), 0)
          )
          var = tf.tile(var[:, None], [1, self.num_latent_gps])
  
      mean = sgpr_mean + cg_mean + self.mean_function(Xnew)
      return mean, var
  
imports: from typing import Any, List, NamedTuple, Optional, Tuple
  import tensorflow
  from check_shapes import check_shapes, inherit_check_shapes
  from ..base import InputData, MeanAndVariance, Parameter, RegressionData, TensorType
  from ..config import default_float, default_int
  from ..covariances import Kuf
  from ..utilities import add_noise_cov, assert_params_false, to_default_float
  from .sgpr import SGPR
label_desc: Use image node_id 5 for calling the CGLB obj's underlying member method code with example usage: obj.predict_f(Xnew, full_cov, full_output_cov, cg_tolerance) and returns: mean,  var