Zum Hauptinhalt springen

SQD und SKQD

In diesem Kapitel erkunden wir, wie Quanten- und klassische Computer zusammenarbeiten, um eine der wichtigsten Herausforderungen der Wissenschaft zu bewältigen: die genaue Schätzung der Energie von Molekülen und Materialien.

Iskandar Sitdikov beschreibt den algorithmischen Ansatz im folgenden Video.

Hamiltonoperator

Der Schlüssel zu diesem Problem ist ein mathematischer Operator – der Hamiltonoperator, der die Gesamtenergie eines Systems beschreibt. Für Rechenzwecke kann man sich diesen Hamiltonoperator als eine große Matrix vorstellen. Die gesuchten Lösungen – insbesondere der Grundzustand des Systems – sind die niedrigsten Eigenwerte dieser Matrix. Die Herausforderung besteht jedoch darin, dass diese Hamiltonmatrix bei praktischen Problemen sehr groß ist. Sie wächst exponentiell mit der Systemgröße und wird schnell zu groß (2n2^n, wobei nn die Anzahl der Qubits ist), um selbst auf den leistungsfähigsten Supercomputern direkt gespeichert oder gelöst zu werden.

H=(H0,0H0,1H0,N1H1,0H1,1H1,N1HN1,0HN1,1HN1,N1)(N=2n)H = \begin{pmatrix} H_{0,0} & H_{0,1} & \cdots & H_{0,N-1} \\ H_{1,0} & H_{1,1} & \cdots & H_{1,N-1} \\ \vdots & \vdots & \ddots & \vdots \\ H_{N-1,0} & H_{N-1,1} & \cdots & H_{N-1,N-1} \end{pmatrix} \quad (N=2^n)

Um dieses Problem zu umgehen, verwenden wir eine wirkungsvolle Strategie, die als Unterraummethode bekannt ist. Anstatt die gesamte Matrix anzugehen, wählen wir intelligent einen kleinen, relevanten Ausschnitt – einen „Unterraum" –, von dem wir annehmen, dass er die wichtigsten Informationen über die gesuchte Niedrigenergie-Lösung enthält.

(Hi,j)Full HamiltonianProjectH~Projected Hamiltonian=(b1Hb1b1HbLbLHb1bLHbL)Diagonalize(E000EL1)Eigenvalues\underset{\text{Full Hamiltonian}}{\begin{pmatrix} \ddots & \vdots \\ \cdots & H_{i,j} & \cdots \\ & \vdots & \ddots \end{pmatrix}} \quad \xrightarrow{\text{Project}} \quad \underset{\text{Projected Hamiltonian}}{\tilde{H}} = \begin{pmatrix} \langle b_1 | H | b_1 \rangle & \cdots & \langle b_1 | H | b_L \rangle \\ \vdots & \ddots & \vdots \\ \langle b_L | H | b_1 \rangle & \cdots & \langle b_L | H | b_L \rangle \end{pmatrix} \quad \xrightarrow{\text{Diagonalize}} \quad \underset{\text{Eigenvalues}}{\begin{pmatrix} E_0 & & 0 \\ & \ddots & \\ 0 & & E_{L-1} \end{pmatrix}}

Sobald dieser kleine Unterraum durch eine Menge von Basiszuständen {bi}\{|b_i\rangle\} definiert ist, wird der vollständige Hamiltonoperator auf ihn projiziert, um die neue, kleinere Matrix H~\tilde{H} zu erzeugen. Jedes Element dieser Matrix wird aus den Unterraum-Basiszuständen und dem ursprünglichen Hamiltonoperator als biHbj\langle b_i | H | b_j \rangle berechnet. Diese kleine Matrix lässt sich dann auf einem klassischen Computer leicht diagonalisieren, und die resultierenden Eigenwerte sind unsere geschätzten Energien.

Wie du dir vorstellen kannst, hängt der Erfolg dieses gesamten Ansatzes stark von der Wahl eines „guten" Unterraums ab. Wenn unser Unterraum den wahren Grundzustand nicht gut repräsentiert, wird unser Endergebnis falsch sein. Hier kommen Quantencomputer ins Spiel: Sie ermöglichen es uns, komplexe Quantenzustände vorzubereiten und aus ihnen zu sampeln, die darauf ausgelegt sind, diese wichtigen Unterräume zu identifizieren. Bei sehr großen Problemen, wie komplexen chemischen Strukturen oder Bindungsstellen, kann selbst die projizierte Matrix noch schwierig zu diagonalisieren sein. Solche Probleme eignen sich daher ideal, um die Stärken von Quanten- und klassischen Rechenressourcen zu kombinieren.

In den folgenden Abschnitten erkunden wir zwei fortgeschrittene Algorithmen – SQD und SKQD –, die Quantenmechanik nutzen, um diese Unterräume zu finden und aufzubauen. Für eine tiefere Betrachtung gibt es einen vollständigen Kurs auf IBM Quantum Learning, der diesen Themen im Detail gewidmet ist. Im Rahmen dieses Kurses halten wir die Erklärung auf einem übergeordneten Niveau.

Sample-based Quantum Diagonalization

Sample-based Quantum Diagonalization (SQD) ist ein leistungsstarker variationaler Algorithmus, der die Unterraummethode auf quantenmechanische Weise umsetzt. Er vermeidet aufwendige, komplexe Verfahren wie Hadamard-Tests, indem er einen Quantencomputer verwendet, um einen Testzustand vorzubereiten und Bitstrings zu sampeln, die den Unterraum für die klassische Diagonalisierung definieren.

Ein Schema des Workflows der stichprobenbasierten Quantendiagonalisierung. Die Schritte umfassen einen variationalen Quantencircuit, die Verwendung von Messungen zur Projektion des Hamiltonoperators in einen Unterraum und dann einen klassischen Optimierer zur Aktualisierung der variationalen Parameter im Circuit, gefolgt von einer Wiederholung.

Der SQD-Algorithmus lässt sich in folgende Schritte aufteilen:

Schritt 1: Ansatz-Zustand vorbereiten

Sei H=j=1QαjPjH = \sum_{j=1}^Q \alpha_j P_j der Hamiltonoperator auf nn Qubits. Obwohl der wahre Grundzustand auf allen 2n2^n Basiszuständen liegen kann, ist SQD am effektivsten in Fällen, in denen der Grundzustand gut durch einen spärlichen Unterraum (eine polynomiell große Menge von Bitstrings) approximiert werden kann.

Um diesen Unterraum zu konstruieren, beginnen wir mit einem Eingangszustand ϕ0|\phi_0\rangle, beispielsweise dem Hartree-Fock-(HF-)Zustand in der Chemie. Dann wenden wir einen parametrisierten Quantencircuit U(θ)U(\theta) an, der als Ansatz bezeichnet wird.

Ein Diagramm, das die Überlappung der Rechenbasisvektoren des Ansatzes mit denen des wahren Grundzustands zeigt. Konkret zeigt das Bild, dass die beiden Regionen eine gewisse Überlappung aufweisen, aber möglicherweise nicht perfekt übereinstimmen.

Dieses Diagramm veranschaulicht das Ziel eines guten Ansatzes. Der Ansatz bereitet einen Quantenzustand vor, dessen Träger (die Menge der Basiszustände, aus denen er besteht) idealerweise eine große Überlappung mit dem Träger des wahren Grundzustands haben sollte. Dieser Circuit ermöglicht es uns, den Ansatz schnell auf Rechenbasisvektoren zu projizieren, die in der klassischen Diagonalisierung weiterverwendet werden. Anders gesagt: Wir müssen keinen Ansatz erraten, der dem Grundzustand entspricht; wir brauchen nur, dass er dieselben Basiszustände enthält. Die klassische Diagonalisierung des projizierten Hamiltonoperators liefert uns dann die Superposition von Basiszuständen, die den Grundzustand am besten approximiert.

Schritt 2: Den Unterraum sampeln

Durch das Sampeln aus dem vom Ansatz vorbereiteten Circuit erhalten wir eine Sammlung von Bitstrings {bj}j=1L\{b_j\}_{j=1}^L. Diese Bitstrings definieren die Basis unseres gewählten Unterraums. Die Quantenlaufzeit für diesen Schritt wird durch die Tiefe des Circuits und die Anzahl der entnommenen Stichproben bestimmt.

Schritt 3: Klassisch projizieren und diagonalisieren

Mithilfe der gesampelten Bitstrings projizieren wir den Hamiltonoperator in den von ihnen aufgespannten Unterraum. Für jedes Paar von Bitstrings (j,k)(j, k) berechnen wir klassisch das Matrixelement H~jk=bjHbk\tilde{H}_{jk} = \langle b_j | H | b_k \rangle. Da Pauli-Operatoren sparse sind, ist dieser Schritt für physikalische Hamiltonoperatoren klassisch effizient. Die resultierende kleine Matrix H~\tilde{H} wird dann auf einem klassischen Prozessor diagonalisiert, um den Grundzustand und seine Energie abzuschätzen.

Schritt 4: Den Ansatz optimieren (optional)

Der Prozess kann iterativ gestaltet werden. Indem wir die geschätzte Grundzustandsenergie als Kostenfunktion behandeln, können wir die Circuit-Parameter (θ\theta) mithilfe von Methoden wie dem Gradientenabstieg optimieren, um den Ansatz und damit die Energieapproximation in der nächsten Iteration zu verbessern.

Wesentliche Vorteile von SQD

SQD bietet mehrere leistungsstarke Eigenschaften, die es zu einem führenden Kandidaten für den Nachweis von Quantenvorteil machen:

  • Starke Robustheit gegenüber Rauschen: Angenommen, der wahre Grundzustand stützt sich nur auf zwei Bitstrings. Wenn diese überhaupt gesampelt werden – selbst wenn ihre Überlappung mit unserem Ansatz klein ist –, weist die Diagonalisierung ihnen die entsprechenden Gewichtungen zu und ignoriert effektiv alle anderen überflüssigen, verrauschten Bitstrings, die möglicherweise ebenfalls gesampelt wurden. Diese inhärente Filterung macht SQD besonders rauschrobust.
  • Klassische Verifizierbarkeit: Anders als QPE oder VQAs liefert SQD eine klassische Approximation an den Grundzustand. Das bedeutet, dass jeder, der die Liste der Bitstrings und ihre Gewichtungen kennt, die Energieschätzung direkt auf einem klassischen Computer nachrechnen und überprüfen kann.

SQD wurde bereits eingesetzt, um die Grundzustands-Dissoziationsenergie von N2_2 und die elektronischen Eigenschaften von [2Fe-2S]- und [4Fe-4S]-Clustern [2] zu schätzen, mit Circuits mit bis zu 77 Qubits und 10.570 Gates.

Verständnisfragen

Wahr oder Falsch: SQD kann auf chemische Systeme angewendet werden.

Antwort:

Wahr

Verständnisfragen

Nenne die Menge aller Rechenbasisvektoren deines Ansatzes AA. Nenne die Menge aller Rechenbasisvektoren des wahren Grundzustands deines Systems GG. Welche der folgenden Aussagen entspricht einem „guten" Ansatz? Wähle alle zutreffenden aus.

(a) AGA \subset G \\ (b) AGA \subseteq G\\ (c) GAG \subset A\\ (d) GAG \subseteq A\\

Antwort:

(c) und (d)

SKQD (Sample-based Krylov Quantum Diagonalization)

Sample-based Krylov Quantum Diagonalization (SKQD) ist ein weiterer leistungsstarker quantenbasierter Stichprobenalgorithmus, der auf den Prinzipien von SQD aufbaut. Obwohl sein Ziel dasselbe ist – einen guten Unterraum für die Diagonalisierung zu finden –, verwendet SKQD eine strukturiertere Methode zur Erzeugung der Bitstrings, insbesondere für Probleme wie Gitter-Hamiltonoperatoren.

Der Kerngedanke von SKQD ist, dass anstelle der Optimierung eines parametrisierten Circuits für einen guten Ansatz nachweislich Konvergenz zum Grundzustand erreicht werden kann, indem aus einer Menge von Zuständen gesampelt wird, die durch die natürliche Zeitentwicklung des Systems selbst erzeugt werden – dem Krylov-Unterraum. Der SKQD-Algorithmus lässt sich in folgende Schritte aufteilen:

Schritt 1: Den Krylov-Unterraum mit Zeitentwicklung aufbauen

Der Prozess beginnt mit einem Anfangszustand ϕ0|\phi_0\rangle. Wichtig ist, dass dieser Anfangszustand keine „gute" Überlappung mit dem Grundzustand aufweisen muss. Er muss lediglich „polynomiell groß" sein, d. h. durch ein Polynom in der Systemgröße beschreibbar sein. Der Algorithmus selbst treibt den Zustand dann immer näher an den Grundzustand des Systems heran. SKQD wendet den Zeitentwicklungsoperator eiHte^{-iHt} für verschiedene Zeitlängen an. Damit wird eine Menge von dd verschiedenen Quantenzuständen erzeugt, definiert als:

ϕj=eiδtjHϕ0,fu¨j=0,1,,d1|\phi_j\rangle = e^{-i \,\delta t j H}|\phi_0\rangle, \quad \text{für } j = 0, 1, \dots, d-1 \quad \text{}

Diese Sammlung zeitentwickelter Zustände bildet eine Krylov-Basis. Dieser Schritt ist besonders effektiv für Gitter-Hamiltonoperatoren, bei denen die Anzahl der Terme im Hamiltonoperator nicht groß ist. Bei Chemieproblemen kann diese Zeitentwicklung zu sehr tiefen Circuits führen, weshalb für solche Fälle SQD oft empfohlen wird.

Schritt 2: Aus den Krylov-Basiszuständen sampeln

Als nächstes werden Bitstring-Stichproben aus jedem der dd verschiedenen Zustände (ϕ0,ϕ1,,ϕd1|\phi_0\rangle, |\phi_1\rangle, \dots, |\phi_{d-1}\rangle) gesammelt, die im vorherigen Schritt vorbereitet wurden. Alle diese Bitstrings werden dann zusammengeführt, um die Basis für den Unterraum zu bilden.

Schritt 3: Klassisch projizieren und diagonalisieren

Dieser Schritt ist identisch mit dem entsprechenden Schritt in SQD. Die gesammelten Bitstrings werden verwendet, um den vollständigen Hamiltonoperator auf den von ihnen aufgespannten Unterraum zu projizieren. Die resultierende kleine Matrix H~\tilde{H} wird dann auf einem klassischen Computer diagonalisiert, um die Grundzustandsenergie zu finden.

Wesentliche Vorteile und Garantien von SKQD

Der strukturierte Ansatz von SKQD bietet einzigartige Vorteile:

  • Nachweisbare Konvergenz: Der Hauptvorteil von SKQD ist seine theoretische Konvergenzgarantie unter spezifischen, klar definierten Bedingungen. Wenn der wahre Grundzustand sparse ist (gut durch eine polynomielle Anzahl von Bitstrings approximiert werden kann) und die Energielücke zum ersten angeregten Zustand nicht zu klein ist, ist die Methode nachweislich effizient. Unter diesen Bedingungen garantiert SKQD, dass es die entscheidenden Bitstrings findet, aus denen der Grundzustand besteht, und kann die Grundzustandsenergie mit hoher Genauigkeit approximieren. Dafür ist lediglich eine polynomielle Anzahl von Quantenexperimenten und Shots erforderlich. Diese Garantie stellt den stichprobenbasierten Ansatz auf eine rigorose theoretische Grundlage, ähnlich wie etablierte Methoden wie die Quantenphasenschätzung.

  • Gemeinsame Vorteile mit SQD: Ähnlich wie SQD besitzt SKQD ebenfalls die Eigenschaft der Rauschrobustheit. Das heißt: Solange alle guten Bitstrings in der Menge der gesampelten Bitstrings vorhanden sind, weist die Diagonalisierung falschen Bitstrings nahezu null Gewicht zu, was das Verfahren robust gegenüber Rauschen macht. Da die Lösung zudem von einem klassischen HPC erzeugt wird, ist die Energie der Lösung klassisch verifizierbar.

In Experimenten wurde SKQD mit bis zu 70 Qubits und Tausenden von Gates eingesetzt, um den Grundzustand komplexer 4-Störstellen-Anderson-Modelle zu untersuchen, und erzielte dabei hervorragende Übereinstimmung mit hochmodernen klassischen Methoden wie DMRG.[1]

Verständnisfragen

Welcher Teil des SKQD-Algorithmus macht ihn für physikalische Probleme wie Spin-Gitter geeigneter als für chemische Probleme? Warum?

Antwort:

Die Zeitentwicklung erfordert Trotter-Circuits, die für komplizierte und nicht-sparse Hamiltonoperatoren sehr tief sind. Spin-Gitter-Wechselwirkungen werden durch Spin-Matrizen beschrieben, die den Pauli-Matrizen entsprechen. Daher lassen sich die Hamiltonoperatoren für Spin-Gitter kompakter in Pauli-Matrizen ausdrücken, insbesondere bei Wechselwirkungen mit nächsten Nachbarn.

SQD und SKQD als heterogenes Computing

Um alles zusammenzuführen, können wir stichprobenbasierte Algorithmen als eine Kombination verschiedener Programmiermodelle auf einer Menge heterogener Ressourcen darstellen. Wir können unseren Algorithmus beispielsweise als einen Task-Workflow repräsentieren.

Ein Schema des Workflows der stichprobenbasierten Quantendiagonalisierung. Die Schritte umfassen einen variationalen Quantencircuit, die Verwendung von Messungen zur Projektion des Hamiltonoperators in einen Unterraum und dann einen klassischen Optimierer zur Aktualisierung der variationalen Parameter im Circuit, gefolgt von einer Wiederholung.

Diese Abbildung veranschaulicht den grundlegenden viergestuften Workflow. Zunächst gibt es einen Task für die Quantencircuit-Vorbereitung, der mit unserem Zielzustand überlappt, gefolgt von einem Task für die Transpilation, der nur klassische Ressourcen erfordert. Als nächstes folgt ein Task, der Primitiven verwendet, um unseren Quantencircuit auszuführen, und der Quantenressourcen benötigt. Schließlich gibt es einen Post-Processing-Task, der selbst ein paralleler Diagonalisierungsalgorithmus sein kann, der auf mehreren Knoten läuft.

Außerdem kann es sinnvoll sein, einen dieser Algorithmen mehrmals auszuführen, während wir unseren Ansatz variieren, oder sie vollständig parallel mit verschiedenen Populationen auszuführen.

Ein Schema einer SQD-Arbeitslast, die auf mehrere Ressourcen aufgeteilt ist. Es zeigt mehrere Prozesse, die sequentiell ablaufen, wobei die Ergebnisse einer Iteration die nächste informieren, aber auch viele solcher Prozesse parallel ausgeführt werden.

Wie oben dargestellt, kannst du mehrere Workflows gleichzeitig ausführen und dabei Folgendes tun:

  • Die Parameter oder die Struktur des Ansatzes variieren, um den effektivsten zu finden.
  • Mit verschiedenen Anfangszuständen oder Konfigurationen („Populationen") starten, um lokale Minima zu vermeiden und ein robusteres Ergebnis sicherzustellen.

Dieser mehrschichtige Ansatz, der task-basierte Heterogenität mit workflow-weitem Parallelismus kombiniert, ist der Schlüssel zur vollen Ausschöpfung des Potenzials dieser Algorithmen.

Programmierpraxis

Üben wir nun den SKQD-Algorithmus und demonstrieren dabei den zuvor beschriebenen heterogenen Workflow. Der Prozess ist in vier verschiedene Stufen unterteilt, jede mit einem eigenen Python-Skript und einem zugehörigen Shell-Skript zur Job-Einreichung.

Mapping (mapping.py und mapping.sh)

Der erste Schritt in unserem Workflow besteht darin, das physikalische Problem zu definieren und auf eine Menge von Quantencircuits abzubilden.

mapping.py definiert die Parameter für ein spezifisches Physikproblem – in diesem Fall ein Anderson-Störstellen-Modell mit sieben Bad-Sites (n_bath = 7). Es konstruiert die Einzel-Körper-(h1e)- und Zwei-Körper-(h2e)-Integrale, die den Hamiltonoperator des Systems beschreiben.


...

n_bath = 7 # number of bath sites

...

# One body matrix elements in the "position" basis
h1e = -t * np.diag(np.ones(n_bath), k=1) - t * np.diag(np.ones(n_bath), k=-1)
h1e[impurity_index, impurity_index + 1] = -V
h1e[impurity_index + 1, impurity_index] = -V
h1e[impurity_index, impurity_index] = eps

# Two body matrix elements in the "position" basis
h2e = np.zeros((n_bath + 1, n_bath + 1, n_bath + 1, n_bath + 1))
h2e[impurity_index, impurity_index, impurity_index, impurity_index] = U

...

# The one-body time evolution
free_fermion_evolution = ffsim.qiskit.OrbitalRotationJW(n_modes, Utar)

# The two-body time evolution
def append_diagonal_evolution(dt, U, impurity_qubit, num_orb, q_circuit):
"""Append two-body time evolution to a quantum circuit."""
if U != 0:
q_circuit.append(
CPhaseGate(-dt / 2 * U),
[impurity_qubit, impurity_qubit + num_orb],
)

Anschließend erzeugt das Skript die für den SKQD-Algorithmus benötigten Quantencircuits. Es beginnt mit der Erstellung eines Anfangszustands (initial_state) und wendet dann Zeitentwicklungsoperatoren für eine variable Anzahl von Schritten (d = 8) an, um die verschiedenen Krylov-Basiszustände ϕj=(eiHt)jϕ0|\phi_j\rangle = (e^{-iHt})^j |\phi_0\rangle zu erzeugen.


# The reference state
def initial_state(q_circuit, norb, nocc):
"""Prepare an initial state."""
for i in range(nocc):
q_circuit.append(XGate(), [i])
q_circuit.append(XGate(), [norb + i])
rot = XXPlusYYGate(np.pi / 2, -np.pi / 2)

for i in range(3):
for j in range(nocc - i - 1, nocc + i, 2):
q_circuit.append(rot, [j, j + 1])
q_circuit.append(rot, [norb + j, norb + j + 1])
q_circuit.append(rot, [j + 1, j + 2])
q_circuit.append(rot, [norb + j + 1, norb + j + 2])

...

# Generate the initial state
qubits = QuantumRegister(2 * n_modes, name="q")
init_state = QuantumCircuit(qubits)
initial_state(init_state, n_modes, n_modes // 2)

...

d = 8 # Number of Krylov basis states
circuits = []
for i in range(d):
circ = init_state.copy()
circuits.append(circ)
for _ in range(i):
append_diagonal_evolution(dt, U, impurity_index, n_modes, circ)
circ.append(free_fermion_evolution, qubits)
append_diagonal_evolution(dt, U, impurity_index, n_modes, circ)
circ.measure_all()

print(circuits[0].draw(scale=0.4, fold=-1))

Das Skript speichert die Liste der 8 erzeugten Circuits (jeweils mit angehängten Messungen) in einer Datei namens circuits.qpy.

mapping.sh ist ein Slurm-Batch-Skript, das zur Einreichung des mapping.py-Jobs verwendet wird. Da es sich um eine klassische Berechnung handelt, werden Ressourcen aus einer Standard-CPU-Partition angefordert (--partition=normal).

#!/bin/bash
#
#SBATCH --job-name=sqd-mapping
#SBATCH --output=sqd-mapping.out
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=1
#SBATCH --partition=normal

srun python /data/ch4/sqd/mapping.py

Optimierung (optimization.py und optimization.sh)

Sobald wir unsere Circuits haben, müssen sie optimiert und kompiliert werden, damit sie effizient auf der Ziel-Quantenhardware laufen können.

In optimization.py lädt das Skript zunächst die in der Mapping-Stufe erstellte Datei circuits.qpy und ruft Quantenressourceninformationen über QRMI(), einen Quantenressourcenmanager, ab. Anschließend verwendet es Qiskits generate_preset_pass_manager mit einem hohen Optimierungsgrad (optimization_level=3), um die abstrakten, logischen Circuits in ISA-Circuits (Instruction Set Architecture) umzuwandeln. Dieser Prozess schreibt die Circuits mithilfe der nativen Gates der Hardware um und optimiert sie, um die Tiefe zu reduzieren und Fehler zu minimieren.


...
qrmi = QRMI()
resources = qrmi.resources()
quantum_resource = resources[0]
target = quantum_resource.target

pass_manager = generate_preset_pass_manager(
optimization_level=3,
target=target
)
isa_circuits = pass_manager.run(circuits)

Die transpilierten, hardwarebereiten Circuits werden in einer neuen Datei isa_circuits.qpy gespeichert.

Ähnlich wie beim Mapping-Skript läuft dieser Slurm-Job ebenfalls auf einer klassischen CPU-Partition (--partition=normal), da Transpilation eine klassische Aufgabe ist.

#!/bin/bash
#
#SBATCH --job-name=sqd-mapping
#SBATCH --output=sqd-mapping.out
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=1
#SBATCH --partition=normal

srun python /data/ch4/sqd/mapping.py

Ausführung (execution.py und execution.sh)

Dies ist die einzige Stufe, in der ein Quantencomputer verwendet wird. Hier werden die optimierten Circuits ausgeführt und Messungsstichproben gesammelt.

execution.py lädt die optimierte Datei isa_circuits.qpy und initialisiert dann einen SamplerV2-Primitiv, der mit einer Quantenressource verbunden ist. Anschließend ruft es sampler.run() auf, um die Circuits auf dem QPU für eine angegebene Anzahl von Shots auszuführen (shots=500).


...

qrmi = QRMI()
resources = qrmi.resources()
quantum_resource = resources[0]

# Sample from the circuits
noisy_sampler = Sampler(quantum_resource)
job = noisy_sampler.run(isa_circuits, shots=500)

Am Ende der Ausführung werden die gemessenen Ergebnisse (Bitstrings) aus allen Circuits gesammelt und zusammengeführt, und ihre Counts werden in einer Datei counts.json gespeichert.

Das Slurm-Skript execution.sh unterscheidet sich in dieser Stufe von den anderen. Es fordert an, auf der Quanten-Partition ausgeführt zu werden (--partition=quantum) und fordert speziell einen QPU an (--gres=qpu:1).

#!/bin/bash
#
#SBATCH --job-name=sqd-execution
#SBATCH --output=sqd-execution.out
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=1
#SBATCH --partition=quantum
#SBATCH --gres=qpu:1

srun python /data/ch4/sqd/execution.py

Post-Processing (postprocessing.py und postprocessing.sh)

Im letzten Schritt kehren wir zum klassischen Computer zurück, um die Daten aus dem Quantenexperiment zu analysieren und das Endergebnis zu berechnen: die Grundzustandsenergie unseres Zielsystems.

postprocessing.py liest zunächst die Datei counts.json mit den Messergebnissen. Dann rekonstruiert es den Hamiltonoperator des Anderson-Modells (mit denselben Parametern wie in mapping.py). Anschließend übergibt es die gemessenen Bitstrings und die Hamiltonoperator-Definition an die Funktion diagonalize_fermionic_hamiltonian. Diese Funktion führt die Kern-SKQD-Logik aus: Sie verwendet die Bitstrings, um den projizierten Hamiltonoperator H~\tilde{H} aufzubauen, und diagonalisiert ihn, um die Grundzustandsenergie zu finden.


...

def callback(results: list[SCIResult]):
result_history.append(results)
iteration = len(result_history)
print(f"Iteration {iteration}")
for i, result in enumerate(results):
print(f"\tSubsample {i}")
print(f"\t\tEnergy: {result.energy}")
print(f"\t\tSubspace dimension: {np.prod(result.sci_state.amplitudes.shape)}")

rng = np.random.default_rng(24)
result = diagonalize_fermionic_hamiltonian(
h1e,
h2e,
bit_array,
samples_per_batch=300,
norb=n_modes,
nelec=nelec,
num_batches=3,
max_iterations=10,
symmetrize_spin=True,
callback=callback,
seed=rng,
)

Abschließend gibt es die berechnete SKQD-Energie aus und vergleicht sie mit der bekannten exakten Energie für dieses Problem, wodurch der endgültige absolute Fehler der Berechnung angezeigt wird.

Das abschließende Job-Skript läuft auf einer klassischen Partition (--partition=normal), da alle Analysen klassischer Natur sind. Bei großen Unterräumen kann dieser Schritt mehr klassische HPC-Ressourcen erfordern.

#!/bin/bash
#
#SBATCH --job-name=sqd-postprocessing
#SBATCH --output=sqd-postprocessing.out
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=1
#SBATCH --partition=normal

srun python /data/ch4/sqd/postprocessing.py

Zusammenfassung

Das war's! Wir haben jetzt mehrere Konzepte und Beispiele durchgearbeitet, die dir den Einstieg in das Management komplexer hybrider Programme erleichtern können. Natürlich ist dies erst der Anfang dessen, was du mit der Kombination aus Quanten- und klassischen HPC-Ressourcen erreichen kannst.

Um weitere Anwendungsfälle und Algorithmen zu erkunden, besuche unsere Dokumentation und Tutorials auf der IBM Quantum Platform, und schau dir unbedingt die in der nächsten Lektion geteilten Ressourcen an, um mehr Informationen zu Algorithmen und Software für Computerwissenschaftler und Rechenzentrumadministratoren zu erhalten.

Referenzen

[1] Quantum-Centric Algorithm for Sample-Based Krylov Diagonalization. https://arxiv.org/abs/2501.09702

[2] Chemistry beyond the scale of exact diagonalization on a quantum-centric supercomputer. https://www.science.org/doi/10.1126/sciadv.adu9991