Krylov-Quanten-Diagonalisierung
In dieser Lektion zur Krylov-Quanten-Diagonalisierung (KQD) werden wir folgende Fragen beantworten:
- Was ist die Krylov-Methode im Allgemeinen?
- Warum funktioniert die Krylov-Methode und unter welchen Bedingungen?
- Welche Rolle spielt Quantencomputing dabei?
Der Quantenteil der Berechnungen basiert größtenteils auf der Arbeit in Ref [1].
Das folgende Video gibt einen Überblick über Krylov-Methoden im klassischen Computing, motiviert deren Einsatz und erklärt, wie Quantencomputing in diesem Arbeitsbereich eine Rolle spielen kann. Der nachfolgende Text bietet mehr Details und implementiert eine Krylov-Methode sowohl klassisch als auch auf einem Quantencomputer.
1. Einführung in Krylov-Methoden
Eine Krylov-Unterraum-Methode kann sich auf eine von mehreren Methoden beziehen, die auf dem sogenannten Krylov-Unterraum aufgebaut sind. Eine vollständige Übersicht dieser Methoden würde den Rahmen dieser Lektion sprengen, aber Ref [2-4] bieten wesentlich mehr Hintergrundinformationen. Hier konzentrieren wir uns darauf, was ein Krylov-Unterraum ist, wie und warum er bei Eigenwertproblemen nützlich ist, und schließlich wie er auf einem Quantencomputer implementiert werden kann.
Definition: Gegeben sei eine symmetrische, positiv semidefinite -Matrix . Der Krylov-Raum der Ordnung ist der Raum, der durch Vektoren aufgespannt wird, die durch Multiplikation höherer Potenzen der Matrix bis zu mit einem Referenzvektor entstehen.
Obwohl die obigen Vektoren das aufspannen, was wir einen Krylov-Unterraum nennen, gibt es keinen Grund anzunehmen, dass sie orthogonal sind. Häufig verwendet man einen iterativen Orthonormierungsprozess ähnlich der Gram-Schmidt-Orthogonalisierung. Hier verläuft der Prozess etwas anders, da jeder neue Vektor orthogonal zu den anderen gemacht wird, während er erzeugt wird. In diesem Zusammenhang nennt man dies Arnoldi-Iteration. Beginnend mit dem Anfangsvektor erzeugt man den nächsten Vektor und stellt dann sicher, dass dieser zweite Vektor orthogonal zum ersten ist, indem man seine Projektion auf abzieht. Das heißt
Es ist nun leicht zu sehen, dass da
Dasselbe tun wir für den nächsten Vektor und stellen sicher, dass er orthogonal zu beiden vorherigen Vektoren ist:
Wenn wir diesen Prozess für alle Vektoren wiederholen, haben wir eine vollständige Orthonormalbasis für einen Krylov-Raum. Beachte, dass der Orthogonalisierungsprozess den Nullvektor liefert, sobald , da orthogonale Vektoren notwendigerweise den gesamten Raum aufspannen. Der Prozess liefert ebenfalls den Nullvektor, wenn ein Vektor ein Eigenvektor von ist, da alle nachfolgenden Vektoren Vielfache dieses Vektors wären.
1.1 Ein einfaches Beispiel: Krylov von Hand
Gehen wir die Erzeugung eines Krylov-Unterraums an einer trivial kleinen Matrix Schritt für Schritt durch, damit wir den Prozess nachvollziehen können. Wir beginnen mit einer Anfangsmatrix , die uns interessiert:
Für dieses kleine Beispiel können wir die Eigenvektoren und Eigenwerte leicht bestimmen, sogar von Hand. Wir zeigen hier die numerische Lösung.
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-ibm-runtime scipy sympy
# One might use linalg.eigh here, but later matrices may not be Hermitian. So we use linalg.eig in this lesson.
import numpy as np
A = np.array([[4, -1, 0], [-1, 4, -1], [0, -1, 4]])
eigenvalues, eigenvectors = np.linalg.eig(A)
print("The eigenvalues are ", eigenvalues)
print("The eigenvectors are ", eigenvectors)
The eigenvalues are [2.58578644 4. 5.41421356]
The eigenvectors are [[ 5.00000000e-01 -7.07106781e-01 5.00000000e-01]
[ 7.07106781e-01 1.37464400e-16 -7.07106781e-01]
[ 5.00000000e-01 7.07106781e-01 5.00000000e-01]]
Wir halten sie hier zum späteren Vergleich fest:
Wir möchten untersuchen, wie dieser Prozess funktioniert (oder scheitert), wenn wir die Dimension unseres Krylov-Unterraums erhöhen. Dazu wenden wir diesen Prozess an:
- Erzeuge einen Unterraum des vollen Vektorraums, beginnend mit einem zufällig gewählten Vektor (nenne ihn , falls er bereits normiert ist, wie oben).
- Projiziere die vollständige Matrix auf diesen Unterraum und bestimme die Eigenwerte der projizierten Matrix .
- Vergrößere den Unterraum durch Erzeugen weiterer Vektoren, indem du sicherstellst, dass sie orthonormal sind, ähnlich der Gram-Schmidt-Orthogonalisierung.
- Projiziere auf den größeren Unterraum und bestimme die Eigenwerte der resultierenden Matrix .
- Wiederhole dies, bis die Eigenwerte konvergieren (oder in diesem Spielzeugbeispiel, bis du Vektoren erzeugt hast, die den gesamten Vektorraum der ursprünglichen Matrix aufspannen).
Eine normale Implementierung der Krylov-Methode müsste das Eigenwertproblem für die auf jeden Krylov-Unterraum projizierte Matrix nicht bei jeder Aufbaustufe lösen. Du könntest den Unterraum der gewünschten Dimension konstruieren, die Matrix auf diesen Unterraum projizieren und die projizierte Matrix diagonalisieren. Das Projizieren und Diagonalisieren bei jeder Unterraumdimension geschieht hier nur zur Überprüfung der Konvergenz.
Dimension :
Wir wählen einen zufälligen Vektor, sagen wir
Falls er noch nicht normiert ist, normieren wir ihn.
Nun projizieren wir unsere Matrix auf den Unterraum dieses einen Vektors:
Dies ist unsere Projektion der Matrix auf unseren Krylov-Unterraum, wenn er nur einen einzigen Vektor enthält. Der Eigenwert dieser Matrix ist trivialerweise 4. Wir können dies als unsere nullte Näherung der Eigenwerte (in diesem Fall nur einer) von betrachten. Obwohl es eine schlechte Schätzung ist, liegt sie in der richtigen Größenordnung.
Dimension :
Wir erzeugen nun den nächsten Vektor in unserem Unterraum durch Anwendung von auf den vorherigen Vektor:
Nun subtrahieren wir die Projektion dieses Vektors auf unseren vorherigen Vektor, um Orthogonalität sicherzustellen.
Falls er noch nicht normiert ist, normieren wir ihn. In diesem Fall war der Vektor bereits normiert, also
Wir projizieren nun unsere Matrix A auf den Unterraum dieser zwei Vektoren:
Wir stehen nach wie vor vor dem Problem, die Eigenwerte dieser Matrix zu bestimmen. Aber diese Matrix ist etwas kleiner als die vollständige Matrix. Bei Problemen mit sehr großen Matrizen kann die Arbeit in diesem kleineren Unterraum sehr vorteilhaft sein.
Obwohl dies immer noch keine gute Schätzung ist, ist sie besser als die nullte Näherung. Wir werden dies noch eine weitere Iteration durchführen, um sicherzustellen, dass der Prozess klar ist. Dies unterläuft jedoch den Sinn der Methode, da wir im nächsten Schritt eine 3x3-Matrix diagonalisieren werden, was bedeutet, dass wir weder Zeit noch Rechenleistung gespart haben.
Dimension :
Wir erzeugen nun den nächsten Vektor in unserem Unterraum durch Anwendung von A auf den vorherigen Vektor:
Nun subtrahieren wir die Projektion dieses Vektors auf beide vorherigen Vektoren, um Orthogonalität sicherzustellen.
Falls er noch nicht normiert ist, normieren wir ihn. In diesem Fall war der Vektor bereits normiert, also
Wir projizieren nun unsere Matrix auf den Unterraum dieser Vektoren:
Nun bestimmen wir die Eigenwerte:
Diese Eigenwerte sind exakt die Eigenwerte der ursprünglichen Matrix . Das muss so sein, da wir unseren Krylov-Unterraum so erweitert haben, dass er den gesamten Vektorraum der ursprünglichen Matrix aufspannt.
In diesem Beispiel erscheint die Krylov-Methode möglicherweise nicht besonders einfacher als die direkte Diagonalisierung. Tatsächlich ist die Krylov-Methode, wie wir in späteren Abschnitten sehen werden, nur oberhalb einer bestimmten Matrixdimension vorteilhaft; sie soll uns helfen, Eigenwert-/Eigenvektorprobleme extrem großer Matrizen zu lösen.

Dies ist das einzige Beispiel, das wir „von Hand" durcharbeiten werden, aber Abschnitt 2 unten zeigt rechnerische Beispiele.
Klärung der Begriffe
Ein häufiges Missverständnis ist, dass es für ein gegebenes Problem nur einen einzigen Krylov-Unterraum gibt. Natürlich gibt es, da es viele Anfangsvektoren gibt, auf die unsere Matrix angewendet werden könnte, viele mögliche Krylov-Unterräume. Wir werden den Ausdruck „der Krylov-Unterraum" nur verwenden, um auf einen bereits für ein konkretes Beispiel definierten spezifischen Krylov-Unterraum zu verweisen. Bei allgemeinen Problemlösungsansätzen werden wir auf „einen Krylov-Unterraum" verweisen.
Eine letzte Klärung: Es ist zulässig, von einem „Krylov-Raum" zu sprechen. Häufig wird er als „Krylov-Unterraum" bezeichnet, weil er im Kontext der Projektion von Matrizen aus einem Ausgangsraum in einen Unterraum verwendet wird. In Übereinstimmung mit diesem Kontext werden wir ihn hier überwiegend als Unterraum bezeichnen.
Überprüfe dein Verständnis
Lies die folgenden Fragen, denke über deine Antwort nach und klicke dann auf das Dreieck, um die jeweilige Lösung einzublenden.
Erkläre, warum es (a) nicht nützlich und (b) nicht möglich ist, die Dimension des Krylov-Unterraums über die Dimension der betrachteten Matrix hinaus zu erweitern.
Antwort:
(a) Da wir die Vektoren beim Erzeugen orthonormieren, bildet ein Satz von solcher Vektoren eine vollständige Basis, d. h. eine Linearkombination von ihnen kann verwendet werden, um jeden Vektor im Raum zu erzeugen. (b) Der Orthogonalisierungsprozess besteht darin, die Projektion eines neuen Vektors auf alle vorherigen Vektoren abzuziehen. Wenn alle vorherigen Vektoren den gesamten Vektorraum aufspannen, ergibt das Abziehen der Projektionen auf den vollständigen Unterraum immer den Nullvektor.
Angenommen, ein Kollege demonstriert die Krylov-Methode, angewendet auf eine kleine Spielzeugmatrix, für einige Kolleginnen und Kollegen. Dieser Kollege plant, die folgende Matrix und den folgenden Anfangsvektor zu verwenden:
und
Gibt es dabei ein Problem? Wie würdest du deinem Kollegen raten?
Antwort:
Dein Kollege hat versehentlich einen Eigenvektor als Anfangsvektor gewählt. Die Anwendung der Matrix auf den Anfangsvektor liefert einfach denselben Vektor zurück, skaliert mit dem Eigenwert. Damit wird kein Unterraum zunehmender Dimension erzeugt. Rate deinem Kollegen, einen anderen Anfangsvektor zu wählen und dabei sicherzustellen, dass es kein Eigenvektor ist.
Wende die Krylov-Methode auf die folgende Matrix an und wähle einen geeigneten neuen Anfangsvektor. Schreibe die Schätzungen des minimalen Eigenwerts bei der nullten und ersten Ordnung deines Krylov-Unterraums auf.
Antwort:
Es gibt viele mögliche Antworten, je nach Wahl des Anfangsvektors. Wir wählen:
Um zu erhalten, wenden wir einmal auf an und machen dann orthogonal zu
Bei nullter Ordnung ist die Projektion auf unseren Krylov-Unterraum
Bei erster Ordnung ist die Projektion auf diesen Krylov-Unterraum
Dies kann von Hand berechnet werden, ist aber am einfachsten mit numpy:
import numpy as np
vstar = np.array([[1/np.sqrt(3),1/np.sqrt(3),1/np.sqrt(3)],[-1/np.sqrt(6),np.sqrt(2/3),-1/np.sqrt(6)]]
)
A = np.array([[1, 1, 0],
[1, 1, 1],
[0, 1, 1]])
v = np.array([[1/np.sqrt(3),-1/np.sqrt(6)],[1/np.sqrt(3),np.sqrt(2/3)],[1/np.sqrt(3),-1/np.sqrt(6)]])
proj = vstar@A@v
print(proj)
eigenvalues, eigenvectors = np.linalg.eig(proj)
print("The eigenvalues are ", eigenvalues)
print("The eigenvectors are ", eigenvectors)
Ausgabe:
[[ 2.33333333 0.47140452]
[ 0.47140452 -0.33333333]]
The eigenvalues are [ 2.41421356 -0.41421356]
The eigenvectors are [[ 0.98559856 -0.16910198]
[ 0.16910198 0.98559856]]
Die Schätzung des minimalen Eigenwerts beträgt -0.414.
1.2 Arten von Krylov-Methoden
„Krylov-Unterraum-Methoden" können sich auf eine von mehreren iterativen Techniken beziehen, die zur Lösung großer linearer Systeme und Eigenwertprobleme verwendet werden. Was sie alle gemeinsam haben, ist, dass sie eine Näherungslösung aus einem Krylov-Unterraum konstruieren:
wobei der Anfangsschätzvektor ist (siehe Ref [5]). Sie unterscheiden sich darin, wie sie die beste Näherung aus diesem Unterraum auswählen, und balancieren dabei Faktoren wie Konvergenzrate, Speicherbedarf und Gesamtrechenaufwand. Der Schwerpunkt dieser Lektion liegt auf der Nutzung von Quantencomputing im Kontext von Krylov-Unterraum-Methoden; eine erschöpfende Diskussion dieser Methoden geht über ihren Rahmen hinaus. Die nachstehenden kurzen Definitionen dienen nur als Kontext und enthalten einige Verweise für eine weiterführende Untersuchung dieser Methoden.
Die konjugierte Gradientenmethode (CG-Methode): Diese Methode wird zur Lösung symmetrischer, positiv definiter linearer Systeme verwendet [6]. Sie minimiert die A-Norm des Fehlers bei jeder Iteration, was sie besonders effektiv für Systeme macht, die aus diskretisierten elliptischen PDEs entstehen [7]. Wir werden diesen Ansatz im nächsten Abschnitt verwenden, um zu motivieren, warum ein Krylov-Unterraum ein effektiver Unterraum wäre, in dem man nach verbesserten Lösungen linearer Systeme suchen könnte.
Die verallgemeinerte minimale Residualmethode (GMRES-Methode): Sie ist zur Lösung allgemeiner nichtsymmetrischer linearer Systeme konzipiert. Sie minimiert die Residualnorm über einen Krylov-Raum bei jeder Iteration, was sie robust, aber potenziell speicherintensiv für große Systeme macht [7].
Die minimale Residualmethode (MINRES-Methode): Diese Methode wird zur Lösung symmetrischer indefiniter linearer Systeme verwendet. Sie ähnelt GMRES, nutzt jedoch die Symmetrie der Matrix, um den Rechenaufwand zu reduzieren [8].
Weitere erwähnenswerte Ansätze sind die vollständige Orthogonalisierungsmethode (FOM), die eng mit der Arnoldi-Methode für Eigenwertprobleme verwandt ist, die bi-konjugierte Gradientenmethode (BiCG) und die Methode der induzierten Dimensionsreduktion (IDR).
1.3 Warum die Krylov-Unterraum-Methode funktioniert
Hier werden wir motivieren, dass die Krylov-Unterraum-Methode eine effiziente Möglichkeit sein sollte, Matrixeigenwerte durch iterative Verfeinerung von Eigenvektornäherungen zu approximieren – aus der Perspektive des steilsten Abstiegs. Wir werden argumentieren, dass der Raum der aufeinanderfolgenden Korrekturen zu einer gegebenen Anfangsschätzung des Grundzustands, der die schnellste Konvergenz liefert, genau ein Krylov-Unterraum ist. Wir verzichten auf einen strengen Konvergenzbeweis.
Angenommen, unsere interessierende Matrix ist symmetrisch und positiv definit. Das macht unser Argument am relevantesten für die oben beschriebene CG-Methode. Wir treffen keine Annahmen über Dünnbesetztheit; wir behaupten auch nicht, dass hermitesch sein muss (was sie sein müsste, wenn sie ein Hamiltonian wäre).
Typischerweise möchten wir ein Problem der Form
lösen. Man könnte sich vorstellen, dass , wobei eine Konstante ist, wie in einem Eigenwertproblem. Aber unsere Problemstellung bleibt vorerst allgemeiner.
Wir beginnen mit einem Vektor , der eine Näherungslösung ist. Obwohl es Parallelen zwischen diesem Schätzvektor und in Abschnitt 1.1 gibt, nutzen wir diese hier nicht. Unser Schätzvektor hat einen Fehler, den wir nennen:
Wir definieren auch das Residuum :
Hier verwenden wir den Großbuchstaben , um das Residuum von der Dimension unseres Krylov-Unterraums zu unterscheiden.

Wir wollen nun einen Korrekturschritt der Form
durchführen, der unsere Näherung hoffentlich verbessert. Hier ist ein noch zu bestimmender Vektor. Sei der Fehler nach der Korrektur. Dann gilt

Wir interessieren uns dafür, wie sich unser Fehler unter der Transformation durch unsere Matrix verhält. Berechnen wir also die -Norm des Fehlers:
wobei wir die Symmetrie von und die Relation verwendet haben. Hier ist eine von unabhängige Konstante. Wie in Abschnitt 1.2 erwähnt, ist die -Norm des Fehlers nicht die einzige Größe, die wir minimieren könnten, aber sie ist eine gute Wahl. Wir möchten sehen, wie diese Größe von unserer Wahl der Korrekturvektoren abhängt. Dazu definieren wir die Funktion durch
ist einfach der Fehler als Funktion der Korrektur , gemessen in der -Norm. Daher wollen wir so wählen, dass möglichst klein ist. Dazu berechnen wir den Gradienten von . Unter Verwendung der Symmetrie von ergibt sich
Der Gradient zeigt in Richtung des steilsten Anstiegs, d. h. sein Gegenteil gibt uns die Richtung, in der die Funktion am stärksten abnimmt: die Richtung des steilsten Abstiegs. Bei unserer Anfangsschätzung , wo , gilt Daher nimmt die Funktion am stärksten in der Richtung des Residuums ab. Unsere Anfangswahl würde also am meisten von der Addition des Vektors für ein Skalar profitieren.
Im nächsten Schritt wählen wir erneut einen Vektor und addieren ihn zur aktuellen Näherung. Mit demselben Argument wie zuvor wählen wir für ein Skalar . Wir setzen dies fort, sodass die -te Iteration unseres Vektors lautet:
Äquivalent dazu möchten wir den Raum, aus dem wir unsere verbesserten Schätzungen wählen, durch sukzessive Addition von , usw. aufbauen. Der -te Schätzvektor liegt in
Nun verwenden wir die Relation
und sehen, dass
Das heißt, der Raum, den wir aufbauen und der die korrekte Lösung am effizientesten approximiert, ist genau der Raum, der durch sukzessive Anwendung der Matrix auf aufgebaut wird. Ein Krylov-Unterraum ist der Raum, der durch die Vektoren der aufeinanderfolgenden Richtungen des steilsten Abstiegs aufgespannt wird.
Abschließend betonen wir noch einmal, dass wir keine numerischen Aussagen über die Skalierung dieses Ansatzes gemacht haben und auch nicht den komparativen Vorteil für dünnbesetzte Matrizen diskutiert haben. Dies dient nur dazu, die Verwendung von Krylov-Unterraum-Methoden zu motivieren und ein intuitives Verständnis für sie zu vermitteln. Wir werden nun das Verhalten dieser Methoden numerisch untersuchen.
Überprüfe dein Verständnis
Lies die folgende Frage, denke über deine Antwort nach und klicke dann auf das Dreieck, um die Lösung einzublenden.
Im obigen Arbeitsablauf haben wir vorgeschlagen, die -Norm des Fehlers zu minimieren. Welche anderen Größen könnte man bei der Suche nach dem Grundzustand und seinem Eigenwert in Betracht ziehen zu minimieren?
Antwort:
Man könnte sich vorstellen, stattdessen den Residualvektor zu verwenden. Es könnte Fälle geben, in denen die Betrachtung des Fehlervektors selbst nützlich ist.
2. Krylov-Methoden in der klassischen Berechnung
In diesem Abschnitt implementieren wir Arnoldi-Iterationen rechnerisch, um einen Krylov-Unterraum bei der Lösung von Eigenwertproblemen nutzen zu können. Wir wenden dies zunächst auf ein kleines Beispiel an und untersuchen anschließend, wie die Rechenzeit mit der Größe der betrachteten Matrix skaliert. Ein zentraler Gedanke dabei ist, dass die Erzeugung der Vektoren, die den Krylov-Raum aufspannen, einen großen Teil der insgesamt benötigten Rechenzeit ausmacht. Der Speicherbedarf variiert je nach konkreter Krylov-Methode, doch Speicherbeschränkungen können den Einsatz traditioneller Krylov-Methoden begrenzen.
2.1 Einfaches kleines Beispiel
Bei der Konstruktion eines Krylov-Unterraums müssen wir die Vektoren in unserem Unterraum orthonormieren. Definieren wir eine Funktion, die einen bereits bekannten Vektor aus unserem Unterraum vknown (nicht notwendigerweise normiert) und einen Kandidatenvektor vnext, der dem Unterraum hinzugefügt werden soll, entgegennimmt und vnext orthogonal zu vknown sowie normiert macht. Definieren wir außerdem eine Funktion, die diesen Prozess für alle etablierten Vektoren in unserem Krylov-Unterraum durchläuft, um eine vollständig orthonormale Menge sicherzustellen.
# vknown is some established vector in our subspace. vnext is one we wish to add, which must be orthogonal to vknown.
def orthog_pair(vknown, vnext):
vknown = vknown / np.sqrt(vknown.T @ vknown)
diffvec = vknown.T @ vnext * vknown
vnext = vnext - diffvec
return vnext
# v is the candidate vector to be added to our subspace. s is the existing subspace.
def orthoset(v, s):
v = v / np.sqrt(v.T @ v)
temp = v
for i in range(len(s)):
temp = orthog_pair(s[i], temp)
v = temp / np.sqrt(temp.T @ temp)
return v
Nun definieren wir eine Funktion, die einen iterativ immer größer werdenden Krylov-Unterraum aufbaut, bis der Raum der Krylov-Vektoren den vollen Raum der ursprünglichen Matrix aufspannt. Damit können wir sehen, wie gut die mit unserer Krylov-Unterraummethode erzielten Eigenwerte mit den exakten Werten übereinstimmen – als Funktion der Dimension des Krylov-Unterraums. Wichtig ist, dass unsere Funktion krylov_full_build die Krylov-Vektoren, die projizierten Hamiltonoperatoren, die Eigenwerte und die benötigte Zeit zurückgibt.
# Necessary imports and definitions to track time in microseconds
import time
def time_mus():
return int(time.time() * 1000000)
# This function constructs a Krylov subspace that spans the whole space of the original matrix.
# Input:
# v0 : initial vector
# matrix : original matrix to be diagonalized
# Output:
# ks : Krylov vectors
# Hs : projected Hamiltonians
# eigs : eigenvalues
# k_tot_times : time required for the operation
def krylov_full_build(v0, matrix):
t0 = time_mus()
b = v0 / np.sqrt(v0 @ v0.T)
A = matrix
ks = []
ks.append(b)
Hs = []
eigs = []
Hs.append(b.T @ A @ b)
eigs.append(np.array([b.T @ A @ b]))
k_tot_times = []
for j in range(len(A) - 1):
vec = A @ ks[j].T
ortho = orthoset(vec, ks)
ks.append(ortho)
ksarray = np.array(ks)
Hs.append(ksarray @ A @ ksarray.T)
eigs.append(np.linalg.eig(Hs[j + 1]).eigenvalues)
k_tot_times.append(time_mus() - t0)
# Return the Krylov vectors, the projected Hamiltonians, the eigenvalues, and the total time required.
return (ks, Hs, eigs, k_tot_times)
Wir testen dies an einer Matrix, die zwar noch recht klein ist, aber größer als etwas, das wir von Hand berechnen möchten.
# Define our small test matrix
test_matrix = np.array(
[
[4, -1, 0, 1, 0],
[-1, 4, -1, 2, 1],
[0, -1, 4, 3, 3],
[1, 2, 3, 4, 0],
[0, 1, 3, 0, 4],
]
)
# Give the test matrix and an initial guess as arguments in the function defined above. Calculate outputs.
test_ks, test_Hs, test_eigs, text_k_tot_times = krylov_full_build(
np.array([0.5, 0.5, 0, 0.5, 0.5]), test_matrix
)
Wir können unsere Funktionen überprüfen, indem wir sicherstellen, dass im letzten Schritt (wenn der Krylov-Raum der vollständige Vektorraum der ursprünglichen Matrix ist) die Eigenwerte der Krylov-Methode exakt mit denen der numerischen Diagonalisierung übereinstimmen:
print(np.linalg.eig(test_matrix).eigenvalues)
print(test_eigs[len(test_matrix) - 1])
[-1.36956923 8.43756009 2.9040308 5.34436028 4.68361806]
[-1.36956923 8.43756009 2.9040308 4.68361806 5.34436028]
Das hat geklappt. Entscheidend ist natürlich, wie gut unsere Näherung als Funktion der Dimension des Krylov-Unterraums ist. Da wir häufig daran interessiert sind, Grundzustände und andere minimale Eigenwerte zu finden (und aus weiteren, weiter unten erläuterten algebraischen Gründen), betrachten wir unsere Schätzung des kleinsten Eigenwerts als Funktion der Krylov-Unterraumdimension. Das ist:
def errors(matrix, krylov_eigs):
targ_min = min(np.linalg.eig(matrix).eigenvalues)
err = []
for i in range(len(matrix)):
err.append(min(krylov_eigs[i]) - targ_min)
return err
import matplotlib.pyplot as plt
krylov_error = errors(test_matrix, test_eigs)
plt.plot(krylov_error)
plt.axhline(y=0, color="red", linestyle="--") # Add dashed red line at y=0
plt.xlabel("Order of Krylov subspace") # Add x-axis label
plt.ylabel("Error in minimum eigenvalue") # Add y-axis label
plt.show()
Wir sehen, dass der minimale Eigenwert recht genau erreicht wird, sobald der Krylov-Unterraum auf angewachsen ist, und bei exakt ist.
2.2 Zeitskalierung mit der Matrixdimension
Überzeugen wir uns davon, dass die Krylov-Methode gegenüber exakten numerischen Eigenwertlösern in folgender Weise vorteilhaft sein kann:
- Konstruiere Zufallsmatrizen (nicht dünn besetzt, also nicht der ideale Anwendungsfall für KQD)
- Bestimme Eigenwerte mit zwei Methoden: direkt mit NumPy und mittels eines Krylov-Unterraums.
- Wir wählen einen Grenzwert für die erforderliche Genauigkeit unserer Eigenwerte, bevor wir die Krylov-Schätzungen akzeptieren.
- Vergleiche die benötigte Wanduhrzeit für beide Methoden.
Vorbehalte: Wie wir weiter unten im Detail besprechen werden, wird Krylov-Quantendiagonalisierung am besten auf Operatoren angewendet, deren Matrixdarstellungen dünn besetzt sind und/oder mit einer kleinen Anzahl von Gruppen kommutierender Pauli-Operatoren geschrieben werden können. Die hier verwendeten Zufallsmatrizen erfüllen diese Bedingung nicht. Sie dienen lediglich dazu, die Größenordnung zu untersuchen, ab der klassische Krylov-Methoden nützlich sein könnten. Zweitens berechnen wir bei Verwendung der Krylov-Methode Eigenwerte mit vielen verschieden großen Krylov-Unterräumen. Wir geben die Zeit an, die für den minimal-dimensionalen Krylov-Unterraum benötigt wird, der unsere geforderte Genauigkeit für den Grundzustands-Eigenwert erreicht. Auch das unterscheidet sich etwas davon, ein Problem zu lösen, das für exakte Eigenwertalgorithmen unlösbar ist, da wir die exakte Lösung zur Beurteilung der benötigten Dimension heranziehen.
Wir beginnen damit, unsere Menge von Zufallsmatrizen zu erzeugen.
import numpy as np
# Set the random seed
np.random.seed(42)
# how many random matrices will we make
num_matrix = 200
matrices = []
for m in range(1, num_matrix):
matrices.append(np.random.rand(m, m))
Wir diagonalisieren nun jede Matrix direkt mit numpy. Wir berechnen die benötigte Zeit für den späteren Vergleich.
matrix_numpy_times = []
matrix_numpy_eigs = []
for mm in range(num_matrix - 1):
t0 = time_mus()
matrix_numpy_eigs.append(min(np.linalg.eig(matrices[mm]).eigenvalues))
matrix_numpy_times.append(time_mus() - t0)
plt.plot(matrix_numpy_times)
plt.xlabel("Dimension of matrix") # Add x-axis label
plt.ylabel("Time to diagonalize (microsec)") # Add y-axis label
plt.show()
Beachte, dass die anomal hohe Zeit im obigen Bild bei einer Dimension von etwa 125 auf die zufällige Natur der Matrizen oder auf die Implementierung auf dem verwendeten klassischen Prozessor zurückzuführen sein kann, sich aber nicht reproduzieren lässt. Wird der Code erneut ausgeführt, ergibt sich ein anderes Profil mit anderen anomalen Spitzen.
Für jede Matrix bauen wir nun schrittweise einen Krylov-Unterraum auf und berechnen die Eigenwerte in Schritten. Bei jedem Schritt prüfen wir, ob der kleinste Eigenwert innerhalb unseres festgelegten absoluten Fehlers erhalten wurde. Der Unterraum, der uns erstmals Eigenwerte innerhalb des festgelegten Fehlers liefert, ist der Unterraum, für den wir die Rechenzeiten notieren. Die Ausführung dieser Zelle kann je nach Prozessorgeschwindigkeit mehrere Minuten dauern. Du kannst die Auswertung überspringen oder die maximale Dimension der diagonalisierten Matrizen reduzieren. Die Betrachtung der vorberechneten Ergebnisse ist ausreichend.
# Choose the absolute error you can tolerate, and make a list for tracking the Krylov subspace size at which that error is achieved.
abserr = 0.05
accept_subspace_size = []
# Lists to store total time spent on the Krylov method, and the subset of that time spent on diagonalizing the projected matrix.
matrix_krylov_tot_times = []
matrix_krylov_dim = []
# Step through all our random matrices
for mm in range(0, num_matrix - 1):
test_ks, test_Hs, test_eigs, test_k_tot_times = krylov_full_build(
np.ones(len(matrices[mm])), matrices[mm]
)
# We have not yet found a Krylov subspace that produces our minimum eigenvalue to within the required error.
found = 0
for j in range(0, len(matrices[mm]) - 1):
# If we still haven't found the desired subspace...
if found == 0:
# ...but if this one satisfies the requirement, then record everything
if (
abs((min(test_eigs[j]) - matrix_numpy_eigs[mm]) / matrix_numpy_eigs[mm])
< abserr
):
accept_subspace_size.append(j)
matrix_krylov_tot_times.append(test_k_tot_times[j])
matrix_krylov_dim.append(mm)
found = 1
Stellen wir die für diese beiden Methoden ermittelten Zeiten zum Vergleich dar:
plt.plot(matrix_numpy_times, color="blue")
plt.plot(matrix_krylov_dim, matrix_krylov_tot_times, color="green")
plt.xlabel("Dimension of matrix") # Add x-axis label
plt.ylabel("Time to diagonalize (microsec)") # Add y-axis label
plt.show()
Dies sind die tatsächlich benötigten Zeiten. Für die Diskussion wollen wir diese Kurven jedoch glätten, indem wir über einige benachbarte Punkte bzw. Matrixdimensionen mitteln. Das geschieht im Folgenden:
smooth_numpy_times = []
smooth_krylov_times = []
# Choose the number of adjacent points over which to average forward; the same will be used backward.
smooth_steps = 10
# We will do this smoothing for all points/matrix dimensions
for i in range(len(matrix_krylov_tot_times)):
# Ensure we don't exceed the boundaries of our lists
start = max(0, i - smooth_steps)
end = min(len(matrix_krylov_tot_times) - 1, i + smooth_steps)
# Dummy variables for accumulating an average over adjacent points. This is done for both Krylov and the NumPy calculations.
smooth_count = 0
smooth_numpy_sum = 0
smooth_krylov_sum = 0
for j in range(start, end):
smooth_numpy_sum = smooth_numpy_sum + matrix_numpy_times[j]
smooth_krylov_sum = smooth_krylov_sum + matrix_krylov_tot_times[j]
smooth_count = smooth_count + 1
# Appending the averaged adjacent values to our new smooth lists
smooth_numpy_times.append(smooth_numpy_sum / smooth_count)
smooth_krylov_times.append(smooth_krylov_sum / smooth_count)
plt.plot(smooth_numpy_times, color="blue")
plt.plot(smooth_krylov_times, color="green")
plt.xlabel("Dimension of matrix") # Add x-axis label
plt.ylabel("Time to diagonalize (smoothed, microsec)") # Add y-axis label
plt.show()
Beachte, dass die für den Aufbau eines Krylov-Unterraums benötigte Zeit anfangs die für NumPys vollständige Diagonalisierung überschreitet. Doch mit zunehmender Matrixgröße wird die Krylov-Methode vorteilhafter. Das gilt auch, wenn wir unseren akzeptablen Fehler verringern, allerdings setzt der Vorteil dann bei einer größeren Matrixgröße ein. Es lohnt sich, das genauer zu untersuchen.
Die Zeitkomplexität der numerischen Diagonalisierung beträgt (mit gewissen Unterschieden zwischen den Algorithmen). Die Zeitkomplexität der Erzeugung einer Orthonormalbasis aus Vektoren ist ebenfalls . Der Vorteil der Krylov-Methode hängt also nicht mit der Verwendung Orthonormalbasis zusammen, sondern mit der Verwendung einer bestimmten Orthonormalbasis, die die Eigenwerte von Interesse effektiv herausgreift. Wir haben das bereits an der Skizze eines Beweises im ersten Abschnitt dieser Lektion gesehen, und das ist entscheidend für die Konvergenzgarantien in Krylov-Methoden.
Fassen wir unseren bisherigen Fortschritt zusammen:
- Für sehr große Matrizen kann die Krylov-Unterraummethode Näherungseigenwerte innerhalb geforderter Toleranzen schneller liefern als traditionelle Diagonalisierungsalgorithmen.
- Bei solch sehr großen Matrizen ist die Erzeugung eines Krylov-Unterraums der zeitaufwändigste Teil der Krylov-Unterraummethode.
- Daher wäre ein effizienter Weg zur Erzeugung eines Krylov-Unterraums von hohem Wert.
Genau hier kommt der Quantencomputer ins Spiel.
Teste dein Verständnis
Lies die folgende Frage, überlege dir deine Antwort und klicke dann auf das Dreieck, um die Lösung zu sehen.
Beziehe dich auf den geglätteten Plot der Diagonalisierungszeiten vs. Matrixdimension weiter oben.
(a) Bei welcher Matrixdimension wurde die Krylov-Methode laut diesem Plot ungefähr schneller?
(b) Welche Aspekte der Berechnung könnten diese Dimension verschieben, ab der die Krylov-Methode schneller wird?
Antwort:
(a) Die Antworten können variieren, wenn du die Berechnung erneut ausführst, aber die Krylov-Methode wird ab etwa Dimension 80–85 schneller. (b) Es gibt viele mögliche Antworten. Einige wichtige Faktoren sind die geforderte Genauigkeit und die Dünnbesetztheit der zu diagonalisierenden Matrizen.
3. Krylov via Zeitentwicklung
Alles, was wir bisher beschrieben haben, lässt sich klassisch durchführen. Wie und wann würden wir also einen Quantencomputer einsetzen? Bei sehr großen Matrizen kann die Krylov-Methode lange Rechenzeiten und große Mengen an Arbeitsspeicher erfordern. Die Zeit, die für die Matrixoperation von auf benötigt wird, skaliert im schlimmsten Fall wie . Selbst die Multiplikation dünnbesetzter Matrizen mit einem Vektor (der typische Fall für klassische Krylov-Löser) hat eine Zeitkomplexität, die wie skaliert. Dies wird für jeden Vektor durchgeführt, den wir in unserem Unterraum haben wollen. Die Unterraumdimension ist üblicherweise kein wesentlicher Bruchteil von und skaliert oft wie . Die Erzeugung aller Vektoren skaliert also im schlimmsten Fall wie . Obwohl es weitere Schritte wie die Orthogonalisierung gibt, ist dies die dominante Skalierung, die man im Blick behalten sollte.
Das Quantencomputing erlaubt es uns, die Attribute des Problems zu verändern, die die Skalierung des Zeit- und Ressourcenbedarfs bestimmen. Anstatt einer durchgängigen Abhängigkeit von der Matrixgröße werden wir Faktoren wie die Anzahl der Shots und die Anzahl der nicht-kommutierenden Pauli-Terme, aus denen der Hamiltonoperator besteht, sehen. Lass uns untersuchen, wie das funktioniert.
3.1 Zeitentwicklung
Erinnere dich daran, dass der Operator, der einen Quantenzustand zeitlich entwickelt, ist (und es ist sehr üblich, insbesondere im Quantencomputing, das aus der Notation wegzulassen). Eine Möglichkeit, eine solche Exponentialfunktion eines Operators zu verstehen und sogar zu realisieren, besteht darin, ihre Taylor-Reihenentwicklung zu betrachten. Beachte, dass diese Operation auf einen anfänglichen Vektor eine Summe von Termen mit zunehmenden Potenzen von ergibt, die auf den Anfangszustand angewendet werden. Es sieht so aus, als könnten wir unseren Krylov-Unterraum einfach durch Zeitentwicklung unseres anfänglichen Schätzzustands erzeugen!
Der Haken liegt in der Realisierung der Zeitentwicklung auf einem echten Quantencomputer. Viele der Terme im Hamiltonoperator werden nicht miteinander kommutieren. Während also einige einfache Exponentialoperatoren wie einfachen Circuits entsprechen, gilt das für allgemeine Hamiltonoperatoren nicht. Und da sie nicht-kommutierende Terme enthalten, können wir den Exponenten nicht einfach in ein Produkt einfacher zerlegen, wie wir es bei Zahlen tun könnten.
Das ist also nicht trivial, aber es handelt sich um einen gut untersuchten Prozess im Quantencomputing. Wir führen die Zeitentwicklung auf Quantencomputern mithilfe eines Verfahrens namens Trotterisierung durch, das selbst ein reichhaltiges Thema ist[10]. Aber auf sehr hohem Niveau: Indem wir die Zeitentwicklung in sehr kleine Schritte aufteilen, zum Beispiel Schritte der Größe , begrenzen wir die Auswirkungen der Nicht-Kommutativität der Terme.
wobei .
Nennen wir einen Krylov-Unterraum der Ordnung r, den wir im klassischen Kontext direkt mithilfe von Potenzen von H erzeugt haben, einen „Power-Krylov-Unterraum".
Jetzt erzeugen wir einen ähnlichen Raum mithilfe des unitären Zeitentwicklungsoperators ; wir bezeichnen diesen als den „unitären Krylov-Raum" . Der Power-Krylov-Unterraum , den wir klassisch verwenden, kann auf einem Quantencomputer nicht direkt erzeugt werden, da kein unitärer Operator ist. Es lässt sich zeigen, dass die Verwendung des unitären Krylov-Unterraums ähnliche Konvergenzgarantien wie der Power-Krylov-Unterraum bietet: Der Grundzustandsfehler konvergiert effizient, solange der Anfangszustand einen nicht exponentiell verschwindenden Überlapp mit dem wahren Grundzustand hat und solange eine ausreichende Lücke zwischen den Eigenwerten besteht. Eine genauere Diskussion der Konvergenz findest du in Ref [1].
Hier werden Potenzen von zu verschiedenen Zeitschritten (die Potenz von entspricht einem Vorwärtsschritt um die Zeit ). Wir können das Element des Unterraums, das für die Gesamtzeit zeitentwickelt wurde, als bezeichnen.
Wir können unseren Hamiltonoperator H auf den unitären Krylov-Unterraum projizieren. Mit anderen Worten: Wir berechnen jedes Matrixelement von in der -Basis. Wir bezeichnen diese projizierte Matrix als .
3.2 Implementierung auf einem Quantencomputer
Die Matrixelemente von sind durch die Erwartungswerte gegeben, die mithilfe des Quantencomputers geschätzt werden können. Bedenke, dass als Summe von Pauli-Operatoren auf verschiedenen Qubits geschrieben werden kann und dass nicht alle Pauli-Operatoren gleichzeitig gemessen werden können. Wir können die Pauli-Terme in Gruppen kommutierender Terme sortieren und alle auf einmal messen. Aber es kann viele solcher Gruppen brauchen, um alle Terme abzudecken. Daher wird die Anzahl der verschiedenen kommutierenden Gruppen, in die die Terme partitioniert werden können, , wichtig.
Hier ist ein Pauli-String der Form oder eine Menge solcher Pauli-Strings, die miteinander kommutieren. Da wir als solche Summe messbarer Operatoren schreiben können, lassen sich die folgenden Ausdrücke für Matrixelemente von mithilfe des Qiskit Runtime Primitiv Estimator realisieren.