Dense Cholesky update in Python

前端 未结 3 1715
轮回少年
轮回少年 2021-02-09 01:36

Could anyone point me to a library/code allowing me to perform low-rank updates on a Cholesky decomposition in python (numpy)? Matlab offers this functionality as a function cal

相关标签:
3条回答
  • 2021-02-09 01:56

    This guy is doing something similar using scikits and numpy/scipy.

    0 讨论(0)
  • 2021-02-09 02:04

    This should do a rank-1 update or downdate on numpy arrays R and x with sign '+' or '-' corresponding to update or downdate. (Ported from MATLAB cholupdate at the Wikipedia page: http://en.wikipedia.org/wiki/Cholesky_decomposition):

    def cholupdate(R,x,sign):
        import numpy as np
          p = np.size(x)
          x = x.T
          for k in range(p):
            if sign == '+':
              r = np.sqrt(R[k,k]**2 + x[k]**2)
            elif sign == '-':
              r = np.sqrt(R[k,k]**2 - x[k]**2)
            c = r/R[k,k]
            s = x[k]/R[k,k]
            R[k,k] = r
            if sign == '+':
              R[k,k+1:p] = (R[k,k+1:p] + s*x[k+1:p])/c
            elif sign == '-':
              R[k,k+1:p] = (R[k,k+1:p] - s*x[k+1:p])/c
            x[k+1:p]= c*x[k+1:p] - s*R[k, k+1:p]
          return R
    
    0 讨论(0)
  • 2021-02-09 02:05

    Here is a Python package that does rank 1 updates and downdates on Cholesky factors using Cython: https://github.com/jcrudy/choldate

    Example:

    from choldate import cholupdate, choldowndate
    import numpy
    
    #Create a random positive definite matrix, V
    numpy.random.seed(1)
    X = numpy.random.normal(size=(100,10))
    V = numpy.dot(X.transpose(),X)
    
    #Calculate the upper Cholesky factor, R
    R = numpy.linalg.cholesky(V).transpose()
    
    #Create a random update vector, u
    u = numpy.random.normal(size=R.shape[0])
    
    #Calculate the updated positive definite matrix, V1, and its Cholesky factor, R1
    V1 = V + numpy.outer(u,u)
    R1 = numpy.linalg.cholesky(V1).transpose()
    
    #The following is equivalent to the above
    R1_ = R.copy()
    cholupdate(R1_,u.copy())
    assert(numpy.all((R1 - R1_)**2 < 1e-16))
    
    #And downdating is the inverse of updating
    R_ = R1.copy()
    choldowndate(R_,u.copy())
    assert(numpy.all((R - R_)**2 < 1e-16))
    
    0 讨论(0)
提交回复
热议问题