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

Wie berechnet man die Cholesky-Zerlegung?

Contents

  • 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 61
  • 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