Плотное холесское обновление в Python - PullRequest
7 голосов
/ 26 декабря 2011

Может ли кто-нибудь указать мне на библиотеку / код, позволяющий мне выполнять низкоранговые обновления разложения Холецкого в python (numpy)?Matlab предлагает эту функцию как функцию, называемую cholupdate.LINPACK также имеет эту функциональность, но (насколько мне известно) еще не был перенесен в LAPACK и, следовательно, недоступен, например, в scipy.

Я обнаружил, что scikits.sparse предлагает аналогичную функцию на основе CHOLMOD, но мои матрицы плотные.

Есть ли какой-нибудь код, доступный для python с функциональностью 'cholupdate', совместимый с numpy?

Спасибо!

Ответы [ 3 ]

4 голосов
/ 18 февраля 2013

Вот пакет Python, который обновляет и понижает рейтинг 1 по факторам Холецкого, используя Cython: https://github.com/jcrudy/choldate

Пример:

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))
2 голосов
/ 23 апреля 2013

Это должно сделать обновление или понижение ранга 1 для numy массивов R и x со знаком '+' или '-', соответствующим обновлению или понижению. (Портировано из MATLAB cholupdate на странице Википедии: 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
1 голос
/ 03 января 2012

Этот парень делает нечто подобное, используя scikits и numpy / scipy.

...