Aller au contenu principal

Écrire ton premier programme Qiskit Serverless

Versions des packages

Le code de cette page a été développé avec les dépendances suivantes. Nous recommandons d'utiliser ces versions ou des versions plus récentes.

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

Cet exemple montre comment utiliser les outils qiskit-serverless pour créer un programme de transpilation parallèle, puis implémenter qiskit-ibm-catalog pour déployer ton programme sur IBM Quantum Platform et l'utiliser comme service distant réutilisable.

Exemple : transpilation à distance avec Qiskit Serverless

Commence avec l'exemple suivant qui transpile un circuit pour un backend donné et un niveau d'optimisation optimization_level cible, puis ajoute progressivement des éléments pour déployer ta charge de travail sur Qiskit Serverless.

Place le code suivant dans le fichier ./source_files/transpile_remote.py. Ce fichier est le programme à téléverser sur Qiskit Serverless.

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-ibm-catalog qiskit-ibm-runtime qiskit-serverless
# This cell is hidden from users, it just creates a new folder
from pathlib import Path

Path("./source_files").mkdir(exist_ok=True)
%%writefile ./source_files/transpile_remote.py

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
Writing ./source_files/transpile_remote.py

Configurer tes fichiers

Qiskit Serverless exige de placer les fichiers .py de ta charge de travail dans un répertoire dédié. La structure suivante est un exemple de bonne pratique :

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

Serverless téléverse le contenu de source_files pour l'exécuter à distance. Une fois cela configuré, tu peux modifier transpile_remote.py pour récupérer les entrées et retourner les sorties.

Récupérer les arguments du programme

Ton transpile_remote.py initial possède trois entrées : circuits, backend_name et optimization_level. Serverless est actuellement limité à n'accepter que des entrées et sorties sérialisables. Pour cette raison, tu ne peux pas passer backend directement ; utilise plutôt backend_name sous forme de chaîne de caractères.

%%writefile --append ./source_files/transpile_remote.py

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")
Appending to ./source_files/transpile_remote.py

À ce stade, tu peux obtenir ton backend avec QiskitRuntimeService et ajouter ton programme existant avec le code suivant. Ce code nécessite que tu aies déjà sauvegardé tes identifiants.

%%writefile --append ./source_files/transpile_remote.py

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
backend = service.backend(backend_name)
Appending to ./source_files/transpile_remote.py

Enfin, tu peux exécuter transpile_remote() sur tous les circuits passés en entrée, et retourner les transpiled_circuits comme résultat :

%%writefile --append ./source_files/transpile_remote.py

results = [
transpile_remote(circuit, 1, backend)
for circuit in circuits
]

save_result({
"transpiled_circuits": results
})
Appending to ./source_files/transpile_remote.py

Déployer sur IBM Quantum Platform

La section précédente a créé un programme destiné à être exécuté à distance. Les cellules de code de cette section téléversent ce programme sur Qiskit Serverless.

Utilise qiskit-ibm-catalog pour t'authentifier auprès de QiskitServerless avec ta clé API, que tu peux trouver sur le tableau de bord IBM Quantum, et téléverser le programme.

Tu peux utiliser save_account() pour sauvegarder tes identifiants (voir la section Configurer l'utilisation d'IBM Cloud). Note que cela écrit tes identifiants dans le même fichier que QiskitRuntimeService.save_account().

from qiskit_ibm_catalog import QiskitServerless, QiskitFunction

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

Qiskit Serverless compresse le contenu de working_dir (dans ce cas, source_files) dans un fichier tar, qui est téléversé puis nettoyé après. L'entrypoint identifie le fichier exécutable principal du programme que Qiskit Serverless doit lancer. De plus, si ton programme possède des dépendances pip personnalisées, tu peux les ajouter dans un tableau dependencies :

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)

Pour vérifier si le téléversement a réussi, utilise serverless.list() :

# 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

Prochaines étapes

Recommandations