Sari la conținutul principal

Sampler cu REST API

Pașii din acest subiect descriu cum să rulezi și să configurezi volume de lucru cu REST API și demonstrează cum să le invoci în orice program dorit.

notă

Această documentație utilizează modulul Python requests pentru a demonstra Qiskit Runtime REST API. Totuși, acest flux de lucru poate fi executat folosind orice limbaj sau framework care suportă lucrul cu REST API-uri. Consultă documentația de referință API pentru detalii.

1. Inițializează contul

Deoarece Qiskit Runtime Sampler este un serviciu gestionat, trebuie mai întâi să îți inițializezi contul. Poți apoi selecta dispozitivul pe care dorești să îl folosești pentru a rula calculele.

Găsește detalii despre cum să îți inițializezi contul, să vizualizezi backend-urile disponibile și să lucrezi cu token-uri în Configurare pentru utilizarea IBM Quantum Platform cu REST API.

2. Creează un circuit QASM

Ai nevoie de cel puțin un circuit ca intrare pentru primitiva Sampler.

Definește un circuit cuantic 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];
'''

Fragmentele de cod de mai jos presupun că qasm_string a fost transpilat într-un nou șir resulting_qasm.

3. Rulează circuitul cuantic folosind Sampler V2 API

notă

Joburile de mai jos folosesc primitivele Qiskit Runtime V2. SamplerV2 primește unul sau mai multe blocuri unificate primitive (PUB-uri) ca intrare. Fiecare PUB este un tuplu care conține un circuit și datele broadcast-ate la acel circuit, care pot fi mai mulți parametri, și returnează un rezultat per 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. Verifică starea jobului și obține rezultate

Apoi, transmite job_id la 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

Obține rezultatele jobului:

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. Lucrează cu opțiunile Qiskit Runtime

Tehnicile de atenuare a erorilor permit utilizatorilor să atenueze erorile circuitelor prin modelarea zgomotului dispozitivului la momentul execuției. Aceasta are de obicei ca rezultat un overhead de pre-procesare cuantică legat de antrenarea modelului și un overhead de post-procesare clasică pentru a atenua erorile din rezultatele brute folosind modelul generat.

Tehnicile de atenuare a erorilor integrate în primitive sunt opțiuni avansate de reziliență. Pentru a specifica aceste opțiuni, folosește opțiunea resilience_level la trimiterea jobului. Sampler V2 nu suportă specificarea nivelurilor de reziliență. Totuși, poți activa sau dezactiva individual metodele de atenuare/suprimare a erorilor.

Exemplele următoare demonstrează opțiunile implicite pentru dynamical decoupling și twirling. Găsești mai multe opțiuni și detalii suplimentare în subiectul Tehnici de atenuare și suprimare a erorilor.

Dynamical decoupling

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}")

Circuite parametrizate

1. Inițializează contul

Deoarece Qiskit Runtime este un serviciu gestionat, trebuie mai întâi să îți inițializezi contul. Poți apoi selecta dispozitivul pe care dorești să îl folosești pentru a rula calculele.

Găsește detalii despre cum să îți inițializezi contul, să vizualizezi backend-urile disponibile și să invalidezi token-uri în acest subiect.

2. Definește parametrii

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. Creează un circuit cuantic și adaugă porți parametrizate

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. Generează cod QASM 3

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

5. Rulează circuitul cuantic folosind Sampler V2 API

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. Verifică starea jobului și obține rezultate

Apoi, transmite job_id la API:

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

Output

{'status': 'Completed'}

Obține rezultatele jobului:

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

Pașii următori

Recomandări