Pular para o conteúdo principal
Este projeto está em fase beta. Encontrou um bug? Abra uma issue no GitHub. Tem uma pergunta ou ideia? Pergunte no Discussions — adoraríamos receber seu feedback!
Como está a qualidade da tradução nesta página?

Dynamics Simulator - uma Qiskit Function da Q-CTRL Fire Opal

Veja a referência da API.

nota

Qiskit Functions são um recurso experimental disponível apenas para usuários do IBM Quantum® Premium Plan, Flex Plan e On-Prem (por meio da API do IBM Quantum Platform). Elas estão em status de versão preliminar e sujeitas a alterações.

Visão geral​

O Dynamics Simulator da Q-CTRL é uma Qiskit Function de aplicação para simular a evolução temporal de modelos quânticos de muitos corpos suportados em hardware IBM Quantum. Em vez de construir circuitos quânticos por conta própria, você especifica o modelo físico, o estado inicial, os parâmetros de evolução temporal e os observáveis a medir.

A função constrói e executa os circuitos dinâmicos necessários e aplica o fluxo de trabalho de otimização e supressão de erros com reconhecimento de hardware do Fire Opal. O resultado é uma série temporal de valores esperados dos observáveis que você solicitou. Como a função aplica supressão de erros automaticamente, você pode executar circuitos em profundidades recordes e ainda ver sinais significativos. O Dynamics Simulator entrega uma precisão de solução que corresponde às ferramentas clássicas de última geração existentes e oferece uma vantagem demonstrável em velocidade.

Testes no mundo real alcançaram concordância dentro de 1% de erro quadrático médio (RMSE) em comparação com as simulações clássicas de redes de tensores de maior resolução. Testes independentes da comunidade de pesquisa validaram que o computador quântico permanece preciso mesmo além das demonstrações iniciais da Q-CTRL.

Two plots of classical tensor-network simulations at bond dimensions χ from 64 to 4096. The left plot shows the RMSE against time t, which stays near 0.01 until it rises sharply, later for larger bond dimensions. The right plot shows the simulation time in minutes against time t on a logarithmic scale, which increases with bond dimension.

Benchmarks​

O número de sítios determina quantos qubits são necessários, enquanto o número de passos de Trotter controla a profundidade dos circuitos de evolução temporal. Cada sítio da rede usa dois qubits para representar as ocupações de spin para cima e spin para baixo.

Este fluxo de trabalho foi demonstrado para cadeias de 60 sítios (120 qubits) com 30 passos de Trotter, e para cadeias de 31 sítios (62 qubits) com 90 passos de Trotter. A tabela abaixo mostra os recursos de circuito e os tempos de execução na QPU dos experimentos reportados, realizados em um dispositivo IBM® Heron r3 (ibm_boston) com 20.000 shots por circuito.

Tamanho do sistemaPassos de TrotterProfundidade de dois qubitsNúmero de portas de dois qubitsTempo de QPUTempo de QPU com REM + DR
10 sítios (20 qubits)301521,4572m 46s4m 25s
10 sítios (20 qubits)603022,8975m 36s8m 42s
10 sítios (20 qubits)904524,3378m 46s13m 26s
31 sítios (62 qubits)301524,6492m 46s4m 25s
31 sítios (62 qubits)603029,2395m 36s8m 42s
31 sítios (62 qubits)9045213,8298m 46s13m 26s
60 sítios (120 qubits)301529,0572m 46s4m 25s

Para um número fixo de passos de Trotter, a profundidade do circuito e o tempo de QPU reportados permanecem os mesmos nos tamanhos de sistema testados, enquanto o número de portas de dois qubits aumenta. Aumentar o número de passos produz circuitos mais profundos e exige mais tempo de QPU.

Aqui, o tempo de QPU é o tempo acumulado de execução em hardware dos circuitos principais de simulação. A última coluna também inclui o tempo de QPU da caracterização de ruído usada na mitigação de erros de leitura (REM) e na recuperação de decaimento (DR). Este guia usa um pequeno exemplo unidimensional de Fermi-Hubbard para mostrar o fluxo de trabalho completo, desde a definição do modelo até o gráfico da dinâmica medida.

Descrição da função​

A dinâmica quântica descreve como um sistema quântico muda ao longo do tempo. Estudar essa evolução ajuda a entender como as partículas se movem, como as correlações se desenvolvem e como um sistema responde a uma mudança em seu estado ou em seu Hamiltoniano.

O modelo de Fermi-Hubbard descreve férmions que se movem entre sítios da rede e interagem quando ocupam o mesmo sítio. A competição entre o salto e as interações o torna um modelo útil para estudar elétrons fortemente correlacionados. Sua evolução temporal pode revelar como o spin e a carga se propagam, e como um sistema inicialmente ordenado relaxa.

Modelo​

O Dynamics Simulator suporta uma cadeia unidimensional de Fermi-Hubbard com contornos abertos. Para uma cadeia de LL sítios, o Hamiltoniano é definido da seguinte forma:

H=−∑i=0L−2∑σ∈{↑,↓}th,i(ciσ†ci+1,σ+ci+1,σ†ciσ)+∑i=0L−1Uini↑ni↓−∑i=0L−1∑σ∈{↑,↓}μiniσ.H = -\sum_{i=0}^{L-2}\sum_{\sigma\in\{\uparrow,\downarrow\}} t_{h,i} \left( c^\dagger_{i\sigma}c_{i+1,\sigma} + c^\dagger_{i+1,\sigma}c_{i\sigma} \right) +\sum_{i=0}^{L-1}U_i n_{i\uparrow}n_{i\downarrow} -\sum_{i=0}^{L-1}\sum_{\sigma\in\{\uparrow,\downarrow\}} \mu_i n_{i\sigma}.

Aqui, ciσ†c^\dagger_{i\sigma} e ciσc_{i\sigma} criam e aniquilam um férmion com spin σ\sigma no sítio ii. O operador número niσ=ciσ†ciσn_{i\sigma}=c^\dagger_{i\sigma}c_{i\sigma} mede a ocupação desse orbital de spin.

As entradas do modelo especificam os seguintes coeficientes:

  • hopping_amplitude: th,it_{h,i}, que controla o salto entre os sítios vizinhos ii e i+1i+1.

  • on_site_interaction: UiU_i, a interação entre férmions de spin para cima e spin para baixo que ocupam o mesmo sítio.

  • chemical_potential: μi\mu_i, o potencial químico local, que entra no Hamiltoniano com sinal negativo.

Forneça um escalar para usar o mesmo coeficiente em toda a cadeia, ou uma lista para especificar coeficientes para ligações ou sítios individuais.

Em unidades em que ℏ=1\hbar=1, o estado inicial evolui da seguinte forma:

∣ψ(t)⟩=e−iHt∣ψ(0)⟩.|\psi(t)\rangle=e^{-iHt}|\psi(0)\rangle.

A função estima os valores esperados dos observáveis que você especifica em tempos de simulação sucessivos.

Fluxo de trabalho​

O fluxo de trabalho da função consiste nas seguintes etapas:

  1. Síntese algorítmica: A função usa o Hamiltoniano e as configurações de tempo de simulação para construir uma sequência de Trotter-Suzuki otimizada, que reduz a profundidade do circuito levando em conta a precisão da simulação.

  2. Mapeamento com reconhecimento de hardware: A função mapeia e roteia os circuitos usando a conectividade dos qubits e as características de erro do Backend do IBM Quantum selecionado.

  3. Supressão de erros na camada física: O Fire Opal incorpora desacoplamento dinâmico e correções em nível de pulso para suprimir o ruído do ambiente e a diafonia durante a execução em hardware.

A função gerencia essas etapas automaticamente e retorna os valores esperados dos observáveis solicitados ao longo do tempo.

Você define o problema físico e as configurações de simulação por meio das entradas da função. A interface atual suporta evolução temporal de Trotter, em que time_step define a duração de cada passo e step_count define o número de passos.

Para mais detalhes, veja a visão geral do Fire Opal dynamics simulator e a referência da API de simulate_dynamics.

Primeiros passos​

Encontre as informações de acesso a esta Qiskit Function no Qiskit Functions Catalog.

Este guia mostra como carregar o Dynamics Simulator e simular uma cadeia de Fermi-Hubbard de quatro sítios. O código a seguir pressupõe que você já salvou sua chave de API do IBM Quantum Platform e o CRN da instância no seu ambiente local.

Para instruções de configuração da conta e instalação do cliente, veja Primeiros passos com Qiskit Functions.

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"matplotlib": "matplotlib", "numpy": "numpy", "qctrlvisualizer": "qctrlvisualizer", "qiskit_ibm_catalog": "qiskit-ibm-catalog"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
from qiskit_ibm_catalog import QiskitFunctionsCatalog

catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")
# Access the Q-CTRL Dynamics Simulator Qiskit Function.
sim_qf = catalog.load("q-ctrl/dynamics-simulator")
# Check the list of backends you have access to
catalog.backends()
[<IBMBackend('ibm_boston')>,
<IBMBackend('ibm_fez')>,
<IBMBackend('ibm_kingston')>,
<IBMBackend('ibm_marrakesh')>,
<IBMBackend('ibm_miami')>,
<IBMBackend('ibm_phoenix')>,
<IBMBackend('ibm_pittsburgh')>]
# Select the backend you want to use
backend = catalog.backend("ibm_phoenix")

Exemplo: simular uma cadeia de Fermi-Hubbard de quatro sítios​

Considere uma cadeia unidimensional de Fermi-Hubbard de quatro sítios com amplitude de salto th=1t_h=1, sem interação no sítio e com potencial químico zero. Um único férmion de spin para cima começa no sítio 0 e evolui ao longo da cadeia.

Este pequeno problema mantém o foco no fluxo de trabalho do Dynamics Simulator:

  1. Defina o modelo e a simulação.

  2. Defina o estado inicial e os observáveis.

  3. Envie o job da Qiskit Function.

  4. Recupere os valores esperados.

  5. Plote a dinâmica.

1. Defina o problema​

site_count = 4

model = {
"hopping_amplitude": 1.0,
"on_site_interaction": 0.0,
"chemical_potential": 0.0,
}

simulation = {
"time_step": 0.2,
"step_count": 8,
}

initial_state = "eeeu"

observables = [
{
"operators": [[["Nup", site]]],
"coefficients": [1.0],
}
for site in range(site_count)
]

shot_count = 2048

A lista de observáveis mede a ocupação de spin-up

⟨ni↑⟩\langle n_{i\uparrow} \rangle

em cada sítio. Os observáveis são retornados na mesma ordem em que foram fornecidos.

2. Execute a simulação da dinâmica​

Envie o problema por meio do Qiskit Function. O Qiskit Functions Catalog cuida da autenticação do IBM Quantum, então você não precisa passar credenciais separadas do Fire Opal ou de provedores de hardware para sim_qf.run().

job = sim_qf.run(
model=model,
simulation=simulation,
observables=observables,
initial_state=initial_state,
shots=shot_count,
backend_name=backend.name,
)
print(job.job_id, job.status())
68202fad-6919-425d-8fd2-c1c649cd15b1 DONE

O objeto retornado é um job de Qiskit Function. Você pode guardar o ID do job para recuperar ou inspecionar a carga de trabalho mais tarde.

3. Recupere o resultado​

result = job.result()

print("Result keys:", sorted(result.keys()))
print("Warnings:", result.get("warnings", []))
Result keys: ['metadata', 'observable_expectation_values', 'observables', 'warnings']
Warnings: []

Converta os valores esperados dos observáveis em um array NumPy. Cada linha corresponde a um observável, e cada coluna corresponde a um tempo de simulação registrado, começando em t=0t=0. Neste exemplo, as quatro linhas contêm as ocupações de spin-up dos sítios 0 a 3.

import numpy as np

expectation_values = np.asarray(
result["observable_expectation_values"],
dtype=float,
)

print("Expectation-value array shape:", expectation_values.shape)
Expectation-value array shape: (4, 9)

4. Visualize a dinâmica​

O estado inicial contém um férmion de spin-up e nenhum férmion de spin-down. Sua evolução, portanto, permanece no subespaço de uma partícula, cujos quatro estados de base correspondem ao férmion ocupando os sítios 0, 1, 2 e 3.

Nesse subespaço, o Hamiltoniano conecta sítios vizinhos com amplitude de salto −th-t_h. Para os parâmetros usados aqui,

H1p=−th(0100101001010010).H_{\mathrm{1p}} = -t_h \begin{pmatrix} 0 & 1 & 0 & 0 \\ 1 & 0 & 1 & 0 \\ 0 & 1 & 0 & 1 \\ 0 & 0 & 1 & 0 \end{pmatrix}.

Diagonalize essa matriz com NumPy e evolua o estado inicial nos mesmos tempos retornados pelo Dynamics Simulator. O módulo quadrado de cada amplitude de estado fornece a ocupação de spin-up do sítio correspondente.

Este cálculo fornece a evolução hamiltoniana exata. As diferenças entre as estimativas do hardware e esta referência podem incluir o passo de Trotter finito, a estatística de medição e erros residuais do hardware.

times = np.arange(expectation_values.shape[1]) * simulation["time_step"]

# This reference is specific to a single spin-up fermion.
if (
len(initial_state) != site_count
or initial_state.count("u") != 1
or initial_state.count("e") != site_count - 1
):
raise ValueError(
"This reference requires one spin-up fermion and otherwise empty sites."
)

# Build the Hamiltonian in the single-particle subspace.
hamiltonian = -model["hopping_amplitude"] * (
np.eye(site_count, k=1) + np.eye(site_count, k=-1)
)
hamiltonian -= model["chemical_potential"] * np.eye(site_count)

# The rightmost character of initial_state corresponds to site 0.
initial_amplitudes = np.zeros(site_count, dtype=complex)
initial_site = initial_state[::-1].index("u")
initial_amplitudes[initial_site] = 1.0

# Evolve the initial state in the Hamiltonian eigenbasis.
energies, eigenvectors = np.linalg.eigh(hamiltonian)
initial_coefficients = eigenvectors.conj().T @ initial_amplitudes

phases = np.exp(-1j * np.outer(energies, times))
states = eigenvectors @ (initial_coefficients[:, None] * phases)

ideal_expectation_values = np.abs(states) ** 2

Plote um painel para cada sítio. As curvas contínuas mostram a referência exata nos tempos registrados, e os marcadores mostram as estimativas do hardware retornadas pelo Dynamics Simulator.

import matplotlib.pyplot as plt
import qctrlvisualizer as qv
from qctrlvisualizer import QCTRL_STYLE_COLORS as colors

plt.style.use(qv.get_qctrl_style())

fig, ax = plt.subplots(figsize=(10, 6))

for site in range(len(expectation_values)):
site_color = colors[site % len(colors)]

ax.plot(
times,
ideal_expectation_values[site],
color=site_color,
linewidth=2,
label=f"Site {site}: exact reference",
)

ax.plot(
times,
expectation_values[site],
color=site_color,
linestyle="--",
linewidth=1.5,
marker="o",
markersize=5,
label=f"Site {site}: hardware estimate",
)

ax.set_xlim(times[0], times[-1])
ax.set_ylim(-0.05, 1.05)

ax.set_xlabel(r"Time (units of $\hbar/t_h$)")
ax.set_ylabel(r"$\langle n_{i\uparrow} \rangle$")
ax.set_title("Spin-up occupation dynamics")

ax.legend(
ncol=2,
fontsize=10,
loc="best",
)

fig.tight_layout()
plt.show()

Output of the previous code cell

Em t=0t=0, a ocupação de spin-up exata é 1 no sítio 0 e 0 nos demais sítios. À medida que o sistema evolui, o salto espalha a probabilidade da partícula pela cadeia. A ocupação do sítio 1 aumenta primeiro, seguida pelo aumento da ocupação nos sítios 2 e 3. Para os parâmetros deste exemplo, o último tempo registrado é t=1.6t=1.6. As ocupações exatas dos sítios 0 a 3 são aproximadamente 0,026, 0,370, 0,392 e 0,211, respectivamente.

As ocupações exatas satisfazem a equação a seguir em todos os instantes, refletindo a conservação do número de partículas:

∑i=03⟨ni↑(t)⟩=1\sum_{i=0}^{3}\langle n_{i\uparrow}(t)\rangle=1

As ocupações individuais dos sítios podem subir e descer conforme a partícula evolui pela cadeia finita.

Obtenha as mensagens de erro​

Se a carga de trabalho entrar no estado ERROR, chame job.result() para recuperar a mensagem de erro. Você também pode inspecionar os logs da função, se estiverem disponíveis.

print(job.status())

if job.status() == "ERROR":
print(job.result())
print(job.logs())
DONE

Problemas comuns de validação de entrada incluem um modelo ou método de simulação não suportado, uma string de estado inicial longa demais, termos e coeficientes de observáveis incompatíveis, ou um observável que faz referência a um sítio fora da string de estado inicial.

Obtenha suporte​

Para dúvidas sobre o comportamento do Dynamics Simulator ou do Fire Opal, consulte a documentação da Q-CTRL ou entre em contato com a Q-CTRL.

Para autenticação do Qiskit Functions, gerenciamento de jobs ou acesso à IBM Quantum Platform, consulte a documentação do Qiskit Functions.

Próximos passos​

Recomendações