Aller au contenu principal

Démarrer avec Qiskit Functions

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-ibm-catalog qiskit-ibm-runtime
# This cell is hidden from users
# It gets these details programmatically so we can test this notebook
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.circuit.random import random_circuit
from qiskit_ibm_catalog import QiskitFunctionsCatalog

service = QiskitRuntimeService()
instance = service.active_account()["instance"]
backend_name = service.least_busy().name
catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")
qesem_function = catalog.load("qedma/qesem")
circuit = random_circuit(num_qubits=2, depth=2, seed=42)
observable = "Z" * circuit.num_qubits

Les utilisateurs des plans Premium, Flex et On-Prem (via l'API IBM Quantum Platform) peuvent commencer à utiliser IBM Qiskit Functions gratuitement, ou peuvent obtenir une licence auprès de l'un des partenaires ayant contribué une fonction au catalogue.

Demander un essai gratuit pour des Qiskit Functions tierces

Pour demander un essai gratuit, accède au Qiskit Functions Catalog et explore le panneau de détails. Clique sur Request a free trial et remplis les informations requises par le partenaire Functions, y compris l'AccessGroupId IBM Cloud :

  1. Accède à IBM Cloud IAM.

  2. Vérifie ton éligibilité.

    • Change de compte dans la barre de menu de l'en-tête pour en choisir un avec le format suivant : XXXXXXX - [Organization Name]

    • Assure-toi que l'organisation est la même que celle associée à ton compte Premium.

    • Si tu vois « [Your Name]'s Account », tu utilises ton compte personnel, qui n'est pas éligible à l'accès premium.

  3. Trouve l'ID de ton groupe d'accès.

    • Clique sur un nom de groupe.

    • Clique sur Details.

    • Copie l'ID du groupe d'accès. Il doit commencer par AccessGroup-.

Installer le client Qiskit Functions Catalog

  1. Pour commencer à utiliser Qiskit Functions, installe le client IBM Qiskit Functions Catalog :

    pip install qiskit-ibm-catalog
  2. Récupère ta clé API depuis le tableau de bord IBM Quantum Platform, et active ton environnement virtuel Python. Consulte les instructions d'installation si tu n'as pas encore configuré d'environnement virtuel.

    If you are working in a trusted Python environment (such as on a personal laptop or workstation), use the save_account() method to save your credentials locally. (Skip to the next step if you are not using a trusted environment, such as a shared or public computer, to authenticate to IBM Quantum Platform.)

    L'instance avec laquelle tu t'authentifies doit avoir l'accès à Qiskit Functions activé. Pour le configurer sur une instance existante, consulte Configurer l'accès à Qiskit Functions sur une instance.

    Pour utiliser save_account(), exécute python dans ton shell, puis saisis ce qui suit :

    from qiskit_ibm_catalog import QiskitFunctionsCatalog

    QiskitFunctionsCatalog.save_account(channel="ibm_quantum_platform", token="<your-token>", instance="<instance-crn>")

    Tape exit(). Désormais, chaque fois que tu dois t'authentifier auprès du service, tu peux charger tes identifiants avec ce qui suit :

    from qiskit_ibm_catalog import QiskitFunctionsCatalog
    catalog = QiskitFunctionsCatalog()

    Par exemple :

# Load saved credentials
from qiskit_ibm_catalog import QiskitFunctionsCatalog

catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")

Avoid executing code on an untrusted machine or an external cloud Python environment to minimize security risks. If you must use an untrusted environment (on, for example, a public computer), change your API key after each use by deleting it on the IBM Cloud API keys page to reduce risk. Learn more in the Managing user API keys topic. To initialize the service in this situation, use this code:

from qiskit_ibm_catalog import QiskitFunctionsCatalog

# After using the following code, delete your API key on the
# IBM Quantum Platform home dashboard
catalog = QiskitFunctionsCatalog(token="<YOUR_API_KEY>") # Use the 44-character
# API_KEY you created and saved from the IBM Quantum Platform Home dashboard
Protéger ta clé API

N'inclus jamais ta clé dans le code source, les scripts Python ou les fichiers de notebook. Lorsque tu partages du code avec d'autres personnes, assure-toi que ta clé API n'est pas intégrée directement dans le script Python. Partage plutôt le script sans la clé et fournis des instructions pour la configurer de manière sécurisée.

Si tu partages accidentellement ta clé avec quelqu'un ou si tu l'inclus dans un système de contrôle de version comme Git, révoque immédiatement ta clé en la supprimant sur la page IBM Cloud API keys afin de réduire les risques. Pour en savoir plus, consulte le sujet Managing user API keys.

Lister les fonctions auxquelles tu as accès

Après t'être authentifié, tu peux lister les fonctions du Qiskit Functions Catalog auxquelles tu as accès :

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)]

Exécuter les fonctions activées

Une fois qu'un objet catalog a été instancié, tu peux sélectionner une fonction en utilisant catalog.load("<provider/function-name>") :

qesem_function = catalog.load("qedma/qesem")

Chaque Qiskit Function a des entrées, options et sorties personnalisées. Consulte les pages de documentation spécifiques de la fonction que tu veux exécuter pour plus d'informations. Par défaut, tous les utilisateurs ne peuvent exécuter qu'un seul job de fonction à la fois :

from qiskit.quantum_info import SparsePauliOp

avg_magnetization = SparsePauliOp.from_sparse_list(
[("Z", [q], 1 / 5) for q in range(5)], num_qubits=5
)

job = qesem_function.run(
pubs=[(circuit, [avg_magnetization, observable])],
backend_name=backend_name, # example: "ibm_fez"
# options = {
# "estimate_time_only": "empirical",
# "default_precision": 0.2, # Default precision is applied to all pubs that don't have a precision specified, see API reference for more details
# "max_execution_time": 3600, # You can specify a maximum QPU time in seconds, see API reference for more details
# "transpilation_level": "standard", # "minimal_with_layout_opt" for minimal transpilation, see API reference for more details
# "parallel_execution": True, # True for parallel execution, see API reference for more details
# },
)
job.job_id
'7f08c9d5-471b-4da2-92e7-4f2cb94c23a8'
conseil

run() vérifie ta capacité restante et l'accès au backend avant de soumettre le job. Si ton instance n'a plus de capacité, ou si le backend que tu as nommé n'est pas accessible, run() génère immédiatement une erreur plutôt que de laisser le job échouer dans la file d'attente. Lorsque la capacité est faible, run() émet un avertissement. Passe suppress_low_usage_warning=True pour le désactiver.

job = qesem_function.run(
pubs=[(circuit, [avg_magnetization, observable])],
backend_name=backend_name, # example: "ibm_fez"
suppress_low_usage_warning=True,
# options = {
# "estimate_time_only": "empirical",
# "default_precision": 0.2, # Default precision is applied to all pubs that don't have a precision specified, see API reference for more details
# "max_execution_time": 3600, # You can specify a maximum QPU time in seconds, see API reference for more details
# "transpilation_level": "standard", # "minimal_with_layout_opt" for minimal transpilation, see API reference for more details
# "parallel_execution": True, # True for parallel execution, see API reference for more details
# },
)

Vérifier le statut d'un job

Avec le job_id de ta Qiskit Function, tu peux vérifier le statut des jobs en cours d'exécution. Cela inclut les statuts suivants :

  • QUEUED : Le programme distant se trouve dans la file d'attente de la Qiskit Function. La priorité dans la file d'attente est basée sur ton utilisation des Qiskit Functions.

  • INITIALIZING : Le programme distant démarre ; cela inclut la configuration de l'environnement distant et l'installation des dépendances.

  • RUNNING : Le programme est en cours d'exécution. Cela inclut également plusieurs statuts plus détaillés si certaines fonctions les prennent en charge.

    • RUNNING: MAPPING : La fonction est en train de mapper tes entrées classiques vers des entrées quantiques.

    • RUNNING: OPTIMIZING_FOR_HARDWARE : La fonction optimise pour la QPU sélectionnée. Cela peut inclure la transpilation de circuit, la caractérisation de la QPU, la rétropropagation d'observables, etc.

    • RUNNING: WAITING_FOR_QPU : La fonction a soumis un job à IBM Quantum Compute Service et attend dans la file d'attente.

    • RUNNING: EXECUTING_QPU : La fonction dispose d'un job Quantum Compute actif.

    • RUNNING: POST_PROCESSING : La fonction post-traite les résultats, ce qui peut inclure l'atténuation d'erreurs, la conversion des résultats quantiques en résultats classiques, etc.

  • DONE : Le programme est terminé, et tu peux récupérer les données de résultat avec job.result().

  • ERROR : Le programme s'est arrêté en raison d'un problème. Utilise job.result() pour obtenir le message d'erreur.

  • CANCELED : Le programme a été annulé par un utilisateur, le service ou le serveur.

job.status()
'QUEUED'

Récupérer les résultats

Une fois qu'un programme est DONE, tu peux utiliser job.result() pour récupérer le résultat. Ce format de sortie varie selon chaque fonction, alors assure-toi de suivre la documentation spécifique :

result = job.result()
print(result)
PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(<shape=(), dtype=float64>), stds=np.ndarray(<shape=(), dtype=float64>), ensemble_standard_error=np.ndarray(<shape=(), dtype=float64>)), metadata={'shots': 4096, 'target_precision': 0.015625, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32})], metadata={'dynamical_decoupling': {'enable': True, 'sequence_type': 'XX', 'extra_slack_distribution': 'middle', 'scheduling_method': 'alap'}, 'twirling': {'enable_gates': False, 'enable_measure': True, 'num_randomizations': 'auto', 'shots_per_randomization': 'auto', 'interleave_randomizations': True, 'strategy': 'active-accum'}, 'resilience': {'measure_mitigation': True, 'zne_mitigation': False, 'pec_mitigation': False}, 'version': 2})

Tu peux également annuler un job à tout moment :

job.cancel()
'Job has been stopped.'

Accéder aux jobs Quantum Compute associés

Une Qiskit Function peut soumettre un ou plusieurs jobs Quantum Compute à une QPU pendant son exécution. Pour récupérer les ID de ces jobs d'exécution, utilise job.runtime_jobs(). Tu peux utiliser ces ID pour récupérer les objets de job d'exécution à partir d'une instance QiskitRuntimeService, ou pour trouver les charges de travail sur le tableau de bord IBM Quantum® Platform.

runtime_job_ids = job.runtime_jobs()
runtime_job_ids

Si une fonction regroupe ses jobs d'exécution en sessions ou en lots, utilise job.runtime_sessions() pour lister les ID de session. Passe un ID de session à job.runtime_jobs() pour ne retourner que les jobs d'exécution de cette session :

sessions = job.runtime_sessions()
if sessions:
session_runtime_jobs = job.runtime_jobs(runtime_session=sessions[0])
print(session_runtime_jobs)
else:
print("No runtime sessions for this job.")
remarque

La liste renvoyée peut être vide. Une fonction ne signale ses jobs d'exécution que lorsqu'elle les soumet via le service d'exécution que la fonction reçoit au moment de l'exécution, et certaines fonctions ne soumettent pas directement de jobs d'exécution.

Consulter les logs d'un job

Utilise job.logs() pour récupérer la sortie des logs qu'une fonction produit pendant son exécution. Les logs sont utiles pour suivre la progression et pour déboguer un job qui se termine dans un état ERROR.

print(job.logs().splitlines())

Pour un job de longue durée qui produit de nombreuses lignes de log, utilise job.filtered_logs() pour ne retourner que les lignes souhaitées. Passe une expression régulière à include pour conserver les lignes correspondantes, ou à exclude pour supprimer les lignes correspondantes :

print(job.filtered_logs(include="iteration"))

Lister les jobs Qiskit Functions exécutés précédemment

Tu peux utiliser jobs() pour lister tous les jobs soumis à Qiskit Functions :

old_jobs = catalog.jobs()
old_jobs
[<Job | f6c29f49-4d5f-4fff-aca6-2e9a115b9763>,
<Job | 7f08c9d5-471b-4da2-92e7-4f2cb94c23a8>,
<Job | 62fe9176-d1e5-467e-b2bd-7a3f3c7be4e5>,
<Job | af525b2e-16b1-45a1-80bb-dbd94ce30258>,
<Job | b95a7a57-c1ad-4958-b7ac-953e4e1ee824>,
<Job | 7bfa33da-0f17-4e67-84b6-f556f7eeb436>,
<Job | ca46c191-9eb9-4de6-bfa7-b60d7eb29b5e>,
<Job | 6ac0ba93-3831-43fb-9fb9-760da2225e06>,
<Job | f0e38071-060d-47e8-988d-9cc1f69358e3>,
<Job | 629cf110-e490-4675-8a07-f6d298d166b0>]

Pour affiner les résultats, passe des filtres. Filtre par fonction avec function, par statut avec status, et par date de soumission avec created_after. Parcours les résultats page par page avec limit et offset :

recent_errors = catalog.jobs(
function=qesem_function,
status="ERROR",
created_after="2024-01-01T00:00:00Z",
limit=5,
)
recent_errors

Si tu as déjà l'ID d'un job donné, tu peux le récupérer avec catalog.job() :

# First, get the most recent job that has been executed.
latest_job = old_jobs[0]

# We can also get that same job with `catalog.job`
job_by_id = catalog.job(latest_job.job_id)

# Verify that the job is the same using both retrieval methods.
assert job_by_id.job_id == latest_job.job_id

# Print the job_id for this job.
print(job_by_id.job_id)
f6c29f49-4d5f-4fff-aca6-2e9a115b9763

Récupérer les messages d'erreur

Si le statut d'un programme est ERROR, utilise job.error_message() pour récupérer le message d'erreur comme suit :

job.error_message()
qiskit.exceptions.QiskitError: 'Workflow execution failed -- https://docs.quantum.ibm.com/errors#9999'

Étapes suivantes

Recommandations