Aller au contenu principal

Sampler avec l'API REST

Les étapes décrites dans cette rubrique expliquent comment exécuter et configurer des workloads avec l'API REST, et montrent comment les invoquer dans n'importe quel programme de ton choix.

remarque

Cette documentation utilise le module Python requests pour illustrer l'API REST IBM Quantum Compute Service. Cependant, ce workflow peut être exécuté en utilisant n'importe quel langage ou framework prenant en charge les API REST. Consulte la documentation de référence de l'API pour plus de détails.

1. Initialiser le compte​

Tu dois d'abord initialiser ton compte. Tu peux ensuite sélectionner l'appareil sur lequel tu veux exécuter tes calculs.

Trouve des détails sur la façon d'initialiser ton compte, d'afficher les backends disponibles et de travailler avec des tokens dans Configurer l'utilisation d'IBM Quantum Platform avec l'API REST.

2. Créer un circuit QASM​

Tu as besoin d'au moins un circuit comme entrée de la primitive Sampler.

Définis un circuit quantique QASM :

qasm_string='''
OPENQASM 3;
include "stdgates.inc";
qreg q[2];
creg c[2];
x q[0];
cx q[0], q[1];
c[0] = measure q[0];
c[1] = measure q[1];
'''

Les extraits de code donnés ci-dessous supposent que le qasm_string a été transcompilé en une nouvelle chaîne resulting_qasm.

3. Exécuter le circuit quantique à l'aide de l'API Sampler V2​

remarque

Les jobs ci-dessous utilisent les primitives IBM Quantum V2. SamplerV2 prend en entrée un ou plusieurs blocs unifiés de primitives (PUBs). Chaque PUB est un tuple qui contient un circuit et les données diffusées à ce circuit, qui peuvent être plusieurs paramètres, et renvoie un résultat par PUB.

import requests

url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "<BACKEND_NAME>"

headers = {
'Content-Type': 'application/json',
'Authorization':auth_id,
'Service-CRN': crn
}
job_input = {
'program_id': 'sampler',
"backend": backend,
"params": {
# primitive unified blocs (PUBs) containing one circuit each:
"pubs": [[resulting_qasm],[resulting_qasm,None,500]]
}}

response = requests.post(url, headers=headers, json=job_input)

if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")

4. Vérifier le statut du job et obtenir les résultats​

Ensuite, passe le job_id à l'API :

response_status_singlejob= requests.get(url+'/'+job_id, headers=headers)
response_status_singlejob.json().get('state')

Output

>>> Job ID: 58223448-5100-4dec-a47a-942fb30edced
>>> Job Status: JobStatus.RUNNING

Obtiens les résultats du job :

response_result= requests.get(url+'/'+job_id+'/results', headers=headers)

res_dict=response_result.json()

# Get results for the first PUB
counts=res_dict['results'][0]['data']['c']['samples']

print(counts[:20])

Output

['0x3', '0x0', '0x2', '0x1', '0x0', '0x3', '0x0', '0x3', '0x1', '0x2', '0x2', '0x0', '0x2', '0x0', '0x3', '0x3', '0x2', '0x0', '0x1', '0x0']

5. Travailler avec les options d'IBM Quantum Compute Service​

Les techniques d'atténuation d'erreurs permettent aux utilisateurs d'atténuer les erreurs de circuit en modélisant le bruit de l'appareil au moment de l'exécution. Cela entraîne généralement un surcoût de pré-traitement quantique lié à l'entraînement du modèle, et un surcoût de post-traitement classique pour atténuer les erreurs dans les résultats bruts en utilisant le modèle généré.

Les techniques d'atténuation d'erreurs intégrées aux primitives sont des options de résilience avancées. Pour spécifier ces options, utilise l'option resilience_level lors de la soumission de ton job. Sampler V2 ne prend pas en charge la spécification de niveaux de résilience. Cependant, tu peux activer ou désactiver des méthodes individuelles d'atténuation / suppression d'erreurs.

Les exemples suivants illustrent les options par défaut pour le découplage dynamique et le twirling. Trouve plus d'options et de détails supplémentaires dans la rubrique Techniques d'atténuation et de suppression d'erreurs.

Découplage dynamique​

import requests

url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "<BACKEND_NAME>"

headers = {
'Content-Type': 'application/json',
'Authorization':auth_id,
'Service-CRN': crn
}
job_input = {
'program_id': 'sampler',
"backend": backend,
"params": {
# primitive unified blocs (PUBs) containing one circuit each:
"pubs": [[resulting_qasm]],
"options": {
"dynamical_decoupling": {
"enable": True,
"sequence_type": 'XpXm',
"extra_slack_distribution": 'middle',
"scheduling_method": 'alap',
},
},
}
}

response = requests.post(url, headers=headers, json=job_input)

if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")

Twirling​

import requests

url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "<BACKEND_NAME>"

headers = {
'Content-Type': 'application/json',
'Authorization':auth_id,
'Service-CRN': crn
}
job_input = {
'program_id': 'sampler',
"backend": backend,
"params": {
# primitive unified blocs (PUBs) containing one circuit each:
"pubs": [[resulting_qasm]],
"options": {
"twirling": {
"enable_gates": True,
"enable_measure": True,
"num_randomizations": "auto",
"shots_per_randomization": "auto",
"strategy": "active-accum",
},
},
}
}

response = requests.post(url, headers=headers, json=job_input)

if response.status_code == 200:
job_id = response.json().get('id')
print("Job created:",response.text)
else:
print(f"Error: {response.status_code}")

Circuits paramétrés​

1. Initialiser le compte​

Tu dois d'abord initialiser ton compte. Tu peux ensuite sélectionner l'appareil sur lequel tu veux exécuter tes calculs.

Trouve des détails sur la façon d'initialiser ton compte, d'afficher les backends disponibles et d'invalider des tokens dans cette rubrique.

2. Définir les paramètres​

import requests
import qiskit_ibm_runtime
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.qasm3 import dumps
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from qiskit import transpile

service = QiskitRuntimeService(channel='ibm_quantum')
backend = service.backend("<SPECIFY BACKEND>")

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)

theta = Parameter('theta')
phi = Parameter('phi')
# In case we want to pass a dictionary:
parameter_values = {'theta': 1.57, 'phi': 3.14}

3. Créer un circuit quantique et ajouter des gates paramétrées​

qc = QuantumCircuit(2)

# Add parameterized gates
qc.rx(theta, 0)
qc.ry(phi, 1)
qc.cx(0, 1)
qc.measure_all()

# Draw the original circuit
qc.draw('mpl')

# Get an ISA circuit
isa_circuit = pm.run(qc)

4. Générer le code QASM 3​

qasm_str = dumps(isa_circuit)
print("Generated QASM 3 code:")
print(qasm_str)

5. Exécuter le circuit quantique à l'aide de l'API Sampler V2​

import requests

url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "<BACKEND_NAME>"

headers = {
'Content-Type': 'application/json',
'Authorization':auth_id,
'Service-CRN': crn
}

job_input = {
'program_id': 'sampler',
"backend": backend,
"params": {
# Choose one option: direct parameter transfer or through a dictionary
# # primitive unified blocs (PUBs) containing one circuit each:
#"pubs": [[qasm_str,[1,2],500]],

# primitive unified blocs (PUBs) containing one circuit each:
"pubs": [[qasm_str,parameter_values,500]],
}}

response = requests.post(url, headers=headers, json=job_input)

if response.status_code == 200:
job_id = response.json().get('id')
print(f"Job created: {response.text}")
else:
print(f"Error: {response.status_code}")
print(response.text)

6. Vérifier le statut du job et obtenir les résultats​

Ensuite, passe le job_id à l'API :

response_status_singlejob = requests.get(f"{url}/{job_id}", headers=headers)
response_status_singlejob.json().get('state')

Output

{'status': 'Completed'}

Obtiens les résultats du job :

response_result = requests.get(f"{url}/{job_id}/results", headers=headers)

res_dict=response_result.json()

# Get results for the first PUB
counts=res_dict['results'][0]['data']['c']['samples']

print(counts[:20])

Output

['0x1', '0x2', '0x1', '0x2', '0x1', '0x2', '0x0', '0x2', '0x1', '0x1', '0x2', '0x2', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1']

Étapes suivantes​

Recommandations
  • Il existe plusieurs façons d'exécuter des workloads, selon tes besoins : mode job, mode session et mode batch. Apprends à travailler avec le mode session et le mode batch dans la rubrique sur les modes d'exécution. Note que les utilisateurs du plan Open ne peuvent pas soumettre de jobs de session.
  • Apprends à initialiser ton compte avec l'API REST.
  • Entraîne-toi avec les primitives en suivant la leçon sur les fonctions de coût dans IBM Quantum Learning.
  • Apprends à transcompiler localement dans la section Transcompilation.