Skip to main content
IBM Quantum Platform

Sample-basierte Krylov-Quanten-Diagonalisierung (SKQD)

Diese Lektion über Sample-basierte Krylov-Quanten-Diagonalisierung (SKQD) kombiniert Methoden, die in früheren Methoden erklärt wurden. Es besteht aus einem einzigen Beispiel, das das Qiskit-Muster-Framework nutzt:

  • Schritt 1: Abbildung des Problems auf Quantenschaltungen und -operatoren
  • Schritt 2: Optimieren für die Zielhardware
  • Schritt 3: Ausführung mithilfe von „ IBM Quantum “-Primitiven
  • Schritt 4: Nachbearbeitung

Ein wichtiger Schritt bei der stichprobenbasierten Quantendiagonalisierungsmethode ist die Erzeugung von Qualitätsvektoren für den Unterraum. In der vorigen Lektion haben wir den LUCJ-Ansatz verwendet, um Unterraumvektoren für einen Chemie-Hamiltonian zu erzeugen. In dieser Lektion werden wir Quanten-Krylov-Zustände [1] verwenden, wie sie in Lektion 2 besprochen wurden. Zunächst werden wir uns ansehen, wie man den Krylov-Raum auf einem Quantencomputer mit Hilfe von Zeitentwicklungsoperationen erzeugt. Daraus werden wir dann Proben entnehmen. Wir projizieren den System-Hamiltonianer auf den abgetasteten Unterraum und diagonalisieren ihn, um die Grundzustandsenergie zu schätzen. Der Algorithmus konvergiert nachweislich und effizient zum Grundzustand, unter den in Lektion 2 beschriebenen Annahmen.


0. Der Krylov-Raum

Ein Krylov-Raum Kr\mathcal{K}^r der Ordnung rr ist der Raum, der von Vektoren aufgespannt wird, die durch Multiplikation höherer Potenzen einer Matrix AA bis zu r−1r-1 mit einem Referenzvektor ∣v⟩\vert v \rangle erhalten werden.

Kr={∣v⟩,A∣v⟩,A2∣v⟩,...,Ar−1∣v⟩}\mathcal{K}^r = \left\{ \vert v \rangle, A \vert v \rangle, A^2 \vert v \rangle, ..., A^{r-1} \vert v \rangle \right\}

Wenn die Matrix AA der Hamiltonian HH ist, wird der entsprechende Raum als Potenz-Krylov-Raum KP\mathcal{K}_P bezeichnet. Ist AA der Zeitentwicklungsoperator, der durch den Hamiltonianer U=e−iH(dt)U=e^{-iH(dt)} erzeugt wird, so wird der Raum als unitärer Krylov-Raum KU\mathcal{K}_U bezeichnet. Der Potenz-Krylov-Unterraum kann nicht direkt auf einem Quantencomputer erzeugt werden, da HH kein unitärer Operator ist. Stattdessen können wir den Zeit-Evolutions-Operator U=e−iH(dt)U = e^{-iH(dt)} verwenden, der nachweislich ähnliche Konvergenzgarantien bietet wie der Krylov-Powerraum. Potenzen von UU werden dann zu verschiedenen Zeitschritten Uk=e−iH(kdt)U^k = e^{-iH(k dt)}, wobei k=0,1,2,...,(r−1)k = 0, 1, 2, ..., (r-1).

KUr={∣ψ⟩,U∣ψ⟩,U2∣ψ⟩,...,Ur−1∣ψ⟩}\mathcal{K}_U^r = \left\{ \vert \psi \rangle, U \vert \psi \rangle, U^2 \vert \psi \rangle, ..., U^{r-1} \vert \psi \rangle \right\}

1. Problem auf Quantenschaltungen und Operatoren abbilden

In dieser Lektion betrachten wir den Hamiltonian für die antiferromagnetische XX-Z spin-1/2 Kette mit L=22L = 22 Stellen mit der periodischen Randbedingung:

H=∑i,jNJxy(XiXj+YiYj)+ZiZj H = \sum_{i, j}^{N} J_{xy} (X_{i} X_{j} + Y_{i} Y_{j}) + Z_{i} Z_{j}
from qiskit.transpiler import CouplingMap
from qiskit_addon_utils.problem_generators import generate_xyz_hamiltonian

num_spins = 22
coupling_map = CouplingMap.from_ring(num_spins)
H_op = generate_xyz_hamiltonian(coupling_map, coupling_constants=(0.3, 0.3, 1.0))

Um den Krylov-Raum zu konstruieren, benötigen wir drei Hauptbestandteile:

  1. Eine Wahl der Krylov-Dimension ( rr ) und des Zeitschritts ( dtdt ).
  2. Ein Anfangszustand (Referenzzustand) (Vektor ∣v⟩\vert v \rangle oben) mit polynomialer Überlappung mit dem Zielzustand (Grundzustand), wobei der Zielzustand spärlich ist. Diese Anforderung an die polynomiale Überlappung ist dieselbe wie beim Algorithmus zur Quantenphasenschätzung.
  3. Operatoren der zeitlichen Entwicklung Uk=e−iH(k∗dt)U^{k}=e^{-iH(k * dt)} ( k=0,1,2,...,r−1k = 0, 1, 2, ..., r-1 ).

Für einen gewählten Wert von rr (und dtdt ) werden wir rr separate Quantenschaltungen erstellen und daraus eine Stichprobe ziehen. Jeder Quantenkreis wird durch die Verknüpfung der Quantenkreisdarstellung des Referenzzustands und des Zeitentwicklungsoperators für einen kk Wert erstellt.

Eine größere Krylov-Dimension verbessert die Konvergenz der geschätzten Energie. In dieser Lektion setzen wir die Dimension auf 55, um den Konvergenztrend zu veranschaulichen.

In [2] wurde gezeigt, dass ein hinreichend kleiner Zeitschritt für KQD π/∣∣H∣∣\pi / \vert \vert H \vert \vert ist und dass es besser ist, diesen Wert zu unterschätzen, als ihn zu überschätzen. Andererseits führt eine zu kleine Wahl von dtdt zu einer schlechteren Konditionierung des Krylov-Unterraums, da sich die Krylov-Basisvektoren von Zeitschritt zu Zeitschritt weniger unterscheiden. Darüber hinaus ist diese Wahl von dtdt zwar nachweislich angemessen für die Konvergenz von SKQD, aber in diesem auf Stichproben basierenden Kontext ist die optimale Wahl von dtdt in der Praxis ein Thema, das derzeit untersucht wird. In dieser Lektion stellen wir dt=0.15dt = 0.15 ein.

Neben der Krylov-Dimension und dem Zeitschritt müssen wir auch die Anzahl der Trotter-Schritte für die Zeitentwicklung festlegen. Die Verwendung von zu wenigen Schritten führt zu größeren Trotterisierungsfehlern, während zu viele Schritte zu tieferen Schaltungen führen. In dieser Lektion setzen wir die Anzahl der Trotterschritte auf 66.

# Set parameters for quantum Krylov algorithm
krylov_dim = 5  # size of krylov subspace
dt = 0.15
num_trotter_steps = 6

Als Nächstes müssen wir einen Referenzzustand ∣ψ⟩\vert \psi \rangle auswählen, der eine gewisse Überschneidung mit dem Grundzustand aufweist. Für diesen Hamiltonian verwenden wir den Neel-Zustand mit abwechselnden 1s und 0s ∣...101...010...101⟩\vert ...101...010...101 \rangle als Referenzzustand.

# Prep `Neel` state as the reference state for evolution
from qiskit import QuantumCircuit

qc_state_prep = QuantumCircuit(num_spins)
for i in range(num_spins):
    if i % 2 == 0:
        qc_state_prep.x(i)

Schließlich müssen wir den Zeitentwicklungsoperator auf eine Quantenschaltung übertragen. Dies wurde in Lektion 2 getan, aber hier werden wir die Methoden in Qiskit nutzen, insbesondere eine Methode namens Synthese. Es gibt verschiedene Methoden zur Synthese von mathematischen Operatoren zu Quantenschaltungen mit Quantengattern. Viele solcher Techniken sind im Qiskit-Synthesemodul verfügbar. Wir verwenden den LieTrotter ansatz für die Synthese [3] [4].

from qiskit.circuit import QuantumRegister
from qiskit.circuit.library import PauliEvolutionGate
from qiskit.synthesis import LieTrotter

evol_gate = PauliEvolutionGate(
    H_op, time=(dt / num_trotter_steps), synthesis=LieTrotter(reps=num_trotter_steps)
)  # `U` operator

qr = QuantumRegister(num_spins)
qc_evol = QuantumCircuit(qr)
qc_evol.append(evol_gate, qargs=qr)

circuits = []
for rep in range(krylov_dim):
    circ = qc_state_prep.copy()

    # Repeating the `U` operator to implement U^0, U^1, U^2, and so on, for power Krylov space
    for _ in range(rep):
        circ.compose(other=qc_evol, inplace=True)

    circ.measure_all()
    circuits.append(circ)
circuits[1].decompose().draw("mpl", fold=-1)

Output:

Output of the previous code cell
circuits[2].decompose().draw("mpl", fold=-1)

Output:

Output of the previous code cell

2. Für die Zielhardware optimieren

Nachdem wir nun die Schaltungen erstellt haben, können wir sie für eine Zielhardware optimieren. Wir entscheiden uns für eine QPU im Versorgungsmaßstab.

import warnings

from qiskit import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService

warnings.filterwarnings("ignore")

service = QiskitRuntimeService()
# Use the least-busy backend or specify a quantum computer using the syntax commented out below.
backend = service.least_busy(operational=True, simulator=False)
# backend = service.backend("ibm_brisbane")

Nun werden die Schaltkreise mithilfe eines voreingestellten Pass-Managers in das Ziel-Backend übertragen.

pm = generate_preset_pass_manager(backend=backend, optimization_level=3)
isa_circuits = pm.run(circuits=circuits)

3. Auf der Zielhardware ausführen

Nach der Optimierung der Schaltungen für die Hardware-Ausführung können wir sie auf der Zielhardware ausführen und Proben für die Abschätzung der Grundzustandsenergie sammeln.

from qiskit_ibm_runtime import SamplerV2 as Sampler

sampler = Sampler(mode=backend)
job = sampler.run(isa_circuits, shots=100_000)  # Takes approximately 2m 58s of QPU time
counts_all = [job.result()[k].data.meas.get_counts() for k in range(krylov_dim)]

4. Nachbearbeitungsergebnisse

Als Nächstes werden die Zählungen für zunehmende Krylov-Dimensionen kumulativ zusammengefasst. Unter Verwendung der kumulativen Zählungen werden wir Unterräume für zunehmende Krylov-Dimensionen aufspannen und das Konvergenzverhalten analysieren.

from collections import Counter

counts_cumulative = []
for i in range(krylov_dim):
    counter = Counter()
    for d in counts_all[: i + 1]:
        counter.update(d)

    counts = dict(counter)
    counts_cumulative.append(counts)

Für die Projektion und Diagonalisierung der Hamiltonfunktion nutzen wir die Fähigkeiten von qiskit-addon-sqd. Das Addon bietet Funktionen, um Pauli-String-basierte Hamiltonianer auf einen Unterraum zu projizieren und Eigenwerte mit SciPy zu lösen.

from qiskit_addon_sqd.counts import counts_to_arrays
from qiskit_addon_sqd.qubit import solve_qubit

Im Prinzip können wir Bitstrings mit falschen Mustern herausfiltern, bevor wir den Unterraum aufspannen. Der Grundzustand für den antiferromagnetischen Hamiltonian in dieser Lektion hat typischerweise eine gleiche Anzahl von "Up"- und "Down"-Spins, d. h. die Anzahl der "1 "s in der Bitkette sollte genau die Hälfte der Gesamtzahl der Bits (Spins) im System betragen. Die folgende Funktion filtert Bitstrings mit einer falschen Anzahl von "1 "s aus den Zählungen heraus.

# Filters out bitstrings that do not have specified number (`num_ones`) of `1` bits.
def postselect_counts(counts, num_ones):
    filtered_counts = {}
    for bitstring, freq in counts.items():
        if bitstring.count("1") == num_ones:
            filtered_counts[bitstring] = freq

    return filtered_counts

Unter Verwendung von Bitstrings mit der korrekten Anzahl von Up/Down-Elektronen werden Unterräume aufgespannt und Eigenwerte für zunehmende Krylov-Dimensionen berechnet. Abhängig von der Größe des Problems und den verfügbaren klassischen Ressourcen müssen wir möglicherweise eine Unterabtastung vornehmen (ähnlich wie in der Lektion über SQD ), um die Dimension des Unterraums in Schach zu halten. Außerdem können wir den Begriff der Konfigurationswiederherstellung ähnlich wie in Lektion 4 anwenden. Aus den rekonstruierten Eigenzuständen können wir die Elektronenbelegung pro Stelle berechnen und die Informationen nutzen, um Bitstrings mit einer falschen Anzahl von Up/Down-Elektronen zu korrigieren. Wir überlassen dies den interessierten Lesern als Übung.

import numpy as np

num_batches = 10
rand_seed = 0
scipy_kwargs = {"k": 2, "which": "SA"}

ground_state_energies = []
for idx, counts in enumerate(counts_cumulative):
    counts = postselect_counts(counts, num_ones=num_spins // 2)
    bitstring_matrix, probs = counts_to_arrays(counts=counts)

    eigenvals, eigenstates = solve_qubit(
        bitstring_matrix, H_op, verbose=False, **scipy_kwargs
    )
    gs_en = np.min(eigenvals)
    ground_state_energies.append(gs_en)

Anschließend wird die berechnete Energie als Funktion der Krylov-Dimension dargestellt und mit der exakten Energie verglichen. Die genaue Energie wird separat mit einer klassischen Brute-Force-Methode berechnet. Es ist zu erkennen, dass die geschätzte Grundzustandsenergie mit zunehmender Krylov-Raumdimension konvergiert. Obwohl die Krylov-Dimension von 55 begrenzt ist, zeigen die Ergebnisse dennoch eine beeindruckende Konvergenz, die sich mit einer größeren Krylov-Dimension verbessern dürfte [1].

import matplotlib.pyplot as plt

exact_gs_en = -23.934184
plt.plot(
    range(1, krylov_dim + 1),
    ground_state_energies,
    color="blue",
    linestyle="-.",
    label="estimate",
)
plt.plot(
    range(1, krylov_dim + 1),
    [exact_gs_en] * krylov_dim,
    color="red",
    linestyle="-",
    label="exact",
)
plt.xticks(range(1, krylov_dim + 1), range(1, krylov_dim + 1))
plt.legend()
plt.xlabel("Krylov space dimension")
plt.ylabel("Energy")
plt.ylim([-24, -22.50])
plt.title(
    "Estimating Ground state energy with Sample-based Krylov Quantum Diagonalization"
)
plt.show()

Output:

Output of the previous code cell

Überprüfen Sie Ihr Verständnis

Lies die folgenden Fragen, denke über deine Antworten nach und klicke dann auf die Dreiecke, um die Lösungen zu finden.

  • Antwort:

    Erhöhen Sie die Krylov-Dimension. Im Allgemeinen könnte man auch die Anzahl der Schüsse erhöhen, aber diese ist in der obigen Berechnung bereits recht hoch.

  • Antwort:

    Es kann auch andere gültige Antworten geben, aber vollständige Antworten sollten Folgendes beinhalten:

    (a) SKQD verfügt über Konvergenzgarantien, die SQD nicht hat. Bei der SQD müssen Sie entweder eine sehr gute Schätzung für Ihren Ansatz vornehmen, die eine hervorragende Überlappung mit der Grundzustandsunterstützung in der Berechnungsbasis aufweist, oder Sie müssen eine Variationskomponente in die Berechnung einführen, um eine Familie von Ansätzen zu wählen.

    (b) SKQD benötigt viel weniger QPU-Zeit, da es die kostspielige Berechnung von Matrixelementen über den Hadamard-Test vermeidet.


5. Zusammenfassung

  • Die Abschätzung der Grundzustandsenergie durch Abtasten von Krylov-Basiszuständen eignet sich sehr gut für Gittermodelle, einschließlich Spinsysteme, Probleme mit kondensierter Materie und Gittereichtheorien. Dieser Ansatz lässt sich viel besser skalieren als VQE, da er keine Optimierung über viele Parameter in einem Variationsansatz wie in VQE oder in heuristischer, auf Ansätzen basierender SQD (z. B. das Chemieproblem in der vorherigen Lektion) erfordert.
    • Um die Schaltungstiefe gering zu halten, ist es ratsam, sich mit Gitterproblemen zu befassen, die sich für eine vorfehlertolerante Hardware eignen.
  • Bei SKQD gibt es kein Quantenmessungsproblem wie bei VQE. Es gibt keine Gruppen von pendelnden Pauli-Operatoren, die geschätzt werden müssen.
  • SKQD ist robust gegenüber verrauschten Stichproben, da man entweder eine aufgabenspezifische Nachselektionsroutine verwenden kann (beispielsweise um Bitfolgen herauszufiltern, die nicht den aufgabenspezifischen Mustern entsprechen) oder den klassischen Diagonalisierungsaufwand in Kauf nehmen kann (d. h. die Diagonalisierung in einem größeren Unterraum durchführen), um den Einfluss des Rauschens wirksam zu beseitigen.

Referenzen

[1] Jeffery Yu et al, "Quantenzentrierter Algorithmus für stichprobenbasierte Krylov-Diagonalisierung" (2025). arxiv:quant-ph/2501.09702.

[2] Ethan N. Epperly, Lin Lin, und Yuji Nakatsukasa. "Eine Theorie der Quantenunterraumdiagonalisierung". SIAM Journal on Matrix Analysis and Applications 43, 1263-1290 (2022).

[2] N. Hatano und M. Suzuki, "Finden von Exponentialproduktformeln höherer Ordnungen" (2005). arXiv:math-ph/0506007.

[4] D. Berry, G. Ahokas, R. Cleve und B. Sanders, "Effiziente Quantenalgorithmen für die Simulation von spärlichen Hamiltonianern" (2006). arXiv:quant-ph/0508139.

War diese Seite hilfreich?
Melden Sie auf GitHub einen Fehler, einen Tippfehler oder fordern Sie Inhalte an.