Estimator con la REST API
Versioni dei pacchetti
Il codice in questa pagina è stato sviluppato usando i seguenti requisiti. Ti consigliamo di usare queste versioni o versioni più recenti.
qiskit[all]~=2.3.0
I passaggi descritti in questo argomento spiegano come eseguire e configurare carichi di lavoro con la REST API, e mostrano come invocarli in qualsiasi programma a tua scelta.
Questa documentazione utilizza il modulo Python requests per illustrare la REST API di Qiskit Runtime. Tuttavia, questo flusso di lavoro può essere eseguito usando qualsiasi linguaggio o framework che supporti il lavoro con le REST API. Consulta la documentazione di riferimento delle API per i dettagli.
1. Inizializza l'account
Poiché Qiskit Runtime Estimator è un servizio gestito, devi prima inizializzare il tuo account. Potrai quindi selezionare il dispositivo da usare per calcolare il valore di aspettazione.
Trovi i dettagli su come inizializzare l'account, visualizzare i Backend disponibili e invalidare i token in questo argomento.
2. Crea un circuito QASM
Hai bisogno di almeno un circuito come input per la primitiva Estimator.
Definisci un circuito quantistico QASM. Per esempio:
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];
'''
I seguenti frammenti di codice assumono che qasm_string sia stato transpilato in una nuova stringa resulting_qasm.
3. Esegui il circuito quantistico usando l'API Estimator V2
I job seguenti usano le primitive Qiskit Runtime V2. Sia SamplerV2 che EstimatorV2 accettano uno o più primitive unified bloc (PUB) come input. Ogni PUB è una tupla che contiene un circuito e i dati trasmessi a quel Circuit, che possono essere più osservabili e parametri. Ogni PUB restituisce un risultato.
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': 'estimator',
"backend": backend,
"params": {
"pubs": [ #primitive unified blocs (PUBs) containing one circuit each.
[resulting_qasm, # QASM circuit
{"IIZII": 1, "XIZZZ": 2.3}, # Observable
None # parameter values
]]
}}
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. Controlla lo stato del job e ottieni i risultati
Successivamente, passa il job_id all'API:
response_status_singlejob= requests.get(url+'/'+job_id, headers=headers)
response_status_singlejob.json().get('state')
Output
>>> Job ID: 58223448-5100-4dec-a47a-942fb30edcad
>>> Job Status: JobStatus.RUNNING
Ottieni i risultati del job:
response_result= requests.get(url+'/'+job_id+'/results', headers=headers)
res_dict=response_result.json()
estimator_result=res_dict['results']
print(estimator_result)
Output
[{'data': {'evs': 0.7428980350102542, 'stds': 0.029884014518789213, 'ensemble_standard_error': 0.03261147170624149}, 'metadata': {'shots': 10016, 'target_precision': 0.01, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32}}]
5. Lavora con le opzioni di Runtime
Le tecniche di mitigazione degli errori consentono agli utenti di mitigare gli errori del circuito modellando il rumore del dispositivo al momento dell'esecuzione. Questo comporta tipicamente un overhead di pre-elaborazione quantistica legato all'addestramento del modello, e un overhead di post-elaborazione classica per mitigare gli errori nei risultati grezzi usando il modello generato.
Le tecniche di mitigazione degli errori integrate nelle primitive sono opzioni avanzate di resilienza. Per specificare queste opzioni, usa l'opzione resilience_level quando invii il tuo job.
Gli esempi seguenti mostrano le opzioni predefinite per il decoupling dinamico, il twirling e TREX + ZNE. Trovi altre opzioni e ulteriori dettagli nell'argomento Tecniche di mitigazione e soppressione degli errori.
TREX + ZNE
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': 'estimator',
"backend": backend,
"params": {
"pubs": [ #primitive unified blocs (PUBs) containing one circuit each
[resulting_qasm, # QASM circuit
{"IIZII": 1, "XIZZZ": 2.3}, # Observable
None # parameter values
]]
"options": {
"resilience": {
"measure_mitigation": True,
"zne_mitigation": True,
"zne": {
"extrapolator":["exponential", "linear"],
"noise_factors":[1, 3, 5],
},
},
},
}
}
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}")
Decoupling dinamico
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': 'estimator',
"backend": backend,
"params": {
"pubs": [ #primitive unified blocs (PUBs) containing one circuit each
[resulting_qasm, # QASM circuit
{"IIZII": 1, "XIZZZ": 2.3}, # Observable
None # parameter values
]]
"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': 'estimator',
"backend": backend,
"params": {
"pubs": [ #primitive unified blocs (PUBs) containing one circuit each
[resulting_qasm, # QASM circuit
{"IIZII": 1, "XIZZZ": 2.3}, # Observable
None # parameter values
]]
"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}")
Circuit parametrizzati
1. Inizializza l'account
Poiché Qiskit Runtime è un servizio gestito, devi prima inizializzare il tuo account. Potrai quindi selezionare il dispositivo su cui vuoi eseguire i tuoi calcoli.
Trovi i dettagli su come inizializzare l'account, visualizzare i Backend disponibili e invalidare i token in questo argomento.
2. Definisci i parametri
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')
parameter_values = {'theta': 1.57, 'phi': 3.14} # In case we want to pass a dictionary
3. Crea un circuito quantistico e aggiungi gate parametrizzati
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. Genera il codice QASM 3
qasm_str = dumps(isa_circuit)
print("Generated QASM 3 code:")
print(qasm_str)
5. Esegui il circuito quantistico usando l'API Estimator 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': 'estimator',
"backend": backend,
"params": {
# Choose one option: direct parameter transfer or through a dictionary
#"pubs": [[qasm_str,[1,2],500]], # primitive unified blocs (PUBs) containing one circuit each.
"pubs": [[qasm_str,parameter_values,500]], # primitive unified blocs (PUBs) containing one circuit each.
}}
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. Controlla lo stato del job e ottieni i risultati
Successivamente, passa il job_id all'API:
response_status_singlejob = requests.get(f"{url}/{job_id}", headers=headers)
response_status_singlejob.json().get('state')
Output
{'status': 'Completed'}
Ottieni i risultati del 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']
Passi successivi
- Esistono diversi modi per eseguire carichi di lavoro, a seconda delle tue esigenze: modalità job, modalità Session e modalità batch. Scopri come lavorare con la modalità Session e la modalità batch nell'argomento sulle modalità di esecuzione. Nota che gli utenti del piano Open non possono inviare job in Session.
- Scopri come inizializzare il tuo account con la REST API.
- Esercitati con le primitive seguendo la lezione sulle funzioni di costo in IBM Quantum® Learning.
- Scopri come transpilare localmente nella sezione Transpile.