class_docstr: Return a triangular matrix square root of positive semi-definite `x`.
  
  L = cholesky(X, lower=True) implies dot(L, L.T) == X.
  
  Parameters
  ----------
  lower : bool, default=True
      Whether to return the lower or upper cholesky factor
  on_error : ['raise', 'nan']
      If on_error is set to 'raise', this Op will raise a
      `scipy.linalg.LinAlgError` if the matrix is not positive definite.
      If on_error is set to 'nan', it will return a matrix containing
      nans instead.
class_docstr_tok: ["Return","a","triangular","matrix","square","root","of","positive","semi-definite","`","x","`",".","L","=","cholesky","(","X",",","lower=True",")","implies","dot","(","L",",","L.T",")","==","X.","Parameters","--","--","--","--","--","lower",":","bool",",","default=True","Whether","to","return","the","lower","or","upper","cholesky","factor","on_error",":","[","'raise","'",",","'nan","'","]","If","on_error","is","set","to","'raise","'",",","this","Op","will","raise","a","`","scipy.linalg.LinAlgError","`","if","the","matrix","is","not","positive","definite",".","If","on_error","is","set","to","'nan","'",",","it","will","return","a","matrix","containing","nans","instead","."]
docstr: Cholesky decomposition reverse-mode gradient update.
  
  Symbolic expression for reverse-mode Cholesky gradient taken from [#]_
  
  References
  ----------
  .. [#] I. Murray, "Differentiation of the Cholesky decomposition",
     http://arxiv.org/abs/1602.07527
code: def L_op(self, inputs, outputs, gradients):
      """
      Cholesky decomposition reverse-mode gradient update.
  
      Symbolic expression for reverse-mode Cholesky gradient taken from [#]_
  
      References
      ----------
      .. [#] I. Murray, "Differentiation of the Cholesky decomposition",
         http://arxiv.org/abs/1602.07527
  
      """
  
      dz = gradients[0]
      chol_x = outputs[0]
  
      # Replace the cholesky decomposition with 1 if there are nans
      # or solve_upper_triangular will throw a ValueError.
      if self.on_error == "nan":
          ok = ~tensor.any(tensor.isnan(chol_x))
          chol_x = tensor.switch(ok, chol_x, 1)
          dz = tensor.switch(ok, dz, 1)
  
      # deal with upper triangular by converting to lower triangular
      if not self.lower:
          chol_x = chol_x.T
          dz = dz.T
  
      def tril_and_halve_diagonal(mtx):
          """Extracts lower triangle of square matrix and halves diagonal."""
          return tensor.tril(mtx) - tensor.diag(
              tensor.diagonal(mtx) / 2.0
          )
  
      def conjugate_solve_triangular(outer, inner):
          """Computes L^{-T} P L^{-1} for lower-triangular L."""
          return solve_upper_triangular(
              outer.T, solve_upper_triangular(outer.T, inner.T).T
          )
  
      s = conjugate_solve_triangular(
          chol_x, tril_and_halve_diagonal(chol_x.T.dot(dz))
      )
  
      if self.lower:
          grad = tensor.tril(s + s.T) - tensor.diag(tensor.diagonal(s))
      else:
          grad = tensor.triu(s + s.T) - tensor.diag(tensor.diagonal(s))
  
      if self.on_error == "nan":
          return [tensor.switch(ok, grad, np.nan)]
      else:
          return [grad]
  
imports: from __future__ import absolute_import, print_function, division
  import logging
  import warnings
  from six.moves import xrange
  import numpy
  from theano import tensor
  import theano.tensor
  from theano.tensor import as_tensor_variable
  from theano.gof import Op, Apply
label_desc: Use image node_id 5 for calling the Cholesky obj's underlying member method code with example usage: obj.L_op(inputs, outputs, gradients) and returns: unknown, solve_upper_triangular, list, list