• Martin Thoma
  • Home
  • Categories
  • Tags
  • Archives
  • Support me

Wie berechnet man die Cholesky-Zerlegung?

Contents

  • Wie berechnet man die Cholesky-Zerlegung?
    • Berechnung der Cholesky-Zerlegung
    • Programmierer-Hinweise
      • Implementierung
      • Bibliotheken
      • Wolfram|Alpha
    • Numerik
    • Siehe auch

Sei \(A \in \mathbb{R}^{n \times n}\) eine symmetrische, positiv definite Matrix. Dann existiert eine Zerlegung \(A = S \cdot D \cdot S^T\), wobei \(S\) eine unipotente Dreiecksmatrix ist und D eine positiv definite Diagonalmatrix.

Berechnung der Cholesky-Zerlegung

Hier ein paar Ausschnitte, aus der englischen Wikipedia:

Einfach von links oben nach rechts unten die Werte nach folgender Formel berechnen: \(D_j = A_{jj} - \sum_{k=1}^{j-1} S_{jk}^2 D_k\) \(S_{ij} = \frac{1}{D_j} \left( A_{ij} - \sum_{k=1}^{j-1} S_{ik} S_{jk} D_k \right), \qquad\text{for } i>j\)

Programmierer-Hinweise

Implementierung

Eine Python-Implementierung sieht so aus:

#!/usr/bin/env python
# -*- coding: utf-8 -*-


def getSD(A):
    """ @param A: eine quadratische, reele, positiv definite Matrix
        @return: Die Matrizen S und D, für die gilt:
                 A = S * D * S^T
    """
    n = len(A)
    S = [[0 for j in range(n)] for i in range(n)]
    D = [[0 for j in range(n)] for i in range(n)]

    for i in range(n):
        S[i][i] = 1.0

    for j in range(n):
        _summe = sum(S[j][k] ** 2 * D[k][k] for k in range(j))
        D[j][j] = A[j][j] - _summe
        _summe = sum(S[i][k] * S[j][k] * D[k][k] for k in range(j))
        S[i][j] = 1.0 / D[j][j] * (A[i][j] - _summe)
    return S, D

Bibliotheken

Ich habe mich mal nach Bibliotheken umgesehen, die die Cholesky-Zerlegung direkt beherrschen. NumPy kann es natürlich:

from numpy import linalg

print(linalg.cholesky([[5, 1], [1, 1]]))

Gibt aus:

array([[ 2.23606798,  0.        ],
       [ 0.4472136 ,  0.89442719]])

Das ist NICHT die Zerlegung \(A = S \cdot D \cdot S^T\), sondern \(A = G \cdot G^T\).

Interessanterweise hat NumPy das nicht direkt selbst implementiert (NumPy-Quelle). Man greift auf LAPACK zurück, was in FORTRAN 90 programmiert wurde (LAPACK-Quelle)!

Wolfram|Alpha

Auch Wolfram|Alpha kennt "cholesky decomposition": Beispiel. Allerdings sieht es schon bei \(3 \times 3\)-Matrizen schlecht aus.

Numerik

In Numerik haben wir bei Herrn Dr. Weiß folgendes als Cholesky-Zerlegung kennen gelernt:

Sei \(A \in \mathbb{R}^{n \times n}\) eine symmetrische, positiv definite Matrix. Dann existiert eine Zerlegung \(A = \bar L \cdot \bar{L}^T\), wobei \(\bar L\) eine untere Dreiecksmatrix ist.

Wenn man wie gewohnt eine LR-Zerlegung der Matrix \(A\) durchführt, erhält man zwei Matrizen \(L, R \in \mathbb{R}^{n \times n}\), wobei gilt: \(R = D \cdot L^T\), wobei \(D\) eine positiv definite Diagonalmatrix ist.

Offensichtlich gilt: \(\bar L = L \cdot D^{\frac{1}{2}}\).

Die Cholesky-Zerlegung kann man folgendermaßen berechnen:

Berechnung der Cholesky-Zerlegung in Pseudocode
Berechnung der Cholesky-Zerlegung in Pseudocode

In Python sieht das dann so aus:

def getL(A):
    n = len(A)
    L = [[0 for i in range(n)] for j in range(n)]
    print(L)
    print("")

    for k in range(n):
        L[k][k] = (A[k][k] - sum([L[k][i] ** 2 for i in range(k)])) ** 0.5
        for i in range(k + 1, n):
            L[i][k] = (A[i][k] - sum([L[i][j] * L[k][j] for j in range(k)])) / L[k][k]
    return L

Siehe auch

  • Cholesky decomposition (Englisch)
  • Cholesky-Zerlegung

Published

Jul 3, 2012
by Martin Thoma

Category

German posts

Tags

  • Linear algebra 18
  • mathematics 59
  • NumPy 4
  • Python 141
  • Wolfram|Alpha 5

Contact

  • Martin Thoma - A blog about Code, the Web and Cyberculture
  • E-mail subscription
  • RSS-Feed
  • Privacy/Datenschutzerklärung
  • Impressum
  • Powered by Pelican. Theme: Elegant by Talha Mansoor