Gram-Schmidt Verfahren für eine Familie von Vektoren anwenden

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Absolvent1993
User
Beiträge: 6
Registriert: Samstag 22. Februar 2020, 13:31

Hallo,

in einer Simulation berechne ich eine Vielzahl von Vektoren A[0], A[1], ... die im unteren Code als eine Matrix A zusammengefasst ist. Auf diese Vektoren wende ich das Gram-Schmidt-Verfahren in zwei Schritten an. Zuerst entferne ich den Anteil der anderen Vektoren und speichere dessen Längen. Erst dann wird der Vektor auf Einheitslänge normiert.

Der oben beschrieben Zusammenhang ist in dem folgenden Code beispielhaft gezeigt:

Code: Alles auswählen

from numpy import random

N = 3                  # Anzahl der Zeilen und Spalten: In meinem Fall ist N = 100

l1, l2, l3 = 0, 0, 0   # In meinem Fall habe ich also 100 Variablen l1,l2,...,l100

for t in range(10**3): 
    
    ''' for i in range(10**5):
        
        In dieser Schleife wird die Matrix A berechnet. '''
    
    A = random.rand(N, N) # Um den Code kurz zu halten, wird diese zufällig erstellt
    
    '''Auf die Vektoren A[0], A[1], A[2] wird das Gram-Schmidt-Verfahren angewendet'''
    
    orth_1 = A[0]                   
    l1    += log(norm(orth_1)) 
    A[0]   = orth_1 / norm(orth_1)        
     
    orth_2 = A[1] - dot(A[1], A[0]) * A[0]
    l2    += log(norm(orth_2)) 
    A[1]   = orth_2 / norm(orth_2)           # orthogonaler und normierter Vektor
    
    orth_3 = A[2] - (dot(A[2], A[1]) * A[1]) - (dot(A[2], A[0]) * A[0]) 
    l3    += log(norm(orth_3)) 
    A[2]   = orth_3 / norm(orth_3)
Ich muss das Gram-Schmidt-Verfahren explizit ausschreiben, da mir keine effizientere Methode einfällt. Es ist zu sehen, dass die Gleichungen
orth_x mit zunehmener Anzahl von Vektoren (also N) immer länger werden. In meinen Fall mit N = 100 wäre es sehr umständlich alle Gleichungen orth_i , i=1,2,..,100 auszuschreiben um so die gesuchten Größen l_i zu bestimmten.

Hat jemand eine Idee, wie ich diesen ganzen Prozess automatisieren kann?



Mir fällt
keine Effiziente Variante ein, deswegen muss ich die Gleichungen explizit ausschreiben. Diese
Gleichungen werden mit zunehmender Anzahl von Vektoren (also N) immer länger und in meinem Fall
wo N = 100 ist
einfachTobi
User
Beiträge: 491
Registriert: Mittwoch 13. November 2019, 08:38

Gibt es einen Grund dafür, dass du das Verfahren selbst implementieren willst? Ansonsten kannst du die Numpy-Version nutzen:

Code: Alles auswählen

Q, R = numpy.linalg.qr(X)
Normalisieren kannst du mit `numpy.linalg.norm()`.
Variablen zu nummerieren ergibt fast nie einen Sinn. Verwende Listen/Arrays. Die Verwendung von Arrays hat den Vorteil, dass du die meisten Funktionen direkt auf alle Werte anwenden kannst du enorm Zeit sparst gegenüber einem iterativen Vorgehen.
Absolvent1993
User
Beiträge: 6
Registriert: Samstag 22. Februar 2020, 13:31

Diese Methode hatte ich auch gefunden:

Q, R = numpy.linalg.qr(X)

In Q sind die Vektoren jedoch doch bereits normiert? Damit ist die Information zur Berechnung der l1,l2,... Werte bereits verloren gegangen.
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Bleibt immer noch die Variante, das ganze mit zwei for-Schleifen zu schreiben. Eine von i=0..N-1 und die innere von j=0..i-1.
einfachTobi
User
Beiträge: 491
Registriert: Mittwoch 13. November 2019, 08:38

Oh, Vertipper im vorherigen Post von mir. Meinte natürlich "Normieren".
Genau, dann Lauf das doch zu Fuß in ner Schleife ab, statt alles einzeln zu schreiben. Sowas in der Art müsste klappen:

Code: Alles auswählen

def gram_schmidt(A):
    n = A.shape[1]
    for i in range(n):
        for k in range(i):
            A[:, i] -= np.dot(A[:, k], A[:, i]) * A[:, k]
        # geheimnisvolle li-Berechnung hier
        A[:, i] = A[:, i] / np.linalg.norm(A[:, i])
    return A
Antworten