Skip to main content
IBM Quantum Platform

Diagonalizzazione quantistica di Krylov basata su campioni (SKQD)

Questa lezione sulla diagonalizzazione quantistica di Krylov basata su campioni (SKQD) combina i metodi spiegati nei metodi precedenti. Si tratta di un singolo esempio che sfrutta il framework di modelli Qiskit:

  • Fase 1: mappare il problema in circuiti e operatori quantistici
  • Fase 2: Ottimizzazione per l'hardware di destinazione
  • Fase 3: Esecuzione tramite le primitive " IBM Quantum "
  • Fase 4: Post-processing

Un passo importante nel metodo di diagonalizzazione quantistica basato sui campioni è la generazione di vettori di qualità per il sottospazio. Nella lezione precedente, abbiamo utilizzato l'ansatz LUCJ per generare vettori di sottospazi per un'hamiltoniana chimica. In questa lezione utilizzeremo gli stati di Krylov quantistici [1], come già discusso nella lezione 2. In primo luogo, esamineremo come creare lo spazio di Krylov su un computer quantistico utilizzando operazioni di evoluzione temporale. Poi ne faremo un campione. Proietteremo l'hamiltoniana del sistema sul sottospazio campionato e la diagonalizzeremo per stimare l'energia dello stato fondamentale. L'algoritmo converge in modo dimostrabile ed efficiente allo stato fondamentale, sotto le ipotesi descritte nella lezione 2.


0. Lo spazio di Krylov

Ricordiamo che uno spazio di Krylov Kr\mathcal{K}^r di ordine rr è lo spazio spaziato dai vettori ottenuti moltiplicando le potenze superiori di una matrice AA, fino a r−1r-1, con un vettore di riferimento ∣v⟩\vert v \rangle.

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\}

Se la matrice AA è l'hamiltoniana HH, lo spazio corrispondente è chiamato spazio di Krylov di potenza KP\mathcal{K}_P. Nel caso in cui AA sia l'operatore di evoluzione temporale generato dall'hamiltoniana U=e−iH(dt)U=e^{-iH(dt)}, lo spazio è chiamato spazio di Krylov unitario KU\mathcal{K}_U. Il sottospazio di Krylov di potenza non può essere generato direttamente su un computer quantistico poiché HH non è un operatore unitario. Si può invece utilizzare l'operatore di evoluzione temporale U=e−iH(dt)U = e^{-iH(dt)}, che si può dimostrare dia garanzie di convergenza simili a quelle dello spazio di Krylov di potenza. Le potenze di UU diventano quindi passi temporali diversi Uk=e−iH(kdt)U^k = e^{-iH(k dt)} dove 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. Mappare il problema su circuiti quantistici e operatori

In questa lezione consideriamo l'hamiltoniana per la catena antiferromagnetica XX-Z spin-1/2 con L=22L = 22 siti con condizione al contorno periodica:

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))

Per costruire lo spazio di Krylov, abbiamo bisogno di tre ingredienti principali:

  1. Una scelta della dimensione di Krylov ( rr ) e del passo temporale ( dtdt ).
  2. Uno stato iniziale (di riferimento) (vettore ∣v⟩\vert v \rangle sopra) con sovrapposizione polinomiale con lo stato target (di terra), dove lo stato target è rado. Questo requisito di sovrapposizione polinomiale è lo stesso dell'algoritmo di stima quantistica della fase.
  3. Operatori di evoluzione temporale Uk=e−iH(k∗dt)U^{k}=e^{-iH(k * dt)} ( k=0,1,2,...,r−1k = 0, 1, 2, ..., r-1 ).

Per un valore scelto di rr (e, dtdt ), creeremo rr circuiti quantistici separati e li campioneremo. Ogni circuito quantistico viene creato unendo la rappresentazione del circuito quantistico dello stato di riferimento e l'operatore di evoluzione temporale per un valore kk.

Una dimensione di Krylov maggiore migliora la convergenza dell'energia stimata. In questa lezione impostiamo la dimensione su 55 per illustrare la tendenza alla convergenza.

Ref [2] ha dimostrato che un passo temporale sufficientemente piccolo per KQD è π/∣∣H∣∣\pi / \vert \vert H \vert \vert, e che è preferibile sottostimare questo valore piuttosto che sovrastimarlo. D'altra parte, la scelta di dtdt troppo piccola porta a un condizionamento peggiore del sottospazio di Krylov, poiché i vettori base di Krylov differiscono meno da un passo all'altro. Inoltre, mentre questa scelta di dtdt è provatamente adeguata per la convergenza di SKQD, in questo contesto basato sul campionamento la scelta ottimale di dtdt nella pratica è un argomento di studio in corso. In questa lezione, impostiamo dt=0.15dt = 0.15.

Oltre alla dimensione di Krylov e al passo temporale, è necessario impostare il numero di passi di Trotter per l'evoluzione temporale. L'utilizzo di un numero insufficiente di passaggi porta a errori di trotterizzazione maggiori, mentre un numero eccessivo di passaggi porta a circuiti più profondi. In questa lezione, impostiamo il numero di passi di Trotter su 66.

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

Successivamente, dobbiamo scegliere uno stato di riferimento ∣ψ⟩\vert \psi \rangle che abbia una certa sovrapposizione con lo stato fondamentale. Per questa hamiltoniana, utilizziamo lo stato di Neel con 1s e 0s ∣...101...010...101⟩\vert ...101...010...101 \rangle alternati come stato di riferimento.

# 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)

Infine, dobbiamo mappare l'operatore di evoluzione temporale in un circuito quantistico. Questo è stato fatto nella lezione 2, ma qui sfrutteremo i metodi di Qiskit, in particolare un metodo chiamato sintesi. Esistono diversi metodi per sintetizzare gli operatori matematici in circuiti quantistici con porte quantistiche. Molte di queste tecniche sono disponibili nel modulo di sintesi Qiskit. Utilizzeremo l'approccio LieTrotter approccio per la sintesi [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. Ottimizzazione per l'hardware di destinazione

Ora che abbiamo creato i circuiti, possiamo ottimizzarli per l'hardware di destinazione. Scegliamo una QPU su scala utility.

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")

A questo punto, transpiliamo i circuiti nel backend di destinazione utilizzando un gestore di pass preimpostati.

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

3. Eseguire sull'hardware di destinazione

Dopo aver ottimizzato i circuiti per l'esecuzione hardware, siamo pronti a eseguirli sull'hardware di destinazione e a raccogliere campioni per la stima dell'energia dello stato di massa.

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. Risultati post-elaborazione

Successivamente, aggreghiamo i conteggi per dimensioni di Krylov crescenti in modo cumulativo. Utilizzando i conteggi cumulativi, si analizzano i sottospazi a dimensione Krylov crescente e si analizza il comportamento di convergenza.

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)

Per proiettare e diagonalizzare l'hamiltoniana, utilizziamo le capacità di qiskit-addon-sqd. L'addon offre funzionalità per proiettare gli hamiltoniani basati sulle stringhe di Pauli su un sottospazio e risolve gli autovalori utilizzando SciPy.

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

In linea di principio, è possibile filtrare le stringhe di bit con un modello errato prima di eseguire lo spanning del sottospazio. Ad esempio, lo stato fondamentale per l'hamiltoniana antiferromagnetica di questa lezione ha un numero uguale di spin "up" e "down", cioè il numero di "1" nella stringa di bit dovrebbe essere esattamente la metà del numero totale di bit (spin) nel sistema. La funzione seguente filtra le stringhe di bit con un numero errato di "1" dai conteggi.

# 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

Utilizzando bitstring con il numero corretto di elettroni up/down, si estendono i sottospazi e si calcolano gli autovalori per una dimensione di Krylov crescente. A seconda delle dimensioni del problema e delle risorse classiche disponibili, potrebbe essere necessario adottare il sottocampionamento (simile alla lezione sull'SQD ) per tenere sotto controllo la dimensione del sottospazio. Inoltre, è possibile applicare la nozione di recupero della configurazione, come nella Lezione 4. Possiamo calcolare l'occupazione degli elettroni per sito dagli autostati ricostruiti e utilizzare le informazioni per correggere le bitstring con un numero errato di elettroni up/down. Lo lasciamo come esercizio per i lettori interessati.

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)

Quindi, tracciamo l'energia calcolata in funzione della dimensione di Krylov e la confrontiamo con l'energia esatta. L'energia esatta viene calcolata separatamente con un metodo classico di forza bruta. Si può notare che l'energia di stato fondamentale stimata converge con l'aumentare della dimensione dello spazio di Krylov. Sebbene la dimensione di Krylov di 55 sia limitante, i risultati mostrano comunque una convergenza impressionante, che dovrebbe migliorare con una dimensione di Krylov maggiore [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

Verifica la tua comprensione

Leggete le domande qui sotto, riflettete sulle vostre risposte, quindi fate clic sui triangoli per scoprire le soluzioni.

  • Risposta:

    Aumentare la dimensione di Krylov. In generale, si potrebbe anche aumentare il numero di colpi, ma questo è già abbastanza alto nel calcolo precedente.

  • Risposta:

    Possono esserci altre risposte valide, ma le risposte complete devono includere quanto segue:

    (a) SKQD offre garanzie di convergenza che SQD non ha. In SQD è necessario fare un'ottima ipotesi per il proprio ansatz che abbia un'eccellente sovrapposizione con il supporto dello stato fondamentale nella base computazionale, oppure introdurre una componente variazionale nel calcolo per campionare una famiglia di ansaetze.

    (b) SKQD richiede molto meno tempo di QPU, perché evita il costoso calcolo degli elementi della matrice tramite il test di Hadamard.


  • La stima dell'energia di stato fondamentale attraverso il campionamento degli stati base di Krylov è molto adatta ai modelli reticolari, compresi i sistemi di spin, i problemi della materia condensata e le teorie di gauge reticolari. Questo approccio si adatta molto meglio del VQE, perché non richiede l'ottimizzazione di molti parametri in un'ipotesi variazionale come nel VQE o in un SQD euristico basato su ipotesi (per esempio, il problema della chimica nella lezione precedente).
    • Per mantenere basse le profondità dei circuiti, è consigliabile affrontare i problemi di reticolo che si prestano a un hardware con tolleranza ai guasti.
  • L'SKQD non incorre in un problema di misurazione quantistica come nel VQE. Non ci sono gruppi di operatori di Pauli pendolari da stimare.
  • SKQD è resistente ai campioni rumorosi, poiché è possibile ricorrere a una routine di post-selezione specifica per il problema (ad esempio, filtrando le stringhe di bit che non rispettano i modelli specifici del problema) oppure sostenere il classico overhead della diagonalizzazione (ovvero, diagonalizzare in un sottospazio più ampio) per eliminare efficacemente l'effetto del rumore.

Riferimenti

[1] Jeffery Yu e altri, "Algoritmo quantistico per la diagonalizzazione di Krylov basata su campioni" (2025). arxiv:quant-ph/2501.09702.

[2] Ethan N. Epperly, Lin Lin e Yuji Nakatsukasa. "Una teoria della diagonalizzazione dei sottospazi quantistici". SIAM Journal on Matrix Analysis and Applications 43, 1263-1290 (2022).

[2] N. Hatano e M. Suzuki, "Trovare formule di prodotti esponenziali di ordine superiore" (2005). arXiv:math-ph/0506007.

[4] D. Berry, G. Ahokas, R. Cleve e B. Sanders, "Efficient quantum algorithms for simulating sparse Hamiltonians" (2006). arXiv:quant-ph/0508139.

Questa pagina è stata utile?
Segnala un bug, un errore di battitura o richiedi contenuti su GitHub.