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?

Performance Management: Uma Função Qiskit pela Q-CTRL Fire Opal

Veja a referência de API

Nota

As Qiskit Functions são um recurso experimental disponível apenas para usuários dos planos IBM Quantum® Premium Plan, Flex Plan e On-Prem (via API da IBM Quantum Platform). Elas estão em status de versão prévia e sujeitas a mudanças.

Package versions

O código nesta página foi desenvolvido usando os seguintes requisitos. Recomendamos usar essas versões ou mais recentes.

qiskit[all]~=2.3.1
qiskit-ibm-runtime~=0.45.1

Visão geral​

O Fire Opal Performance Management torna simples para qualquer pessoa obter resultados significativos de computadores quânticos em escala, sem precisar ser especialista em hardware quântico. Ao executar circuitos com o Fire Opal Performance Management, técnicas de supressão de erros baseadas em IA são aplicadas automaticamente, permitindo o escalonamento de problemas maiores com mais gates e qubits. Essa abordagem reduz o número de shots necessários para chegar à resposta correta, sem nenhuma sobrecarga adicional — resultando em economias significativas em tempo de computação e custo.

O Performance Management suprime erros e aumenta a probabilidade de obter a resposta correta em hardware com ruído. Em outras palavras, ele aumenta a relação sinal-ruído. A imagem a seguir mostra como a maior precisão proporcionada pelo Performance Management pode reduzir a necessidade de shots adicionais no caso de um algoritmo de Transformada de Fourier Quântica de 10 qubits. Com apenas 30 shots, a Q-CTRL atinge o limiar de confiança de 99%, enquanto o padrão (QiskitRuntime Sampler, optimization_level=3 e resilience_level=1, ibm_sherbrooke) requer 170.000 shots. Ao obter a resposta correta mais rapidamente, você economiza tempo de computação significativo.

Visualização do tempo de execução melhorado

A função Performance Management pode ser usada com qualquer algoritmo, e você pode facilmente utilizá-la no lugar das primitivas padrão do IBM Quantum. Nos bastidores, múltiplas técnicas de supressão de erros trabalham em conjunto para evitar que erros ocorram em tempo de execução. Todos os métodos de pipeline do Fire Opal são pré-configurados e agnósticos ao algoritmo, o que significa que você sempre obtém o melhor desempenho logo de início.

Para obter acesso ao Performance Management, entre em contato com a Q-CTRL.

Descrição​

O Fire Opal Performance Management possui duas opções de execução semelhantes às primitivas do IBM Quantum, para que você possa facilmente substituir pelo Sampler e Estimator da Q-CTRL. O fluxo de trabalho geral para usar a função Performance Management é:

  1. Defina seu Circuit (e operadores no caso do Estimator).
  2. Execute o Circuit.
  3. Recupere os resultados.

Para reduzir o ruído do hardware, o Fire Opal emprega uma série de técnicas de supressão de erros baseadas em IA, descritas na imagem a seguir. Com o Fire Opal, todo o pipeline é completamente automatizado, sem necessidade de configuração.

O pipeline do Fire Opal elimina a necessidade de sobrecarga adicional, como aumento do tempo de execução quântica ou qubits físicos extras. Observe que o tempo de processamento clássico continua sendo um fator (consulte a seção Benchmarks para estimativas, onde "Tempo total" reflete tanto o processamento clássico quanto o quântico). Ao contrário da mitigação de erros, que requer sobrecarga na forma de amostragem, a supressão de erros do Fire Opal funciona nos níveis de gate e pulso para lidar com várias fontes de ruído e prevenir a ocorrência de erros. Ao prevenir erros, a necessidade de pós-processamento custoso é eliminada.

A imagem a seguir mostra os métodos de supressão de erros automatizados pelo Fire Opal Performance Management.

Visualização do pipeline de supressão de erros

A função oferece duas primitivas, Sampler e Estimator, e as entradas e saídas de ambas estendem a especificação implementada para as primitivas IBM Quantum V2.

Benchmarks​

Os resultados de benchmarking algorítmico publicados demonstram melhora significativa de desempenho em vários algoritmos, incluindo Bernstein-Vazirani, transformada de Fourier quântica, busca de Grover, algoritmo de otimização aproximada quântica e eigensolver variacional quântico. O restante desta seção fornece mais detalhes sobre os tipos de algoritmos que você pode executar, bem como o desempenho e os tempos de execução esperados.

Os seguintes estudos independentes demonstram como o Performance Management da Q-CTRL viabiliza pesquisa algorítmica em escala recorde:

A tabela a seguir fornece um guia aproximado de precisão e tempos de execução de execuções de benchmarking anteriores no ibm_fez. O desempenho em outros dispositivos pode variar. O tempo de uso é baseado em uma suposição de 10.000 shots por circuito. O "Número de qubits" indicado não é uma limitação rígida, mas representa limiares aproximados onde você pode esperar precisão de solução extremamente consistente. Problemas maiores foram resolvidos com sucesso, e testes além desses limites são encorajados.

ExemploNúmero de qubitsPrecisãoMedida de precisãoTempo total (s)Uso de runtime (s)Primitiva (Modo)
Bernstein–Vazirani50Q100%Taxa de Sucesso (Porcentagem de execuções em que a resposta correta é a bitstring com maior contagem)108Sampler
Transformada de Fourier Quântica30Q100%Taxa de Sucesso (Porcentagem de execuções em que a resposta correta é a bitstring com maior contagem)108Sampler
Estimativa de Fase Quântica30Q99,9998%Precisão do ângulo encontrado: 1- abs(real_angle - angle_found)/pi108Sampler
Simulação quântica: Modelo de Ising (15 passos)20Q99,775%AA (definido abaixo)60 (por passo)15 (por passo)Estimator
Simulação quântica 2: dinâmica molecular (20 pontos de tempo)34Q96,78%AmeanA_{mean} (definido abaixo)10 (por ponto de tempo)6 (por ponto de tempo)Estimator

Definindo a precisão da medição de um valor esperado - a métrica AA é definida como segue:

A=1−∣ϵideal−ϵmeas∣ϵmaxideal−ϵminideal,A = 1 - \frac{|\epsilon^{ideal} - \epsilon^{meas}|}{\epsilon^{ideal}_{max} - \epsilon^{ideal}_{min}},

onde ϵideal\epsilon^{ideal} = valor esperado ideal, ϵmeas\epsilon^{meas} = valor esperado medido, ϵmaxideal\epsilon^{ideal}_{max} = valor máximo ideal, e ϵminideal\epsilon^{ideal}_{min} = valor mínimo ideal. AmeanA_{mean} é simplesmente a média do valor de AA ao longo de múltiplas medições.

Essa métrica é usada porque é invariante a deslocamentos globais e escalonamento no intervalo de valores atingíveis. Em outras palavras, independentemente de você deslocar o intervalo de possíveis valores esperados para cima ou para baixo, ou aumentar a dispersão, o valor de AA deve permanecer consistente.

Primeiros passos​

O Fire Opal Performance Management usa Qiskit v2.0.0, que é a versão recomendada. As versões suportadas são Qiskit >=v2.0.0. Autentique-se usando sua chave de API da IBM Quantum Platform e selecione a Função Qiskit conforme mostrado a seguir. (Este trecho assume que você já salvou sua conta no seu ambiente local.)

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

_needed = {"matplotlib": "matplotlib", "numpy": "numpy", "qiskit": "qiskit", "qiskit_ibm_catalog": "qiskit-ibm-catalog", "qiskit_ibm_runtime": "qiskit-ibm-runtime"}
_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")
# This cell is hidden from users. It hides the "...You have imported samplomatic..." warning.
import warnings

warnings.filterwarnings("ignore", message=".*You have imported samplomatic*")
from qiskit_ibm_catalog import QiskitFunctionsCatalog

catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")

# verify that you have access to the function
catalog.list()
[QiskitFunction(qunova/hivqe-chemistry),
QiskitFunction(global-data-quantum/quantum-portfolio-optimizer),
QiskitFunction(algorithmiq/tem),
QiskitFunction(qedma/qesem),
QiskitFunction(multiverse/singularity),
QiskitFunction(ibm/circuit-function),
QiskitFunction(q-ctrl/optimization-solver),
QiskitFunction(colibritd/quick-pde),
QiskitFunction(q-ctrl/performance-management),
QiskitFunction(kipu-quantum/iskay-quantum-optimizer)]
# Access Function
perf_mgmt = catalog.load("q-ctrl/performance-management")
Esta função suporta todos os backends IBM?

Se você quiser usar um backend que esta função não suporta atualmente, entre em contato com a Q-CTRL para adicionar suporte.

Primitiva Estimator​

Exemplo com Estimator​

Use a primitiva Estimator do Fire Opal Performance Management para determinar o valor esperado de um par circuito-observável. Além dos pacotes qiskit-ibm-catalog e qiskit, você também usará o pacote numpy para executar este exemplo. Você pode instalar esse pacote descomentando a célula a seguir, se estiver executando este exemplo em um notebook usando o kernel IPython.

# %pip install numpy

1. Criar o circuito

Como exemplo, gere um operador Hermitiano aleatório e um observável para inserir na função Performance Management.

import numpy as np
from qiskit.circuit.library import iqp
from qiskit.quantum_info import random_hermitian, SparsePauliOp

n_qubits = 50

# Generate a random circuit
mat = np.real(random_hermitian(n_qubits, seed=1234))
circuit = iqp(mat)
circuit.measure_all()

# Define observables as a string
observable = SparsePauliOp("Z" * n_qubits)
# Create PUB tuple
estimator_pubs = [(circuit, observable)]

2. Executar o circuito

Execute o circuito e, opcionalmente, defina o backend e o número de shots.

# This cell is hidden from users
from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
backend_name = service.least_busy().name
# Run the circuit using Estimator
qctrl_estimator_job = perf_mgmt.run(
primitive="estimator",
pubs=estimator_pubs,
backend_name=backend_name,
)

Você pode usar as APIs do Qiskit Serverless familiares para verificar o status da sua carga de trabalho da Função Qiskit:

qctrl_estimator_job.status()
'QUEUED'

3. Recuperar o resultado

# Retrieve the counts from the result list
result = qctrl_estimator_job.result()

Os resultados têm o mesmo formato de um resultado do Estimator:

import numpy

result_str = str(result)

with numpy.printoptions(threshold=200):
print(
f"The result of the submitted job had {len(result)} PUB "
f"and has a value:\n {result[0]}\n"
)

print("The associated PubResult of this job has the following DataBins:")
print(f"{result[0].data}\n")

print(f"And this DataBin has attributes: {result[0].data.keys()}")

print("The expectation values measured from this PUB are:")
print(f"{result[0].data.evs}")
The result of the submitted job had 1 PUB
The result of the submitted job had 1 PUB and has a value:
PubResult(data=DataBin(evs=0.0195, stds=0.9998098569228051), metadata={'precision': None})

The associated PubResult of this job has the following DataBins:
DataBin(evs=0.0195, stds=0.9998098569228051)

And this DataBin has attributes: dict_keys(['evs', 'stds'])
The expectation values measured from this PUB are:
0.0195

Primitiva Sampler​

Exemplo com Sampler​

Use a primitiva Sampler do Fire Opal Performance Management para executar um circuito Bernstein–Vazirani. Esse algoritmo, usado para encontrar uma string oculta a partir das saídas de uma função de caixa-preta, é um algoritmo de benchmarking comum porque existe uma única resposta correta. 1. Criar o circuito

Defina a resposta correta para o algoritmo, a bitstring oculta, e o circuito Bernstein–Vazirani. Você pode ajustar a largura do circuito simplesmente alterando o circuit_width.

import qiskit

circuit_width = 35
hidden_bitstring = "1" * circuit_width

# Create circuit, reserving one qubit for BV oracle
bv_circuit = qiskit.QuantumCircuit(circuit_width + 1, circuit_width)
bv_circuit.x(circuit_width)
bv_circuit.h(range(circuit_width + 1))
for input_qubit, bit in enumerate(reversed(hidden_bitstring)):
if bit == "1":
bv_circuit.cx(input_qubit, circuit_width)
bv_circuit.barrier()
bv_circuit.h(range(circuit_width + 1))
bv_circuit.barrier()
for input_qubit in range(circuit_width):
bv_circuit.measure(input_qubit, input_qubit)

# Create PUB tuple
sampler_pubs = [(bv_circuit,)]

2. Executar o circuito

Execute o circuito e, opcionalmente, defina o backend e o número de shots.

# Run the circuit using Sampler
qctrl_sampler_job = perf_mgmt.run(
primitive="sampler",
pubs=sampler_pubs,
backend_name=backend_name,
)

Verifique o status da sua carga de trabalho da Função Qiskit ou recupere os resultados da seguinte forma:

# Print the ID so you can use it later, if necessary
print(qctrl_sampler_job.job_id)

qctrl_sampler_job.status()
60fe2fa1-a860-43e4-8615-c6ac4180f93b
'QUEUED'

3. Recuperar o resultado

# Retrieve the job results
sampler_result = qctrl_sampler_job.result()
# Get results for the first (and only) PUB
pub_result = sampler_result[0]
counts = pub_result.data.c.get_counts()

print("Counts for the meas output register (limited to 30 results):")
for i, (bitstring, count) in enumerate(counts.items()):
if i >= 50:
print(f" ... ({len(counts) - 30} more items)")
break
print(f" {bitstring}: {count}")
Counts for the meas output register (limited to 30 results):
11111111111111111111111111111111111: 1661
11111111111111111111111111110111111: 60
11111111111111111111111111111101111: 54
11111111111111111111111111111110111: 54
11111111111111011111111111111111111: 46
11111111111111111110111111111111111: 44
11111111111111111111111101111111111: 42
11111111111111111111111110111111111: 42
11111111111111110111111111111111111: 41
11111111111111111111111111111111101: 39
11111111111111111111101111111111111: 38
11111111111111111111110111111111111: 38
11111111111111111111111111101111111: 37
11111111111111111111111111111111110: 36
11111111111110111111111111111111111: 35
11111111111111111111111111111011111: 32
11111111111111101111111111111111111: 32
01111111111111111111111111111111111: 27
11111111111111111011111111111111111: 23
11111111101111111111111111111111111: 22
11111111111111111111111111111111011: 21
11111111011111111111111111111111111: 20
00000000000000011111111111111111111: 18
11111111111111111111110101111111111: 18
00000001111111111111111111111111111: 17
11111111001111111111111111111111111: 16
11101111111111111111111111111111111: 16
11111111111101111111111111111111111: 16
00000101111111111111111111111111111: 13
11111111111111111111111011111111111: 13
11111111111111111111111110101111111: 13
11111111111111111101111111111111111: 12
10111111111111111111111111111111111: 12
11111111111111111111111110001111111: 12
00000000000000000011111111111111111: 11
11111111111111111111111111111110110: 10
00000000000000000000000001111111111: 10
11111111111011111111111111111111111: 9
11111111111111101011111111111111111: 9
00000000011111111111111111111111111: 8
10101111111111111111111111111111111: 8
00000000000000000000000001011111111: 8
11111111111111111111111111111111001: 8
00000111111111111111111111111111111: 7
11111111111111111111111111111101110: 7
11111111110111111111111111111111111: 7
00000000000001011111111111111111111: 6
00000000000000001111111111111111111: 6
00000000000000000001011111111111111: 6
11111111111111111111111111011111111: 6
... (1050 more items)

3. Plotar as principais bitstrings

Plote a bitstring com o maior número de contagens para ver se a bitstring oculta foi a moda.

import matplotlib.pyplot as plt

def plot_top_bitstrings(counts_dict, hidden_bitstring=None):
# Sort and take the top 100 bitstrings
top_100 = sorted(counts_dict.items(), key=lambda x: x[1], reverse=True)[
:100
]
if not top_100:
print("No bitstrings found in the input dictionary.")
return

# Unzip the bitstrings and their counts
bitstrings, counts = zip(*top_100)

# Assign colors: purple if the bitstring matches hidden_bitstring,
# otherwise gray
colors = [
"#680CE9" if bit == hidden_bitstring else "gray" for bit in bitstrings
]

# Create the bar plot
plt.figure(figsize=(15, 8))
plt.bar(
range(len(bitstrings)), counts, tick_label=bitstrings, color=colors
)

# Rotate the bitstrings for better readability
plt.xticks(rotation=90, fontsize=8)
plt.xlabel("Bitstrings")
plt.ylabel("Counts")
plt.title("Top 100 Bitstrings by Counts")

# Show the plot
plt.tight_layout()
plt.show()

A bitstring oculta é destacada em roxo, e deve ser a bitstring com o maior número de contagens.

plot_top_bitstrings(counts, hidden_bitstring)

Output of the previous code cell

Registro de alterações​

  • 2026-02-20: Aviso de descontinuação - o campo de metadados provider_job_ids será descontinuado em 30 dias na versão 0.13.0. Os usuários podem acessar o ID do job pelo método job_id() do serviço de runtime.

  • 2026-02-11: Adicionamos suporte para ibm_miami e incluímos metadados de execução no PubResult.

Obter suporte​

Para quaisquer dúvidas ou problemas, entre em contato com a Q-CTRL.

Próximos passos​

Recomendações