Vai al contenuto principale

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.

nota

Questa documentazione utilizza il modulo Python requests per illustrare la REST API. 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é 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​

nota

I job seguenti usano le primitive IBM Quantum 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 circuito, 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​

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 dynamical decoupling, 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}")

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

Circuiti parametrizzati​

1. Inizializza l'account​

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​

Raccomandazioni
  • 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.