Saltar al contenido principal

Escribe tu primer programa con Qiskit Serverless

Versiones de paquetes

El código de esta página fue desarrollado con los siguientes requisitos. Recomendamos usar estas versiones o versiones más recientes.

qiskit[all]~=1.3.1
qiskit-ibm-runtime~=0.34.0
qiskit-aer~=0.15.1
qiskit-serverless~=0.18.1
qiskit-ibm-catalog~=0.2
qiskit-addon-sqd~=0.8.1
qiskit-addon-utils~=0.1.0
qiskit-addon-mpf~=0.2.0
qiskit-addon-aqc-tensor~=0.1.2
qiskit-addon-obp~=0.1.0
scipy~=1.15.0
pyscf~=2.8.0
consejo

Qiskit Serverless está siendo actualizado y sus funciones están cambiando rápidamente. Durante esta fase de desarrollo, consulta las notas de versión y la documentación más reciente en la página de Qiskit Serverless en GitHub.

Este ejemplo demuestra cómo usar las herramientas de qiskit-serverless para crear un programa de transpilación en paralelo, y luego implementar qiskit-ibm-catalog para subir tu programa a IBM Quantum Platform y usarlo como un servicio remoto reutilizable.

Descripción general del flujo de trabajo

  1. Crea un directorio local y un archivo de programa vacío (./source_files/transpile_remote.py)
  2. Agrega código a tu programa que, cuando se suba a Qiskit Serverless, transpilará un circuito
  3. Usa qiskit-ibm-catalog para autenticarte en Qiskit Serverless
  4. Sube el programa a Qiskit Serverless

Después de subir tu programa, puedes ejecutarlo para transpilar el circuito siguiendo la guía Ejecuta tu primera carga de trabajo de Qiskit Serverless de forma remota.

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-ibm-catalog qiskit-ibm-runtime qiskit-serverless

Ejemplo: Transpilación remota con Qiskit Serverless

Este ejemplo te guía por el proceso de crear y completar un archivo de programa que, cuando lo subas a Qiskit Serverless, transpilará un circuit contra un backend dado y un optimization_level objetivo.

consejo

Qiskit Serverless requiere organizar los archivos .py de tu carga de trabajo en un directorio dedicado. La siguiente estructura es un ejemplo de buenas prácticas:

serverless_program
├── program_uploader.ipynb
└── source_files
├── transpile_remote.py
└── *.py

Serverless sube el contenido de un directorio específico (en este ejemplo, el directorio source_files) para ejecutarlo de forma remota. Una vez configurados, puedes ajustar transpile_remote.py para obtener entradas y devolver salidas.

Crea el directorio y un archivo de programa vacío

Primero, crea un directorio llamado source_files, luego crea un archivo de programa en ese directorio, de modo que su ruta sea ./source_files/transpile_remote.py. Este es el archivo que subirás a Qiskit Serverless.

Agrega código a tu archivo de programa

Completa tu archivo de programa con el siguiente código y luego guárdalo.

precaución

Si estás leyendo las celdas de código localmente en un notebook, verás el comando mágico %%writefile. Ejecutar celdas con este comando mágico las guarda en disco en lugar de ejecutarlas.

# This cell is hidden from users, it creates a new folder
from pathlib import Path

Path("./source_files").mkdir(exist_ok=True)
%%writefile ./source_files/transpile_remote.py
# If you include the preceding `%%writefile` command (visible only when you read this locally in a notebook), running this cell saves to disk rather than executing the code.

from qiskit.transpiler import generate_preset_pass_manager

def transpile_remote(circuit, optimization_level, backend):
"""Transpiles an abstract circuit into an ISA circuit for a given backend."""
pass_manager = generate_preset_pass_manager(
optimization_level=optimization_level,
backend=backend
)
isa_circuit = pass_manager.run(circuit)
return isa_circuit

Agrega código para obtener los argumentos del programa

Ahora agrega el siguiente código a tu archivo de programa, que configura los argumentos del programa.

Tu archivo inicial transpile_remote.py tiene tres entradas: circuits, backend_name y optimization_level. Serverless actualmente solo acepta entradas y salidas serializables. Por esta razón, no puedes pasar backend directamente, así que usa backend_name como cadena de texto en su lugar.

%%writefile --append ./source_files/transpile_remote.py
# If you include the preceding `%%writefile` command (visible only when you read this locally in a notebook), running this cell saves to disk rather than executing the code.

from qiskit_serverless import get_arguments, save_result, distribute_task, get

# Get program arguments
arguments = get_arguments()
circuits = arguments.get("circuits")
backend_name = arguments.get("backend_name")
optimization_level = arguments.get("optimization_level")

Agrega código que llame al backend

Agrega el siguiente código a tu archivo de programa, que llama a tu backend con QiskitRuntimeService.

El siguiente código asume que ya seguiste el proceso para guardar tus credenciales usando QiskitRuntimeService.save_account, y cargará tu cuenta guardada predeterminada a menos que especifiques lo contrario. Consulta Guarda tus credenciales de inicio de sesión e Inicializa tu cuenta de servicio de Qiskit Runtime para más información.

%%writefile --append ./source_files/transpile_remote.py
# If you include the preceding `%%writefile` command (visible only when you read this locally in a notebook), running this cell saves to disk rather than executing the code.

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
backend = service.backend(backend_name)

Agrega código para transpilar

Por último, agrega el siguiente código a tu archivo de programa. Este código ejecuta transpile_remote() sobre todos los circuits pasados como entrada y devuelve los transpiled_circuits como resultado:

%%writefile --append ./source_files/transpile_remote.py
# If you include the preceding `%%writefile` command (visible only when you read this locally in a notebook), running this cell saves to disk rather than executing the code.

# Each circuit is being transpiled and will populate the array
results = [
transpile_remote(circuit, 1, backend)
for circuit in circuits
]

save_result({
"transpiled_circuits": results
})

Autentícate en Qiskit Serverless

Usa qiskit-ibm-catalog para autenticarte en QiskitServerless con tu clave de API (puedes usar tu clave de API de QiskitRuntimeService, o crear una nueva clave de API en el panel de IBM Quantum Platform).

from qiskit_ibm_catalog import QiskitServerless, QiskitFunction

# Authenticate to the remote cluster and submit the pattern for remote execution
serverless = QiskitServerless()

Ejecuta el código para subir

Ejecuta el siguiente código para subir el programa. Qiskit Serverless comprime el contenido de working_dir (en este caso, source_files) en un archivo tar, que se sube y luego se limpia. El entrypoint identifica el ejecutable principal del programa que Qiskit Serverless debe ejecutar.

transpile_remote_demo = QiskitFunction(
title="transpile_remote_serverless",
entrypoint="transpile_remote.py",
working_dir="./source_files/",
)
serverless.upload(transpile_remote_demo)
QiskitFunction(transpile_remote_serverless)

Verifica la subida

Para verificar si se subió correctamente, usa serverless.list(), como en el siguiente código:

# Get program from serverless.list() that matches the title of the one we uploaded
next(
program
for program in serverless.list()
if program.title == "transpile_remote_serverless"
)
QiskitFunction(transpile_remote_serverless)
# This cell is hidden from users, it checks the program uploaded correctly
assert _.title == "transpile_remote_serverless" # noqa: F821
# This cell is hidden from users, it checks the program executes correctly
from time import sleep
from qiskit import QuantumCircuit

qc = QuantumCircuit(2)
transpile_remote_serverless = serverless.load("transpile_remote_serverless")
job = transpile_remote_serverless.run(
circuits=[qc],
backend="ibm_sherbrooke",
optimization_level=1,
)
while True:
sleep(5)
status = job.status()
if status not in ["QUEUED", "INITIALIZING", "RUNNING", "DONE"]:
raise Exception(
f"Unexpected job status: '{status}'\n"
+ "Here are the logs:\n"
+ job.logs()
)
if status == "DONE":
break

Próximos pasos

Recomendaciones