Diagonalização quântica de Krylov baseada em amostras (SKQD)
Esta lição sobre Sample-based Krylov quantum diagonalization (SKQD) combina métodos explicados em métodos anteriores. Ele consiste em um único exemplo que utiliza a estrutura de padrões do Qiskit:
- Etapa 1: Mapear o problema para circuitos e operadores quânticos
- Etapa 2: otimizar para o hardware de destino
- Etapa 3: Executar usando as primitivas d IBM Quantum
- Etapa 4: Pós-processamento
Uma etapa importante do método de diagonalização quântica baseado em amostras é gerar vetores de qualidade para o subespaço. Na lição anterior, usamos o ansatz LUCJ para gerar vetores de subespaço para um Hamiltoniano químico. Nesta lição, usaremos os estados quânticos de Krylov [1], conforme discutido na lição 2. Primeiro, analisaremos como criar o espaço de Krylov em um computador quântico usando operações de evolução do tempo. Em seguida, faremos uma amostragem a partir dele. Projetaremos o sistema Hamiltoniano no subespaço amostrado e o diagonalizaremos para estimar a energia do estado fundamental. O algoritmo converge de forma comprovada e eficiente para o estado fundamental, de acordo com as suposições descritas na lição 2.
0. O espaço de Krylov
Lembre-se de que um espaço de Krylov de ordem é o espaço abrangido pelos vetores obtidos pela multiplicação das potências mais altas de uma matriz , até , com um vetor de referência .
Se a matriz for o Hamiltoniano , o espaço correspondente será chamado de espaço de Krylov de potência . No caso de ser o operador de evolução temporal gerado pelo Hamiltoniano , o espaço é chamado de espaço de Krylov unitário . O subespaço de Krylov de potência não pode ser gerado diretamente em um computador quântico, pois não é um operador unitário. Em vez disso, podemos usar o operador de evolução temporal , que pode ser mostrado como garantia de convergência semelhante à do espaço de Krylov de potência. As potências de tornam-se, então, etapas de tempo diferentes onde .
1. Mapear o problema para circuitos e operadores quânticos
Nesta lição, consideramos o Hamiltoniano para a cadeia antiferromagnética XX-Z spin-1/2 com locais com a condição de limite periódico:
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))Para construir o espaço de Krylov, precisamos de três ingredientes principais:
- Uma opção de dimensão de Krylov ( ) e etapa de tempo ( ).
- Um estado inicial (de referência) (vetor acima) com sobreposição polinomial com o estado-alvo (solo), em que o estado-alvo é esparso. Esse requisito de sobreposição polinomial é o mesmo do algoritmo de estimativa de fase quântica.
- Operadores de evolução temporal ( ).
Para um valor escolhido de (e, ), criaremos circuitos quânticos separados e coletaremos amostras deles. Cada circuito quântico é criado unindo a representação do circuito quântico do estado de referência e o operador de evolução do tempo para um valor .
Uma dimensão de Krylov maior melhora a convergência da energia estimada. Nesta lição, definimos a dimensão como para ilustrar a tendência de convergência.
A Ref [2] mostrou que uma etapa de tempo suficientemente pequena para o KQD é , e que é preferível subestimar esse valor em vez de superestimá-lo. Por outro lado, escolher para ser muito pequeno leva a um condicionamento pior do subespaço de Krylov, já que os vetores da base de Krylov diferem menos de um intervalo de tempo para outro. Além disso, embora essa escolha de seja comprovadamente adequada para a convergência do SKQD, nesse contexto baseado em amostragem, a escolha ideal de na prática é um tópico de estudo em andamento. Nesta lição, definimos .
Além da dimensão de Krylov e da etapa de tempo, precisamos definir o número de etapas de Trotter para a evolução do tempo. O uso de poucas etapas leva a erros de trotterização maiores, enquanto muitas etapas levam a circuitos mais profundos. Nesta lição, definimos o número de etapas de Trotter como .
# Set parameters for quantum Krylov algorithm
krylov_dim = 5 # size of krylov subspace
dt = 0.15
num_trotter_steps = 6Em seguida, precisamos escolher um estado de referência que tenha alguma sobreposição com o estado fundamental. Para esse hamiltoniano, usamos o estado Neel com alternância de 1s e 0s como nosso estado de referência.
# 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)Por fim, precisamos mapear o operador de evolução temporal para um circuito quântico. Isso foi feito na lição 2, mas aqui utilizaremos os métodos do Qiskit, especificamente um método chamado synthesis (síntese ). Há diferentes métodos para sintetizar operadores matemáticos em circuitos quânticos com portas quânticas. Muitas dessas técnicas estão disponíveis no módulo de síntese do Qiskit. Usaremos a abordagem LieTrotter abordagem para síntese [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:
circuits[2].decompose().draw("mpl", fold=-1)Output:
2. Otimize para o hardware de destino
Agora que criamos os circuitos, podemos otimizá-los para um hardware de destino. Escolhemos uma QPU em escala de utilidade.
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")Agora, transpilamos os circuitos para o backend de destino usando um gerenciador de passes predefinido.
pm = generate_preset_pass_manager(backend=backend, optimization_level=3)
isa_circuits = pm.run(circuits=circuits)3. Executar no hardware de destino
Depois de otimizar os circuitos para execução em hardware, estamos prontos para executá-los no hardware de destino e coletar amostras para a estimativa de energia do estado fundamental.
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 timecounts_all = [job.result()[k].data.meas.get_counts() for k in range(krylov_dim)]4. Resultados pós-processamento
Em seguida, agregamos as contagens para aumentar as dimensões de Krylov de forma cumulativa. Usando as contagens cumulativas, abrangeremos subespaços para aumentar a dimensão de Krylov e analisaremos o comportamento da convergência.
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)Para projetar e diagonalizar o Hamiltoniano, usamos os recursos de qiskit-addon-sqd. O complemento oferece funcionalidades para projetar Hamiltonianos baseados em cadeias de Pauli em um subespaço e resolve os valores próprios usando SciPy.
from qiskit_addon_sqd.counts import counts_to_arrays
from qiskit_addon_sqd.qubit import solve_qubitEm princípio, podemos filtrar as cadeias de bits com padrão incorreto antes de abranger o subespaço. Por exemplo, o estado fundamental do Hamiltoniano antiferromagnético desta lição normalmente tem um número igual de spins "para cima" e "para baixo", ou seja, o número de "1 "s na cadeia de bits deve ser exatamente a metade do número total de bits (spins) no sistema. A função a seguir filtra as cadeias de bits com o número incorreto de "1" das contagens.
# 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_countsUsando cadeias de bits com o número correto de elétrons para cima/para baixo, abrangemos subespaços e calculamos valores próprios para aumentar a dimensão de Krylov. Dependendo do tamanho do problema e dos recursos clássicos disponíveis, talvez seja necessário adotar a subamostragem (semelhante à lição sobre SQD ) para manter a dimensão do subespaço sob controle. Além disso, podemos aplicar a noção de recuperação de configuração semelhante à da Lição 4. Podemos computar a ocupação de elétrons por local a partir de estados próprios reconstruídos e usar as informações para corrigir cadeias de bits com um número incorreto de elétrons up/down. Deixamos isso como um exercício para os leitores interessados.
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)Em seguida, plotamos a energia calculada como uma função da dimensão de Krylov e comparamos com a energia exata. A energia exata é calculada separadamente usando um método clássico de força bruta. Podemos ver que a energia estimada do estado fundamental converge com o aumento da dimensão do espaço de Krylov. Embora a dimensão de Krylov de seja limitante, os resultados ainda mostram uma convergência impressionante, que deve melhorar com uma dimensão de Krylov maior [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:
Verifique sua compreensão
Leia as perguntas abaixo, reflita sobre suas respostas e clique nos triângulos para revelar as soluções.
Resposta:
Aumentar a dimensão de Krylov. Em geral, também é possível aumentar o número de disparos, mas isso já é bastante alto no cálculo acima.
Resposta:
Pode haver outras respostas válidas, mas as respostas completas devem incluir o seguinte:
(a) O SKQD vem com garantias de convergência que o SQD não tem. Na SQD, você precisa fazer uma estimativa muito boa para o seu ansatz que tenha uma excelente sobreposição com o suporte do estado fundamental na base computacional, ou precisa introduzir um componente variacional no cálculo para obter uma amostra de uma família de ansatz.
(b) O SKQD requer muito menos tempo de QPU, pois evita o cálculo dispendioso dos elementos da matriz por meio do teste Hadamard.
5. Resumo
- As estimativas de energia do estado fundamental por meio da amostragem dos estados da base de Krylov são muito adequadas aos modelos de rede, incluindo sistemas de spin, problemas de matéria condensada e teorias de calibre de rede. Essa abordagem é muito melhor do que a VQE, porque não exige otimização de muitos parâmetros em um ansatz variacional, como na VQE, ou na SQD baseada em ansatz heurístico (por exemplo, o problema de química na lição anterior).
- Para manter a profundidade do circuito baixa, é aconselhável abordar problemas de rede que sejam passíveis de hardware tolerante a falhas.
- O SKQD não incorre em um problema de medição quântica como no VQE. Não há grupos de operadores Pauli comutantes a serem estimados.
- O SKQD é resistente a amostras ruidosas, pois é possível utilizar uma rotina de pós-seleção específica para o problema (por exemplo, filtrar cadeias de bits que não se enquadram nos padrões específicos do problema) ou incorrer na sobrecarga clássica da diagonalização (ou seja, diagonalizar em um subespaço maior) para eliminar efetivamente o efeito do ruído.
Referências
[1] Jeffery Yu et al, "Algoritmo centrado em quantum para diagonalização de Krylov baseada em amostra" (2025). arxiv:quant-ph/2501.09702.
[2] Ethan N. Epperly, Lin Lin e Yuji Nakatsukasa. "Uma teoria da diagonalização do subespaço quântico". SIAM Journal on Matrix Analysis and Applications 43, 1263-1290 (2022).
[2] N. Hatano e M. Suzuki, "Finding Exponential Product Formulas of Higher Orders" (2005). arXiv:math-ph/0506007.
[4] D. Berry, G. Ahokas, R. Cleve e B. Sanders, "Efficient quantum algorithms for simulating sparse Hamiltonians" (Algoritmos quânticos eficientes para simular hamiltonianos esparsos) (2006). arXiv:quant-ph/0508139.