Saltar al contenido principal
Este proyecto está en fase beta. ¿Encontraste un error? Abre un issue en GitHub. ¿Tienes una pregunta o una idea? Pregunta en Discussions — ¡nos encantaría tu opinión!
¿Cómo es la calidad de la traducción en esta página?

Gestión del rendimiento: una función de Qiskit de Q-CTRL Fire Opal

Consulta la referencia de la API

Nota

Qiskit Functions son una funcionalidad experimental disponible únicamente para los usuarios de los planes IBM Quantum® Premium, Flex y On-Prem (a través de la API de IBM Quantum Platform). Se encuentran en estado de versión preliminar y están sujetas a cambios.

Package versions

El código de esta página se desarrolló utilizando los siguientes requisitos. Te recomendamos usar estas versiones o más recientes.

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

Descripción general​

Fire Opal Performance Management hace que sea sencillo para cualquier persona obtener resultados significativos de las computadoras cuánticas a escala sin necesidad de ser experto en hardware cuántico. Al ejecutar circuitos con Fire Opal Performance Management, se aplican automáticamente técnicas de supresión de errores basadas en inteligencia artificial, lo que permite escalar problemas más grandes con más puertas y qubits. Este enfoque reduce la cantidad de shots necesarios para obtener la respuesta correcta, sin sobrecarga adicional, lo que resulta en un ahorro significativo tanto en tiempo de cómputo como en costos.

Performance Management suprime los errores y aumenta la probabilidad de obtener la respuesta correcta en hardware con ruido. En otras palabras, aumenta la relación señal-ruido. La siguiente imagen muestra cómo la mayor precisión habilitada por Performance Management puede reducir la necesidad de shots adicionales en el caso de un algoritmo de Transformada de Fourier Cuántica de 10 qubits. Con solo 30 shots, Q-CTRL alcanza el umbral de confianza del 99 %, mientras que el método predeterminado (QiskitRuntime Sampler, optimization_level=3 y resilience_level=1, ibm_sherbrooke) requiere 170 000 shots. Al obtener la respuesta correcta más rápido, ahorras un tiempo de cómputo significativo.

Visualización del tiempo de ejecución mejorado

La función Performance Management se puede usar con cualquier algoritmo, y puedes utilizarla fácilmente en lugar de las primitivas estándar de IBM Quantum. Internamente, múltiples técnicas de supresión de errores trabajan juntas para evitar que los errores ocurran en tiempo de ejecución. Todos los métodos del pipeline de Fire Opal están preconfigurados y son agnósticos al algoritmo, lo que significa que siempre obtienes el mejor rendimiento desde el primer momento.

Para obtener acceso a Performance Management, contacta a Q-CTRL.

Descripción​

Fire Opal Performance Management ofrece dos opciones de ejecución similares a las primitivas de IBM Quantum, por lo que puedes intercambiarlas fácilmente con el Sampler y el Estimator de Q-CTRL. El flujo de trabajo general para usar la función Performance Management es:

  1. Define tu circuito (y operadores en el caso del Estimator).
  2. Ejecuta el circuito.
  3. Recupera los resultados.

Para reducir el ruido del hardware, Fire Opal emplea una serie de técnicas de supresión de errores basadas en inteligencia artificial que se muestran en la siguiente imagen. Con Fire Opal, todo el pipeline está completamente automatizado sin necesidad de ninguna configuración.

El pipeline de Fire Opal elimina la necesidad de sobrecargas adicionales, como un mayor tiempo de ejecución cuántica o qubits físicos adicionales. Cabe señalar que el tiempo de procesamiento clásico sigue siendo un factor (consulta la sección de Benchmarks para obtener estimaciones, donde "Tiempo total" refleja el procesamiento tanto clásico como cuántico). A diferencia de la mitigación de errores, que requiere sobrecarga en forma de muestreo, la supresión de errores de Fire Opal funciona tanto a nivel de puertas como de pulsos para abordar diversas fuentes de ruido y prevenir la probabilidad de que ocurra un error. Al prevenir los errores, se elimina la necesidad de un posprocesamiento costoso.

La siguiente imagen muestra los métodos de supresión de errores automatizados por Fire Opal Performance Management.

Visualización del pipeline de supresión de errores

La función ofrece dos primitivas, Sampler y Estimator, y las entradas y salidas de ambas extienden la especificación implementada para las primitivas V2 de IBM Quantum.

Benchmarks​

Los resultados de benchmarking algorítmico publicados demuestran una mejora significativa del rendimiento en diversos algoritmos, incluidos Bernstein-Vazirani, la transformada de Fourier cuántica, la búsqueda de Grover, el algoritmo de optimización aproximada cuántica y el estimador variacional de valores propios cuánticos. El resto de esta sección ofrece más detalles sobre los tipos de algoritmos que puedes ejecutar, así como el rendimiento y los tiempos de ejecución esperados.

Los siguientes estudios independientes demuestran cómo el Performance Management de Q-CTRL permite la investigación algorítmica a escala sin precedentes:

La siguiente tabla ofrece una guía aproximada sobre la precisión y los tiempos de ejecución de benchmarks previos realizados en ibm_fez. El rendimiento en otros dispositivos puede variar. El tiempo de uso se basa en un supuesto de 10 000 shots por circuito. El "Número de qubits" indicado no es un límite estricto, sino que representa umbrales aproximados donde puedes esperar una precisión de solución extremadamente consistente. Se han resuelto con éxito problemas de mayor tamaño, y se recomienda probar más allá de estos límites.

EjemploNúmero de qubitsPrecisiónMedida de precisiónTiempo total (s)Uso de runtime (s)Primitiva (Modo)
Bernstein–Vazirani50Q100%Tasa de éxito (porcentaje de ejecuciones donde la respuesta correcta es la cadena de bits con mayor conteo)108Sampler
Transformada de Fourier Cuántica30Q100%Tasa de éxito (porcentaje de ejecuciones donde la respuesta correcta es la cadena de bits con mayor conteo)108Sampler
Estimación de Fase Cuántica30Q99.9998%Precisión del ángulo encontrado: 1- abs(real_angle - angle_found)/pi108Sampler
Simulación cuántica: modelo de Ising (15 pasos)20Q99.775%AA (definido a continuación)60 (por paso)15 (por paso)Estimator
Simulación cuántica 2: dinámica molecular (20 puntos temporales)34Q96.78%AmeanA_{mean} (definido a continuación)10 (por punto temporal)6 (por punto temporal)Estimator

Definiendo la precisión de la medición de un valor esperado, la métrica AA se define de la siguiente manera:

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

donde ϵideal\epsilon^{ideal} = valor esperado ideal, ϵmeas\epsilon^{meas} = valor esperado medido, ϵmaxideal\epsilon^{ideal}_{max} = valor máximo ideal, y ϵminideal\epsilon^{ideal}_{min} = valor mínimo ideal. AmeanA_{mean} es simplemente el promedio del valor de AA a través de múltiples mediciones.

Esta métrica se utiliza porque es invariante a desplazamientos globales y escalados en el rango de valores alcanzables. En otras palabras, independientemente de si desplazas el rango de posibles valores esperados hacia arriba o hacia abajo, o aumentas la dispersión, el valor de AA debe permanecer consistente.

Primeros pasos​

Fire Opal Performance Management utiliza Qiskit v2.0.0, que es la versión recomendada. Las versiones compatibles son Qiskit >=v2.0.0. Autentícate usando tu clave API de IBM Quantum Platform y selecciona la función de Qiskit de la siguiente manera. (Este fragmento asume que ya has guardado tu cuenta en tu entorno 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 función es compatible con todos los backends de IBM?

Si quieres usar un backend que esta función no admite actualmente, contacta a Q-CTRL para agregar compatibilidad.

Primitiva Estimator​

Ejemplo de Estimator​

Usa la primitiva Estimator de Fire Opal Performance Management para determinar el valor esperado de un par circuito-observable. Además de los paquetes qiskit-ibm-catalog y qiskit, también usarás el paquete numpy para ejecutar este ejemplo. Puedes instalar este paquete descomentando la siguiente celda si estás ejecutando este ejemplo en un notebook con el kernel de IPython.

# %pip install numpy

1. Crear el circuito

Como ejemplo, genera un operador hermitiano aleatorio y un observable para introducir en la función 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. Ejecutar el circuito

Ejecuta el circuito y, de manera opcional, define el backend y el 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,
)

Puedes usar las conocidas APIs de Qiskit Serverless para comprobar el estado de tu carga de trabajo de la función de Qiskit:

qctrl_estimator_job.status()
'QUEUED'

3. Recuperar el resultado

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

Los resultados tienen el mismo formato que un resultado de 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​

Ejemplo de Sampler​

Usa la primitiva Sampler de Fire Opal Performance Management para ejecutar un circuito de Bernstein–Vazirani. Este algoritmo, utilizado para encontrar una cadena oculta a partir de las salidas de una función de caja negra, es un algoritmo de benchmarking común porque tiene una única respuesta correcta. 1. Crear el circuito

Define la respuesta correcta al algoritmo, la cadena de bits oculta, y el circuito de Bernstein–Vazirani. Puedes ajustar el ancho del circuito simplemente cambiando 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. Ejecutar el circuito

Ejecuta el circuito y, de manera opcional, define el backend y el número de shots.

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

Comprueba el estado de tu carga de trabajo de la función de Qiskit o recupera los resultados de la siguiente manera:

# 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 el 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. Graficar las principales cadenas de bits

Grafica la cadena de bits con el mayor número de conteos para ver si la cadena de bits oculta fue la 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()

La cadena de bits oculta aparece destacada en morado y debería ser la cadena de bits con el mayor número de conteos.

plot_top_bitstrings(counts, hidden_bitstring)

Output of the previous code cell

Registro de cambios​

  • 2026-02-20: Aviso de obsolescencia: el campo de metadatos provider_job_ids quedará obsoleto en 30 días en la versión 0.13.0. Los usuarios pueden acceder al ID de trabajo a través del método job_id() del servicio de runtime.

  • 2026-02-11: Ahora tenemos soporte para ibm_miami y se agregaron metadatos de ejecución al PubResult.

Obtener soporte​

Para cualquier pregunta o problema, contacta a Q-CTRL.

Próximos pasos​

Recomendaciones