code: def _symmetric_increment_chol(chol, idx, increment):
      """Effectly increments a row and column of a Cholesky-factorized matrix.
  
      Let `M = chol @ chol.T` be an `[m, m]` symmetric matrix. This function
      implements the symmetry-preserving operation:
  
      ```
      M[idx, :] += increment
      M[:, idx] += increment
      # Correct for double-incrementing the diagonal.
      M[idx, idx] -= increment[idx]
      ```
  
      in Cholesky space, but in an optimized form as 2 steps, where `increment` is
      a vector of length `m`.
  
      That is, this function adds `increment` to the `idx`th row, and
      (by symmetry) also to the `idx`th column. For example:
  
      ```python
      M = [[1., 0., 0.],
           [0., 1., 0.],
           [0., 0., 1.]]
      new_chol = _symmetric_increment_chol(tf.linalg.cholesky(M),
                                           idx=2,
                                           increment=[0., -0.3, 1.])
      new_M = tf.matmul(new_chol, new_chol, adjoint_b=True)
      # ==> [[1., 0., 0.],
      #      [0., 1., -0.3],
      #      [0., -0.3, 2.]]
      ```
  
      This is implemented efficiently as two consecutive rank-1 updates of
      `chol(M)`.
  
      Args:
        chol: (batch of) float `Tensor` lower-triangular Cholesky factor(s) of a
          matrix `M`.
        idx: (batch of) int `Tensor` scalar index(s) of the row and column to
          update.
        increment: (batch of) float `Tensor` vector(s) to add to the given row and
          column of `M`.
  
      Returns:
        updated_chol: float `Tensor` lower-triangular Cholesky factor of the
          symmetric matrix resulting from adding `increment` to the
          given row and column of `M`.
      """
      with tf.name_scope("symmetric_increment_chol"):
          # TODO(jburnim): Can we make this more numerically accurate by doing both
          # rank-1 Cholesky updates in a single pass?
          chol = tf.convert_to_tensor(chol, name="chol")
          increment = tf.convert_to_tensor(increment, name="increment")
          orig_chol = chol
  
          # This does an update of the row and column in 2 rank-1 updates.
          # Consider an example update vector of v = [x, y, z]. Thus v @ v.T is:
          # [[x^2, xy, xz],
          #  [xy, y^2, yz],
          #  [xz, yz, z^2]]
          # cholesky_update will compute the return the updated cholesky given
          # this being added to the original matrix.
          #
          # Say we want update row and column 1, then the needed offset matrix is:
          # [[0, x, 0],
          #  [x, y, z],
          #  [0, z, 0]]
          # which is rank 2 and will require at least two rank 1 operations.
          #
          # If we do two updates, by adding v1 and subtracting v2, where
          #  v1 = [x, (y + 1)/2, z]
          #  v2 = [x, (y - 1)/2, z]
          # this accomplishes the goal, since:
          # [[0, x, 0],
          #  [x, y, z],   = v1 @ v1.T - v2 @ v2.T
          #  [0, z, 0]]
          a = (increment[..., idx] + 1.0) / 2.0
          b = (increment[..., idx] - 1.0) / 2.0
          chol = linalg.cholesky_update(
              chol,
              update_vector=_set_vector_index(increment, idx, a),
              multiplier=1,
          )
          chol = linalg.cholesky_update(
              chol,
              update_vector=_set_vector_index(increment, idx, b),
              multiplier=-1,
          )
  
          # There Cholesky decomposition should be unchanged in rows/cols before idx.
          #
          # TODO(b/229298550): Investigate whether this is really necessary, or if the
          # test failures we see without this line are due to an underlying bug.
          return tf.where(
              (tf.range(chol.shape[-1]) < idx)[..., tf.newaxis],
              orig_chol,
              chol,
          )
  
imports: import collections
  import tensorflow.compat.v2
  from tensorflow_probability.python.bijectors import softplus
  from tensorflow_probability.python.distributions import bernoulli
  from tensorflow_probability.python.distributions import inverse_gamma
  from tensorflow_probability.python.distributions import joint_distribution_auto_batched
  from tensorflow_probability.python.distributions import sample
  from tensorflow_probability.python.experimental.distributions.mvn_precision_factor_linop import MultivariateNormalPrecisionFactorLinearOperator
  from tensorflow_probability.python.internal import broadcast_util
  from tensorflow_probability.python.internal import dtype_util
  from tensorflow_probability.python.internal import parameter_properties
  from tensorflow_probability.python.internal import prefer_static
  from tensorflow_probability.python.internal import samplers
  from tensorflow_probability.python.internal import vectorization_util
  from tensorflow_probability.python.math import linalg
  from tensorflow_probability.python.mcmc.internal import util
label_desc: Use image node_id 3 for calling a global function with example usage: _symmetric_increment_chol(chol, idx, increment) and returns: tf