Ejecute su primer circuito en hardware
El código de esta página se ha desarrollado siguiendo los siguientes requisitos. Recomendamos utilizar estas versiones o posteriores.
qiskit[all]~=2.5.0 qiskit-ibm-runtime~=0.47.0
Este ejemplo consta de dos partes. Primero crearás un sencillo programa cuántico «Hola mundo» y lo ejecutarás en una unidad de procesamiento cuántico (QPU). Dado que la investigación cuántica real requiere programas mucho más robustos, en la segunda sección ( Escalado a un gran número de qubits ), ampliarás el programa simple hasta alcanzar un nivel de utilidad.
Instalar y autenticar
-
Si aún no ha instalado Qiskit, consulte las instrucciones de la guía de inicio rápido.
-
Instalar Qiskit Runtime para ejecutar trabajos en hardware cuántico:
pip install qiskit-ibm-runtime -
Configure un entorno para ejecutar cuadernos Jupyter localmente:
pip install jupyter
-
-
Configure su autenticación para acceder al hardware cuántico a través del plan gratuito Open Plan.
(Si ha recibido una invitación por correo electrónico para unirse a una cuenta, siga los pasos para usuarios invitados )
-
Vaya a IBM Quantum Platform para iniciar sesión o crear una cuenta.
ImportanteSi se conecta a través de un servidor proxy, debe utilizar Qiskit Runtime v0.44.0 o una versión posterior.
-
Genere su clave API (también denominada token API) en el panel de control y, a continuación, cópiela en una ubicación segura.
-
Vaya a la página Instancias y busque la instancia que desea utilizar. Pase el cursor sobre su CRN y haga clic para copiarlo.
-
Guarda tus credenciales localmente con este código:
from qiskit_ibm_runtime import QiskitRuntimeService QiskitRuntimeService.save_account( # For `token`, use the 44-character API_KEY you created # and saved from the IBM Quantum Platform Home dashboard token="<your-api-key>", instance="<CRN>", # Optional )
-
-
Ahora puede utilizar este Python código cada vez que desee autenticarse en el Qiskit Runtime servicio:
from qiskit_ibm_runtime import QiskitRuntimeService # Run every time you need the service service = QiskitRuntimeService()
Si utiliza un ordenador público u otro entorno no seguro, siga las instrucciones de autenticación manual para mantener seguras sus credenciales de autenticación.
Crear y ejecutar un programa cuántico sencillo
Los cuatro pasos para escribir un programa cuántico utilizando patrones Qiskit son:
-
Asigne el problema a un formato cuántico nativo.
-
Optimizar los circuitos y los operadores.
-
Ejecutar utilizando una función primitiva cuántica.
-
Analice los resultados.
Paso 1. Asignar el problema a un formato cuántico nativo
En un programa cuántico, los circuitos cuánticos son el formato nativo en el que se representan las instrucciones cuánticas, y los operadores representan los observables que se van a medir. Al crear un circuito, normalmente se crea un nuevo QuantumCircuit objeto y luego se le añaden instrucciones en secuencia.
La siguiente celda de código crea un circuito que produce un estado Bell, que es un estado en el que dos qubits están completamente entrelazados entre sí.
El Qiskit SDK utiliza la numeración de bits LSb 0, donde el dígito tiene un valor o . Para obtener más detalles, consulte el Qiskit SDK tema Ordenación de bits en el.
from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import EstimatorOptions
from qiskit_ibm_runtime import EstimatorV2 as Estimator
from matplotlib import pyplot as plt
# Uncomment the next line if you want to use a simulator:
# from qiskit_ibm_runtime.fake_provider import FakeBelemV2
# Create a new circuit with two qubits
qc = QuantumCircuit(2)
# Add a Hadamard gate to qubit 0
qc.h(0)
# Perform a controlled-X gate on qubit 1, controlled by qubit 0
qc.cx(0, 1)
# Return a drawing of the circuit using MatPlotLib ("mpl").
# These guides are written by using Jupyter notebooks, which
# display the output of the last line of each cell.
# If you're running this in a script, use `print(qc.draw())` to
# print a text drawing.
qc.draw("mpl")Output:
Consulte QuantumCircuit la documentación para ver todas las operaciones disponibles.
Al crear circuitos cuánticos, también hay que tener en cuenta qué tipo de datos se desea obtener tras la ejecución. Qiskit ofrece dos formas de obtener datos: puedes obtener resultados de muestreo para un conjunto de qubits que elijas medir, o puedes obtener el valor esperado de una observable. Prepara tu carga de trabajo para medir tu circuito de una de estas dos formas con Qiskit primitives (se explica con detalle en el paso 3 ).
Este ejemplo mide los valores esperados utilizando el qiskit.quantum_info submódulo, que se especifica mediante operadores (objetos matemáticos utilizados para representar una acción o proceso que cambia un estado cuántico). La siguiente celda de código crea seis operadores de Pauli de dos qubits: IZ, IX, ZI XI, ZZ, y XX.
# Set up six different observables.
observables_labels = ["IZ", "IX", "ZI", "XI", "ZZ", "XX"]
observables = [SparsePauliOp(label) for label in observables_labels]Aquí, algo como el ZZ operador es una abreviatura del producto tensorial , lo que significa medir Z en el qubit 1 y Z en el qubit 0 juntos, y obtener información sobre la correlación entre el qubit 1 y el qubit 0. Los valores esperados como este también se suelen escribir como .
Si el estado está entrelazado, entonces la medición de debería ser diferente de la medición de . Para el estado entrelazado específico creado por nuestro circuito descrito anteriormente, la medición de debería ser 1 y la medición de debería ser cero.
Paso 2. Optimizar los circuitos y los operadores
Al ejecutar circuitos en un dispositivo, es importante optimizar el conjunto de instrucciones que contiene el circuito y minimizar la profundidad total (aproximadamente el número de instrucciones) del circuito. Esto garantiza que obtenga los mejores resultados posibles al reducir los efectos del error y el ruido. Además, las instrucciones del circuito deben ajustarse a la arquitectura del conjunto de instrucciones (ISA) del dispositivo backend y deben tener en cuenta las puertas básicas y la conectividad de los qubits del dispositivo.
El siguiente código instancia un dispositivo real al que enviar un trabajo y transforma el circuito y los observables para que coincidan con la ISA de ese backend. Es necesario que ya haya guardado sus credenciales.
service = QiskitRuntimeService()
backend = service.least_busy(simulator=False, operational=True)
# Convert to an ISA circuit and layout-mapped observables.
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(qc)
isa_circuit.draw("mpl", idle_wires=False)Output:
Paso 3. Ejecutar utilizando las primitivas cuánticas
Los ordenadores cuánticos pueden generar resultados aleatorios, por lo que normalmente se recopila una muestra de los resultados ejecutando el circuito varias veces. Puedes calcular el valor de la variable observable utilizando la Estimator clase. Estimator es una de las dos funciones primitivas; la otra es Sampler, que se puede utilizar para obtener datos de un ordenador cuántico. Estos objetos disponen de un run() método que lleva a cabo la selección de circuitos, observables y parámetros (si procede), utilizando un bloque unificado primitivo ( PUB ).
# Construct the Estimator instance.
estimator = Estimator(mode=backend)
estimator.options.resilience_level = 1
estimator.options.default_shots = 5000
mapped_observables = [
observable.apply_layout(isa_circuit.layout) for observable in observables
]
# One pub, with one circuit to run against five different observables.
job = estimator.run([(isa_circuit, mapped_observables)])
# Use the job ID to retrieve your job data later
print(f">>> Job ID: {job.job_id()}")Output:
>>> Job ID: d9bjj3u6hjac73ffpth0
Después de enviar un trabajo, puede esperar hasta que se complete dentro de su instancia actual de Python o utilizar job_id para recuperar los datos más tarde. (Consulte la sección sobre recuperación de trabajos para obtener más detalles)
Una vez completado el trabajo, examine su resultado a través del atributo result() del trabajo.
# This is the result of the entire submission. You submitted one Pub,
# so this contains one inner result (and some metadata of its own).
job_result = job.result()
# This is the result from our single pub, which had six observables,
# so contains information on all six.
pub_result = job.result()[0]Cuando ejecutas tu programa cuántico en un dispositivo real, tu carga de trabajo debe esperar en una cola antes de ejecutarse. Para ahorrar tiempo, puede utilizar el siguiente código para ejecutar esta pequeña carga de trabajo en el fake_provider con el modo de Qiskit Runtime prueba local. Tenga en cuenta que esto solo es posible para un circuito pequeño. Cuando amplíes la siguiente sección, necesitarás utilizar un dispositivo real.
# Use the following code instead if you want to run on a simulator:
from qiskit_ibm_runtime.fake_provider import FakeBelemV2
backend = FakeBelemV2()
estimator = Estimator(backend)
# Convert to an ISA circuit and layout-mapped observables.
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(qc)
mapped_observables = [
observable.apply_layout(isa_circuit.layout) for observable in observables
]
job = estimator.run([(isa_circuit, mapped_observables)])
result = job.result()
# This is the result of the entire submission. You submitted one Pub,
# so this contains one inner result (and some metadata of its own).
job_result = job.result()
# This is the result from our single pub, which had five observables,
# so contains information on all five.
pub_result = job.result()[0]Paso 4. Analizar los resultados
El paso de análisis es normalmente donde se pueden procesar los resultados utilizando, por ejemplo, la mitigación del error de medición o la extrapolación de ruido cero (ZNE). Puede introducir estos resultados en otro flujo de trabajo para realizar análisis adicionales o preparar un gráfico con los valores y datos clave. En general, este paso es específico para su problema. Para este ejemplo, represente gráficamente cada uno de los valores esperados que se midieron para nuestro circuito.
Se puede acceder a los valores esperados y a las desviaciones estándar de las magnitudes observables que se han especificado en Estimator a través de los atributos y PubResult.data.stds del PubResult.data.evs resultado del trabajo. Para obtener los resultados de Sampler, utiliza la PubResult.data.meas.get_counts() función, que devolverá un dict conjunto de mediciones en forma de cadenas de bits como claves y recuentos como sus valores correspondientes. Para obtener más información, consulta la guía de inicio rápido de Sampler.
# Plot the result
values = pub_result.data.evs
errors = pub_result.data.stds
# plotting graph
plt.plot(observables_labels, values, "-o")
plt.xlabel("Observables")
plt.ylabel("Values")
plt.show()Output:
Obsérvese que para los qubits 0 y 1, los valores esperados independientes tanto de X como de Z son 0, mientras que las correlaciones (XX y ZZ) son 1. Esta es una característica distintiva del entrelazamiento cuántico.
Escalar a un gran número de qubits
En la informática cuántica, el trabajo a escala industrial es crucial para avanzar en este campo. Este tipo de trabajo requiere realizar cálculos a una escala mucho mayor, trabajando con circuitos que pueden utilizar más de 100 qubits y más de 1000 puertas. Este ejemplo muestra cómo se puede realizar un trabajo a escala industrial en IBM® QPU creando y analizando un estado GHZ de 100 qubits. Utiliza el flujo de trabajo de patrones de Qiskit y termina midiendo el valor esperado para cada qubit.
Paso 1. Identificar el problema
Escribe una función que devuelva un QuantumCircuit que prepare un estado GHZ de qubits (esencialmente un estado Bell extendido) y, a continuación, utiliza esa función para preparar un estado GHZ de 100 qubits y recopilar los observables que se van a medir.
def get_qc_for_n_qubit_GHZ_state(n: int) -> QuantumCircuit:
"""This function will create a qiskit.QuantumCircuit (qc)
for an n-qubit GHZ state.
Args:
n (int): Number of qubits in the n-qubit GHZ state
Returns:
QuantumCircuit: Quantum circuit that generate the n-qubit GHZ state,
assuming all qubits start in the 0 state
"""
if isinstance(n, int) and n >= 2:
qc = QuantumCircuit(n)
qc.h(0)
for i in range(n - 1):
qc.cx(i, i + 1)
else:
raise Exception("n is not a valid input")
return qc
# Create a new circuit with 100 qubits in the GHZ state
n = 100
qc = get_qc_for_n_qubit_GHZ_state(n)A continuación, asigne los operadores de interés. Este ejemplo utiliza los ZZ operadores entre qubits para examinar el comportamiento a medida que se alejan entre sí. Los valores de expectativa cada vez más inexactos (corruptos) entre qubits distantes revelarían el nivel de ruido presente.
# ZZII...II, ZIZI...II, ... , ZIII...IZ
operator_strings = [
"Z" + "I" * i + "Z" + "I" * (n - 2 - i) for i in range(n - 1)
]
operators = [SparsePauliOp(operator) for operator in operator_strings]Paso 2. Optimizar el problema para su ejecución en hardware cuántico
El siguiente código transforma el circuito y los observables para que coincidan con la ISA del backend. Es necesario que ya haya guardado sus credenciales.
service = QiskitRuntimeService()
backend = service.least_busy(
simulator=False, operational=True, min_num_qubits=100
)
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
isa_circuit = pm.run(qc)
isa_operators_list = [op.apply_layout(isa_circuit.layout) for op in operators]Paso 3. Ejecutar en hardware
Envía el trabajo y activa la supresión de errores utilizando una técnica para reducir los errores denominada «desacoplamiento dinámico ». El nivel de resiliencia indica el grado de resiliencia que se debe implementar frente a los errores. Los niveles más altos generan resultados más precisos, aunque a costa de tiempos de procesamiento más largos. Para obtener más información sobre las opciones configuradas en el siguiente código, consulte «Configurar la mitigación de errores para Qiskit Runtime ».
options = EstimatorOptions()
options.resilience_level = 1
options.dynamical_decoupling.enable = True
options.dynamical_decoupling.sequence_type = "XY4"
# Create an Estimator object
estimator = Estimator(backend, options=options)# Submit the circuit to Estimator
job = estimator.run([(isa_circuit, isa_operators_list)])
job_id = job.job_id()
print(job_id)Output:
d9bk5brv6alc73ct68ag
Paso 4. Resultados del procesamiento posterior
Una vez completado el trabajo, represente gráficamente los resultados y observe que disminuye al aumentar , aunque en una simulación ideal todos los deberían ser 1.
# data
data = list(range(1, len(operators) + 1)) # Distance between the Z operators
result = job.result()[0]
values = result.data.evs # Expectation value at each Z operator.
values = [
v / values[0] for v in values
] # Normalize the expectation values to evaluate how they decay with distance.
# plotting graph
plt.plot(data, values, marker="o", label="100-qubit GHZ state")
plt.xlabel("Distance between qubits $i$")
plt.ylabel(r"$\langle Z_i Z_0 \rangle / \langle Z_1 Z_0 \rangle $")
plt.legend()
plt.show()Output:
El gráfico anterior muestra que, a medida que aumenta la distancia entre los qubits, la señal se debilita debido a la presencia de ruido.
Próximos pasos
- Prueba uno de estos tutoriales:
- Estimación de la energía del estado fundamental de la cadena de Heisenberg con VQE
- Resuelve problemas de optimización utilizando QAOA.
- Entrenar modelos de kernel cuántico para tareas de aprendizaje automático
- Encuentre instrucciones detalladas de instalación en la guía Instalar Qiskit.
- Si prefiere no instalar Qiskit localmente, lea sobre las opciones para utilizar Qiskit en un entorno de desarrollo en línea.
- Para guardar las credenciales de varias cuentas o especificar otras opciones de cuenta, consulte las instrucciones detalladas en la guía Guardar sus credenciales de inicio de sesión.